Merge "Revert "Revert "Hide _tolower_tab_ and _toupper_tab_ on LP64."""
diff --git a/benchmarks/unistd_benchmark.cpp b/benchmarks/unistd_benchmark.cpp
index c35e7c3..7e2ac30 100644
--- a/benchmarks/unistd_benchmark.cpp
+++ b/benchmarks/unistd_benchmark.cpp
@@ -30,6 +30,17 @@
 }
 BENCHMARK(BM_unistd_getpid);
 
+static void BM_unistd_getpid_syscall(int iters) {
+  StartBenchmarkTiming();
+
+  for (int i = 0; i < iters; ++i) {
+    syscall(__NR_getpid);
+  }
+
+  StopBenchmarkTiming();
+}
+BENCHMARK(BM_unistd_getpid_syscall);
+
 // Stop GCC optimizing out our pure function.
 /* Must not be static! */ pid_t (*gettid_fp)() = gettid;
 
diff --git a/libc/Android.mk b/libc/Android.mk
index 2747a3e..078be59 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -127,6 +127,7 @@
     bionic/getauxval.cpp \
     bionic/getcwd.cpp \
     bionic/getpgrp.cpp \
+    bionic/getpid.cpp \
     bionic/gettid.cpp \
     bionic/inotify_init.cpp \
     bionic/lchown.cpp \
@@ -216,7 +217,7 @@
     bionic/system_properties.cpp \
     bionic/tdestroy.cpp \
     bionic/termios.cpp \
-    bionic/thread_atexit.cpp \
+    bionic/thread_private.cpp \
     bionic/tmpfile.cpp \
     bionic/umount.cpp \
     bionic/unlink.cpp \
@@ -233,7 +234,6 @@
     upstream-freebsd/lib/libc/stdio/fclose.c \
     upstream-freebsd/lib/libc/stdio/flags.c \
     upstream-freebsd/lib/libc/stdio/fopen.c \
-    upstream-freebsd/lib/libc/stdio/mktemp.c \
     upstream-freebsd/lib/libc/stdlib/abs.c \
     upstream-freebsd/lib/libc/stdlib/getopt_long.c \
     upstream-freebsd/lib/libc/stdlib/imaxabs.c \
@@ -262,7 +262,6 @@
     upstream-freebsd/lib/libc/string/wmemset.c \
 
 libc_upstream_netbsd_src_files := \
-    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
     upstream-netbsd/common/lib/libc/stdlib/random.c \
     upstream-netbsd/lib/libc/gen/ftw.c \
     upstream-netbsd/lib/libc/gen/nftw.c \
@@ -271,10 +270,12 @@
     upstream-netbsd/lib/libc/gen/psignal.c \
     upstream-netbsd/lib/libc/gen/utime.c \
     upstream-netbsd/lib/libc/gen/utmp.c \
+    upstream-netbsd/lib/libc/inet/nsap_addr.c \
     upstream-netbsd/lib/libc/regex/regcomp.c \
     upstream-netbsd/lib/libc/regex/regerror.c \
     upstream-netbsd/lib/libc/regex/regexec.c \
     upstream-netbsd/lib/libc/regex/regfree.c \
+    upstream-netbsd/lib/libc/resolv/mtctxres.c \
     upstream-netbsd/lib/libc/stdlib/bsearch.c \
     upstream-netbsd/lib/libc/stdlib/div.c \
     upstream-netbsd/lib/libc/stdlib/drand48.c \
@@ -412,6 +413,7 @@
     upstream-openbsd/lib/libc/stdio/getwc.c \
     upstream-openbsd/lib/libc/stdio/getwchar.c \
     upstream-openbsd/lib/libc/stdio/makebuf.c \
+    upstream-openbsd/lib/libc/stdio/mktemp.c \
     upstream-openbsd/lib/libc/stdio/perror.c \
     upstream-openbsd/lib/libc/stdio/printf.c \
     upstream-openbsd/lib/libc/stdio/putc.c \
@@ -494,6 +496,7 @@
     -Werror=pointer-to-int-cast \
     -Werror=int-to-pointer-cast \
     -Werror=type-limits \
+    -Werror \
 
 ifeq ($(strip $(DEBUG_BIONIC_LIBC)),true)
   libc_common_cflags += -DDEBUG
@@ -563,7 +566,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := bionic/__stack_chk_fail.cpp
-LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector -Werror
+LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -585,7 +588,9 @@
 # tzcode doesn't include wcsftime, so we use the OpenBSD one.
 LOCAL_SRC_FILES += upstream-openbsd/lib/libc/time/wcsftime.c
 
-LOCAL_CFLAGS := $(libc_common_cflags)
+LOCAL_CFLAGS := $(libc_common_cflags) \
+    -fvisibility=hidden \
+
 # Don't use ridiculous amounts of stack.
 LOCAL_CFLAGS += -DALL_STATE
 # Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
@@ -597,6 +602,7 @@
 # Include timezone and daylight globals.
 LOCAL_CFLAGS += -DUSG_COMPAT=1
 LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
+LOCAL_CFLAGS += -Dlint
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -625,12 +631,12 @@
     -DANDROID_CHANGES \
     -DINET6 \
     -fvisibility=hidden \
+    -Wno-unused-parameter \
     -I$(LOCAL_PATH)/dns/include \
     -I$(LOCAL_PATH)/private \
     -I$(LOCAL_PATH)/upstream-netbsd/lib/libc/include \
     -I$(LOCAL_PATH)/upstream-netbsd/android/include \
     -include netbsd-compat.h \
-#    -Werror \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -659,7 +665,6 @@
     -I$(LOCAL_PATH)/upstream-freebsd/android/include \
     -I$(LOCAL_PATH)/upstream-freebsd/lib/libc/include \
     -include freebsd-compat.h \
-#    -Werror \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -685,7 +690,6 @@
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
     -Wno-sign-compare -Wno-uninitialized \
-    -Werror \
     -DPOSIX_MISTAKE \
     -I$(LOCAL_PATH)/upstream-netbsd/android/include \
     -I$(LOCAL_PATH)/upstream-netbsd/lib/libc/include \
@@ -699,6 +703,7 @@
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
 $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
+$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_netbsd_src_files))
 include $(BUILD_STATIC_LIBRARY)
 
 
@@ -715,7 +720,6 @@
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
     -Wno-sign-compare -Wno-uninitialized -Wno-unused-parameter \
-    -Werror \
     -I$(LOCAL_PATH)/upstream-openbsd/android/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/gdtoa/ \
@@ -746,7 +750,6 @@
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
     -Wno-sign-compare -Wno-uninitialized \
-    -Werror \
     -fvisibility=hidden \
     -I$(LOCAL_PATH)/upstream-openbsd/android/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
@@ -771,7 +774,6 @@
 
 LOCAL_SRC_FILES := $(libc_bionic_src_files)
 LOCAL_CFLAGS := $(libc_common_cflags) \
-    -Werror \
     -Wframe-larger-than=2048 \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
@@ -867,7 +869,6 @@
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_CFLAGS := $(libc_common_cflags) \
     -DLIBC_STATIC \
-    -Werror \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -889,7 +890,6 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(libc_malloc_src)
 LOCAL_CFLAGS := $(libc_common_cflags) \
-    -Werror \
     -fvisibility=hidden \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
@@ -913,7 +913,6 @@
 
 LOCAL_CFLAGS := $(libc_common_cflags) \
     -DLIBC_STATIC \
-    -Werror \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -933,7 +932,7 @@
 # ========================================================
 include $(CLEAR_VARS)
 
-LOCAL_CFLAGS := $(libc_common_cflags) -Werror
+LOCAL_CFLAGS := $(libc_common_cflags)
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -966,6 +965,13 @@
 LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
+# We'd really like to do this for all architectures, but since this wasn't done
+# before, these symbols must continue to be exported on LP32 for binary
+# compatibility.
+LOCAL_LDFLAGS_arm64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_mips64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_x86_64 := -Wl,--exclude-libs,libgcc.a
+
 $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 $(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_arch_dynamic_src_files))
 $(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_static_common_src_files))
@@ -996,7 +1002,6 @@
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
     -DMALLOC_LEAK_CHECK \
-    -Werror \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -1032,7 +1037,6 @@
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
     -DMALLOC_QEMU_INSTRUMENT \
-    -Werror \
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 369b23c..b4c8134 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -97,7 +97,7 @@
 ssize_t     pwrite64(int, void*, size_t, off64_t) arm,mips,x86
 ssize_t     pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
 int         close(int)                      all
-pid_t       getpid()    all
+pid_t       __getpid:getpid()  all
 int         munmap(void*, size_t)  all
 void*       mremap(void*, size_t, size_t, unsigned long)  all
 int         msync(const void*, size_t, int)    all
@@ -285,6 +285,10 @@
 int     sysinfo(struct sysinfo*)  all
 int     personality(unsigned long)  all
 
+ssize_t tee(int, int, size_t, unsigned int)  all
+ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int)  all
+ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int)  all
+
 int epoll_create1(int)  all
 int epoll_ctl(int, int op, int, struct epoll_event*)  all
 int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t)  all
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 38301bc..47e436c 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -65,6 +65,9 @@
 libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
 libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
 
+libc_netbsd_src_files_arm := \
+    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+
 ## CPU variant specific source files
 ifeq ($(strip $(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)),)
   $(warning TARGET_$(my_2nd_arch_prefix)ARCH is arm, but TARGET_$(my_2nd_arch_prefix)CPU_VARIANT is not defined)
diff --git a/libc/arch-arm/syscalls/getpid.S b/libc/arch-arm/syscalls/__getpid.S
similarity index 89%
rename from libc/arch-arm/syscalls/getpid.S
rename to libc/arch-arm/syscalls/__getpid.S
index 10bcb8e..eedc33a 100644
--- a/libc/arch-arm/syscalls/getpid.S
+++ b/libc/arch-arm/syscalls/__getpid.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(__getpid)
     mov     ip, r7
     ldr     r7, =__NR_getpid
     swi     #0
@@ -11,4 +11,4 @@
     bxls    lr
     neg     r0, r0
     b       __set_errno
-END(getpid)
+END(__getpid)
diff --git a/libc/arch-arm/syscalls/splice.S b/libc/arch-arm/syscalls/splice.S
new file mode 100644
index 0000000..782ba6c
--- /dev/null
+++ b/libc/arch-arm/syscalls/splice.S
@@ -0,0 +1,22 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(splice)
+    mov     ip, sp
+    stmfd   sp!, {r4, r5, r6, r7}
+    .cfi_def_cfa_offset 16
+    .cfi_rel_offset r4, 0
+    .cfi_rel_offset r5, 4
+    .cfi_rel_offset r6, 8
+    .cfi_rel_offset r7, 12
+    ldmfd   ip, {r4, r5, r6}
+    ldr     r7, =__NR_splice
+    swi     #0
+    ldmfd   sp!, {r4, r5, r6, r7}
+    .cfi_def_cfa_offset 0
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(splice)
diff --git a/libc/arch-arm/syscalls/getpid.S b/libc/arch-arm/syscalls/tee.S
similarity index 80%
copy from libc/arch-arm/syscalls/getpid.S
copy to libc/arch-arm/syscalls/tee.S
index 10bcb8e..9174617 100644
--- a/libc/arch-arm/syscalls/getpid.S
+++ b/libc/arch-arm/syscalls/tee.S
@@ -2,13 +2,13 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(tee)
     mov     ip, r7
-    ldr     r7, =__NR_getpid
+    ldr     r7, =__NR_tee
     swi     #0
     mov     r7, ip
     cmn     r0, #(MAX_ERRNO + 1)
     bxls    lr
     neg     r0, r0
     b       __set_errno
-END(getpid)
+END(tee)
diff --git a/libc/arch-arm/syscalls/getpid.S b/libc/arch-arm/syscalls/vmsplice.S
similarity index 78%
copy from libc/arch-arm/syscalls/getpid.S
copy to libc/arch-arm/syscalls/vmsplice.S
index 10bcb8e..3b89623 100644
--- a/libc/arch-arm/syscalls/getpid.S
+++ b/libc/arch-arm/syscalls/vmsplice.S
@@ -2,13 +2,13 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(vmsplice)
     mov     ip, r7
-    ldr     r7, =__NR_getpid
+    ldr     r7, =__NR_vmsplice
     swi     #0
     mov     r7, ip
     cmn     r0, #(MAX_ERRNO + 1)
     bxls    lr
     neg     r0, r0
     b       __set_errno
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 2d34f52..20d9cf1 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -3,7 +3,6 @@
 libc_common_src_files_arm64 := \
     bionic/memchr.c \
     bionic/memrchr.c \
-    bionic/strchr.cpp \
     bionic/strrchr.cpp \
     upstream-freebsd/lib/libc/string/wcscat.c \
     upstream-freebsd/lib/libc/string/wcschr.c \
@@ -12,10 +11,8 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
-    upstream-openbsd/lib/libc/string/stpcpy.c \
     upstream-openbsd/lib/libc/string/stpncpy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
-    upstream-openbsd/lib/libc/string/strcpy.c \
     upstream-openbsd/lib/libc/string/strlcat.c \
     upstream-openbsd/lib/libc/string/strlcpy.c \
     upstream-openbsd/lib/libc/string/strncat.c \
@@ -57,7 +54,7 @@
 endif
 cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
 ifeq ($(wildcard $(cpu_variant_mk)),)
-$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
 endif
 include $(cpu_variant_mk)
 libc_common_additional_dependencies += $(cpu_variank_mk)
diff --git a/libc/arch-arm64/denver64/bionic/memcpy.S b/libc/arch-arm64/denver64/bionic/memcpy.S
new file mode 100644
index 0000000..700f0d0
--- /dev/null
+++ b/libc/arch-arm64/denver64/bionic/memcpy.S
@@ -0,0 +1,205 @@
+/* Copyright (c) 2012, Linaro Limited
+   All rights reserved.
+   Copyright (c) 2014, NVIDIA Corporation.  All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the Linaro nor the
+         names of its contributors may be used to endorse or promote products
+         derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Assumptions:
+ *
+ * denver, ARMv8-a, AArch64
+ * Unaligned accesses
+ *
+ */
+
+#include <private/bionic_asm.h>
+
+#define dstin	x0
+#define src	x1
+#define count	x2
+#define tmp1	x3
+#define tmp1w	w3
+#define tmp2	x4
+#define tmp2w	w4
+#define tmp3	x5
+#define tmp3w	w5
+#define dst	x6
+
+#define A_l	x7
+#define A_h	x8
+#define B_l	x9
+#define B_h	x10
+#define C_l	x11
+#define C_h	x12
+#define D_l	x13
+#define D_h	x14
+
+#define QA_l	q0
+#define QA_h	q1
+#define QB_l	q2
+#define QB_h	q3
+
+ENTRY(memcpy)
+
+	mov	dst, dstin
+	cmp	count, #64
+	b.ge	.Lcpy_not_short
+	cmp	count, #15
+	b.le	.Ltail15tiny
+
+	/* Deal with small copies quickly by dropping straight into the
+	 * exit block.  */
+.Ltail63:
+	/* Copy up to 48 bytes of data.  At this point we only need the
+	 * bottom 6 bits of count to be accurate.  */
+	ands	tmp1, count, #0x30
+	b.eq	.Ltail15
+	add	dst, dst, tmp1
+	add	src, src, tmp1
+	cmp	tmp1w, #0x20
+	b.eq	1f
+	b.lt	2f
+	ldp	A_l, A_h, [src, #-48]
+	stp	A_l, A_h, [dst, #-48]
+1:
+	ldp	A_l, A_h, [src, #-32]
+	stp	A_l, A_h, [dst, #-32]
+2:
+	ldp	A_l, A_h, [src, #-16]
+	stp	A_l, A_h, [dst, #-16]
+
+.Ltail15:
+	ands	count, count, #15
+	beq	1f
+	add	src, src, count
+	ldp	A_l, A_h, [src, #-16]
+	add	dst, dst, count
+	stp	A_l, A_h, [dst, #-16]
+1:
+	ret
+
+.Ltail15tiny:
+	/* Copy up to 15 bytes of data.  Does not assume additional data
+	   being copied.  */
+	tbz	count, #3, 1f
+	ldr	tmp1, [src], #8
+	str	tmp1, [dst], #8
+1:
+	tbz	count, #2, 1f
+	ldr	tmp1w, [src], #4
+	str	tmp1w, [dst], #4
+1:
+	tbz	count, #1, 1f
+	ldrh	tmp1w, [src], #2
+	strh	tmp1w, [dst], #2
+1:
+	tbz	count, #0, 1f
+	ldrb	tmp1w, [src]
+	strb	tmp1w, [dst]
+1:
+	ret
+
+.Lcpy_not_short:
+	/* We don't much care about the alignment of DST, but we want SRC
+	 * to be 128-bit (16 byte) aligned so that we don't cross cache line
+	 * boundaries on both loads and stores.  */
+	neg	tmp2, src
+	ands	tmp2, tmp2, #15		/* Bytes to reach alignment.  */
+	b.eq	2f
+	sub	count, count, tmp2
+	/* Copy more data than needed; it's faster than jumping
+	 * around copying sub-Quadword quantities.  We know that
+	 * it can't overrun.  */
+	ldp	A_l, A_h, [src]
+	add	src, src, tmp2
+	stp	A_l, A_h, [dst]
+	add	dst, dst, tmp2
+	/* There may be less than 63 bytes to go now.  */
+	cmp	count, #63
+	b.le	.Ltail63
+2:
+	subs	count, count, #128
+	b.ge	.Lcpy_body_large
+	/* Less than 128 bytes to copy, so handle 64 here and then jump
+	 * to the tail.  */
+	ldp	QA_l, QA_h, [src]
+	ldp	QB_l, QB_h, [src, #32]
+	stp	QA_l, QA_h, [dst]
+	stp	QB_l, QB_h, [dst, #32]
+	tst	count, #0x3f
+	add	src, src, #64
+	add	dst, dst, #64
+	b.ne	.Ltail63
+	ret
+
+	/* Critical loop.  Start at a new cache line boundary.  Assuming
+	 * 64 bytes per line this ensures the entire loop is in one line.  */
+	.p2align 6
+.Lcpy_body_large:
+	cmp	count, 65536
+	bhi	.Lcpy_body_huge
+	/* There are at least 128 bytes to copy.  */
+	ldp	QA_l, QA_h, [src, #0]
+	sub	dst, dst, #32		/* Pre-bias.  */
+	ldp	QB_l, QB_h, [src, #32]!	/* src += 64 - Pre-bias.  */
+1:
+	stp	QA_l, QA_h, [dst, #32]
+	ldp	QA_l, QA_h, [src, #32]
+	stp	QB_l, QB_h, [dst, #64]!
+	ldp	QB_l, QB_h, [src, #64]!
+
+	subs	count, count, #64
+	b.ge	1b
+
+	stp	QA_l, QA_h, [dst, #32]
+	stp	QB_l, QB_h, [dst, #64]
+	add	src, src, #32
+	add	dst, dst, #64 + 32
+	tst	count, #0x3f
+	b.ne	.Ltail63
+	ret
+.Lcpy_body_huge:
+	/* There are at least 128 bytes to copy.  */
+	ldp	QA_l, QA_h, [src, #0]
+	sub	dst, dst, #32		/* Pre-bias.  */
+	ldp	QB_l, QB_h, [src, #32]!
+1:
+	stnp	QA_l, QA_h, [dst, #32]
+	stnp	QB_l, QB_h, [dst, #64]
+	ldp	QA_l, QA_h, [src, #32]
+	ldp	QB_l, QB_h, [src, #64]!
+	add	dst, dst, #64
+
+	subs	count, count, #64
+	b.ge	1b
+
+	stnp	QA_l, QA_h, [dst, #32]
+	stnp	QB_l, QB_h, [dst, #64]
+	add	src, src, #32
+	add	dst, dst, #64 + 32
+	tst	count, #0x3f
+	b.ne	.Ltail63
+	ret
+
+END(memcpy)
diff --git a/libc/arch-arm64/denver64/bionic/memset.S b/libc/arch-arm64/denver64/bionic/memset.S
new file mode 100644
index 0000000..9127d89
--- /dev/null
+++ b/libc/arch-arm64/denver64/bionic/memset.S
@@ -0,0 +1,271 @@
+/* Copyright (c) 2012, Linaro Limited
+   All rights reserved.
+   Copyright (c) 2014, NVIDIA Corporation.  All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the Linaro nor the
+         names of its contributors may be used to endorse or promote products
+         derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Assumptions:
+ *
+ * denver, ARMv8-a, AArch64
+ * Unaligned accesses
+ *
+ */
+
+#include <private/bionic_asm.h>
+
+/* By default we assume that the DC instruction can be used to zero
+   data blocks more efficiently.  In some circumstances this might be
+   unsafe, for example in an asymmetric multiprocessor environment with
+   different DC clear lengths (neither the upper nor lower lengths are
+   safe to use).  The feature can be disabled by defining DONT_USE_DC.
+
+   If code may be run in a virtualized environment, then define
+   MAYBE_VIRT.  This will cause the code to cache the system register
+   values rather than re-reading them each call.  */
+
+#define dstin		x0
+#define val		w1
+#define count		x2
+#define tmp1		x3
+#define tmp1w		w3
+#define tmp2		x4
+#define tmp2w		w4
+#define zva_len_x	x5
+#define zva_len		w5
+#define zva_bits_x	x6
+
+#define A_l		x7
+#define A_lw		w7
+#define dst		x8
+#define tmp3w		w9
+
+#define QA_l		q0
+
+ENTRY(memset)
+
+	mov	dst, dstin		/* Preserve return value.  */
+	ands	A_lw, val, #255
+#ifndef DONT_USE_DC
+#	b.eq	.Lzero_mem
+#endif
+	orr	A_lw, A_lw, A_lw, lsl #8
+	orr	A_lw, A_lw, A_lw, lsl #16
+	orr	A_l, A_l, A_l, lsl #32
+.Ltail_maybe_long:
+	cmp	count, #256
+	b.ge	.Lnot_short
+.Ltail_maybe_tiny:
+	cmp	count, #15
+	b.le	.Ltail15tiny
+.Ltail255:
+	ands	tmp1, count, #0xC0
+	b.eq	.Ltail63
+	dup	v0.4s, A_lw
+	cmp	tmp1w, #0x80
+	b.eq	1f
+	b.lt	2f
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+1:
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+2:
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+.Ltail63:
+	ands	tmp1, count, #0x30
+	b.eq	.Ltail15
+	add	dst, dst, tmp1
+	cmp	tmp1w, #0x20
+	b.eq	1f
+	b.lt	2f
+	stp	A_l, A_l, [dst, #-48]
+1:
+	stp	A_l, A_l, [dst, #-32]
+2:
+	stp	A_l, A_l, [dst, #-16]
+
+.Ltail15:
+	and	count, count, #15
+	add	dst, dst, count
+	stp	A_l, A_l, [dst, #-16]	/* Repeat some/all of last store. */
+	ret
+
+.Ltail15tiny:
+	/* Set up to 15 bytes.  Does not assume earlier memory
+	   being set.  */
+	tbz	count, #3, 1f
+	str	A_l, [dst], #8
+1:
+	tbz	count, #2, 1f
+	str	A_lw, [dst], #4
+1:
+	tbz	count, #1, 1f
+	strh	A_lw, [dst], #2
+1:
+	tbz	count, #0, 1f
+	strb	A_lw, [dst]
+1:
+	ret
+
+	/* Critical loop.  Start at a new cache line boundary.  Assuming
+	 * 64 bytes per line, this ensures the entire loop is in one line.  */
+	.p2align 6
+.Lnot_short:
+	dup	v0.4s, A_lw
+	neg	tmp2, dst
+	ands	tmp2, tmp2, #15
+	b.eq	2f
+	/* Bring DST to 128-bit (16-byte) alignment.  We know that there's
+	 * more than that to set, so we simply store 16 bytes and advance by
+	 * the amount required to reach alignment.  */
+	sub	count, count, tmp2
+	stp	A_l, A_l, [dst]
+	add	dst, dst, tmp2
+	/* There may be less than 63 bytes to go now.  */
+	cmp	count, #255
+	b.le	.Ltail255
+2:
+	cmp	count, #2097152
+	b.gt	3f
+1:
+	sub	count, count, #256
+2:
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+	stp	QA_l, QA_l, [dst], #32
+	subs	count, count, #256
+	b.ge	2b
+	tst	count, #0xff
+	b.ne	.Ltail255
+	ret
+3:
+	sub	count, count, #64
+4:
+	subs	count, count, #64
+	stnp	QA_l, QA_l, [dst]
+	stnp	QA_l, QA_l, [dst, #32]
+	add	dst, dst, #64
+	b.ge	4b
+	tst	count, #0x3f
+	b.ne	.Ltail63
+	ret
+
+#ifndef DONT_USE_DC
+	/* For zeroing memory, check to see if we can use the ZVA feature to
+	 * zero entire 'cache' lines.  */
+.Lzero_mem:
+	mov	A_l, #0
+	cmp	count, #63
+	b.le	.Ltail_maybe_tiny
+	neg	tmp2, dst
+	ands	tmp2, tmp2, #15
+	b.eq	1f
+	sub	count, count, tmp2
+	stp	A_l, A_l, [dst]
+	add	dst, dst, tmp2
+	cmp	count, #63
+	b.le	.Ltail63
+1:
+	/* For zeroing small amounts of memory, it's not worth setting up
+	 * the line-clear code.  */
+	cmp	count, #128
+	b.lt	.Lnot_short
+#ifdef MAYBE_VIRT
+	/* For efficiency when virtualized, we cache the ZVA capability.  */
+	adrp	tmp2, .Lcache_clear
+	ldr	zva_len, [tmp2, #:lo12:.Lcache_clear]
+	tbnz	zva_len, #31, .Lnot_short
+	cbnz	zva_len, .Lzero_by_line
+	mrs	tmp1, dczid_el0
+	tbz	tmp1, #4, 1f
+	/* ZVA not available.  Remember this for next time.  */
+	mov	zva_len, #~0
+	str	zva_len, [tmp2, #:lo12:.Lcache_clear]
+	b	.Lnot_short
+1:
+	mov	tmp3w, #4
+	and	zva_len, tmp1w, #15	/* Safety: other bits reserved.  */
+	lsl	zva_len, tmp3w, zva_len
+	str	zva_len, [tmp2, #:lo12:.Lcache_clear]
+#else
+	mrs	tmp1, dczid_el0
+	tbnz	tmp1, #4, .Lnot_short
+	mov	tmp3w, #4
+	and	zva_len, tmp1w, #15	/* Safety: other bits reserved.  */
+	lsl	zva_len, tmp3w, zva_len
+#endif
+
+.Lzero_by_line:
+	/* Compute how far we need to go to become suitably aligned.  We're
+	 * already at quad-word alignment.  */
+	cmp	count, zva_len_x
+	b.lt	.Lnot_short		/* Not enough to reach alignment.  */
+	sub	zva_bits_x, zva_len_x, #1
+	neg	tmp2, dst
+	ands	tmp2, tmp2, zva_bits_x
+	b.eq	1f			/* Already aligned.  */
+	/* Not aligned, check that there's enough to copy after alignment.  */
+	sub	tmp1, count, tmp2
+	cmp	tmp1, #64
+	ccmp	tmp1, zva_len_x, #8, ge	/* NZCV=0b1000 */
+	b.lt	.Lnot_short
+	/* We know that there's at least 64 bytes to zero and that it's safe
+	 * to overrun by 64 bytes.  */
+	mov	count, tmp1
+2:
+	stp	A_l, A_l, [dst]
+	stp	A_l, A_l, [dst, #16]
+	stp	A_l, A_l, [dst, #32]
+	subs	tmp2, tmp2, #64
+	stp	A_l, A_l, [dst, #48]
+	add	dst, dst, #64
+	b.ge	2b
+	/* We've overrun a bit, so adjust dst downwards.  */
+	add	dst, dst, tmp2
+1:
+	sub	count, count, zva_len_x
+3:
+	dc	zva, dst
+	add	dst, dst, zva_len_x
+	subs	count, count, zva_len_x
+	b.ge	3b
+	ands	count, count, zva_bits_x
+	b.ne	.Ltail_maybe_long
+	ret
+END(memset)
+
+#ifdef MAYBE_VIRT
+	.bss
+	.p2align 2
+.Lcache_clear:
+	.space 4
+#endif
+#endif /* DONT_USE_DC */
diff --git a/libc/arch-arm64/denver64/denver64.mk b/libc/arch-arm64/denver64/denver64.mk
new file mode 100644
index 0000000..c6ddb3f
--- /dev/null
+++ b/libc/arch-arm64/denver64/denver64.mk
@@ -0,0 +1,13 @@
+libc_bionic_src_files_arm64 += \
+    arch-arm64/generic/bionic/memcmp.S \
+    arch-arm64/denver64/bionic/memcpy.S \
+    arch-arm64/generic/bionic/memmove.S \
+    arch-arm64/denver64/bionic/memset.S \
+    arch-arm64/generic/bionic/stpcpy.S \
+    arch-arm64/generic/bionic/strchr.S \
+    arch-arm64/generic/bionic/strcmp.S \
+    arch-arm64/generic/bionic/strcpy.S \
+    arch-arm64/generic/bionic/strlen.S \
+    arch-arm64/generic/bionic/strncmp.S \
+    arch-arm64/generic/bionic/strnlen.S \
+    arch-arm64/generic/bionic/wmemmove.S
diff --git a/libc/arch-arm64/generic-neon/generic-neon.mk b/libc/arch-arm64/generic-neon/generic-neon.mk
index 2cbe3cf..f3bde5c 100644
--- a/libc/arch-arm64/generic-neon/generic-neon.mk
+++ b/libc/arch-arm64/generic-neon/generic-neon.mk
@@ -2,7 +2,10 @@
     arch-arm64/generic/bionic/memcmp.S \
     arch-arm64/generic/bionic/memmove.S \
     arch-arm64/generic/bionic/memset.S \
+    arch-arm64/generic/bionic/stpcpy.S \
+    arch-arm64/generic/bionic/strchr.S \
     arch-arm64/generic/bionic/strcmp.S \
+    arch-arm64/generic/bionic/strcpy.S \
     arch-arm64/generic/bionic/strlen.S \
     arch-arm64/generic/bionic/strncmp.S \
     arch-arm64/generic/bionic/strnlen.S \
diff --git a/libc/bionic/thread_atexit.cpp b/libc/arch-arm64/generic/bionic/stpcpy.S
similarity index 73%
copy from libc/bionic/thread_atexit.cpp
copy to libc/arch-arm64/generic/bionic/stpcpy.S
index 68c119d..e4a7993 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/arch-arm64/generic/bionic/stpcpy.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,22 +25,5 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-/* some simple glue used to make the BSD atexit code happy */
-
-#include <pthread.h>
-
-static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
-
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
-
-void _thread_atexit_lock() {
-  pthread_mutex_lock(&g_atexit_lock);
-}
-
-void _thread_atexit_unlock() {
-  pthread_mutex_unlock(&g_atexit_lock);
-}
+#define STPCPY
+#include "string_copy.S"
diff --git a/libc/arch-arm64/generic/bionic/strchr.S b/libc/arch-arm64/generic/bionic/strchr.S
new file mode 100644
index 0000000..158eaf7
--- /dev/null
+++ b/libc/arch-arm64/generic/bionic/strchr.S
@@ -0,0 +1,153 @@
+/*
+   strchr - find a character in a string
+
+   Copyright (c) 2014, ARM Limited
+   All rights Reserved.
+   Copyright (c) 2014, Linaro Ltd.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the company nor the names of its contributors
+         may be used to endorse or promote products derived from this
+         software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64
+ * Neon Available.
+ */
+
+#include <private/bionic_asm.h>
+
+/* Arguments and results.  */
+#define srcin		x0
+#define chrin		w1
+
+#define result		x0
+
+#define src		x2
+#define	tmp1		x3
+#define wtmp2		w4
+#define tmp3		x5
+
+#define vrepchr		v0
+#define vdata1		v1
+#define vdata2		v2
+#define vhas_nul1	v3
+#define vhas_nul2	v4
+#define vhas_chr1	v5
+#define vhas_chr2	v6
+#define vrepmask_0	v7
+#define vrepmask_c	v16
+#define vend1		v17
+#define vend2		v18
+
+/* Core algorithm.
+
+   For each 32-byte hunk we calculate a 64-bit syndrome value, with
+   two bits per byte (LSB is always in bits 0 and 1, for both big
+   and little-endian systems).  For each tuple, bit 0 is set iff
+   the relevant byte matched the requested character; bit 1 is set
+   iff the relevant byte matched the NUL end of string (we trigger
+   off bit0 for the special case of looking for NUL).  Since the bits
+   in the syndrome reflect exactly the order in which things occur
+   in the original string a count_trailing_zeros() operation will
+   identify exactly which byte is causing the termination, and why.  */
+
+/* Locals and temporaries.  */
+
+ENTRY(strchr)
+	/* Magic constant 0x40100401 to allow us to identify which lane
+	   matches the requested byte.  Magic constant 0x80200802 used
+	   similarly for NUL termination.  */
+	mov	wtmp2, #0x0401
+	movk	wtmp2, #0x4010, lsl #16
+	dup	vrepchr.16b, chrin
+	bic	src, srcin, #31		/* Work with aligned 32-byte hunks.  */
+	dup	vrepmask_c.4s, wtmp2
+	ands	tmp1, srcin, #31
+	add	vrepmask_0.4s, vrepmask_c.4s, vrepmask_c.4s /* equiv: lsl #1 */
+	b.eq	.Lloop
+
+	/* Input string is not 32-byte aligned.  Rather than forcing
+	   the padding bytes to a safe value, we calculate the syndrome
+	   for all the bytes, but then mask off those bits of the
+	   syndrome that are related to the padding.  */
+	ld1	{vdata1.16b, vdata2.16b}, [src], #32
+	neg	tmp1, tmp1
+	cmeq	vhas_nul1.16b, vdata1.16b, #0
+	cmeq	vhas_chr1.16b, vdata1.16b, vrepchr.16b
+	cmeq	vhas_nul2.16b, vdata2.16b, #0
+	cmeq	vhas_chr2.16b, vdata2.16b, vrepchr.16b
+	and	vhas_nul1.16b, vhas_nul1.16b, vrepmask_0.16b
+	and	vhas_nul2.16b, vhas_nul2.16b, vrepmask_0.16b
+	and	vhas_chr1.16b, vhas_chr1.16b, vrepmask_c.16b
+	and	vhas_chr2.16b, vhas_chr2.16b, vrepmask_c.16b
+	orr	vend1.16b, vhas_nul1.16b, vhas_chr1.16b
+	orr	vend2.16b, vhas_nul2.16b, vhas_chr2.16b
+	lsl	tmp1, tmp1, #1
+	addp	vend1.16b, vend1.16b, vend2.16b		// 256->128
+	mov	tmp3, #~0
+	addp	vend1.16b, vend1.16b, vend2.16b		// 128->64
+	lsr	tmp1, tmp3, tmp1
+
+	mov	tmp3, vend1.2d[0]
+	bic	tmp1, tmp3, tmp1	// Mask padding bits.
+	cbnz	tmp1, .Ltail
+
+.Lloop:
+	ld1	{vdata1.16b, vdata2.16b}, [src], #32
+	cmeq	vhas_nul1.16b, vdata1.16b, #0
+	cmeq	vhas_chr1.16b, vdata1.16b, vrepchr.16b
+	cmeq	vhas_nul2.16b, vdata2.16b, #0
+	cmeq	vhas_chr2.16b, vdata2.16b, vrepchr.16b
+	/* Use a fast check for the termination condition.  */
+	orr	vend1.16b, vhas_nul1.16b, vhas_chr1.16b
+	orr	vend2.16b, vhas_nul2.16b, vhas_chr2.16b
+	orr	vend1.16b, vend1.16b, vend2.16b
+	addp	vend1.2d, vend1.2d, vend1.2d
+	mov	tmp1, vend1.2d[0]
+	cbz	tmp1, .Lloop
+
+	/* Termination condition found.  Now need to establish exactly why
+	   we terminated.  */
+	and	vhas_nul1.16b, vhas_nul1.16b, vrepmask_0.16b
+	and	vhas_nul2.16b, vhas_nul2.16b, vrepmask_0.16b
+	and	vhas_chr1.16b, vhas_chr1.16b, vrepmask_c.16b
+	and	vhas_chr2.16b, vhas_chr2.16b, vrepmask_c.16b
+	orr	vend1.16b, vhas_nul1.16b, vhas_chr1.16b
+	orr	vend2.16b, vhas_nul2.16b, vhas_chr2.16b
+	addp	vend1.16b, vend1.16b, vend2.16b		// 256->128
+	addp	vend1.16b, vend1.16b, vend2.16b		// 128->64
+
+	mov	tmp1, vend1.2d[0]
+.Ltail:
+	/* Count the trailing zeros, by bit reversing...  */
+	rbit	tmp1, tmp1
+	/* Re-bias source.  */
+	sub	src, src, #32
+	clz	tmp1, tmp1	/* And counting the leading zeros.  */
+	/* Tmp1 is even if the target charager was found first.  Otherwise
+	   we've found the end of string and we weren't looking for NUL.  */
+	tst	tmp1, #1
+	add	result, src, tmp1, lsr #1
+	csel	result, result, xzr, eq
+	ret
+END(strchr)
diff --git a/libc/bionic/thread_atexit.cpp b/libc/arch-arm64/generic/bionic/strcpy.S
similarity index 73%
copy from libc/bionic/thread_atexit.cpp
copy to libc/arch-arm64/generic/bionic/strcpy.S
index 68c119d..260c321 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/arch-arm64/generic/bionic/strcpy.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,22 +25,5 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-/* some simple glue used to make the BSD atexit code happy */
-
-#include <pthread.h>
-
-static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
-
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
-
-void _thread_atexit_lock() {
-  pthread_mutex_lock(&g_atexit_lock);
-}
-
-void _thread_atexit_unlock() {
-  pthread_mutex_unlock(&g_atexit_lock);
-}
+#define STRCPY
+#include "string_copy.S"
diff --git a/libc/arch-arm64/generic/bionic/string_copy.S b/libc/arch-arm64/generic/bionic/string_copy.S
new file mode 100644
index 0000000..3d753b6
--- /dev/null
+++ b/libc/arch-arm64/generic/bionic/string_copy.S
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* Copyright (c) 2014, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the Linaro nor the
+         names of its contributors may be used to endorse or promote products
+         derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64
+ */
+
+#if !defined(STPCPY) && !defined(STRCPY)
+#error "Either STPCPY or STRCPY must be defined."
+#endif
+
+#include <private/bionic_asm.h>
+
+/* Arguments and results.  */
+#if defined(STPCPY)
+#define dst         x0
+#elif defined(STRCPY)
+#define dstin       x0
+#endif
+#define src         x1
+
+/* Locals and temporaries.  */
+#if defined(STRCPY)
+#define dst         x2
+#endif
+#define data1       x3
+#define data1_w     w3
+#define data2       x4
+#define data2_w     w4
+#define has_nul1    x5
+#define has_nul1_w  w5
+#define has_nul2    x6
+#define tmp1        x7
+#define tmp2        x8
+#define tmp3        x9
+#define tmp4        x10
+#define zeroones    x11
+#define zeroones_w  w11
+#define pos         x12
+
+#define REP8_01 0x0101010101010101
+#define REP8_7f 0x7f7f7f7f7f7f7f7f
+#define REP8_80 0x8080808080808080
+
+#if defined(STPCPY)
+ENTRY(stpcpy)
+#elif defined(STRCPY)
+ENTRY(strcpy)
+#endif
+    mov     zeroones, #REP8_01
+#if defined(STRCPY)
+    mov     dst, dstin
+#endif
+    ands    tmp1, src, #15
+    b.ne    .Lmisaligned
+    // NUL detection works on the principle that (X - 1) & (~X) & 0x80
+    // (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+    // can be done in parallel across the entire word.
+    // The inner loop deals with two Dwords at a time.  This has a
+    // slightly higher start-up cost, but we should win quite quickly,
+    // especially on cores with a high number of issue slots per
+    // cycle, as we get much better parallelism out of the operations.
+.Lloop:
+    ldp     data1, data2, [src], #16
+    sub     tmp1, data1, zeroones
+    orr     tmp2, data1, #REP8_7f
+    bic     has_nul1, tmp1, tmp2
+    cbnz    has_nul1, .Lnul_in_data1
+    sub     tmp3, data2, zeroones
+    orr     tmp4, data2, #REP8_7f
+    bic     has_nul2, tmp3, tmp4
+    cbnz    has_nul2, .Lnul_in_data2
+    // No NUL in either register, copy it in a single instruction.
+    stp     data1, data2, [dst], #16
+    b       .Lloop
+
+.Lnul_in_data1:
+    rev     has_nul1, has_nul1
+    clz     pos, has_nul1
+    add     tmp1, pos, #0x8
+
+    tbz     tmp1, #6, 1f
+#if defined(STPCPY)
+    str     data1, [dst], #7
+#elif defined(STRCPY)
+    str     data1, [dst]
+#endif
+    ret
+1:
+    tbz     tmp1, #5, 1f
+    str     data1_w, [dst], #4
+    lsr     data1, data1, #32
+1:
+    tbz     tmp1, #4, 1f
+    strh    data1_w, [dst], #2
+    lsr     data1, data1, #16
+1:
+    tbz     tmp1, #3, 1f
+    strb    data1_w, [dst]
+#if defined(STPCPY)
+    ret
+#endif
+1:
+#if defined(STPCPY)
+    // Back up one so that dst points to the '\0' string terminator.
+    sub     dst, dst, #1
+#endif
+    ret
+
+.Lnul_in_data2:
+    str     data1, [dst], #8
+    rev     has_nul2, has_nul2
+    clz     pos, has_nul2
+    add     tmp1, pos, #0x8
+
+    tbz     tmp1, #6, 1f
+#if defined(STPCPY)
+    str     data2, [dst], #7
+#elif defined(STRCPY)
+    str     data2, [dst]
+#endif
+    ret
+1:
+    tbz     tmp1, #5, 1f
+    str     data2_w, [dst], #4
+    lsr     data2, data2, #32
+1:
+    tbz     tmp1, #4, 1f
+    strh    data2_w, [dst], #2
+    lsr     data2, data2, #16
+1:
+    tbz     tmp1, #3, 1f
+    strb    data2_w, [dst]
+#if defined(STPCPY)
+    ret
+#endif
+1:
+#if defined(STPCPY)
+    // Back up one so that dst points to the '\0' string terminator.
+    sub     dst, dst, #1
+#endif
+    ret
+
+.Lmisaligned:
+    tbz     src, #0, 1f
+    ldrb    data1_w, [src], #1
+    strb    data1_w, [dst], #1
+    cbnz    data1_w, 1f
+#if defined(STPCPY)
+    // Back up one so that dst points to the '\0' string terminator.
+    sub     dst, dst, #1
+#endif
+    ret
+1:
+    tbz     src, #1, 1f
+    ldrb    data1_w, [src], #1
+    strb    data1_w, [dst], #1
+    cbz     data1_w, .Ldone
+    ldrb    data2_w, [src], #1
+    strb    data2_w, [dst], #1
+    cbnz    data2_w, 1f
+.Ldone:
+#if defined(STPCPY)
+    // Back up one so that dst points to the '\0' string terminator.
+    sub     dst, dst, #1
+#endif
+    ret
+1:
+    tbz     src, #2, 1f
+    ldr     data1_w, [src], #4
+    // Check for a zero.
+    sub     has_nul1_w, data1_w, zeroones_w
+    bic     has_nul1_w, has_nul1_w, data1_w
+    ands    has_nul1_w, has_nul1_w, #0x80808080
+    b.ne    .Lnul_in_data1
+    str     data1_w, [dst], #4
+1:
+    tbz     src, #3, .Lloop
+    ldr     data1, [src], #8
+    // Check for a zero.
+    sub     tmp1, data1, zeroones
+    orr     tmp2, data1, #REP8_7f
+    bics    has_nul1, tmp1, tmp2
+    b.ne    .Lnul_in_data1
+    str     data1, [dst], #8
+    b       .Lloop
+#if defined(STPCPY)
+END(stpcpy)
+#elif defined(STRCPY)
+END(strcpy)
+#endif
diff --git a/libc/arch-arm64/generic/generic.mk b/libc/arch-arm64/generic/generic.mk
index e10cf66..878dcdf 100644
--- a/libc/arch-arm64/generic/generic.mk
+++ b/libc/arch-arm64/generic/generic.mk
@@ -3,7 +3,10 @@
     arch-arm64/generic/bionic/memcpy.S \
     arch-arm64/generic/bionic/memmove.S \
     arch-arm64/generic/bionic/memset.S \
+    arch-arm64/generic/bionic/stpcpy.S \
+    arch-arm64/generic/bionic/strchr.S \
     arch-arm64/generic/bionic/strcmp.S \
+    arch-arm64/generic/bionic/strcpy.S \
     arch-arm64/generic/bionic/strlen.S \
     arch-arm64/generic/bionic/strncmp.S \
     arch-arm64/generic/bionic/strnlen.S \
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/__getpid.S
similarity index 82%
rename from libc/arch-arm64/syscalls/getpid.S
rename to libc/arch-arm64/syscalls/__getpid.S
index 1802ce8..c3003c3 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/__getpid.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(__getpid)
     mov     x8, __NR_getpid
     svc     #0
 
@@ -11,4 +11,5 @@
     b.hi    __set_errno
 
     ret
-END(getpid)
+END(__getpid)
+.hidden __getpid
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/splice.S
similarity index 77%
copy from libc/arch-arm64/syscalls/getpid.S
copy to libc/arch-arm64/syscalls/splice.S
index 1802ce8..103805a 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/splice.S
@@ -2,8 +2,8 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
-    mov     x8, __NR_getpid
+ENTRY(splice)
+    mov     x8, __NR_splice
     svc     #0
 
     cmn     x0, #(MAX_ERRNO + 1)
@@ -11,4 +11,4 @@
     b.hi    __set_errno
 
     ret
-END(getpid)
+END(splice)
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/tee.S
similarity index 77%
copy from libc/arch-arm64/syscalls/getpid.S
copy to libc/arch-arm64/syscalls/tee.S
index 1802ce8..d730076 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/tee.S
@@ -2,8 +2,8 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
-    mov     x8, __NR_getpid
+ENTRY(tee)
+    mov     x8, __NR_tee
     svc     #0
 
     cmn     x0, #(MAX_ERRNO + 1)
@@ -11,4 +11,4 @@
     b.hi    __set_errno
 
     ret
-END(getpid)
+END(tee)
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/vmsplice.S
similarity index 75%
copy from libc/arch-arm64/syscalls/getpid.S
copy to libc/arch-arm64/syscalls/vmsplice.S
index 1802ce8..b4bec3f 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/vmsplice.S
@@ -2,8 +2,8 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
-    mov     x8, __NR_getpid
+ENTRY(vmsplice)
+    mov     x8, __NR_vmsplice
     svc     #0
 
     cmn     x0, #(MAX_ERRNO + 1)
@@ -11,4 +11,4 @@
     b.hi    __set_errno
 
     ret
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index fe5e24d..0a3718b 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -68,6 +68,8 @@
     arch-mips/string/memset.S \
     arch-mips/string/mips_strlen.c \
 
+libc_netbsd_src_files_mips := \
+    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
 
 libc_crt_target_cflags_mips := \
     $($(my_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/__getpid.S
similarity index 89%
rename from libc/arch-mips/syscalls/getpid.S
rename to libc/arch-mips/syscalls/__getpid.S
index a053f5b..52cf6f4 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/__getpid.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(__getpid)
     .set noreorder
     .cpload t9
     li v0, __NR_getpid
@@ -16,4 +16,4 @@
     j t9
     nop
     .set reorder
-END(getpid)
+END(__getpid)
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/splice.S
similarity index 82%
copy from libc/arch-mips/syscalls/getpid.S
copy to libc/arch-mips/syscalls/splice.S
index a053f5b..d344a6c 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/splice.S
@@ -2,10 +2,10 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(splice)
     .set noreorder
     .cpload t9
-    li v0, __NR_getpid
+    li v0, __NR_splice
     syscall
     bnez a3, 1f
     move a0, v0
@@ -16,4 +16,4 @@
     j t9
     nop
     .set reorder
-END(getpid)
+END(splice)
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/tee.S
similarity index 82%
copy from libc/arch-mips/syscalls/getpid.S
copy to libc/arch-mips/syscalls/tee.S
index a053f5b..e51732d 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/tee.S
@@ -2,10 +2,10 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(tee)
     .set noreorder
     .cpload t9
-    li v0, __NR_getpid
+    li v0, __NR_tee
     syscall
     bnez a3, 1f
     move a0, v0
@@ -16,4 +16,4 @@
     j t9
     nop
     .set reorder
-END(getpid)
+END(tee)
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/vmsplice.S
similarity index 80%
copy from libc/arch-mips/syscalls/getpid.S
copy to libc/arch-mips/syscalls/vmsplice.S
index a053f5b..24da515 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/vmsplice.S
@@ -2,10 +2,10 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(vmsplice)
     .set noreorder
     .cpload t9
-    li v0, __NR_getpid
+    li v0, __NR_vmsplice
     syscall
     bnez a3, 1f
     move a0, v0
@@ -16,4 +16,4 @@
     j t9
     nop
     .set reorder
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/__getpid.S
similarity index 87%
rename from libc/arch-mips64/syscalls/getpid.S
rename to libc/arch-mips64/syscalls/__getpid.S
index 3b457b5..0977ff0 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/__getpid.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(__getpid)
     .set push
     .set noreorder
     li v0, __NR_getpid
@@ -22,4 +22,5 @@
     j t9
     move ra, t0
     .set pop
-END(getpid)
+END(__getpid)
+.hidden __getpid
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/splice.S
similarity index 86%
copy from libc/arch-mips64/syscalls/getpid.S
copy to libc/arch-mips64/syscalls/splice.S
index 3b457b5..d626904 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/splice.S
@@ -2,10 +2,10 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(splice)
     .set push
     .set noreorder
-    li v0, __NR_getpid
+    li v0, __NR_splice
     syscall
     bnez a3, 1f
     move a0, v0
@@ -22,4 +22,4 @@
     j t9
     move ra, t0
     .set pop
-END(getpid)
+END(splice)
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/tee.S
similarity index 86%
copy from libc/arch-mips64/syscalls/getpid.S
copy to libc/arch-mips64/syscalls/tee.S
index 3b457b5..429700c 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/tee.S
@@ -2,10 +2,10 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(tee)
     .set push
     .set noreorder
-    li v0, __NR_getpid
+    li v0, __NR_tee
     syscall
     bnez a3, 1f
     move a0, v0
@@ -22,4 +22,4 @@
     j t9
     move ra, t0
     .set pop
-END(getpid)
+END(tee)
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/vmsplice.S
similarity index 85%
copy from libc/arch-mips64/syscalls/getpid.S
copy to libc/arch-mips64/syscalls/vmsplice.S
index 3b457b5..aa03585 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/vmsplice.S
@@ -2,10 +2,10 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(vmsplice)
     .set push
     .set noreorder
-    li v0, __NR_getpid
+    li v0, __NR_vmsplice
     syscall
     bnez a3, 1f
     move a0, v0
@@ -22,4 +22,4 @@
     j t9
     move ra, t0
     .set pop
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-x86/syscalls/getpid.S b/libc/arch-x86/syscalls/__getpid.S
similarity index 89%
rename from libc/arch-x86/syscalls/getpid.S
rename to libc/arch-x86/syscalls/__getpid.S
index 0e12d5a..f138d2f 100644
--- a/libc/arch-x86/syscalls/getpid.S
+++ b/libc/arch-x86/syscalls/__getpid.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(__getpid)
     movl    $__NR_getpid, %eax
     int     $0x80
     cmpl    $-MAX_ERRNO, %eax
@@ -13,4 +13,4 @@
     addl    $4, %esp
 1:
     ret
-END(getpid)
+END(__getpid)
diff --git a/libc/arch-x86/syscalls/splice.S b/libc/arch-x86/syscalls/splice.S
new file mode 100644
index 0000000..46e2312
--- /dev/null
+++ b/libc/arch-x86/syscalls/splice.S
@@ -0,0 +1,46 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(splice)
+    pushl   %ebx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    pushl   %ecx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset ecx, 0
+    pushl   %edx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset edx, 0
+    pushl   %esi
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset esi, 0
+    pushl   %edi
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset edi, 0
+    pushl   %ebp
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset ebp, 0
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
+    mov     48(%esp), %ebp
+    movl    $__NR_splice, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+1:
+    popl    %ebp
+    popl    %edi
+    popl    %esi
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
+END(splice)
diff --git a/libc/arch-x86/syscalls/tee.S b/libc/arch-x86/syscalls/tee.S
new file mode 100644
index 0000000..9422660
--- /dev/null
+++ b/libc/arch-x86/syscalls/tee.S
@@ -0,0 +1,36 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(tee)
+    pushl   %ebx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    pushl   %ecx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset ecx, 0
+    pushl   %edx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset edx, 0
+    pushl   %esi
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset esi, 0
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
+    mov     32(%esp), %esi
+    movl    $__NR_tee, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+1:
+    popl    %esi
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
+END(tee)
diff --git a/libc/arch-x86/syscalls/vmsplice.S b/libc/arch-x86/syscalls/vmsplice.S
new file mode 100644
index 0000000..2afba60
--- /dev/null
+++ b/libc/arch-x86/syscalls/vmsplice.S
@@ -0,0 +1,36 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(vmsplice)
+    pushl   %ebx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    pushl   %ecx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset ecx, 0
+    pushl   %edx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset edx, 0
+    pushl   %esi
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset esi, 0
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
+    mov     32(%esp), %esi
+    movl    $__NR_vmsplice, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+1:
+    popl    %esi
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
+END(vmsplice)
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index 3dc71d1..8aa2645 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -40,6 +40,9 @@
 include $(arch_variant_mk)
 libc_common_additional_dependencies += $(arch_variant_mk)
 
+libc_netbsd_src_files_x86 := \
+    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+
 arch_variant_mk :=
 
 libc_crt_target_cflags_x86 := \
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/__getpid.S
similarity index 83%
rename from libc/arch-x86_64/syscalls/getpid.S
rename to libc/arch-x86_64/syscalls/__getpid.S
index a2d732c..bd1bf1e 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/__getpid.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
+ENTRY(__getpid)
     movl    $__NR_getpid, %eax
     syscall
     cmpq    $-MAX_ERRNO, %rax
@@ -12,4 +12,5 @@
     call    __set_errno
 1:
     ret
-END(getpid)
+END(__getpid)
+.hidden __getpid
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/splice.S
similarity index 72%
copy from libc/arch-x86_64/syscalls/getpid.S
copy to libc/arch-x86_64/syscalls/splice.S
index a2d732c..3c245a5 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/splice.S
@@ -2,8 +2,9 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
-    movl    $__NR_getpid, %eax
+ENTRY(splice)
+    movq    %rcx, %r10
+    movl    $__NR_splice, %eax
     syscall
     cmpq    $-MAX_ERRNO, %rax
     jb      1f
@@ -12,4 +13,4 @@
     call    __set_errno
 1:
     ret
-END(getpid)
+END(splice)
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/tee.S
similarity index 74%
copy from libc/arch-x86_64/syscalls/getpid.S
copy to libc/arch-x86_64/syscalls/tee.S
index a2d732c..ad5698c 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/tee.S
@@ -2,8 +2,9 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
-    movl    $__NR_getpid, %eax
+ENTRY(tee)
+    movq    %rcx, %r10
+    movl    $__NR_tee, %eax
     syscall
     cmpq    $-MAX_ERRNO, %rax
     jb      1f
@@ -12,4 +13,4 @@
     call    __set_errno
 1:
     ret
-END(getpid)
+END(tee)
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/vmsplice.S
similarity index 71%
copy from libc/arch-x86_64/syscalls/getpid.S
copy to libc/arch-x86_64/syscalls/vmsplice.S
index a2d732c..cc94cc6 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/vmsplice.S
@@ -2,8 +2,9 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(getpid)
-    movl    $__NR_getpid, %eax
+ENTRY(vmsplice)
+    movq    %rcx, %r10
+    movl    $__NR_vmsplice, %eax
     syscall
     cmpq    $-MAX_ERRNO, %rax
     jb      1f
@@ -12,4 +13,4 @@
     call    __set_errno
 1:
     ret
-END(getpid)
+END(vmsplice)
diff --git a/libc/bionic/arc4random.c b/libc/bionic/arc4random.c
index 687030b..9bdf341 100644
--- a/libc/bionic/arc4random.c
+++ b/libc/bionic/arc4random.c
@@ -1,8 +1,9 @@
-/*      $OpenBSD: arc4random.c,v 1.19 2008/06/04 00:50:23 djm Exp $        */
+/*	$OpenBSD: arc4random.c,v 1.33 2014/06/13 18:58:58 deraadt Exp $	*/
 
 /*
  * Copyright (c) 1996, David Mazieres <dm@uun.org>
  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,214 +19,236 @@
  */
 
 /*
- * Arc4 random number generator for OpenBSD.
- *
- * This code is derived from section 17.1 of Applied Cryptography,
- * second edition, which describes a stream cipher allegedly
- * compatible with RSA Labs "RC4" cipher (the actual description of
- * which is a trade secret).  The same algorithm is used as a stream
- * cipher called "arcfour" in Tatu Ylonen's ssh package.
- *
- * Here the stream cipher has been modified always to include the time
- * when initializing the state.  That makes it impossible to
- * regenerate the same random sequence twice, so this can't be used
- * for encryption, but will generate good random numbers.
- *
- * RC4 is a registered trademark of RSA Laboratories.
+ * ChaCha based random number generator for OpenBSD.
  */
 
 #include <fcntl.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/time.h>
+#include <sys/mman.h>
+
+#if defined(__ANDROID__)
+#include <sys/stat.h>
+#include <linux/random.h>
+#include "private/libc_logging.h"
 #include "private/thread_private.h"
 
-/* BIONIC-BEGIN */
-/* this lock should protect the global variables in this file */
-static pthread_mutex_t  _arc4_lock = PTHREAD_MUTEX_INITIALIZER;
-#define  _ARC4_LOCK()      pthread_mutex_lock(&_arc4_lock)
-#define  _ARC4_UNLOCK()    pthread_mutex_unlock(&_arc4_lock)
-/* BIONIC-END */
+#define explicit_bzero(p, s) memset(p, 0, s)
+
+#undef MAP_ANON
+#define MAP_ANON (MAP_PRIVATE | MAP_ANONYMOUS)
+
+/*
+ * XXX Should be replaced with a proper entropy measure.
+ */
+static int
+gotdata(u_char *buf, size_t len)
+{
+	char	any_set = 0;
+	size_t	i;
+
+	for (i = 0; i < len; ++i)
+		any_set |= buf[i];
+	if (any_set == 0)
+		return -1;
+	return 0;
+}
+
+static int
+getentropy/*_urandom*/(u_char *buf, size_t len)
+{
+	int save_errno = errno;
+
+	int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOFOLLOW, 0));
+	if (fd == -1) {
+		__libc_fatal("getentropy_urandom failed to open \"/dev/urandom\": %s",
+				strerror(errno));
+	}
+
+	/* Lightly verify that the device node looks sane */
+	struct stat st;
+	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+		__libc_fatal("getentropy_urandom failed to fstat \"/dev/urandom\": %s",
+				strerror(errno));
+	}
+	int cnt;
+	if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
+		__libc_fatal("getentropy_urandom failed to ioctl \"/dev/urandom\": %s",
+				strerror(errno));
+	}
+	for (size_t i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = TEMP_FAILURE_RETRY(read(fd, buf + i, wanted));
+
+		if (ret == -1) {
+			__libc_fatal("getentropy_urandom failed to read \"/dev/urandom\": %s",
+					strerror(errno));
+		}
+		i += ret;
+	}
+	close(fd);
+	if (gotdata(buf, len) == -1) {
+		__libc_fatal("getentropy_urandom failed to get enough entropy: %s",
+				strerror(errno));
+	}
+
+	errno = save_errno;
+	return 0;
+}
+#endif /* __ANDROID__ */
+
+#define KEYSTREAM_ONLY
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include "../upstream-openbsd/lib/libc/crypt/chacha_private.h"
+#pragma GCC diagnostic pop
 
 #ifdef __GNUC__
 #define inline __inline
-#else                           /* !__GNUC__ */
+#else				/* !__GNUC__ */
 #define inline
-#endif                          /* !__GNUC__ */
+#endif				/* !__GNUC__ */
 
-struct arc4_stream {
-        u_int8_t i;
-        u_int8_t j;
-        u_int8_t s[256];
-};
-
+#define KEYSZ	32
+#define IVSZ	8
+#define BLOCKSZ	64
+#define RSBUFSZ	(16*BLOCKSZ)
 static int rs_initialized;
-static struct arc4_stream rs;
-static pid_t arc4_stir_pid;
-static int arc4_count;
+static pid_t rs_stir_pid;
+static chacha_ctx *rs;		/* chacha context for random keystream */
+static u_char *rs_buf;		/* keystream blocks */
+static size_t rs_have;		/* valid bytes at end of rs_buf */
+static size_t rs_count;		/* bytes till reseed */
 
-static inline u_int8_t arc4_getbyte(void);
+static inline void _rs_rekey(u_char *dat, size_t datlen);
 
 static inline void
-arc4_init(void)
+_rs_init(u_char *buf, size_t n)
 {
-        int     n;
+	if (n < KEYSZ + IVSZ)
+		return;
 
-        for (n = 0; n < 256; n++)
-                rs.s[n] = n;
-        rs.i = 0;
-        rs.j = 0;
-}
+	if (rs == NULL && (rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
+	    MAP_ANON, -1, 0)) == MAP_FAILED)
+		abort();
+	if (rs_buf == NULL && (rs_buf = mmap(NULL, RSBUFSZ, PROT_READ|PROT_WRITE,
+	    MAP_ANON, -1, 0)) == MAP_FAILED)
+		abort();
 
-static inline void
-arc4_addrandom(u_char *dat, int datlen)
-{
-        int     n;
-        u_int8_t si;
-
-        rs.i--;
-        for (n = 0; n < 256; n++) {
-                rs.i = (rs.i + 1);
-                si = rs.s[rs.i];
-                rs.j = (rs.j + si + dat[n % datlen]);
-                rs.s[rs.i] = rs.s[rs.j];
-                rs.s[rs.j] = si;
-        }
-        rs.j = rs.i;
+	chacha_keysetup(rs, buf, KEYSZ * 8, 0);
+	chacha_ivsetup(rs, buf + KEYSZ);
 }
 
 static void
-arc4_stir(void)
+_rs_stir(void)
 {
-#if 1  /* BIONIC-BEGIN */
-	int     i, fd;
-	union {
-		struct timeval tv;
-		u_int rnd[128 / sizeof(u_int)];
-	}       rdat;
-	int	n;
+	u_char rnd[KEYSZ + IVSZ];
 
-        if (!rs_initialized) {
-                arc4_init();
-                rs_initialized = 1;
-        }
+	/* XXX */
+	(void) getentropy(rnd, sizeof rnd);
 
-	fd = open("/dev/urandom", O_RDONLY);
-	if (fd != -1) {
-		read(fd, rdat.rnd, sizeof(rdat.rnd));
-		close(fd);
-	}
-        else
-        {
-	    /* fd < 0 ?  Ah, what the heck. We'll just take
-	     * whatever was on the stack. just add a little more
-             * time-based randomness though
-             */
-            gettimeofday(&rdat.tv, NULL);
-        }
+	if (!rs_initialized) {
+		rs_initialized = 1;
+		_rs_init(rnd, sizeof(rnd));
+	} else
+		_rs_rekey(rnd, sizeof(rnd));
+	explicit_bzero(rnd, sizeof(rnd));
 
-        arc4_stir_pid = getpid();
-	arc4_addrandom((void *) &rdat, sizeof(rdat));
-#else  /* BIONIC-END */
-        int     i, mib[2];
-        size_t        len;
-        u_char rnd[128];
+	/* invalidate rs_buf */
+	rs_have = 0;
+	memset(rs_buf, 0, RSBUFSZ);
 
-        if (!rs_initialized) {
-                arc4_init();
-                rs_initialized = 1;
-        }
+	rs_count = 1600000;
+}
 
-        mib[0] = CTL_KERN;
-        mib[1] = KERN_ARND;
+static inline void
+_rs_stir_if_needed(size_t len)
+{
+	pid_t pid = getpid();
 
-        len = sizeof(rnd);
-        sysctl(mib, 2, rnd, &len, NULL, 0);
+	if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
+		rs_stir_pid = pid;
+		_rs_stir();
+	} else
+		rs_count -= len;
+}
 
-        arc4_stir_pid = getpid();
-        arc4_addrandom(rnd, sizeof(rnd));
+static inline void
+_rs_rekey(u_char *dat, size_t datlen)
+{
+#ifndef KEYSTREAM_ONLY
+	memset(rs_buf, 0,RSBUFSZ);
 #endif
-        /*
-         * Discard early keystream, as per recommendations in:
-         * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
-         */
-        for (i = 0; i < 256; i++)
-                (void)arc4_getbyte();
-        arc4_count = 1600000;
+	/* fill rs_buf with the keystream */
+	chacha_encrypt_bytes(rs, rs_buf, rs_buf, RSBUFSZ);
+	/* mix in optional user provided data */
+	if (dat) {
+		size_t i, m;
+
+		m = MIN(datlen, KEYSZ + IVSZ);
+		for (i = 0; i < m; i++)
+			rs_buf[i] ^= dat[i];
+	}
+	/* immediately reinit for backtracking resistance */
+	_rs_init(rs_buf, KEYSZ + IVSZ);
+	memset(rs_buf, 0, KEYSZ + IVSZ);
+	rs_have = RSBUFSZ - KEYSZ - IVSZ;
 }
 
-static inline u_int8_t
-arc4_getbyte(void)
+static inline void
+_rs_random_buf(void *_buf, size_t n)
 {
-        u_int8_t si, sj;
+	u_char *buf = (u_char *)_buf;
+	size_t m;
 
-        rs.i = (rs.i + 1);
-        si = rs.s[rs.i];
-        rs.j = (rs.j + si);
-        sj = rs.s[rs.j];
-        rs.s[rs.i] = sj;
-        rs.s[rs.j] = si;
-        return (rs.s[(si + sj) & 0xff]);
+	_rs_stir_if_needed(n);
+	while (n > 0) {
+		if (rs_have > 0) {
+			m = MIN(n, rs_have);
+			memcpy(buf, rs_buf + RSBUFSZ - rs_have, m);
+			memset(rs_buf + RSBUFSZ - rs_have, 0, m);
+			buf += m;
+			n -= m;
+			rs_have -= m;
+		}
+		if (rs_have == 0)
+			_rs_rekey(NULL, 0);
+	}
 }
 
-static inline u_int32_t
-arc4_getword(void)
+static inline void
+_rs_random_u32(u_int32_t *val)
 {
-        u_int32_t val;
-        val = arc4_getbyte() << 24;
-        val |= arc4_getbyte() << 16;
-        val |= arc4_getbyte() << 8;
-        val |= arc4_getbyte();
-        return val;
-}
-
-void
-arc4random_stir(void)
-{
-        _ARC4_LOCK();
-        arc4_stir();
-        _ARC4_UNLOCK();
-}
-
-void
-arc4random_addrandom(u_char *dat, int datlen)
-{
-        _ARC4_LOCK();
-        if (!rs_initialized)
-                arc4_stir();
-        arc4_addrandom(dat, datlen);
-        _ARC4_UNLOCK();
+	_rs_stir_if_needed(sizeof(*val));
+	if (rs_have < sizeof(*val))
+		_rs_rekey(NULL, 0);
+	memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val));
+	memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val));
+	rs_have -= sizeof(*val);
 }
 
 u_int32_t
 arc4random(void)
 {
-        u_int32_t val;
-        _ARC4_LOCK();
-        arc4_count -= 4;
-        if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != getpid())
-                arc4_stir();
-        val = arc4_getword();
-        _ARC4_UNLOCK();
-        return val;
+	u_int32_t val;
+
+	_ARC4_LOCK();
+	_rs_random_u32(&val);
+	_ARC4_UNLOCK();
+	return val;
 }
 
 void
-arc4random_buf(void *_buf, size_t n)
+arc4random_buf(void *buf, size_t n)
 {
-        u_char *buf = (u_char *)_buf;
-        _ARC4_LOCK();
-        if (!rs_initialized || arc4_stir_pid != getpid())
-                arc4_stir();
-        while (n--) {
-                if (--arc4_count <= 0)
-                        arc4_stir();
-                buf[n] = arc4_getbyte();
-        }
-        _ARC4_UNLOCK();
+	_ARC4_LOCK();
+	_rs_random_buf(buf, n);
+	_ARC4_UNLOCK();
 }
 
 /*
@@ -241,55 +264,25 @@
 u_int32_t
 arc4random_uniform(u_int32_t upper_bound)
 {
-        u_int32_t r, min;
+	u_int32_t r, min;
 
-        if (upper_bound < 2)
-                return 0;
+	if (upper_bound < 2)
+		return 0;
 
-#if (ULONG_MAX > 0xffffffffUL)
-        min = 0x100000000UL % upper_bound;
-#else
-        /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
-        if (upper_bound > 0x80000000)
-                min = 1 + ~upper_bound;                /* 2**32 - upper_bound */
-        else {
-                /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
-                min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
-        }
-#endif
+	/* 2**32 % x == (2**32 - x) % x */
+	min = -upper_bound % upper_bound;
 
-        /*
-         * This could theoretically loop forever but each retry has
-         * p > 0.5 (worst case, usually far better) of selecting a
-         * number inside the range we need, so it should rarely need
-         * to re-roll.
-         */
-        for (;;) {
-                r = arc4random();
-                if (r >= min)
-                        break;
-        }
+	/*
+	 * This could theoretically loop forever but each retry has
+	 * p > 0.5 (worst case, usually far better) of selecting a
+	 * number inside the range we need, so it should rarely need
+	 * to re-roll.
+	 */
+	for (;;) {
+		r = arc4random();
+		if (r >= min)
+			break;
+	}
 
-        return r % upper_bound;
+	return r % upper_bound;
 }
-
-#if 0
-/*-------- Test code for i386 --------*/
-#include <stdio.h>
-#include <machine/pctr.h>
-int
-main(int argc, char **argv)
-{
-        const int iter = 1000000;
-        int     i;
-        pctrval v;
-
-        v = rdtsc();
-        for (i = 0; i < iter; i++)
-                arc4random();
-        v = rdtsc() - v;
-        v /= iter;
-
-        printf("%qd cycles\n", v);
-}
-#endif
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index 001e245..0a0fdd5 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -31,6 +31,8 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
+#include "pthread_internal.h"
+
 extern "C" pid_t __bionic_clone(uint32_t flags, void* child_stack, int* parent_tid, void* tls, int* child_tid, int (*fn)(void*), void* arg);
 extern "C" __noreturn void __exit(int status);
 
@@ -64,5 +66,18 @@
   child_stack_addr &= ~0xf;
   child_stack = reinterpret_cast<void*>(child_stack_addr);
 
-  return __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
+  // Remember the parent pid and invalidate the cached value while we clone.
+  pthread_internal_t* self = __get_thread();
+  pid_t parent_pid = self->invalidate_cached_pid();
+
+  // Actually do the clone.
+  int clone_result = __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
+
+  // We're the parent, so put our known pid back in place.
+  // We leave the child without a cached pid, but:
+  // 1. pthread_create gives its children their own pthread_internal_t with the correct pid.
+  // 2. fork makes a clone system call directly.
+  // If any other cases become important, we could use a double trampoline like __pthread_start.
+  self->set_cached_pid(parent_pid);
+  return clone_result;
 }
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/cmsg_nxthdr.cpp
index 6f0a47c..8a2b33e 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/cmsg_nxthdr.cpp
@@ -28,7 +28,7 @@
 
 #include <sys/socket.h>
 
-cmsghdr* cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
+cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
   cmsghdr* ptr;
   ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
   size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
@@ -37,3 +37,6 @@
   }
   return ptr;
 }
+
+// TODO: remove after NDK refresh.
+__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index a0f98e4..6cfc736 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -31,19 +31,26 @@
 
 #include "pthread_internal.h"
 
+#define FORK_FLAGS (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD)
+
 int fork() {
   __bionic_atfork_run_prepare();
 
   pthread_internal_t* self = __get_thread();
-  int flags = CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD;
+
+  // Remember the parent pid and invalidate the cached value while we fork.
+  pid_t parent_pid = self->invalidate_cached_pid();
+
 #if defined(__x86_64__) // sys_clone's last two arguments are flipped on x86-64.
-  int result = syscall(__NR_clone, flags, NULL, NULL, &(self->tid), NULL);
+  int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, &(self->tid), NULL);
 #else
-  int result = syscall(__NR_clone, flags, NULL, NULL, NULL, &(self->tid));
+  int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, NULL, &(self->tid));
 #endif
   if (result == 0) {
+    self->set_cached_pid(gettid());
     __bionic_atfork_run_child();
   } else {
+    self->set_cached_pid(parent_pid);
     __bionic_atfork_run_parent();
   }
   return result;
diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c
index ec0baf7..c491b6a 100644
--- a/libc/bionic/fts.c
+++ b/libc/bionic/fts.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fts.c,v 1.43 2009/08/27 16:19:27 millert Exp $	*/
+/*	$OpenBSD: fts.c,v 1.46 2014/05/25 17:47:04 tedu Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993, 1994
@@ -36,6 +36,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <fts.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -97,7 +98,7 @@
 	 * Start out with 1K of path space, and enough, in any case,
 	 * to hold the user's paths.
 	 */
-	if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+	if (fts_palloc(sp, MAX(fts_maxarglen(argv), PATH_MAX)))
 		goto mem1;
 
 	/* Allocate/initialize root's parent. */
@@ -447,7 +448,7 @@
  */
 /* ARGSUSED */
 int
-fts_set(FTS *sp, FTSENT *p, int instr)
+fts_set(FTS *sp __unused, FTSENT *p, int instr)
 {
 	if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
 	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
@@ -637,7 +638,7 @@
 	maxlen = sp->fts_pathlen - len;
 
 	/*
-	 * fts_level is a short so we must prevent it from wrapping
+	 * fts_level is signed so we must prevent it from wrapping
 	 * around to FTS_ROOTLEVEL and FTS_ROOTPARENTLEVEL.
 	 */
 	level = cur->fts_level;
@@ -908,10 +909,9 @@
 	len = sizeof(FTSENT) + namelen;
 	if (!ISSET(FTS_NOSTAT))
 		len += sizeof(struct stat) + ALIGNBYTES;
-	if ((p = malloc(len)) == NULL)
+	if ((p = calloc(1, len)) == NULL)
 		return (NULL);
 
-	memset(p, 0, len);
 	p->fts_path = sp->fts_path;
 	p->fts_namelen = namelen;
 	p->fts_instr = FTS_NOINSTR;
@@ -936,7 +936,7 @@
 
 /*
  * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
- * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * Most systems will allow creation of paths much longer than PATH_MAX, even
  * though the kernel won't resolve them.  Add the size (not just what's needed)
  * plus 256 bytes so don't realloc the path 2 bytes at a time.
  */
diff --git a/libc/bionic/thread_atexit.cpp b/libc/bionic/getpid.cpp
similarity index 71%
copy from libc/bionic/thread_atexit.cpp
copy to libc/bionic/getpid.cpp
index 68c119d..a3d5b35 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/bionic/getpid.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,21 +26,22 @@
  * SUCH DAMAGE.
  */
 
-/* some simple glue used to make the BSD atexit code happy */
+#include <unistd.h>
 
-#include <pthread.h>
+#include "pthread_internal.h"
 
-static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
+extern "C" pid_t __getpid();
 
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
+pid_t getpid() {
+  pthread_internal_t* self = __get_thread();
 
-void _thread_atexit_lock() {
-  pthread_mutex_lock(&g_atexit_lock);
-}
+  // Do we have a valid cached pid?
+  pid_t cached_pid;
+  if (__predict_true(self->get_cached_pid(&cached_pid))) {
+    return cached_pid;
+  }
 
-void _thread_atexit_unlock() {
-  pthread_mutex_unlock(&g_atexit_lock);
+  // We're still in the dynamic linker or we're in the middle of forking, so ask the kernel.
+  // We don't know whether it's safe to update the cached value, so don't try.
+  return __getpid();
 }
diff --git a/libc/bionic/if_indextoname.c b/libc/bionic/if_indextoname.c
index dc08b28..f0db512 100644
--- a/libc/bionic/if_indextoname.c
+++ b/libc/bionic/if_indextoname.c
@@ -41,7 +41,6 @@
 char*
 if_indextoname(unsigned ifindex, char *ifname)
 {
-    int index;
     int ctl_sock;
     struct ifreq ifr;
     char*  ret = NULL;
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 625d789..d1fe960 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -14,13 +14,19 @@
  * limitations under the License.
  */
 
+#include <sys/param.h>
 #include <unistd.h>
 
 #include "jemalloc.h"
+#include "private/bionic_macros.h"
 
 void* je_pvalloc(size_t bytes) {
   size_t pagesize = sysconf(_SC_PAGESIZE);
-  return je_memalign(pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
+  size_t size = BIONIC_ALIGN(bytes, pagesize);
+  if (size < bytes) {
+    return NULL;
+  }
+  return je_memalign(pagesize, size);
 }
 
 #ifdef je_memalign
@@ -31,11 +37,9 @@
 // but this is not true. Both glibc and dlmalloc round up to the next power
 // of 2, so we'll do the same.
 void* je_memalign_round_up_boundary(size_t boundary, size_t size) {
-  unsigned int power_of_2 = static_cast<unsigned int>(boundary);
-  if (power_of_2 != 0) {
-    power_of_2 = 1UL << (sizeof(unsigned int)*8 - 1 - __builtin_clz(power_of_2));
-    if (power_of_2 != boundary) {
-      boundary = power_of_2 << 1;
+  if (boundary != 0) {
+    if (!powerof2(boundary)) {
+      boundary = BIONIC_ROUND_UP_POWER_OF_2(boundary);
     }
   } else {
     boundary = 1;
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index abf2d36..fa61c3c 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -86,21 +86,24 @@
 void __libc_init_tls(KernelArgumentBlock& args) {
   __libc_auxv = args.auxv;
 
-  uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
-  size_t stack_size = get_main_thread_stack_size();
-  uintptr_t stack_bottom = stack_top - stack_size;
-
   static void* tls[BIONIC_TLS_SLOTS];
   static pthread_internal_t main_thread;
   main_thread.tls = tls;
 
   // Tell the kernel to clear our tid field when we exit, so we're like any other pthread.
+  // As a side-effect, this tells us our pid (which is the same as the main thread's tid).
   main_thread.tid = __set_tid_address(&main_thread.tid);
+  main_thread.set_cached_pid(main_thread.tid);
 
-  // We already have a stack, and we don't want to free it up on exit (because things like
-  // environment variables with global scope live on it).
+  // Work out the extent of the main thread's stack.
+  uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+  size_t stack_size = get_main_thread_stack_size();
+  void* stack_bottom = reinterpret_cast<void*>(stack_top - stack_size);
+
+  // We don't want to free the main thread's stack even when the main thread exits
+  // because things like environment variables with global scope live on it.
   pthread_attr_init(&main_thread.attr);
-  pthread_attr_setstack(&main_thread.attr, (void*) stack_bottom, stack_size);
+  pthread_attr_setstack(&main_thread.attr, stack_bottom, stack_size);
   main_thread.attr.flags = PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK | PTHREAD_ATTR_FLAG_MAIN_THREAD;
 
   __init_thread(&main_thread, false);
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index 8966a5f..e656a12 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -453,7 +453,7 @@
   // found that all logd crashes thus far have had no problem stuffing
   // the UNIX domain socket and moving on so not critical *today*.
 
-  int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM, 0));
+  int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
   if (log_fd < 0) {
     return -1;
   }
@@ -619,7 +619,8 @@
   BufferOutputStream os(msg, sizeof(msg));
   out_vformat(os, format, args);
 
-  // TODO: log to stderr for the benefit of "adb shell" users.
+  // log to stderr for the benefit of "adb shell" users.
+  write(2, msg, strlen(msg));
 
   // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
   __libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index faf61bf..e4e4c2e 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -38,6 +38,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/system_properties.h>
 #include <sys/types.h>
@@ -47,8 +48,9 @@
 
 #include "debug_mapinfo.h"
 #include "debug_stacktrace.h"
-#include "private/libc_logging.h"
 #include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
 #define MAX_BACKTRACE_DEPTH 16
@@ -350,8 +352,8 @@
     }
 
     // Make the alignment a power of two.
-    if (alignment & (alignment-1)) {
-        alignment = 1L << (31 - __builtin_clz(alignment));
+    if (!powerof2(alignment)) {
+        alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
     }
 
     // here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -526,7 +528,7 @@
 }
 
 extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
-  if ((alignment & (alignment - 1)) != 0) {
+  if (!powerof2(alignment)) {
     return EINVAL;
   }
   int saved_errno = errno;
@@ -537,7 +539,7 @@
 
 extern "C" void* chk_pvalloc(size_t bytes) {
   size_t pagesize = sysconf(_SC_PAGESIZE);
-  size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+  size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     return NULL;
   }
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 2cc38cc..308d40b 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -37,6 +37,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/param.h>
 #include <sys/select.h>
 #include <sys/socket.h>
 #include <sys/system_properties.h>
@@ -48,6 +49,7 @@
 #include "debug_stacktrace.h"
 #include "malloc_debug_common.h"
 
+#include "private/bionic_macros.h"
 #include "private/libc_logging.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
@@ -255,7 +257,7 @@
 }
 
 extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
-  if ((alignment & (alignment - 1)) != 0) {
+  if (!powerof2(alignment)) {
     return EINVAL;
   }
   int saved_errno = errno;
@@ -266,7 +268,7 @@
 
 extern "C" void* fill_pvalloc(size_t bytes) {
   size_t pagesize = sysconf(_SC_PAGESIZE);
-  size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+  size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     return NULL;
   }
@@ -401,8 +403,8 @@
     }
 
     // need to make sure it's a power of two
-    if (alignment & (alignment-1)) {
-        alignment = 1L << (31 - __builtin_clz(alignment));
+    if (!powerof2(alignment)) {
+        alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
     }
 
     // here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -464,7 +466,7 @@
 }
 
 extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
-  if ((alignment & (alignment - 1)) != 0) {
+  if (!powerof2(alignment)) {
     return EINVAL;
   }
   int saved_errno = errno;
@@ -475,7 +477,7 @@
 
 extern "C" void* leak_pvalloc(size_t bytes) {
   size_t pagesize = sysconf(_SC_PAGESIZE);
-  size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+  size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     return NULL;
   }
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index 9b3bb55..fd5161a 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -47,11 +47,13 @@
 #include <stdio.h>
 #include <fcntl.h>
 #include <sys/mman.h>
+#include <sys/param.h>
 #include <pthread.h>
 #include <unistd.h>
 #include <errno.h>
-#include "private/libc_logging.h"
 #include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
 
 /* This file should be included into the build only when
  * MALLOC_QEMU_INSTRUMENT macro is defined. */
@@ -970,8 +972,8 @@
     // size.
     if (alignment < DEFAULT_PREFIX_SIZE) {
         alignment = DEFAULT_PREFIX_SIZE;
-    } else if (alignment & (alignment - 1)) {
-        alignment = 1L << (31 - __builtin_clz(alignment));
+    } else if (!powerof2(alignment)) {
+        alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
     }
     desc.prefix_size = alignment;
     desc.requested_bytes = bytes;
@@ -1047,7 +1049,7 @@
 
 extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
   size_t pagesize = sysconf(_SC_PAGESIZE);
-  size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+  size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
                    malloc_pid, getpid(), bytes, size);
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index c4cb262..2ded22b 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -30,9 +30,11 @@
 
 #include <errno.h>
 #include <sys/mman.h>
+#include <unistd.h>
 
 #include "pthread_internal.h"
 
+#include "private/bionic_macros.h"
 #include "private/bionic_ssp.h"
 #include "private/bionic_tls.h"
 #include "private/libc_logging.h"
@@ -183,8 +185,8 @@
   }
 
   // Make sure the stack size and guard size are multiples of PAGE_SIZE.
-  thread->attr.stack_size = (thread->attr.stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
-  thread->attr.guard_size = (thread->attr.guard_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+  thread->attr.stack_size = BIONIC_ALIGN(thread->attr.stack_size, PAGE_SIZE);
+  thread->attr.guard_size = BIONIC_ALIGN(thread->attr.guard_size, PAGE_SIZE);
 
   if (thread->attr.stack_base == NULL) {
     // The caller didn't provide a stack, so allocate one.
@@ -219,6 +221,8 @@
   thread->start_routine = start_routine;
   thread->start_routine_arg = arg;
 
+  thread->set_cached_pid(getpid());
+
   int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
       CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
   void* tls = thread->tls;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 490ae86..e05d15c 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -36,6 +36,26 @@
 
   pid_t tid;
 
+ private:
+  pid_t cached_pid_;
+
+ public:
+  pid_t invalidate_cached_pid() {
+    pid_t old_value;
+    get_cached_pid(&old_value);
+    set_cached_pid(0);
+    return old_value;
+  }
+
+  void set_cached_pid(pid_t value) {
+    cached_pid_ = value;
+  }
+
+  bool get_cached_pid(pid_t* cached_pid) {
+    *cached_pid = cached_pid_;
+    return (*cached_pid != 0);
+  }
+
   void** tls;
 
   pthread_attr_t attr;
diff --git a/libc/bionic/recv.cpp b/libc/bionic/recv.cpp
index 60f264d..061cd46 100644
--- a/libc/bionic/recv.cpp
+++ b/libc/bionic/recv.cpp
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 
+#undef _FORTIFY_SOURCE
 #include <sys/socket.h>
 
 ssize_t recv(int socket, void *buf, size_t len, int flags) {
diff --git a/libc/bionic/semaphore.c b/libc/bionic/semaphore.c
index b12a37d..7387d6e 100644
--- a/libc/bionic/semaphore.c
+++ b/libc/bionic/semaphore.c
@@ -147,7 +147,7 @@
 }
 
 
-int sem_unlink(const char * name)
+int sem_unlink(const char* name __unused)
 {
     errno = ENOSYS;
     return -1;
@@ -266,7 +266,6 @@
 
 int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
 {
-    int  ret;
     unsigned int shared;
 
     if (sem == NULL) {
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 7618586..a564c39 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -55,9 +55,6 @@
 #include "private/bionic_futex.h"
 #include "private/bionic_macros.h"
 
-#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
-
-
 static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
 
 
@@ -301,7 +298,7 @@
 static void *allocate_obj(const size_t size, uint32_t *const off)
 {
     prop_area *pa = __system_property_area__;
-    const size_t aligned = ALIGN(size, sizeof(uint32_t));
+    const size_t aligned = BIONIC_ALIGN(size, sizeof(uint32_t));
     if (pa->bytes_used + aligned > pa_data_size) {
         return NULL;
     }
diff --git a/libc/bionic/thread_atexit.cpp b/libc/bionic/thread_private.cpp
similarity index 84%
rename from libc/bionic/thread_atexit.cpp
rename to libc/bionic/thread_private.cpp
index 68c119d..1c04019 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/bionic/thread_private.cpp
@@ -26,17 +26,13 @@
  * SUCH DAMAGE.
  */
 
-/* some simple glue used to make the BSD atexit code happy */
-
 #include <pthread.h>
+#include "private/thread_private.h"
+
+// Some simple glue used to make BSD code thread-safe.
 
 static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
 
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
-
 void _thread_atexit_lock() {
   pthread_mutex_lock(&g_atexit_lock);
 }
@@ -44,3 +40,13 @@
 void _thread_atexit_unlock() {
   pthread_mutex_unlock(&g_atexit_lock);
 }
+
+static pthread_mutex_t g_arc4_lock = PTHREAD_MUTEX_INITIALIZER;
+
+void _thread_arc4_lock() {
+  pthread_mutex_lock(&g_arc4_lock);
+}
+
+void _thread_arc4_unlock() {
+  pthread_mutex_unlock(&g_arc4_lock);
+}
diff --git a/libc/bionic/time64.c b/libc/bionic/time64.c
index 7163b34..62ee903 100644
--- a/libc/bionic/time64.c
+++ b/libc/bionic/time64.c
@@ -252,6 +252,7 @@
 }
 
 
+#if !defined(NDEBUG)
 static int check_tm(struct TM *tm)
 {
     /* Don't forget leap seconds */
@@ -283,6 +284,7 @@
 
     return 1;
 }
+#endif
 
 
 /* The exceptional centuries without leap years cause the cycle to
diff --git a/libc/dns/gethnamaddr.c b/libc/dns/gethnamaddr.c
index 1afad6d..6f30f75 100644
--- a/libc/dns/gethnamaddr.c
+++ b/libc/dns/gethnamaddr.c
@@ -539,7 +539,7 @@
 	const int one = 1;
 	struct sockaddr_un proxy_addr;
 
-	sock = socket(AF_UNIX, SOCK_STREAM, 0);
+	sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
 	if (sock < 0) {
 		return NULL;
 	}
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index be692e3..65fd1c1 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -362,7 +362,7 @@
  */
 static int
 _test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
-	int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+	int s = socket(pf, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
 	if (s < 0)
 		return 0;
 	if (mark != MARK_UNSET && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
@@ -433,7 +433,7 @@
 		return EAI_NODATA;
 	}
 
-	sock = socket(AF_UNIX, SOCK_STREAM, 0);
+	sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
 	if (sock < 0) {
 		return EAI_NODATA;
 	}
@@ -884,7 +884,7 @@
 	 * filter out AFs that are not supported by the kernel
 	 * XXX errno?
 	 */
-	s = socket(pai->ai_family, SOCK_DGRAM, 0);
+	s = socket(pai->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
 	if (s < 0) {
 		if (errno != EMFILE)
 			return 0;
@@ -1792,7 +1792,7 @@
 		return 0;
 	}
 
-	sock = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	sock = socket(addr->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
 	if (sock == -1) {
 		if (errno == EAFNOSUPPORT) {
 			return 0;
diff --git a/libc/dns/net/getservbyname.c b/libc/dns/net/getservbyname.c
index 5ea528e..c95c9b0 100644
--- a/libc/dns/net/getservbyname.c
+++ b/libc/dns/net/getservbyname.c
@@ -34,7 +34,6 @@
 getservbyname(const char *name, const char *proto)
 {
     res_static       rs = __res_get_static();
-    struct servent*  s;
 
     if (rs == NULL || proto == NULL || name == NULL) {
         errno = EINVAL;
diff --git a/libc/dns/net/getservbyport.c b/libc/dns/net/getservbyport.c
index fad7e23..7dcaafb 100644
--- a/libc/dns/net/getservbyport.c
+++ b/libc/dns/net/getservbyport.c
@@ -33,7 +33,6 @@
 getservbyport(int port, const char *proto)
 {
     res_static       rs = __res_get_static();
-    struct servent*  s;
 
     if (rs == NULL || proto == NULL) {
         errno = EINVAL;
diff --git a/libc/dns/net/nsdispatch.c b/libc/dns/net/nsdispatch.c
index 15282be..fb6d8f6 100644
--- a/libc/dns/net/nsdispatch.c
+++ b/libc/dns/net/nsdispatch.c
@@ -69,26 +69,14 @@
  */
 
 #include <sys/cdefs.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
 
 #include <assert.h>
-#ifdef __ELF__
-#include <dlfcn.h>
-#endif /* __ELF__ */
-#include <fcntl.h>
-#define _NS_PRIVATE
 #include <nsswitch.h>
 #include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <strings.h>
-#include <unistd.h>
 
 static nss_method
-_nsmethod(const char *source, const char *database, const char *method,
+_nsmethod(const char *source, const char *database __unused, const char *method __unused,
     const ns_dtab disp_tab[], void **cb_data)
 {
 	int	curdisp;
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index 9df97cd..77a1b4d 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -2043,7 +2043,7 @@
         register char **pp = statp->dnsrch;
         register int *p = info->dnsrch_offset;
         while (pp < statp->dnsrch + MAXDNSRCH && *p != -1) {
-            *pp++ = &statp->defdname + *p++;
+            *pp++ = &statp->defdname[0] + *p++;
         }
     }
     pthread_mutex_unlock(&_res_cache_list_lock);
diff --git a/libc/dns/resolv/res_init.c b/libc/dns/resolv/res_init.c
index 9f3a9da..f1cbed8 100644
--- a/libc/dns/resolv/res_init.c
+++ b/libc/dns/resolv/res_init.c
@@ -104,10 +104,6 @@
 #include <sys/system_properties.h>
 #endif /* ANDROID_CHANGES */
 
-#ifndef MIN
-#define	MIN(x,y)	((x)<(y)?(x):(y))
-#endif
-
 /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
 #ifdef ANDROID_CHANGES
 #include "resolv_netid.h"
@@ -125,9 +121,11 @@
 
 static void res_setoptions __P((res_state, const char *, const char *));
 
+#ifdef RESOLVSORT
 static const char sort_mask[] = "/&";
 #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
-static u_int32_t net_mask __P((struct in_addr));
+static uint32_t net_mask(struct in_addr);
+#endif
 
 #if !defined(isascii)	/* XXX - could be a function */
 # define isascii(c) (!(c & 0200))
@@ -168,15 +166,25 @@
 /* This function has to be reachable by res_data.c but not publicly. */
 int
 __res_vinit(res_state statp, int preinit) {
+#if !defined(__ANDROID__)
 	register FILE *fp;
+#endif
 	register char *cp, **pp;
+#if !defined(__ANDROID__)
 	register int n;
+#endif
 	char buf[BUFSIZ];
 	int nserv = 0;    /* number of nameserver records read from file */
+#if !defined(__ANDROID__)
 	int haveenv = 0;
+#endif
 	int havesearch = 0;
+#ifdef RESOLVSORT
 	int nsort = 0;
+#endif
+#if !defined(__ANDROID__)
 	char *net;
+#endif
 	int dots;
 	union res_sockaddr_union u[2];
 
@@ -235,7 +243,7 @@
 	statp->nsort = 0;
 	res_setservers(statp, u, nserv);
 
-#if 0 /* IGNORE THE ENVIRONMENT */
+#if !defined(__ANDROID__) /* IGNORE THE ENVIRONMENT */
 	/* Allow user to override the local domain definition */
 	if ((cp = getenv("LOCALDOMAIN")) != NULL) {
 		(void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
@@ -593,12 +601,12 @@
 	}
 }
 
+#ifdef RESOLVSORT
 /* XXX - should really support CIDR which means explicit masks always. */
-static u_int32_t
-net_mask(in)		/* XXX - should really use system's version of this */
-	struct in_addr in;
+static uint32_t
+net_mask(struct in_addr in)	/*!< XXX - should really use system's version of this */
 {
-	register u_int32_t i = ntohl(in.s_addr);
+	register uint32_t i = ntohl(in.s_addr);
 
 	if (IN_CLASSA(i))
 		return (htonl(IN_CLASSA_NET));
@@ -606,19 +614,19 @@
 		return (htonl(IN_CLASSB_NET));
 	return (htonl(IN_CLASSC_NET));
 }
+#endif
 
 #ifdef ANDROID_CHANGES
 static int
 real_randomid(u_int *random_value) {
 	/* open the nonblocking random device, returning -1 on failure */
-	int random_device = open("/dev/urandom", O_RDONLY);
+	int random_device = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
 	if (random_device < 0) {
 		return -1;
 	}
 
 	/* read from the random device, returning -1 on failure (or too many retries)*/
-	u_int retry = 5;
-	for (retry; retry > 0; retry--) {
+	for (u_int retry = 5; retry > 0; retry--) {
 		int retval = read(random_device, random_value, sizeof(u_int));
 		if (retval == sizeof(u_int)) {
 			*random_value &= 0xffff;
@@ -649,7 +657,7 @@
 	return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
 }
 
-/*
+/*%
  * This routine is for closing the socket if a virtual circuit is used and
  * the program wants to close it.  This provides support for endhostent()
  * which expects to close the socket.
@@ -657,7 +665,8 @@
  * This routine is not expected to be user visible.
  */
 void
-res_nclose(res_state statp) {
+res_nclose(res_state statp)
+{
 	int ns;
 
 	if (statp->_vcsock >= 0) {
@@ -674,7 +683,8 @@
 }
 
 void
-res_ndestroy(res_state statp) {
+res_ndestroy(res_state statp)
+{
 	res_nclose(statp);
 	if (statp->_u._ext.ext != NULL)
 		free(statp->_u._ext.ext);
@@ -683,21 +693,24 @@
 }
 
 const char *
-res_get_nibblesuffix(res_state statp) {
+res_get_nibblesuffix(res_state statp)
+{
 	if (statp->_u._ext.ext)
 		return (statp->_u._ext.ext->nsuffix);
 	return ("ip6.arpa");
 }
 
 const char *
-res_get_nibblesuffix2(res_state statp) {
+res_get_nibblesuffix2(res_state statp)
+{
 	if (statp->_u._ext.ext)
 		return (statp->_u._ext.ext->nsuffix2);
 	return ("ip6.int");
 }
 
 void
-res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
+res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt)
+{
 	int i, nserv;
 	size_t size;
 
@@ -718,10 +731,8 @@
 			if (size <= sizeof(statp->nsaddr_list[nserv]))
 				memcpy(&statp->nsaddr_list[nserv],
 					&set->sin, size);
-#ifdef notdef
 			else
 				statp->nsaddr_list[nserv].sin_family = 0;
-#endif
 			nserv++;
 			break;
 
@@ -750,10 +761,11 @@
 }
 
 int
-res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
+res_getservers(res_state statp, union res_sockaddr_union *set, int cnt)
+{
 	int i;
 	size_t size;
-	u_int16_t family;
+	uint16_t family;
 
 	for (i = 0; i < statp->nscount && i < cnt; i++) {
 		if (statp->_u._ext.ext)
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index 9b36f55..4a010d5 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -764,7 +764,7 @@
 		struct sockaddr_storage peer;
 		socklen_t size = sizeof peer;
 		unsigned old_mark;
-		int mark_size = sizeof(old_mark);
+		socklen_t mark_size = sizeof(old_mark);
 		if (getpeername(statp->_vcsock,
 				(struct sockaddr *)(void *)&peer, &size) < 0 ||
 		    !sock_eq((struct sockaddr *)(void *)&peer, nsap) ||
@@ -779,7 +779,7 @@
 		if (statp->_vcsock >= 0)
 			res_nclose(statp);
 
-		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
+		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
 		if (statp->_vcsock > highestFD) {
 			res_nclose(statp);
 			errno = ENOTSOCK;
@@ -1062,7 +1062,7 @@
 	nsap = get_nsaddr(statp, (size_t)ns);
 	nsaplen = get_salen(nsap);
 	if (EXT(statp).nssocks[ns] == -1) {
-		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
+		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
 		if (EXT(statp).nssocks[ns] > highestFD) {
 			res_nclose(statp);
 			errno = ENOTSOCK;
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index 90962fa..616e08e 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -49,11 +49,17 @@
    */
   ANDROID_DLEXT_USE_RELRO             = 0x8,
 
+  /* Instruct dlopen to use library_fd instead of opening file by name.
+   * The filename parameter is still used to identify the library.
+   */
+  ANDROID_DLEXT_USE_LIBRARY_FD        = 0x10,
+
   /* Mask of valid bits */
   ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
                                         ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
                                         ANDROID_DLEXT_WRITE_RELRO |
-                                        ANDROID_DLEXT_USE_RELRO,
+                                        ANDROID_DLEXT_USE_RELRO |
+                                        ANDROID_DLEXT_USE_LIBRARY_FD,
 };
 
 typedef struct {
@@ -61,6 +67,7 @@
   void*   reserved_addr;
   size_t  reserved_size;
   int     relro_fd;
+  int     library_fd;
 } android_dlextinfo;
 
 extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index cd68154..4450bb6 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <linux/fadvise.h>
 #include <linux/fcntl.h>
+#include <linux/uio.h>
 #include <unistd.h>  /* this is not required, but makes client code much happier */
 
 __BEGIN_DECLS
@@ -51,9 +52,12 @@
 #define F_SETLKW64 F_SETLKW
 #endif
 
-#ifndef O_ASYNC
-#define O_ASYNC  FASYNC
-#endif
+#define O_ASYNC FASYNC
+
+#define SPLICE_F_MOVE 1
+#define SPLICE_F_NONBLOCK 2
+#define SPLICE_F_MORE 4
+#define SPLICE_F_GIFT 8
 
 #define SYNC_FILE_RANGE_WAIT_BEFORE 1
 #define SYNC_FILE_RANGE_WRITE 2
@@ -70,7 +74,10 @@
 extern int open64(const char*, int, ...);
 extern int posix_fallocate64(int, off64_t, off64_t);
 extern int posix_fallocate(int, off_t, off_t);
+extern ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int);
+extern ssize_t tee(int, int, size_t, unsigned int);
 extern int unlinkat(int, const char*, int);
+extern ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int);
 
 #if defined(__BIONIC_FORTIFY)
 
diff --git a/libc/dns/include/nsswitch.h b/libc/include/nsswitch.h
similarity index 91%
rename from libc/dns/include/nsswitch.h
rename to libc/include/nsswitch.h
index e03844b..af88433 100644
--- a/libc/dns/include/nsswitch.h
+++ b/libc/include/nsswitch.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: nsswitch.h,v 1.18 2005/11/29 03:12:58 christos Exp $	*/
+/*	$NetBSD: nsswitch.h,v 1.21 2011/07/17 20:54:34 joerg Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -137,6 +130,7 @@
 #else
 #   define NS_NIS_CB(F,C)
 #endif
+#define	NS_NULL_CB		{ .src = NULL },
 
 /*
  * ns_src - `nsswitch source'
@@ -149,7 +143,6 @@
 } ns_src;
 
 
-#if 0
 /*
  * Default sourcelists (if nsswitch.conf is missing, corrupt,
  * or the requested database doesn't have an entry)
@@ -161,7 +154,7 @@
 extern const ns_src __nsdefaultfiles_forceall[];
 extern const ns_src __nsdefaultnis[];
 extern const ns_src __nsdefaultnis_forceall[];
-#endif
+
 
 /*
  * ns_mtab - `nsswitch method table'
@@ -222,7 +215,7 @@
 
 __BEGIN_DECLS
 int	nsdispatch(void *, const ns_dtab [], const char *,
-			const char *, const ns_src [], ...);
+			const char *, const ns_src [], ...) __LIBC_ABI_PUBLIC__;
 
 #ifdef _NS_PRIVATE
 int		 _nsdbtaddsrc(ns_dbt *, const ns_src *);
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 0063b24..f1849c5 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -34,6 +34,7 @@
 #include <limits.h>		/* For LONG_BIT */
 #include <string.h>		/* For memset() */
 #include <sys/types.h>
+#include <asm/sigcontext.h>
 
 #if defined(__LP64__) || defined(__mips__)
 /* For 64-bit (and mips), the kernel's struct sigaction doesn't match the POSIX one,
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 266aa5e..62b7a67 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -100,9 +100,10 @@
 extern double erand48(unsigned short xsubi[3]);
 extern double drand48(void);
 extern void srand48(long);
-extern unsigned int arc4random(void);
-extern void arc4random_stir(void);
-extern void arc4random_addrandom(unsigned char *, int);
+
+unsigned int arc4random(void);
+unsigned int arc4random_uniform(unsigned int);
+void arc4random_buf(void*, size_t);
 
 #define RAND_MAX 0x7fffffff
 
diff --git a/libc/include/strings.h b/libc/include/strings.h
index c4d5f6c..ae261cf 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -43,8 +43,16 @@
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
-#define bcopy(b1, b2, len) (void)(memmove((b2), (b1), (len)))
-#define bzero(b, len) (void)(memset((b), '\0', (len)))
+#if defined(__BIONIC_FORTIFY)
+#define bcopy(b1, b2, len) \
+  (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
+#define bzero(b, len) \
+  (void)(__builtin___memset_chk((b), '\0', (len), __bos0(b)))
+#else
+#define bcopy(b1, b2, len) (void)(__builtin_memmove((b2), (b1), (len)))
+#define bzero(b, len) (void)(__builtin_memset((b), '\0', (len)))
+#endif
+
 
 int	 ffs(int);
 int	 strcasecmp(const char *, const char *);
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 7edaac9..ae2f238 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -107,7 +107,7 @@
   int cmsg_type;
 };
 
-#define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg))
+#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr((mhdr), (cmsg))
 #define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
 #define CMSG_DATA(cmsg) ((void*)((char*)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
 #define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
@@ -117,7 +117,7 @@
    ? (struct cmsghdr*) (msg)->msg_control : (struct cmsghdr*) NULL)
 #define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) &&   (cmsg)->cmsg_len <= (unsigned long)   ((mhdr)->msg_controllen -   ((char*)(cmsg) - (char*)(mhdr)->msg_control)))
 
-struct cmsghdr* cmsg_nxthdr(struct msghdr*, struct cmsghdr*);
+struct cmsghdr* __cmsg_nxthdr(struct msghdr*, struct cmsghdr*);
 
 #define SCM_RIGHTS 0x01
 #define SCM_CREDENTIALS 0x02
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index 9a76ad2..a5fa692 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -91,12 +91,17 @@
 typedef __time_t time_t;
 
 /* This historical accident means that we had a 32-bit off_t on 32-bit architectures. */
-#ifndef _OFF_T_DEFINED_
-#define _OFF_T_DEFINED_
+#if !defined(__LP64__)
 typedef __kernel_off_t off_t;
-#endif
 typedef __kernel_loff_t loff_t;
 typedef loff_t off64_t;
+#else
+/* We could re-use the LP32 definitions, but that would mean that although off_t and loff_t/off64_t
+ * would be the same size, they wouldn't actually be the same type, which can lead to warnings. */
+typedef __kernel_off_t off_t;
+typedef off_t loff_t;
+typedef loff_t off64_t;
+#endif
 
 /* while POSIX wants these in <sys/types.h>, we
  * declare then in <pthread.h> instead */
diff --git a/libc/include/time.h b/libc/include/time.h
index 0f86fd3..0587a2d 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -36,9 +36,9 @@
 
 #define CLOCKS_PER_SEC 1000000
 
-extern char* tzname[];
-extern int daylight;
-extern long int timezone;
+extern char* tzname[] __LIBC_ABI_PUBLIC__;
+extern int daylight __LIBC_ABI_PUBLIC__;
+extern long int timezone __LIBC_ABI_PUBLIC__;
 
 struct sigevent;
 
@@ -58,44 +58,43 @@
 
 #define TM_ZONE tm_zone
 
-extern time_t time(time_t*);
-extern int nanosleep(const struct timespec*, struct timespec*);
+extern time_t time(time_t*) __LIBC_ABI_PUBLIC__;
+extern int nanosleep(const struct timespec*, struct timespec*) __LIBC_ABI_PUBLIC__;
 
-extern char* asctime(const struct tm*);
-extern char* asctime_r(const struct tm*, char*);
+extern char* asctime(const struct tm*) __LIBC_ABI_PUBLIC__;
+extern char* asctime_r(const struct tm*, char*) __LIBC_ABI_PUBLIC__;
 
-extern double difftime(time_t, time_t);
-extern time_t mktime(struct tm*);
+extern double difftime(time_t, time_t) __LIBC_ABI_PUBLIC__;
+extern time_t mktime(struct tm*) __LIBC_ABI_PUBLIC__;
 
-extern struct tm* localtime(const time_t*);
-extern struct tm* localtime_r(const time_t*, struct tm*);
+extern struct tm* localtime(const time_t*) __LIBC_ABI_PUBLIC__;
+extern struct tm* localtime_r(const time_t*, struct tm*) __LIBC_ABI_PUBLIC__;
 
-extern struct tm* gmtime(const time_t*);
-extern struct tm* gmtime_r(const time_t*, struct tm*);
+extern struct tm* gmtime(const time_t*) __LIBC_ABI_PUBLIC__;
+extern struct tm* gmtime_r(const time_t*, struct tm*) __LIBC_ABI_PUBLIC__;
 
-extern char* strptime(const char*, const char*, struct tm*);
-extern size_t strftime(char*, size_t, const char*, const struct tm*);
+extern char* strptime(const char*, const char*, struct tm*) __LIBC_ABI_PUBLIC__;
+extern size_t strftime(char*, size_t, const char*, const struct tm*) __LIBC_ABI_PUBLIC__;
 
-extern char* ctime(const time_t*);
-extern char* ctime_r(const time_t*, char*);
+extern char* ctime(const time_t*) __LIBC_ABI_PUBLIC__;
+extern char* ctime_r(const time_t*, char*) __LIBC_ABI_PUBLIC__;
 
-extern void tzset(void);
+extern void tzset(void) __LIBC_ABI_PUBLIC__;
 
-extern clock_t clock(void);
+extern clock_t clock(void) __LIBC_ABI_PUBLIC__;
 
-extern int clock_getres(int, struct timespec*);
-extern int clock_gettime(int, struct timespec*);
+extern int clock_getres(int, struct timespec*) __LIBC_ABI_PUBLIC__;
+extern int clock_gettime(int, struct timespec*) __LIBC_ABI_PUBLIC__;
 
-extern int timer_create(int, struct sigevent*, timer_t*);
-extern int timer_delete(timer_t);
-extern int timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*);
-extern int timer_gettime(timer_t, struct itimerspec*);
-extern int timer_getoverrun(timer_t);
+extern int timer_create(int, struct sigevent*, timer_t*) __LIBC_ABI_PUBLIC__;
+extern int timer_delete(timer_t) __LIBC_ABI_PUBLIC__;
+extern int timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) __LIBC_ABI_PUBLIC__;
+extern int timer_gettime(timer_t, struct itimerspec*) __LIBC_ABI_PUBLIC__;
+extern int timer_getoverrun(timer_t) __LIBC_ABI_PUBLIC__;
 
-extern time_t timelocal(struct tm*);
-extern time_t timegm(struct tm*);
-extern time_t time2posix(time_t);
-extern time_t posix2time(time_t);
+/* Non-standard extensions that are in the BSDs and glibc. */
+extern time_t timelocal(struct tm*) __LIBC_ABI_PUBLIC__;
+extern time_t timegm(struct tm*) __LIBC_ABI_PUBLIC__;
 
 __END_DECLS
 
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index d50e9ec..014fed3 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -118,7 +118,7 @@
 extern int               wcscoll(const wchar_t *, const wchar_t *);
 extern wchar_t          *wcscpy(wchar_t *, const wchar_t *);
 extern size_t            wcscspn(const wchar_t *, const wchar_t *);
-extern size_t            wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *);
+extern size_t            wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *) __LIBC_ABI_PUBLIC__;
 extern size_t            wcslen(const wchar_t *);
 extern int               wcsncasecmp(const wchar_t *, const wchar_t *, size_t);
 extern wchar_t          *wcsncat(wchar_t *, const wchar_t *, size_t);
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 67ab702..2efd455 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -44,7 +44,11 @@
 kernel_default_arch_macros = {
     "arm": {"__ARMEB__": kCppUndefinedMacro, "__ARM_EABI__": "1"},
     "arm64": {},
-    "mips": {"CONFIG_32BIT":"1", "__MIPSEB__": kCppUndefinedMacro, "__MIPSEL__": "1"},
+    "mips": {"__MIPSEB__": kCppUndefinedMacro,
+             "__MIPSEL__": "1",
+             "CONFIG_32BIT": "_ABIO32",
+             "CONFIG_CPU_LITTLE_ENDIAN": "1",
+             "__SANE_USERSPACE_TYPES__": "1",},
     "x86": {},
     }
 
diff --git a/libc/kernel/uapi/asm-mips/asm/fcntl.h b/libc/kernel/uapi/asm-mips/asm/fcntl.h
index 4a9bf5c..e77f79a 100644
--- a/libc/kernel/uapi/asm-mips/asm/fcntl.h
+++ b/libc/kernel/uapi/asm-mips/asm/fcntl.h
@@ -46,19 +46,21 @@
 #define F_SETLKW64 35
 #endif
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#ifdef _ABIO32
 #include <linux/types.h>
 struct flock {
  short l_type;
- short l_whence;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ short l_whence;
  __kernel_off_t l_start;
  __kernel_off_t l_len;
  long l_sysid;
- __kernel_pid_t l_pid;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __kernel_pid_t l_pid;
  long pad[4];
 };
 #define HAVE_ARCH_STRUCT_FLOCK
-#include <asm-generic/fcntl.h>
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
+#include <asm-generic/fcntl.h>
+#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/msgbuf.h b/libc/kernel/uapi/asm-mips/asm/msgbuf.h
index d81da73..624bddf 100644
--- a/libc/kernel/uapi/asm-mips/asm/msgbuf.h
+++ b/libc/kernel/uapi/asm-mips/asm/msgbuf.h
@@ -21,21 +21,29 @@
 struct msqid64_ds {
  struct ipc64_perm msg_perm;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- unsigned long __unused1;
  __kernel_time_t msg_stime;
- unsigned long __unused2;
- __kernel_time_t msg_rtime;
+#ifdef _ABIO32
+ unsigned long __unused1;
+#endif
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- unsigned long __unused3;
+ __kernel_time_t msg_rtime;
+#ifdef _ABIO32
+ unsigned long __unused2;
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __kernel_time_t msg_ctime;
+#ifdef _ABIO32
+ unsigned long __unused3;
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  unsigned long msg_cbytes;
  unsigned long msg_qnum;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  unsigned long msg_qbytes;
  __kernel_pid_t msg_lspid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __kernel_pid_t msg_lrpid;
  unsigned long __unused4;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  unsigned long __unused5;
 };
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/resource.h b/libc/kernel/uapi/asm-mips/asm/resource.h
index 8761697..ff7cfd5 100644
--- a/libc/kernel/uapi/asm-mips/asm/resource.h
+++ b/libc/kernel/uapi/asm-mips/asm/resource.h
@@ -24,7 +24,10 @@
 #define RLIMIT_RSS 7
 #define RLIMIT_NPROC 8
 #define RLIMIT_MEMLOCK 9
-#define RLIM_INFINITY 0x7fffffffUL
+#ifdef _ABIO32
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define RLIM_INFINITY 0x7fffffffUL
+#endif
 #include <asm-generic/resource.h>
 #endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/kernel/uapi/asm-mips/asm/siginfo.h b/libc/kernel/uapi/asm-mips/asm/siginfo.h
index 45b418a..4abc7af 100644
--- a/libc/kernel/uapi/asm-mips/asm/siginfo.h
+++ b/libc/kernel/uapi/asm-mips/asm/siginfo.h
@@ -24,80 +24,82 @@
 #define HAVE_ARCH_SIGINFO_T
 #define HAVE_ARCH_COPY_SIGINFO
 struct siginfo;
-#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
+#ifdef _ABIO32
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
+#endif
 #ifdef __LP64__
 #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
 #include <asm-generic/siginfo.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 typedef struct siginfo {
  int si_signo;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int si_code;
  int si_errno;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int __pad0[SI_MAX_SIZE / sizeof(int) - SI_PAD_SIZE - 3];
  union {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int _pad[SI_PAD_SIZE];
  struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  pid_t _pid;
  __ARCH_SI_UID_T _uid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  } _kill;
  struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  timer_t _tid;
  int _overrun;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
  sigval_t _sigval;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int _sys_private;
  } _timer;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  struct {
  pid_t _pid;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __ARCH_SI_UID_T _uid;
  sigval_t _sigval;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  } _rt;
  struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  pid_t _pid;
  __ARCH_SI_UID_T _uid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int _status;
  clock_t _utime;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  clock_t _stime;
  } _sigchld;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  struct {
  pid_t _pid;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  clock_t _utime;
  int _status;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  clock_t _stime;
  } _irix_sigchld;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  struct {
  void __user *_addr;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #ifdef __ARCH_SI_TRAPNO
  int _trapno;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
  short _addr_lsb;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  } _sigfault;
  struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __ARCH_SI_BAND_T _band;
  int _fd;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  } _sigpoll;
  } _sifields;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 } siginfo_t;
 #undef SI_ASYNCIO
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #undef SI_TIMER
 #undef SI_MESGQ
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define SI_ASYNCIO -2
 #define SI_TIMER __SI_CODE(__SI_TIMER, -3)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define SI_MESGQ __SI_CODE(__SI_MESGQ, -4)
 #endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/kernel/uapi/asm-mips/asm/types.h b/libc/kernel/uapi/asm-mips/asm/types.h
index 45fea6c..9ef7b7c 100644
--- a/libc/kernel/uapi/asm-mips/asm/types.h
+++ b/libc/kernel/uapi/asm-mips/asm/types.h
@@ -18,11 +18,6 @@
  ****************************************************************************/
 #ifndef _UAPI_ASM_TYPES_H
 #define _UAPI_ASM_TYPES_H
-#if _MIPS_SZLONG == 64
-#include <asm-generic/int-l64.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#else
 #include <asm-generic/int-ll64.h>
 #endif
-#endif
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/private/ScopedFd.h b/libc/private/ScopedFd.h
new file mode 100644
index 0000000..e56c139
--- /dev/null
+++ b/libc/private/ScopedFd.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SCOPED_FD_H
+#define SCOPED_FD_H
+
+#include <unistd.h>
+#include "bionic_macros.h"
+
+// A smart pointer that closes the given fd on going out of scope.
+// Use this when the fd is incidental to the purpose of your function,
+// but needs to be cleaned up on exit.
+class ScopedFd {
+public:
+    explicit ScopedFd(int fd) : fd(fd) {
+    }
+
+    ~ScopedFd() {
+      reset();
+    }
+
+    int get() const {
+        return fd;
+    }
+
+    int release() __attribute__((warn_unused_result)) {
+        int localFd = fd;
+        fd = -1;
+        return localFd;
+    }
+
+    void reset(int new_fd = -1) {
+      if (fd != -1) {
+          TEMP_FAILURE_RETRY(close(fd));
+      }
+      fd = new_fd;
+    }
+
+private:
+    int fd;
+
+    // Disallow copy and assignment.
+    DISALLOW_COPY_AND_ASSIGN(ScopedFd);
+};
+
+#endif  // SCOPED_FD_H
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 34da501..a3a6985 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -33,4 +33,10 @@
   TypeName();                                    \
   DISALLOW_COPY_AND_ASSIGN(TypeName)
 
+#define BIONIC_ALIGN(value, alignment) \
+  (((value) + (alignment) - 1) & ~((alignment) - 1))
+
+#define BIONIC_ROUND_UP_POWER_OF_2(value) \
+  (1UL << (sizeof(value) * 8 - 1 - __builtin_clz(value)))
+
 #endif // _BIONIC_MACROS_H_
diff --git a/libc/private/bionic_time.h b/libc/private/bionic_time.h
index 7c80f59..ca5c146 100644
--- a/libc/private/bionic_time.h
+++ b/libc/private/bionic_time.h
@@ -52,10 +52,11 @@
 
 /*
  * Note: you should consider these extensions deprecated and use managed code or icu4c instead.
+ * We'd like to hide them but they're currently still used in frameworks code.
  */
-extern size_t strftime_tz(char* s, size_t max, const char* format, const struct tm* tm, const struct strftime_locale* lc);
-extern time_t mktime_tz(struct tm* const tmp, char const* tz);
-extern void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz);
+extern size_t strftime_tz(char*, size_t, const char*, const struct tm*, const struct strftime_locale*);
+extern time_t mktime_tz(struct tm* const, char const*);
+extern void localtime_tz(const time_t* const, struct tm*, const char*);
 
 #endif /* _BIONIC_STRFTIME_TZ_DECLARED */
 
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index b52013f..56a61be 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -31,6 +31,7 @@
 
 #include <sys/cdefs.h>
 #include <sys/limits.h>
+#include "bionic_macros.h"
 #include "__get_tls.h"
 
 __BEGIN_DECLS
@@ -84,8 +85,6 @@
 #define BIONIC_TLS_RESERVED_SLOTS GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT
 #endif
 
-#define BIONIC_ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
-
 /*
  * Maximum number of elements in the TLS array.
  * This includes space for pthread keys and our own internal slots.
diff --git a/libc/private/thread_private.h b/libc/private/thread_private.h
index f731181..724808a 100644
--- a/libc/private/thread_private.h
+++ b/libc/private/thread_private.h
@@ -7,6 +7,8 @@
 
 #include <pthread.h>
 
+__BEGIN_DECLS
+
 /*
  * This file defines the thread library interface to libc.  Thread
  * libraries must implement the functions described here for proper
@@ -31,10 +33,18 @@
 #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
 	pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock )
 
-void	_thread_atexit_lock(void);
-void	_thread_atexit_unlock(void);
+__LIBC_HIDDEN__ void	_thread_atexit_lock(void);
+__LIBC_HIDDEN__ void	_thread_atexit_unlock(void);
 
 #define _ATEXIT_LOCK() _thread_atexit_lock()
 #define _ATEXIT_UNLOCK() _thread_atexit_unlock()
 
+__LIBC_HIDDEN__ void    _thread_arc4_lock(void);
+__LIBC_HIDDEN__ void    _thread_arc4_unlock(void);
+
+#define  _ARC4_LOCK() _thread_arc4_lock()
+#define  _ARC4_UNLOCK() _thread_arc4_unlock()
+
+__END_DECLS
+
 #endif /* _THREAD_PRIVATE_H_ */
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index c607206..05f2faa 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -37,7 +37,6 @@
 #include "atexit.h"
 #include "private/thread_private.h"
 
-int __atexit_invalid = 1;
 struct atexit *__atexit;
 
 /*
@@ -131,8 +130,6 @@
 		    sizeof(p->fns[0]);
 		p->next = __atexit;
 		__atexit = p;
-		if (__atexit_invalid)
-			__atexit_invalid = 0;
 	}
 	fnp = &p->fns[p->ind++];
 	fnp->cxa_func = func;
@@ -159,8 +156,6 @@
 	int n, pgsize = getpagesize(), original_ind;
 	static int call_depth;
 
-	if (__atexit_invalid)
-		return;
 	_ATEXIT_LOCK();
 	call_depth++;
 
diff --git a/libc/stdlib/atexit.h b/libc/stdlib/atexit.h
index 2e88ad6..b530ade 100644
--- a/libc/stdlib/atexit.h
+++ b/libc/stdlib/atexit.h
@@ -45,8 +45,7 @@
 
 __BEGIN_DECLS
 
-extern int __atexit_invalid;
-extern struct atexit *__atexit;		/* points to head of LIFO stack */
+__LIBC_HIDDEN__ extern struct atexit *__atexit;		/* points to head of LIFO stack */
 
 int	__cxa_atexit(void (*)(void *), void *, void *);
 void	__cxa_finalize(void *);
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 0033652..4dd7ab0 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -74,7 +74,7 @@
 #define WILDABBR    "   "
 #endif /* !defined WILDABBR */
 
-static char       wildabbr[] = WILDABBR;
+static const char       wildabbr[] = WILDABBR;
 
 static const char gmt[] = "GMT";
 
@@ -128,16 +128,16 @@
 };
 
 struct rule {
-    int          r_type; /* type of rule--see below */
+    int          r_type; /* type of rule; see below */
     int          r_day;  /* day number of rule */
     int          r_week; /* week number of rule */
     int          r_mon;  /* month number of rule */
     int_fast32_t r_time; /* transition time of rule */
 };
 
-#define JULIAN_DAY            0 /* Jn - Julian day */
-#define DAY_OF_YEAR           1 /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
+#define JULIAN_DAY             0       /* Jn = Julian day */
+#define DAY_OF_YEAR            1       /* n = day of year */
+#define MONTH_NTH_DAY_OF_WEEK  2       /* Mm.n.d = month, week, day of week */
 
 /*
 ** Prototypes for static functions.
@@ -158,10 +158,10 @@
 static const char * getoffset(const char * strp, int_fast32_t * offsetp);
 static const char * getrule(const char * strp, struct rule * rulep);
 static void     gmtload(struct state * sp);
-static struct tm *  gmtsub(const time_t * timep, const int_fast32_t offset,
-                struct tm * tmp, const struct state * sp); // android-changed: added sp.
+static struct tm *  gmtsub(const time_t * timep, int_fast32_t offset,
+                struct tm * tmp, struct state * sp); // android-changed: added sp.
 static struct tm *  localsub(const time_t * timep, int_fast32_t offset,
-                struct tm * tmp, const struct state * sp); // android-changed: added sp.
+                struct tm * tmp, struct state * sp); // android-changed: added sp.
 static int      increment_overflow(int * number, int delta);
 static int      leaps_thru_end_of(int y) ATTRIBUTE_PURE;
 static int      increment_overflow32(int_fast32_t * number, int delta);
@@ -173,16 +173,16 @@
 static void     settzname(void);
 static time_t       time1(struct tm * tmp,
                 struct tm * (*funcp)(const time_t *,
-                int_fast32_t, struct tm *, const struct state *), // android-changed: added state*.
-                int_fast32_t offset, const struct state * sp); // android-changed: added sp.
-static time_t       time2(struct tm * const tmp,
-                struct tm * (*const funcp)(const time_t *,
-                int_fast32_t, struct tm*, const struct state *), // android-changed: added state*.
-                int_fast32_t offset, int * okayp, const struct state * sp); // android-changed: added sp.
+                int_fast32_t, struct tm *, struct state *), // android-changed: added state*.
+                int_fast32_t, struct state * sp); // android-changed: added sp.
+static time_t       time2(struct tm * tmp,
+                struct tm * (*funcp)(const time_t *,
+                int_fast32_t, struct tm*, struct state *), // android-changed: added state*.
+                int_fast32_t offset, int * okayp, struct state * sp); // android-changed: added sp.
 static time_t       time2sub(struct tm *tmp,
                 struct tm * (*funcp) (const time_t *,
-                int_fast32_t, struct tm*, const struct state *), // android-changed: added state*.
-                int_fast32_t offset, int * okayp, int do_norm_secs, const struct state * sp); // android-change: added sp.
+                int_fast32_t, struct tm*, struct state *), // android-changed: added state*.
+                int_fast32_t offset, int * okayp, int do_norm_secs, struct state * sp); // android-change: added sp.
 static struct tm *  timesub(const time_t * timep, int_fast32_t offset,
                 const struct state * sp, struct tm * tmp);
 static int      tmcomp(const struct tm * atmp,
@@ -217,8 +217,8 @@
 static int  gmt_is_set;
 
 char * tzname[2] = {
-    wildabbr,
-    wildabbr
+    (char *) wildabbr,
+    (char *) wildabbr
 };
 
 /*
@@ -270,8 +270,7 @@
     register struct state * const sp = lclptr;
     register int                  i;
 
-    tzname[0] = wildabbr;
-    tzname[1] = wildabbr;
+    tzname[0] = tzname[1] = (char *) wildabbr;
 #ifdef USG_COMPAT
     daylight = 0;
     timezone = 0;
@@ -279,12 +278,10 @@
 #ifdef ALTZONE
     altzone = 0;
 #endif /* defined ALTZONE */
-#ifdef ALL_STATE
     if (sp == NULL) {
         tzname[0] = tzname[1] = (char *) gmt;
         return;
     }
-#endif /* defined ALL_STATE */
     /*
     ** And to get the latest zone names into tzname. . .
     */
@@ -356,25 +353,50 @@
                       2 * sizeof *sp +
                       4 * TZ_MAX_TIMES];
     } u_t;
-#ifdef ALL_STATE
-    register u_t *        up;
+    union local_storage {
+        /*
+        ** Section 4.9.1 of the C standard says that
+        ** "FILENAME_MAX expands to an integral constant expression
+        ** that is the size needed for an array of char large enough
+        ** to hold the longest file name string that the implementation
+        ** guarantees can be opened."
+        */
+        //char            fullname[FILENAME_MAX + 1];
 
-    up = (u_t *) calloc(1, sizeof *up);
-    if (up == NULL)
+        /* The main part of the storage for this function.  */
+        struct {
+            u_t u;
+            struct state st;
+        } u;
+    };
+    //register char *fullname;
+    register u_t *up;
+    register union local_storage *lsp;
+#ifdef ALL_STATE
+    lsp = malloc(sizeof *lsp);
+    if (!lsp)
         return -1;
 #else /* !defined ALL_STATE */
-    u_t                   u;
-    register u_t * const  up = &u;
+    union local_storage ls;
+    lsp = &ls;
 #endif /* !defined ALL_STATE */
+    //fullname = lsp->fullname;
+    up = &lsp->u.u;
 
     sp->goback = sp->goahead = FALSE;
-    if (name == NULL && (name = TZDEFAULT) == NULL)
-        goto oops;
+
+    if (! name) {
+        name = TZDEFAULT;
+        if (! name)
+            goto oops;
+    }
+
     int toread;
     fid = __bionic_open_tzdata(name, &toread);
     if (fid < 0)
         goto oops;
-    nread = read(fid, up->buf, toread);
+
+    nread = read(fid, up->buf, sizeof up->buf);
     if (close(fid) < 0 || nread <= 0)
         goto oops;
     for (stored = 4; stored <= 8; stored *= 2) {
@@ -506,12 +528,9 @@
     if (doextend && nread > 2 &&
         up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
         sp->typecnt + 2 <= TZ_MAX_TYPES) {
-            struct state * ts = malloc(sizeof *ts);
+            struct state    *ts = &lsp->u.st;
             register int result;
 
-            if (ts == NULL)
-                goto oops;
-
             up->buf[nread - 1] = '\0';
             result = tzparse(&up->buf[1], ts, FALSE);
             if (result == 0 && ts->typecnt == 2 &&
@@ -540,7 +559,6 @@
                     sp->ttis[sp->typecnt++] = ts->ttis[0];
                     sp->ttis[sp->typecnt++] = ts->ttis[1];
             }
-            free(ts);
     }
     if (sp->timecnt > 1) {
         for (i = 1; i < sp->timecnt; ++i)
@@ -712,10 +730,10 @@
     int num;
 
     /*
-    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
+    ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
     ** "M10.4.6/26", which does not conform to Posix,
     ** but which specifies the equivalent of
-    ** ``02:00 on the first Sunday on or after 23 Oct''.
+    ** "02:00 on the first Sunday on or after 23 Oct".
     */
     strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
     if (strp == NULL)
@@ -729,7 +747,7 @@
         *secsp += num * SECSPERMIN;
         if (*strp == ':') {
             ++strp;
-            /* `SECSPERMIN' allows for leap seconds. */
+            /* 'SECSPERMIN' allows for leap seconds. */
             strp = getnum(strp, &num, 0, SECSPERMIN);
             if (strp == NULL)
                 return NULL;
@@ -927,7 +945,6 @@
     register int         load_result;
     static struct ttinfo zttinfo;
 
-    INITIALIZE(dstname);
     stdname = name;
     if (lastditch) {
         stdlen = strlen(name);  /* length of standard zone name */
@@ -1005,6 +1022,7 @@
             sp->ttis[1].tt_gmtoff = -stdoffset;
             sp->ttis[1].tt_isdst = 0;
             sp->ttis[1].tt_abbrind = 0;
+            sp->defaulttype = 0;
             timecnt = 0;
             janfirst = 0;
             yearlim = EPOCH_YEAR + YEARSPERREPEAT;
@@ -1130,6 +1148,7 @@
             sp->ttis[1].tt_isdst = TRUE;
             sp->ttis[1].tt_abbrind = stdlen + 1;
             sp->typecnt = 2;
+            sp->defaulttype = 0;
         }
     } else {
         dstlen = 0;
@@ -1139,6 +1158,7 @@
         sp->ttis[0].tt_gmtoff = -stdoffset;
         sp->ttis[0].tt_isdst = 0;
         sp->ttis[0].tt_abbrind = 0;
+        sp->defaulttype = 0;
     }
     sp->charcnt = stdlen + 1;
     if (dstlen != 0)
@@ -1179,7 +1199,7 @@
 
 #ifdef ALL_STATE
     if (lclptr == NULL) {
-        lclptr = calloc(1, sizeof *lclptr);
+        lclptr = malloc(sizeof *lclptr);
         if (lclptr == NULL) {
             settzname();    /* all we can do */
             return;
@@ -1196,7 +1216,7 @@
 static void
 tzset_locked(void)
 {
-    register const char * name = NULL;
+    register const char * name;
 
     name = getenv("TZ");
 
@@ -1219,7 +1239,7 @@
 
 #ifdef ALL_STATE
     if (lclptr == NULL) {
-        lclptr = calloc(1, sizeof *lclptr);
+        lclptr = malloc(sizeof *lclptr);
         if (lclptr == NULL) {
             settzname();    /* all we can do */
             return;
@@ -1263,7 +1283,7 @@
 /*ARGSUSED*/
 static struct tm *
 localsub(const time_t * const timep, const int_fast32_t offset,
-         struct tm * const tmp, const struct state * sp) // android-changed: added sp.
+         struct tm * const tmp, struct state * sp) // android-changed: added sp.
 {
     register const struct ttinfo * ttisp;
     register int         i;
@@ -1275,10 +1295,8 @@
         sp = lclptr;
     }
     // END android-changed
-#ifdef ALL_STATE
     if (sp == NULL)
         return gmtsub(timep, offset, tmp, sp); // android-changed: added sp.
-#endif /* defined ALL_STATE */
     if ((sp->goback && t < sp->ats[0]) ||
         (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
             time_t          newt = t;
@@ -1371,18 +1389,18 @@
 
 static struct tm *
 gmtsub(const time_t * const timep, const int_fast32_t offset,
-       struct tm *const tmp, const struct state * sp) // android-changed: added sp.
+       struct tm *const tmp, struct state * sp __unused) // android-changed: added sp.
 {
     register struct tm * result;
 
-    (void) sp; // android-added: unused.
-
     if (!gmt_is_set) {
-        gmt_is_set = TRUE;
 #ifdef ALL_STATE
-        gmtptr = calloc(1, sizeof *gmtptr);
-        if (gmtptr != NULL)
+        gmtptr = malloc(sizeof *gmtptr);
+        gmt_is_set = gmtptr != NULL;
+#else
+        gmt_is_set = TRUE;
 #endif /* defined ALL_STATE */
+        if (gmt_is_set)
             gmtload(gmtptr);
     }
     result = timesub(timep, offset, gmtptr, tmp);
@@ -1392,18 +1410,7 @@
     ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
     ** but this is no time for a treasure hunt.
     */
-    if (offset != 0)
-        tmp->TM_ZONE = wildabbr;
-    else {
-#ifdef ALL_STATE
-        if (gmtptr == NULL)
-            tmp->TM_ZONE = gmt;
-        else    tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
-        tmp->TM_ZONE = gmtptr->chars;
-#endif /* State Farm */
-    }
+    tmp->TM_ZONE = offset ? wildabbr : gmtptr ? gmtptr->chars : gmt;
 #endif /* defined TM_ZONE */
     return result;
 }
@@ -1430,6 +1437,16 @@
     return result;
 }
 
+#ifdef STD_INSPIRED
+
+struct tm *
+offtime(const time_t *const timep, const long offset)
+{
+    return gmtsub(timep, offset, &tmGlobal, NULL); // android-changed: extra parameter.
+}
+
+#endif /* defined STD_INSPIRED */
+
 /*
 ** Return the number of leap years through the end of the given year
 ** where, to make the math easy, the answer for year zero is defined as zero.
@@ -1459,12 +1476,7 @@
 
     corr = 0;
     hit = 0;
-#ifdef ALL_STATE
     i = (sp == NULL) ? 0 : sp->leapcnt;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
-    i = sp->leapcnt;
-#endif /* State Farm */
     while (--i >= 0) {
         lp = &sp->lsis[i];
         if (*timep >= lp->ls_trans) {
@@ -1699,10 +1711,10 @@
 
 static time_t
 time2sub(struct tm * const tmp,
-         struct tm *(*const funcp)(const time_t*, int_fast32_t, struct tm*, const struct state*),
+         struct tm *(*const funcp)(const time_t*, int_fast32_t, struct tm*, struct state*),
          const int_fast32_t offset,
          int * const okayp,
-         const int do_norm_secs, const struct state * sp) // android-changed: added sp
+         const int do_norm_secs, struct state * sp) // android-changed: added sp
 {
     register int          dir;
     register int          i, j;
@@ -1837,14 +1849,12 @@
         */
         // BEGIN android-changed: support user-supplied sp
         if (sp == NULL) {
-            sp = (const struct state *)
+            sp = (struct state *)
                 ((funcp == localsub) ? lclptr : gmtptr);
         }
         // END android-changed
-#ifdef ALL_STATE
         if (sp == NULL)
             return WRONG;
-#endif /* defined ALL_STATE */
         for (i = sp->typecnt - 1; i >= 0; --i) {
             if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
                 continue;
@@ -1880,9 +1890,9 @@
 
 static time_t
 time2(struct tm * const tmp,
-      struct tm * (*const funcp)(const time_t *, int_fast32_t, struct tm *, const struct state *), // android-changed: added sp.
+      struct tm * (*const funcp)(const time_t *, int_fast32_t, struct tm *, struct state *), // android-changed: added sp.
       const int_fast32_t offset,
-      int *const okayp, const struct state* sp) // android-changed: added sp.
+      int *const okayp, struct state* sp) // android-changed: added sp.
 {
     time_t t;
 
@@ -1897,16 +1907,16 @@
 
 static time_t
 time1(struct tm * const tmp,
-      struct tm * (* const funcp) (const time_t *, int_fast32_t, struct tm *, const struct state *), // android-changed: added sp.
-      const int_fast32_t offset, const struct state * sp) // android-changed: added sp.
+      struct tm * (* const funcp) (const time_t *, int_fast32_t, struct tm *, struct state *), // android-changed: added sp.
+      const int_fast32_t offset, struct state * sp) // android-changed: added sp.
 {
     register time_t t;
     register int    samei, otheri;
     register int    sameind, otherind;
     register int    i;
     register int    nseen;
-    int             seen[TZ_MAX_TYPES];
-    int             types[TZ_MAX_TYPES];
+    char            seen[TZ_MAX_TYPES];
+    unsigned char   types[TZ_MAX_TYPES];
     int             okay;
 
     if (tmp == NULL) {
@@ -1916,17 +1926,15 @@
     if (tmp->tm_isdst > 1)
         tmp->tm_isdst = 1;
     t = time2(tmp, funcp, offset, &okay, sp); // android-changed: added sp.
-#ifdef PCTS
-    /*
-    ** PCTS code courtesy Grant Sullivan.
-    */
     if (okay)
         return t;
     if (tmp->tm_isdst < 0)
+#ifdef PCTS
+        /*
+        ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
+        */
         tmp->tm_isdst = 0;  /* reset to std and try again */
-#endif /* defined PCTS */
-#ifndef PCTS
-    if (okay || tmp->tm_isdst < 0)
+#else
         return t;
 #endif /* !defined PCTS */
     /*
@@ -1937,13 +1945,11 @@
     */
     // BEGIN android-changed: support user-supplied sp.
     if (sp == NULL) {
-        sp = (const struct state *) ((funcp == localsub) ?  lclptr : gmtptr);
+        sp = (struct state *) ((funcp == localsub) ?  lclptr : gmtptr);
     }
     // BEGIN android-changed
-#ifdef ALL_STATE
     if (sp == NULL)
         return WRONG;
-#endif /* defined ALL_STATE */
     for (i = 0; i < sp->typecnt; ++i)
         seen[i] = FALSE;
     nseen = 0;
@@ -2008,6 +2014,14 @@
     return result;
 }
 
+time_t
+timeoff(struct tm *const tmp, const long offset)
+{
+    if (tmp != NULL)
+        tmp->tm_isdst = 0;
+    return time1(tmp, gmtsub, offset, NULL); // android-changed: extra parameter.
+}
+
 #endif /* defined STD_INSPIRED */
 
 #ifdef CMUCS
@@ -2279,7 +2293,7 @@
 }
 
 // Non-standard API: mktime(3) but with an explicit timezone parameter.
-time_t mktime_tz(struct tm* const tmp, const char* tz) {
+time_t __attribute__((visibility("default"))) mktime_tz(struct tm* const tmp, const char* tz) {
   struct state* st = malloc(sizeof(*st));
   time_t return_value;
 
@@ -2296,7 +2310,7 @@
 }
 
 // Non-standard API: localtime(3) but with an explicit timezone parameter.
-void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
+void __attribute__((visibility("default"))) localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
   struct state* st = malloc(sizeof(*st));
 
   if (st == NULL)
diff --git a/libc/tzcode/private.h b/libc/tzcode/private.h
index 4eb0ab6..c30c711 100644
--- a/libc/tzcode/private.h
+++ b/libc/tzcode/private.h
@@ -19,7 +19,7 @@
 
 /*
 ** Defaults for preprocessor symbols.
-** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+** You can override these in your C compiler options, e.g. '-DHAVE_ADJTIME=0'.
 */
 
 #ifndef HAVE_ADJTIME
@@ -62,9 +62,11 @@
 #define HAVE_UTMPX_H		0
 #endif /* !defined HAVE_UTMPX_H */
 
+#if !defined(__ANDROID__)
 #ifndef LOCALE_HOME
 #define LOCALE_HOME		"/usr/lib/locale"
 #endif /* !defined LOCALE_HOME */
+#endif // __ANDROID__
 
 #if HAVE_INCOMPATIBLE_CTIME_R
 #define asctime_r _incompatible_asctime_r
@@ -120,8 +122,9 @@
 */
 #ifndef HAVE_STDINT_H
 #define HAVE_STDINT_H \
-	(199901 <= __STDC_VERSION__ || \
-	2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+   (199901 <= __STDC_VERSION__ \
+    || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__)	\
+    || __CYGWIN__)
 #endif /* !defined HAVE_STDINT_H */
 
 #if HAVE_STDINT_H
@@ -205,6 +208,10 @@
 #define INT32_MIN (-1 - INT32_MAX)
 #endif /* !defined INT32_MIN */
 
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
+
 #if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
 # define ATTRIBUTE_CONST __attribute__ ((const))
 # define ATTRIBUTE_PURE __attribute__ ((__pure__))
@@ -347,29 +354,15 @@
 ** INITIALIZE(x)
 */
 
-#ifndef GNUC_or_lint
 #ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */
-#ifndef lint
-#ifdef __GNUC__
-#define GNUC_or_lint
-#endif /* defined __GNUC__ */
-#endif /* !defined lint */
-#endif /* !defined GNUC_or_lint */
-
-#ifndef INITIALIZE
-#ifdef GNUC_or_lint
-#define INITIALIZE(x)	((x) = 0)
-#endif /* defined GNUC_or_lint */
-#ifndef GNUC_or_lint
-#define INITIALIZE(x)
-#endif /* !defined GNUC_or_lint */
-#endif /* !defined INITIALIZE */
+# define INITIALIZE(x)	((x) = 0)
+#else
+# define INITIALIZE(x)
+#endif
 
 /*
 ** For the benefit of GNU folk...
-** `_(MSGID)' uses the current locale's message library string for MSGID.
+** '_(MSGID)' uses the current locale's message library string for MSGID.
 ** The default is to use gettext if available, and use MSGID otherwise.
 */
 
@@ -381,9 +374,9 @@
 #endif /* !HAVE_GETTEXT */
 #endif /* !defined _ */
 
-#ifndef TZ_DOMAIN
-#define TZ_DOMAIN "tz"
-#endif /* !defined TZ_DOMAIN */
+#if !defined TZ_DOMAIN && defined TZ_DOMAINDIR
+# define TZ_DOMAIN "tz"
+#endif
 
 #if HAVE_INCOMPATIBLE_CTIME_R
 #undef asctime_r
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 967629d..f996f48 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -1,12 +1,9 @@
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)strftime.c 8.1";
 /*
-** Based on the UCB version with the ID appearing below.
+** Based on the UCB version with the copyright notice and sccsid
+** appearing below.
+**
 ** This is ANSIish only when "multibyte character == plain character".
 */
-#endif /* !defined NOID */
-#endif /* !defined lint */
 
 #include "private.h"
 
@@ -22,35 +19,27 @@
 ** by the University of California, Berkeley. The name of the
 ** University may not be used to endorse or promote products derived
 ** from this software without specific prior written permission.
-** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+** THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
 ** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
 
-#ifndef LIBC_SCCS
-#ifndef lint
-static const char   sccsid[] = "@(#)strftime.c  5.4 (Berkeley) 3/14/89";
-#endif /* !defined lint */
-#endif /* !defined LIBC_SCCS */
-
 #include "tzfile.h"
 #include "fcntl.h"
 #include "locale.h"
-#include <ctype.h>
+
+#if __ANDROID__
+/* Android: struct lc_time_T is defined as strftime_locale in "bionic_time.h" */
+#include "private/bionic_time.h"  /* for strftime_tz */
+#define  lc_time_T    strftime_locale
 #if defined(__LP64__)
 #define time64_t time_t
 #define mktime64 mktime
 #else
 #include <time64.h>
 #endif
-#include "private/bionic_time.h"  /* for strftime_tz */
-
-/* struct lc_time_T is now defined as strftime_locale
- * in <time.h>
- */
-#if 1
-#define  lc_time_T    strftime_locale
-#else
+#include <ctype.h>
+#else // not __ANDROID__
 struct lc_time_T {
     const char *    mon[MONSPERYEAR];
     const char *    month[MONSPERYEAR];
@@ -65,7 +54,15 @@
 };
 #endif
 
+#if LOCALE_HOME
+#include "sys/stat.h"
+static struct lc_time_T                localebuf;
+static struct lc_time_T *      _loc(void);
+#define Locale _loc()
+#endif /* defined LOCALE_HOME */
+#ifndef LOCALE_HOME
 #define Locale  (&C_time_locale)
+#endif /* !defined LOCALE_HOME */
 
 static const struct lc_time_T   C_time_locale = {
     {
@@ -147,7 +144,7 @@
 }
 
 size_t
-strftime_tz(s, maxsize, format, t, locale)
+__attribute__((visibility("default"))) strftime_tz(s, maxsize, format, t, locale)
 char * const        s;
 const size_t        maxsize;
 const char * const  format;
diff --git a/libc/upstream-freebsd/lib/libc/stdio/mktemp.c b/libc/upstream-freebsd/lib/libc/stdio/mktemp.c
deleted file mode 100644
index 58783dd..0000000
--- a/libc/upstream-freebsd/lib/libc/stdio/mktemp.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "namespace.h"
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "un-namespace.h"
-
-char *_mktemp(char *);
-
-static int _gettemp(char *, int *, int, int);
-
-static const unsigned char padchar[] =
-"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-int
-mkstemps(char *path, int slen)
-{
-	int fd;
-
-	return (_gettemp(path, &fd, 0, slen) ? fd : -1);
-}
-
-int
-mkstemp(char *path)
-{
-	int fd;
-
-	return (_gettemp(path, &fd, 0, 0) ? fd : -1);
-}
-
-char *
-mkdtemp(char *path)
-{
-	return (_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
-}
-
-char *
-_mktemp(char *path)
-{
-	return (_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
-}
-
-__warn_references(mktemp,
-    "warning: mktemp() possibly used unsafely; consider using mkstemp()");
-
-char *
-mktemp(char *path)
-{
-	return (_mktemp(path));
-}
-
-static int
-_gettemp(char *path, int *doopen, int domkdir, int slen)
-{
-	char *start, *trv, *suffp, *carryp;
-	char *pad;
-	struct stat sbuf;
-	int rval;
-	uint32_t rand;
-	char carrybuf[MAXPATHLEN];
-
-	if ((doopen != NULL && domkdir) || slen < 0) {
-		errno = EINVAL;
-		return (0);
-	}
-
-	for (trv = path; *trv != '\0'; ++trv)
-		;
-	if (trv - path >= MAXPATHLEN) {
-		errno = ENAMETOOLONG;
-		return (0);
-	}
-	trv -= slen;
-	suffp = trv;
-	--trv;
-	if (trv < path || NULL != strchr(suffp, '/')) {
-		errno = EINVAL;
-		return (0);
-	}
-
-	/* Fill space with random characters */
-	while (trv >= path && *trv == 'X') {
-		rand = arc4random_uniform(sizeof(padchar) - 1);
-		*trv-- = padchar[rand];
-	}
-	start = trv + 1;
-
-	/* save first combination of random characters */
-	memcpy(carrybuf, start, suffp - start);
-
-	/*
-	 * check the target directory.
-	 */
-	if (doopen != NULL || domkdir) {
-		for (; trv > path; --trv) {
-			if (*trv == '/') {
-				*trv = '\0';
-				rval = stat(path, &sbuf);
-				*trv = '/';
-				if (rval != 0)
-					return (0);
-				if (!S_ISDIR(sbuf.st_mode)) {
-					errno = ENOTDIR;
-					return (0);
-				}
-				break;
-			}
-		}
-	}
-
-	for (;;) {
-		if (doopen) {
-			if ((*doopen =
-			    _open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
-				return (1);
-			if (errno != EEXIST)
-				return (0);
-		} else if (domkdir) {
-			if (mkdir(path, 0700) == 0)
-				return (1);
-			if (errno != EEXIST)
-				return (0);
-		} else if (lstat(path, &sbuf))
-			return (errno == ENOENT);
-
-		/* If we have a collision, cycle through the space of filenames */
-		for (trv = start, carryp = carrybuf;;) {
-			/* have we tried all possible permutations? */
-			if (trv == suffp)
-				return (0); /* yes - exit with EEXIST */
-			pad = strchr(padchar, *trv);
-			if (pad == NULL) {
-				/* this should never happen */
-				errno = EIO;
-				return (0);
-			}
-			/* increment character */
-			*trv = (*++pad == '\0') ? padchar[0] : *pad;
-			/* carry to next position? */
-			if (*trv == *carryp) {
-				/* increment position and loop */
-				++trv;
-				++carryp;
-			} else {
-				/* try with new name */
-				break;
-			}
-		}
-	}
-	/*NOTREACHED*/
-}
diff --git a/libc/include/sys/sha1.h b/libc/upstream-netbsd/android/include/sys/sha1.h
similarity index 100%
rename from libc/include/sys/sha1.h
rename to libc/upstream-netbsd/android/include/sys/sha1.h
diff --git a/libc/upstream-netbsd/lib/libc/include/resolv_mt.h b/libc/upstream-netbsd/lib/libc/include/resolv_mt.h
new file mode 100644
index 0000000..73a8dcc
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/include/resolv_mt.h
@@ -0,0 +1,49 @@
+/*	$NetBSD: resolv_mt.h,v 1.1.1.3 2009/04/12 16:35:44 christos Exp $	*/
+
+#ifndef _RESOLV_MT_H
+#define _RESOLV_MT_H
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+/* Access functions for the libresolv private interface */
+
+int	__res_enable_mt(void);
+int	__res_disable_mt(void);
+
+/* Per-thread context */
+
+typedef struct {
+int	no_hosts_fallback_private;
+int	retry_save;
+int	retry_private;
+char	inet_nsap_ntoa_tmpbuf[255*3];
+char	sym_ntos_unname[20];
+char	sym_ntop_unname[20];
+char	p_option_nbuf[40];
+char	p_time_nbuf[40];
+char	precsize_ntoa_retbuf[sizeof "90000000.00"];
+char	loc_ntoa_tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+char	p_secstodate_output[15];
+} mtctxres_t;
+
+/* Thread-specific data (TSD) */
+
+mtctxres_t	*___mtctxres(void);
+#define mtctxres	(___mtctxres())
+
+/* Various static data that should be TSD */
+
+#define sym_ntos_unname		(mtctxres->sym_ntos_unname)
+#define sym_ntop_unname		(mtctxres->sym_ntop_unname)
+#define inet_nsap_ntoa_tmpbuf	(mtctxres->inet_nsap_ntoa_tmpbuf)
+#define p_option_nbuf		(mtctxres->p_option_nbuf)
+#define p_time_nbuf		(mtctxres->p_time_nbuf)
+#define precsize_ntoa_retbuf	(mtctxres->precsize_ntoa_retbuf)
+#define loc_ntoa_tmpbuf		(mtctxres->loc_ntoa_tmpbuf)
+#define p_secstodate_output	(mtctxres->p_secstodate_output)
+
+#endif /* _RESOLV_MT_H */
diff --git a/libc/dns/inet/nsap_addr.c b/libc/upstream-netbsd/lib/libc/inet/nsap_addr.c
similarity index 81%
rename from libc/dns/inet/nsap_addr.c
rename to libc/upstream-netbsd/lib/libc/inet/nsap_addr.c
index 4deabac..8633205 100644
--- a/libc/dns/inet/nsap_addr.c
+++ b/libc/upstream-netbsd/lib/libc/inet/nsap_addr.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: nsap_addr.c,v 1.2 2004/05/20 23:12:33 christos Exp $	*/
+/*	$NetBSD: nsap_addr.c,v 1.6 2009/04/12 17:07:17 christos Exp $	*/
 
 /*
  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
@@ -20,12 +20,15 @@
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
 #if 0
-static const char rcsid[] = "Id: nsap_addr.c,v 1.2.206.1 2004/03/09 08:33:33 marka Exp";
+static const char rcsid[] = "Id: nsap_addr.c,v 1.5 2005/07/28 06:51:48 marka Exp";
 #else
-__RCSID("$NetBSD: nsap_addr.c,v 1.2 2004/05/20 23:12:33 christos Exp $");
+__RCSID("$NetBSD: nsap_addr.c,v 1.6 2009/04/12 17:07:17 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
+#include "port_before.h"
+
+#include "namespace.h"
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -36,10 +39,14 @@
 
 #include <assert.h>
 #include <ctype.h>
-#ifdef ANDROID_CHANGES
-#include "resolv_private.h"
-#else
 #include <resolv.h>
+#include <resolv_mt.h>
+
+#include "port_after.h"
+
+#ifdef __weak_alias
+__weak_alias(inet_nsap_addr,_inet_nsap_addr)
+__weak_alias(inet_nsap_ntoa,_inet_nsap_ntoa)
 #endif
 
 static char
@@ -52,8 +59,8 @@
 	u_char c, nib;
 	u_int len = 0;
 
-	assert(ascii != NULL);
-	assert(binary != NULL);
+	_DIAGASSERT(ascii != NULL);
+	_DIAGASSERT(binary != NULL);
 
 	if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X'))
 		return (0);
@@ -90,10 +97,10 @@
 inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) {
 	int nib;
 	int i;
-	static char tmpbuf[2+255*3];
+	char *tmpbuf = inet_nsap_ntoa_tmpbuf;
 	char *start;
 
-	assert(binary != NULL);
+	_DIAGASSERT(binary != NULL);
 
 	if (ascii)
 		start = ascii;
@@ -119,3 +126,5 @@
 	*ascii = '\0';
 	return (start);
 }
+
+/*! \file */
diff --git a/libc/upstream-netbsd/lib/libc/resolv/mtctxres.c b/libc/upstream-netbsd/lib/libc/resolv/mtctxres.c
new file mode 100644
index 0000000..6e3281a
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/resolv/mtctxres.c
@@ -0,0 +1,130 @@
+/*	$NetBSD: mtctxres.c,v 1.4 2007/03/30 20:40:52 ghen Exp $	*/
+
+#include <port_before.h>
+#ifdef DO_PTHREADS
+#include <pthread.h>
+#endif
+#include <errno.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <resolv_mt.h>
+#include <port_after.h>
+
+#ifdef DO_PTHREADS
+static pthread_key_t	key;
+static int		mt_key_initialized = 0;
+
+static int		__res_init_ctx(void);
+static void		__res_destroy_ctx(void *);
+
+#if defined(sun) && !defined(__GNUC__)
+#pragma init	(_mtctxres_init)
+#endif
+#endif
+
+static mtctxres_t	sharedctx;
+
+#ifdef DO_PTHREADS
+/*
+ * Initialize the TSD key. By doing this at library load time, we're
+ * implicitly running without interference from other threads, so there's
+ * no need for locking.
+ */
+static void
+_mtctxres_init(void) {
+	int pthread_keycreate_ret;
+
+	pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
+	if (pthread_keycreate_ret == 0)
+		mt_key_initialized = 1;
+}
+#endif
+
+/*
+ * To support binaries that used the private MT-safe interface in
+ * Solaris 8, we still need to provide the __res_enable_mt()
+ * and __res_disable_mt() entry points. They're do-nothing routines.
+ */
+int
+__res_enable_mt(void) {
+	return (-1);
+}
+
+int
+__res_disable_mt(void) {
+	return (0);
+}
+
+#ifdef DO_PTHREADS
+static int
+__res_init_ctx(void) {
+
+	mtctxres_t	*mt;
+	int		ret;
+
+
+	if (pthread_getspecific(key) != 0) {
+		/* Already exists */
+		return (0);
+	}
+
+	if ((mt = malloc(sizeof (mtctxres_t))) == 0) {
+		errno = ENOMEM;
+		return (-1);
+	}
+
+	memset(mt, 0, sizeof (mtctxres_t));
+
+	if ((ret = pthread_setspecific(key, mt)) != 0) {
+		free(mt);
+		errno = ret;
+		return (-1);
+	}
+
+	return (0);
+}
+
+static void
+__res_destroy_ctx(void *value) {
+
+	mtctxres_t	*mt = (mtctxres_t *)value;
+
+	if (mt != 0)
+		free(mt);
+}
+#endif
+
+mtctxres_t *
+___mtctxres(void) {
+#ifdef DO_PTHREADS
+	mtctxres_t	*mt;
+
+	/*
+	 * This if clause should only be executed if we are linking
+	 * statically.  When linked dynamically _mtctxres_init() should
+	 * be called at binding time due the #pragma above.
+	 */
+	if (!mt_key_initialized) {
+		static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
+                if (pthread_mutex_lock(&keylock) == 0) {
+			_mtctxres_init();
+			(void) pthread_mutex_unlock(&keylock);
+		}
+	}
+
+	/*
+	 * If we have already been called in this thread return the existing
+	 * context.  Otherwise recreat a new context and return it.  If
+	 * that fails return a global context.
+	 */
+	if (mt_key_initialized) {
+		if (((mt = pthread_getspecific(key)) != 0) ||
+		    (__res_init_ctx() == 0 &&
+		     (mt = pthread_getspecific(key)) != 0)) {
+			return (mt);
+		}
+	}
+#endif
+	return (&sharedctx);
+}
diff --git a/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h b/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h
new file mode 100644
index 0000000..7c3680f
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h
@@ -0,0 +1,222 @@
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
+typedef struct
+{
+  u32 input[16]; /* could be compressed */
+} chacha_ctx;
+
+#define U8C(v) (v##U)
+#define U32C(v) (v##U)
+
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+
+#define ROTL32(v, n) \
+  (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define U8TO32_LITTLE(p) \
+  (((u32)((p)[0])      ) | \
+   ((u32)((p)[1]) <<  8) | \
+   ((u32)((p)[2]) << 16) | \
+   ((u32)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+  do { \
+    (p)[0] = U8V((v)      ); \
+    (p)[1] = U8V((v) >>  8); \
+    (p)[2] = U8V((v) >> 16); \
+    (p)[3] = U8V((v) >> 24); \
+  } while (0)
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+static void
+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
+{
+  const char *constants;
+
+  x->input[4] = U8TO32_LITTLE(k + 0);
+  x->input[5] = U8TO32_LITTLE(k + 4);
+  x->input[6] = U8TO32_LITTLE(k + 8);
+  x->input[7] = U8TO32_LITTLE(k + 12);
+  if (kbits == 256) { /* recommended */
+    k += 16;
+    constants = sigma;
+  } else { /* kbits == 128 */
+    constants = tau;
+  }
+  x->input[8] = U8TO32_LITTLE(k + 0);
+  x->input[9] = U8TO32_LITTLE(k + 4);
+  x->input[10] = U8TO32_LITTLE(k + 8);
+  x->input[11] = U8TO32_LITTLE(k + 12);
+  x->input[0] = U8TO32_LITTLE(constants + 0);
+  x->input[1] = U8TO32_LITTLE(constants + 4);
+  x->input[2] = U8TO32_LITTLE(constants + 8);
+  x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *x,const u8 *iv)
+{
+  x->input[12] = 0;
+  x->input[13] = 0;
+  x->input[14] = U8TO32_LITTLE(iv + 0);
+  x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+static void
+chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
+{
+  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+  u8 *ctarget = NULL;
+  u8 tmp[64];
+  u_int i;
+
+  if (!bytes) return;
+
+  j0 = x->input[0];
+  j1 = x->input[1];
+  j2 = x->input[2];
+  j3 = x->input[3];
+  j4 = x->input[4];
+  j5 = x->input[5];
+  j6 = x->input[6];
+  j7 = x->input[7];
+  j8 = x->input[8];
+  j9 = x->input[9];
+  j10 = x->input[10];
+  j11 = x->input[11];
+  j12 = x->input[12];
+  j13 = x->input[13];
+  j14 = x->input[14];
+  j15 = x->input[15];
+
+  for (;;) {
+    if (bytes < 64) {
+      for (i = 0;i < bytes;++i) tmp[i] = m[i];
+      m = tmp;
+      ctarget = c;
+      c = tmp;
+    }
+    x0 = j0;
+    x1 = j1;
+    x2 = j2;
+    x3 = j3;
+    x4 = j4;
+    x5 = j5;
+    x6 = j6;
+    x7 = j7;
+    x8 = j8;
+    x9 = j9;
+    x10 = j10;
+    x11 = j11;
+    x12 = j12;
+    x13 = j13;
+    x14 = j14;
+    x15 = j15;
+    for (i = 20;i > 0;i -= 2) {
+      QUARTERROUND( x0, x4, x8,x12)
+      QUARTERROUND( x1, x5, x9,x13)
+      QUARTERROUND( x2, x6,x10,x14)
+      QUARTERROUND( x3, x7,x11,x15)
+      QUARTERROUND( x0, x5,x10,x15)
+      QUARTERROUND( x1, x6,x11,x12)
+      QUARTERROUND( x2, x7, x8,x13)
+      QUARTERROUND( x3, x4, x9,x14)
+    }
+    x0 = PLUS(x0,j0);
+    x1 = PLUS(x1,j1);
+    x2 = PLUS(x2,j2);
+    x3 = PLUS(x3,j3);
+    x4 = PLUS(x4,j4);
+    x5 = PLUS(x5,j5);
+    x6 = PLUS(x6,j6);
+    x7 = PLUS(x7,j7);
+    x8 = PLUS(x8,j8);
+    x9 = PLUS(x9,j9);
+    x10 = PLUS(x10,j10);
+    x11 = PLUS(x11,j11);
+    x12 = PLUS(x12,j12);
+    x13 = PLUS(x13,j13);
+    x14 = PLUS(x14,j14);
+    x15 = PLUS(x15,j15);
+
+#ifndef KEYSTREAM_ONLY
+    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
+    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
+    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
+    x3 = XOR(x3,U8TO32_LITTLE(m + 12));
+    x4 = XOR(x4,U8TO32_LITTLE(m + 16));
+    x5 = XOR(x5,U8TO32_LITTLE(m + 20));
+    x6 = XOR(x6,U8TO32_LITTLE(m + 24));
+    x7 = XOR(x7,U8TO32_LITTLE(m + 28));
+    x8 = XOR(x8,U8TO32_LITTLE(m + 32));
+    x9 = XOR(x9,U8TO32_LITTLE(m + 36));
+    x10 = XOR(x10,U8TO32_LITTLE(m + 40));
+    x11 = XOR(x11,U8TO32_LITTLE(m + 44));
+    x12 = XOR(x12,U8TO32_LITTLE(m + 48));
+    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
+    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
+    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+#endif
+
+    j12 = PLUSONE(j12);
+    if (!j12) {
+      j13 = PLUSONE(j13);
+      /* stopping at 2^70 bytes per nonce is user's responsibility */
+    }
+
+    U32TO8_LITTLE(c + 0,x0);
+    U32TO8_LITTLE(c + 4,x1);
+    U32TO8_LITTLE(c + 8,x2);
+    U32TO8_LITTLE(c + 12,x3);
+    U32TO8_LITTLE(c + 16,x4);
+    U32TO8_LITTLE(c + 20,x5);
+    U32TO8_LITTLE(c + 24,x6);
+    U32TO8_LITTLE(c + 28,x7);
+    U32TO8_LITTLE(c + 32,x8);
+    U32TO8_LITTLE(c + 36,x9);
+    U32TO8_LITTLE(c + 40,x10);
+    U32TO8_LITTLE(c + 44,x11);
+    U32TO8_LITTLE(c + 48,x12);
+    U32TO8_LITTLE(c + 52,x13);
+    U32TO8_LITTLE(c + 56,x14);
+    U32TO8_LITTLE(c + 60,x15);
+
+    if (bytes <= 64) {
+      if (bytes < 64) {
+        for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+      }
+      x->input[12] = j12;
+      x->input[13] = j13;
+      return;
+    }
+    bytes -= 64;
+    c += 64;
+#ifndef KEYSTREAM_ONLY
+    m += 64;
+#endif
+  }
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
new file mode 100644
index 0000000..cb154c4
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
@@ -0,0 +1,143 @@
+/*	$OpenBSD: mktemp.c,v 1.33 2014/05/06 22:55:27 millert Exp $ */
+/*
+ * Copyright (c) 1996-1998, 2008 Theo de Raadt
+ * Copyright (c) 1997, 2008-2009 Todd C. Miller
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#define MKTEMP_NAME	0
+#define MKTEMP_FILE	1
+#define MKTEMP_DIR	2
+
+#define TEMPCHARS	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+#define NUM_CHARS	(sizeof(TEMPCHARS) - 1)
+#define MIN_X		6
+
+#ifndef nitems
+#define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+static int
+mktemp_internal(char *path, int slen, int mode)
+{
+	char *start, *cp, *ep;
+	const char *tempchars = TEMPCHARS;
+	unsigned int tries;
+	struct stat sb;
+	size_t len;
+	int fd;
+
+	len = strlen(path);
+	if (len < MIN_X || slen < 0 || (size_t)slen > len - MIN_X) {
+		errno = EINVAL;
+		return(-1);
+	}
+	ep = path + len - slen;
+
+	for (start = ep; start > path && start[-1] == 'X'; start--)
+		;
+	if (ep - start < MIN_X) {
+		errno = EINVAL;
+		return(-1);
+	}
+
+	tries = INT_MAX;
+	do {
+		cp = start;
+		do {
+			unsigned short rbuf[16];
+			unsigned int i;
+
+			/*
+			 * Avoid lots of arc4random() calls by using
+			 * a buffer sized for up to 16 Xs at a time.
+			 */
+			arc4random_buf(rbuf, sizeof(rbuf));
+			for (i = 0; i < nitems(rbuf) && cp != ep; i++)
+				*cp++ = tempchars[rbuf[i] % NUM_CHARS];
+		} while (cp != ep);
+
+		switch (mode) {
+		case MKTEMP_NAME:
+			if (lstat(path, &sb) != 0)
+				return(errno == ENOENT ? 0 : -1);
+			break;
+		case MKTEMP_FILE:
+			fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
+			if (fd != -1 || errno != EEXIST)
+				return(fd);
+			break;
+		case MKTEMP_DIR:
+			if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0)
+				return(0);
+			if (errno != EEXIST)
+				return(-1);
+			break;
+		}
+	} while (--tries);
+
+	errno = EEXIST;
+	return(-1);
+}
+
+char *_mktemp(char *);
+
+char *
+_mktemp(char *path)
+{
+	if (mktemp_internal(path, 0, MKTEMP_NAME) == -1)
+		return(NULL);
+	return(path);
+}
+
+__warn_references(mktemp,
+    "warning: mktemp() possibly used unsafely; consider using mkstemp()");
+
+char *
+mktemp(char *path)
+{
+	return(_mktemp(path));
+}
+
+int
+mkstemp(char *path)
+{
+	return(mktemp_internal(path, 0, MKTEMP_FILE));
+}
+
+int
+mkstemps(char *path, int slen)
+{
+	return(mktemp_internal(path, slen, MKTEMP_FILE));
+}
+
+char *
+mkdtemp(char *path)
+{
+	int error;
+
+	error = mktemp_internal(path, 0, MKTEMP_DIR);
+	return(error ? NULL : path);
+}
diff --git a/libm/Android.mk b/libm/Android.mk
index 90b4906..994caa0 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -291,5 +291,12 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 LOCAL_WHOLE_STATIC_LIBRARIES := libm
+
+# We'd really like to do this for all architectures, but since this wasn't done
+# before, these symbols must continue to be exported on LP32 for binary
+# compatibility.
+LOCAL_LDFLAGS_arm64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_mips64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_x86_64 := -Wl,--exclude-libs,libgcc.a
 include $(BUILD_SHARED_LIBRARY)
 endif
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 6d63ad6..efb829e 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -100,30 +100,23 @@
 
   soinfo* found = NULL;
   ElfW(Sym)* sym = NULL;
-  if (handle == RTLD_DEFAULT || handle == (void*)0xffffffffL) {
-    sym = dlsym_linear_lookup(symbol, &found, NULL);
-  } else if (handle == RTLD_NEXT || handle == (void*)0xfffffffeL) {
-    void* caller_addr = __builtin_return_address(0);
-    soinfo* si = find_containing_library(caller_addr);
+  void* caller_addr = __builtin_return_address(0);
+  soinfo* caller_si = find_containing_library(caller_addr);
 
+  if (handle == RTLD_DEFAULT) {
+    sym = dlsym_linear_lookup(symbol, &found, NULL, caller_si);
+  } else if (handle == RTLD_NEXT) {
     sym = NULL;
-    if (si && si->next) {
-      sym = dlsym_linear_lookup(symbol, &found, si->next);
+    if (caller_si && caller_si->next) {
+      sym = dlsym_linear_lookup(symbol, &found, caller_si->next, caller_si);
     }
   } else {
     found = reinterpret_cast<soinfo*>(handle);
-    sym = dlsym_handle_lookup(found, symbol);
+    sym = dlsym_handle_lookup(found, symbol, caller_si);
   }
 
-  if (sym != NULL) {
-    unsigned bind = ELF_ST_BIND(sym->st_info);
-
-    if (bind == STB_GLOBAL && sym->st_shndx != 0) {
-      return reinterpret_cast<void*>(sym->st_value + found->load_bias);
-    }
-
-    __bionic_format_dlerror("symbol found but not global", symbol);
-    return NULL;
+  if (sym != NULL && sym->st_shndx != 0) {
+    return reinterpret_cast<void*>(sym->st_value + found->load_bias);
   } else {
     __bionic_format_dlerror("undefined symbol", symbol);
     return NULL;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index a22233d..506c3f2 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -42,6 +42,7 @@
 #include "private/bionic_tls.h"
 #include "private/KernelArgumentBlock.h"
 #include "private/ScopedPthreadMutexLocker.h"
+#include "private/ScopedFd.h"
 
 #include "linker.h"
 #include "linker_debug.h"
@@ -124,6 +125,11 @@
     kRelocMax
 };
 
+enum class SymbolLookupScope {
+  kAllowLocal,
+  kExcludeLocal,
+};
+
 #if STATS
 struct linker_stats_t {
     int count[kRelocMax];
@@ -162,10 +168,7 @@
 #define DISALLOW_ALLOCATION(return_type, name, ...) \
     return_type name __VA_ARGS__ \
     { \
-        const char* msg = "ERROR: " #name " called from the dynamic linker!\n"; \
-        __libc_format_log(ANDROID_LOG_FATAL, "linker", "%s", msg); \
-        write(2, msg, strlen(msg)); \
-        abort(); \
+        __libc_fatal("ERROR: " #name " called from the dynamic linker!\n"); \
     }
 DISALLOW_ALLOCATION(void*, malloc, (size_t u __unused));
 DISALLOW_ALLOCATION(void, free, (void* u __unused));
@@ -430,7 +433,7 @@
     return rv;
 }
 
-static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {
+static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name, const SymbolLookupScope& lookup_scope) {
   ElfW(Sym)* symtab = si->symtab;
   const char* strtab = si->strtab;
 
@@ -441,18 +444,28 @@
     ElfW(Sym)* s = symtab + n;
     if (strcmp(strtab + s->st_name, name)) continue;
 
-    /* only concern ourselves with global and weak symbol definitions */
     switch (ELF_ST_BIND(s->st_info)) {
       case STB_GLOBAL:
       case STB_WEAK:
         if (s->st_shndx == SHN_UNDEF) {
-        continue;
-      }
+          continue;
+        }
 
-      TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
+        TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
                  name, si->name, reinterpret_cast<void*>(s->st_value),
                  static_cast<size_t>(s->st_size));
-      return s;
+        return s;
+      case STB_LOCAL:
+        if (lookup_scope != SymbolLookupScope::kAllowLocal) {
+          continue;
+        }
+        TRACE_TYPE(LOOKUP, "FOUND LOCAL %s in %s (%p) %zd",
+                name, si->name, reinterpret_cast<void*>(s->st_value),
+                static_cast<size_t>(s->st_size));
+        return s;
+      default:
+        __libc_fatal("ERROR: Unexpected ST_BIND value: %d for '%s' in '%s'",
+            ELF_ST_BIND(s->st_info), name, si->name);
     }
   }
 
@@ -483,7 +496,7 @@
          */
 
         if (si == somain) {
-            s = soinfo_elf_lookup(si, elf_hash, name);
+            s = soinfo_elf_lookup(si, elf_hash, name, SymbolLookupScope::kAllowLocal);
             if (s != NULL) {
                 *lsi = si;
                 goto done;
@@ -500,7 +513,7 @@
             if (!si->has_DT_SYMBOLIC) {
                 DEBUG("%s: looking up %s in executable %s",
                       si->name, name, somain->name);
-                s = soinfo_elf_lookup(somain, elf_hash, name);
+                s = soinfo_elf_lookup(somain, elf_hash, name, SymbolLookupScope::kExcludeLocal);
                 if (s != NULL) {
                     *lsi = somain;
                     goto done;
@@ -517,7 +530,7 @@
              * and some the first non-weak definition.   This is system dependent.
              * Here we return the first definition found for simplicity.  */
 
-            s = soinfo_elf_lookup(si, elf_hash, name);
+            s = soinfo_elf_lookup(si, elf_hash, name, SymbolLookupScope::kAllowLocal);
             if (s != NULL) {
                 *lsi = si;
                 goto done;
@@ -531,7 +544,7 @@
             if (si->has_DT_SYMBOLIC) {
                 DEBUG("%s: looking up %s in executable %s after local scope",
                       si->name, name, somain->name);
-                s = soinfo_elf_lookup(somain, elf_hash, name);
+                s = soinfo_elf_lookup(somain, elf_hash, name, SymbolLookupScope::kExcludeLocal);
                 if (s != NULL) {
                     *lsi = somain;
                     goto done;
@@ -542,7 +555,7 @@
 
     /* Next, look for it in the preloads list */
     for (int i = 0; g_ld_preloads[i] != NULL; i++) {
-        s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
+        s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name, SymbolLookupScope::kExcludeLocal);
         if (s != NULL) {
             *lsi = g_ld_preloads[i];
             goto done;
@@ -552,7 +565,7 @@
     for (int i = 0; needed[i] != NULL; i++) {
         DEBUG("%s: looking up %s in %s",
               si->name, name, needed[i]->name);
-        s = soinfo_elf_lookup(needed[i], elf_hash, name);
+        s = soinfo_elf_lookup(needed[i], elf_hash, name, SymbolLookupScope::kExcludeLocal);
         if (s != NULL) {
             *lsi = needed[i];
             goto done;
@@ -581,8 +594,9 @@
    Binary Interface) where in Chapter 5 it discuss resolving "Shared
    Object Dependencies" in breadth first search order.
  */
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name) {
-    return soinfo_elf_lookup(si, elfhash(name), name);
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller) {
+    return soinfo_elf_lookup(si, elfhash(name), name,
+        caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
 }
 
 /* This is used by dlsym(3) to performs a global symbol lookup. If the
@@ -590,7 +604,7 @@
    beginning of the global solist. Otherwise the search starts at the
    specified soinfo (for RTLD_NEXT).
  */
-ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) {
+ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start, soinfo* caller) {
   unsigned elf_hash = elfhash(name);
 
   if (start == NULL) {
@@ -599,7 +613,8 @@
 
   ElfW(Sym)* s = NULL;
   for (soinfo* si = start; (s == NULL) && (si != NULL); si = si->next) {
-    s = soinfo_elf_lookup(si, elf_hash, name);
+    s = soinfo_elf_lookup(si, elf_hash, name,
+        caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
     if (s != NULL) {
       *found = si;
       break;
@@ -668,8 +683,7 @@
     }
     // ...but nvidia binary blobs (at least) rely on this behavior, so fall through for now.
 #if defined(__LP64__)
-    // TODO: uncomment this after bug b/7465467 is fixed.
-    // return -1;
+    return -1;
 #endif
   }
 
@@ -682,11 +696,20 @@
 }
 
 static soinfo* load_library(const char* name, int dlflags, const android_dlextinfo* extinfo) {
-    // Open the file.
-    int fd = open_library(name);
-    if (fd == -1) {
+    int fd = -1;
+    ScopedFd file_guard(-1);
+
+    if (extinfo != NULL && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
+      fd = extinfo->library_fd;
+    } else {
+      // Open the file.
+      fd = open_library(name);
+      if (fd == -1) {
         DL_ERR("library \"%s\" not found", name);
         return NULL;
+      }
+
+      file_guard.reset(fd);
     }
 
     ElfReader elf_reader(name, fd);
@@ -730,7 +753,7 @@
 
     // At this point we know that whatever is loaded @ base is a valid ELF
     // shared library whose segments are properly mapped in.
-    TRACE("[ find_library_internal base=%p size=%zu name='%s' ]",
+    TRACE("[ load_library base=%p size=%zu name='%s' ]",
           reinterpret_cast<void*>(si->base), si->size, si->name);
 
     if (!soinfo_link_image(si, extinfo)) {
@@ -1863,10 +1886,8 @@
     if (si->has_text_relocations) {
         // Make segments writable to allow text relocations to work properly. We will later call
         // phdr_table_protect_segments() after all of them are applied and all constructors are run.
-#if !defined(__i386__) // The platform itself has too many text relocations on x86.
         DL_WARN("%s has text relocations. This is wasting memory and prevents "
                 "security hardening. Please fix.", si->name);
-#endif
         if (phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias) < 0) {
             DL_ERR("can't unprotect loadable segments for \"%s\": %s",
                    si->name, strerror(errno));
diff --git a/linker/linker.h b/linker/linker.h
index 0a72d92..e1112e6 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -234,11 +234,11 @@
 soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
 void do_dlclose(soinfo* si);
 
-ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start);
+ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start, soinfo* caller_si);
 soinfo* find_containing_library(const void* addr);
 
 ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr);
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name);
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller_si);
 
 void debuggerd_init();
 extern "C" abort_msg_t* g_abort_message;
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 12e9779..11585af 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -127,9 +127,6 @@
 }
 
 ElfReader::~ElfReader() {
-  if (fd_ != -1) {
-    close(fd_);
-  }
   if (phdr_mmap_ != NULL) {
     munmap(phdr_mmap_, phdr_size_);
   }
diff --git a/linker/tests/Android.mk b/linker/tests/Android.mk
index 683f9ee..fe64e77 100644
--- a/linker/tests/Android.mk
+++ b/linker/tests/Android.mk
@@ -19,7 +19,6 @@
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
-LOCAL_MULTILIB := both
 LOCAL_MODULE := linker-unit-tests
 LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
 LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 6433d55..bb00648 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -21,14 +21,15 @@
 ifeq ($(build_type),host)
 # Always make host multilib
 LOCAL_MULTILIB := both
-else
-LOCAL_MULTILIB := $($(module)_multilib)
 endif
 
 ifneq ($(findstring LIBRARY, $(build_target)),LIBRARY)
-ifeq ($(LOCAL_MULTILIB),both)
     LOCAL_MODULE_STEM_32 := $(module)32
     LOCAL_MODULE_STEM_64 := $(module)64
+else
+ifeq ($($(module)_install_to_out_data),true)
+    LOCAL_MODULE_PATH_32 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(module)
+    LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)64/$(module)
 endif
 endif
 
diff --git a/tests/Android.mk b/tests/Android.mk
index 47e6272..278511b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -244,8 +244,8 @@
     dlext_test.cpp \
     dlfcn_test.cpp \
 
-bionic-unit-tests_cppflags := \
-    $(test_cppflags)
+bionic-unit-tests_cflags := $(test_cflags)
+bionic-unit-tests_cppflags := $(test_cppflags)
 
 bionic-unit-tests_ldflags := \
     -Wl,--export-dynamic \
@@ -260,7 +260,6 @@
 
 module := bionic-unit-tests
 module_tag := optional
-bionic-unit-tests_multilib := both
 build_type := target
 build_target := NATIVE_TEST
 include $(LOCAL_PATH)/Android.build.mk
@@ -282,7 +281,6 @@
 
 module := bionic-unit-tests-static
 module_tag := optional
-bionic-unit-tests-static_multilib := both
 build_type := target
 build_target := NATIVE_TEST
 include $(LOCAL_PATH)/Android.build.mk
@@ -303,12 +301,11 @@
 bionic-unit-tests-glibc_ldlibs := \
     -lrt -ldl \
 
-bionic-unit-tests-glibc_cppflags := \
-    $(test_cppflags)
+bionic-unit-tests-glibc_cflags := $(test_cflags)
+bionic-unit-tests-glibc_cppflags := $(test_cppflags)
 
 module := bionic-unit-tests-glibc
 module_tag := optional
-bionic-unit-tests-glibc_multilib := both
 build_type := host
 build_target := NATIVE_TEST
 include $(LOCAL_PATH)/Android.build.mk
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index b56fc41..da63046 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -45,6 +45,11 @@
 #define LIBNAME_NORELRO "libdlext_test_norelro.so"
 #define LIBSIZE 1024*1024 // how much address space to reserve for it
 
+#if defined(__LP64__)
+#define LIBPATH "%s/nativetest64/libdlext_test_fd/libdlext_test_fd.so"
+#else
+#define LIBPATH "%s/nativetest/libdlext_test_fd/libdlext_test_fd.so"
+#endif
 
 class DlExtTest : public ::testing::Test {
 protected:
@@ -83,6 +88,23 @@
   EXPECT_EQ(4, f());
 }
 
+TEST_F(DlExtTest, ExtInfoUseFd) {
+  const char* android_data = getenv("ANDROID_DATA");
+  ASSERT_TRUE(android_data != NULL);
+  char lib_path[PATH_MAX];
+  snprintf(lib_path, sizeof(lib_path), LIBPATH, android_data);
+
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
+  extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path, O_RDONLY | O_CLOEXEC));
+  ASSERT_TRUE(extinfo.library_fd != -1);
+  handle_ = android_dlopen_ext(lib_path, RTLD_NOW, &extinfo);
+  ASSERT_DL_NOTNULL(handle_);
+  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+  ASSERT_DL_NOTNULL(f);
+  EXPECT_EQ(4, f());
+}
+
 TEST_F(DlExtTest, Reserved) {
   void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
                      -1, 0);
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 49cbb7d..a79263d 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -50,6 +50,25 @@
   ASSERT_EQ(0, dlclose(self));
 }
 
+#if !defined(__LP64__)
+// Current compiler/static linker used for aarch64
+// platform optimizes LOCAL PROTECTED symbol
+// in libtest_local_symbol.so out of existence
+TEST(dlfcn, dlsym_local_symbol) {
+  void* handle = dlopen("libtest_local_symbol.so", RTLD_NOW);
+  ASSERT_TRUE(handle != NULL);
+  dlerror();
+  void* sym = dlsym(handle, "private_taxicab_number");
+  ASSERT_TRUE(sym == NULL);
+  ASSERT_STREQ("undefined symbol: private_taxicab_number", dlerror());
+
+  uint32_t (*f)(void);
+  f = reinterpret_cast<uint32_t (*)(void)>(dlsym(handle, "dlsym_local_symbol_get_taxicab_number_using_dlsym"));
+  ASSERT_TRUE(f != NULL);
+  ASSERT_EQ(1729U, f());
+}
+#endif
+
 TEST(dlfcn, dlopen_noload) {
   void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
   ASSERT_TRUE(handle == NULL);
@@ -254,6 +273,18 @@
   ASSERT_TRUE(addr != NULL);
 }
 
+TEST(dlfcn, dlsym_weak_func) {
+  dlerror();
+  void* handle = dlopen("libtest_dlsym_weak_func.so",RTLD_NOW);
+  ASSERT_TRUE(handle != NULL);
+
+  int (*weak_func)();
+  weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func"));
+  ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror();
+  EXPECT_EQ(42, weak_func());
+  dlclose(handle);
+}
+
 TEST(dlfcn, dlopen_symlink) {
   void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
   void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW);
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index fb6b07e..5f20295 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -132,3 +132,87 @@
 
   close(fd);
 }
+
+TEST(fcntl, splice) {
+  int pipe_fds[2];
+  ASSERT_EQ(0, pipe(pipe_fds));
+
+  int in = open("/proc/cpuinfo", O_RDONLY);
+  ASSERT_NE(in, -1);
+
+  TemporaryFile tf;
+
+  ssize_t bytes_read = splice(in, 0, pipe_fds[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE);
+  ASSERT_NE(bytes_read, -1);
+
+  ssize_t bytes_written = splice(pipe_fds[0], NULL, tf.fd, 0, bytes_read, SPLICE_F_MORE | SPLICE_F_MOVE);
+  ASSERT_EQ(bytes_read, bytes_written);
+
+  close(pipe_fds[0]);
+  close(pipe_fds[1]);
+  close(in);
+}
+
+TEST(fcntl, vmsplice) {
+  int pipe_fds[2];
+  ASSERT_EQ(0, pipe(pipe_fds));
+
+  iovec v[2];
+  v[0].iov_base = const_cast<char*>("hello ");
+  v[0].iov_len = 6;
+  v[1].iov_base = const_cast<char*>("world\n");
+  v[1].iov_len = 6;
+  ssize_t bytes_written = vmsplice(pipe_fds[1], v, sizeof(v)/sizeof(iovec), 0);
+  ASSERT_EQ(v[0].iov_len + v[1].iov_len, static_cast<size_t>(bytes_written));
+  close(pipe_fds[1]);
+
+  char buf[BUFSIZ];
+  FILE* fp = fdopen(pipe_fds[0], "r");
+  ASSERT_TRUE(fp != NULL);
+  ASSERT_TRUE(fgets(buf, sizeof(buf), fp) != NULL);
+  fclose(fp);
+  ASSERT_STREQ("hello world\n", buf);
+}
+
+TEST(fcntl, tee) {
+  char expected[256];
+  FILE* expected_fp = fopen("/proc/version", "r");
+  ASSERT_TRUE(expected_fp != NULL);
+  ASSERT_TRUE(fgets(expected, sizeof(expected), expected_fp) != NULL);
+  fclose(expected_fp);
+
+  int pipe1[2];
+  ASSERT_EQ(0, pipe(pipe1));
+
+  int pipe2[2];
+  ASSERT_EQ(0, pipe(pipe2));
+
+  int in = open("/proc/version", O_RDONLY);
+  ASSERT_NE(in, -1);
+
+  // Write /proc/version into pipe1.
+  ssize_t bytes_read = splice(in, 0, pipe1[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE);
+  ASSERT_NE(bytes_read, -1);
+  close(pipe1[1]);
+
+  // Tee /proc/version from pipe1 into pipe2.
+  ssize_t bytes_teed = tee(pipe1[0], pipe2[1], SIZE_MAX, 0);
+  ASSERT_EQ(bytes_read, bytes_teed);
+  close(pipe2[1]);
+
+  // The out fds of both pipe1 and pipe2 should now contain /proc/version.
+  char buf1[BUFSIZ];
+  FILE* fp1 = fdopen(pipe1[0], "r");
+  ASSERT_TRUE(fp1 != NULL);
+  ASSERT_TRUE(fgets(buf1, sizeof(buf1), fp1) != NULL);
+  fclose(fp1);
+
+  char buf2[BUFSIZ];
+  FILE* fp2 = fdopen(pipe2[0], "r");
+  ASSERT_TRUE(fp2 != NULL);
+  ASSERT_TRUE(fgets(buf2, sizeof(buf2), fp2) != NULL);
+  fclose(fp2);
+
+  ASSERT_STREQ(expected, buf1);
+  ASSERT_STREQ(expected, buf2);
+}
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index e75582d..a374e48 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -78,6 +78,19 @@
 include $(TEST_PATH)/Android.build.mk
 
 # -----------------------------------------------------------------------------
+# Library used by dlext tests - different name non-default location
+# -----------------------------------------------------------------------------
+libdlext_test_fd_src_files := \
+    dlext_test_library.cpp \
+
+libdlext_test_fd_install_to_out_data := true
+module := libdlext_test_fd
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
 # Library used by dlfcn tests
 # -----------------------------------------------------------------------------
 libtest_simple_src_files := \
@@ -88,6 +101,20 @@
 build_target := SHARED_LIBRARY
 include $(TEST_PATH)/Android.build.mk
 
+# -----------------------------------------------------------------------------
+# Library used to test local symbol lookup
+# -----------------------------------------------------------------------------
+libtest_local_symbol_src_files := \
+    dlsym_local_symbol_private.cpp \
+    dlsym_local_symbol_public.cpp
+
+module := libtest_local_symbol
+build_target := SHARED_LIBRARY
+libtest_local_symbol_ldflags := -Wl,--version-script=$(LOCAL_PATH)/dlsym_local_symbol.map
+libtest_local_symbol_cppflags := -std=gnu++11
+libtest_local_symbol_shared_libraries_target := libdl
+build_type := target
+include $(TEST_PATH)/Android.build.mk
 
 # -----------------------------------------------------------------------------
 # Library used by atexit tests
@@ -103,3 +130,15 @@
 build_type := host
 include $(TEST_PATH)/Android.build.mk
 
+# -----------------------------------------------------------------------------
+# Library with weak function
+# -----------------------------------------------------------------------------
+libtest_dlsym_weak_func_src_files := \
+    dlsym_weak_function.cpp
+
+module := libtest_dlsym_weak_func
+build_target := SHARED_LIBRARY
+build_type := target
+include $(TEST_PATH)/Android.build.mk
+build_type := host
+include $(TEST_PATH)/Android.build.mk
diff --git a/libc/include/sha1.h b/tests/libs/dlsym_local_symbol.map
similarity index 72%
copy from libc/include/sha1.h
copy to tests/libs/dlsym_local_symbol.map
index 7f6cf5d..58a2299 100644
--- a/libc/include/sha1.h
+++ b/tests/libs/dlsym_local_symbol.map
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,11 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#ifndef _SHA1_H_
-#define _SHA1_H_
-
-#warning "include <sys/sha1.h> instead for better portability"
-#include <sys/sha1.h>
-
-#endif
+LIBTEST_LOCAL_SYMBOL_1.0 {
+  global:
+    dlsym_local_symbol_get_taxicab_number;
+    dlsym_local_symbol_get_taxicab_number_using_dlsym;
+  local:
+    *;
+};
diff --git a/libc/include/sha1.h b/tests/libs/dlsym_local_symbol_private.cpp
similarity index 61%
copy from libc/include/sha1.h
copy to tests/libs/dlsym_local_symbol_private.cpp
index 7f6cf5d..2587508 100644
--- a/libc/include/sha1.h
+++ b/tests/libs/dlsym_local_symbol_private.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef _SHA1_H_
-#define _SHA1_H_
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
 
-#warning "include <sys/sha1.h> instead for better portability"
-#include <sys/sha1.h>
-
-#endif
+// This symbol is declared local in
+// the linker version map: libdlsym_local_symbol.map.
+// It should not be visible from the outside.
+extern "C" const uint32_t __attribute__ ((visibility ("protected"))) private_taxicab_number = 1729;
diff --git a/tests/libs/dlsym_local_symbol_public.cpp b/tests/libs/dlsym_local_symbol_public.cpp
new file mode 100644
index 0000000..d9da32a
--- /dev/null
+++ b/tests/libs/dlsym_local_symbol_public.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+extern const uint32_t private_taxicab_number;
+
+extern "C" {
+uint32_t dlsym_local_symbol_get_taxicab_number();
+uint32_t dlsym_local_symbol_get_taxicab_number_using_dlsym();
+}
+
+uint32_t dlsym_local_symbol_get_taxicab_number() {
+  return private_taxicab_number;
+}
+
+// Let's make sure that dlsym works correctly for local symbol
+uint32_t dlsym_local_symbol_get_taxicab_number_using_dlsym() {
+  dlerror();
+  uint32_t* ptr = reinterpret_cast<uint32_t*>(dlsym(RTLD_DEFAULT, "private_taxicab_number"));
+  if (ptr == nullptr) {
+    const char* dlerr = dlerror();
+    if (dlerr != nullptr) {
+      fprintf(stderr, "dlsym error: %s\n", dlerr);
+    } else {
+      fprintf(stderr, "dlsym returned NULL with no dlerror.\n");
+    }
+    return 0;
+  }
+
+  return *ptr;
+}
diff --git a/libc/include/sha1.h b/tests/libs/dlsym_weak_function.cpp
similarity index 75%
rename from libc/include/sha1.h
rename to tests/libs/dlsym_weak_function.cpp
index 7f6cf5d..e38f2b8 100644
--- a/libc/include/sha1.h
+++ b/tests/libs/dlsym_weak_function.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _SHA1_H_
-#define _SHA1_H_
+extern "C" int __attribute__((weak)) weak_func() {
+  return 42;
+}
 
-#warning "include <sys/sha1.h> instead for better portability"
-#include <sys/sha1.h>
-
-#endif
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 0f42d43..36da481 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -69,6 +69,19 @@
 #endif // __BIONIC__
 }
 
+TEST(pthread, pthread_key_delete) {
+  void* expected = reinterpret_cast<void*>(1234);
+  pthread_key_t key;
+  ASSERT_EQ(0, pthread_key_create(&key, NULL));
+  ASSERT_EQ(0, pthread_setspecific(key, expected));
+  ASSERT_EQ(expected, pthread_getspecific(key));
+  ASSERT_EQ(0, pthread_key_delete(key));
+  // After deletion, pthread_getspecific returns NULL.
+  ASSERT_EQ(NULL, pthread_getspecific(key));
+  // And you can't use pthread_setspecific with the deleted key.
+  ASSERT_EQ(EINVAL, pthread_setspecific(key, expected));
+}
+
 static void* IdFn(void* arg) {
   return arg;
 }
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 2ab60d7..bc2c05b 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -359,6 +359,24 @@
   EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s)));
 }
 
+TEST(string, strchr_multiple) {
+  char str[128];
+  memset(str, 'a', sizeof(str) - 1);
+  str[sizeof(str)-1] = '\0';
+
+  // Verify that strchr finds the first occurrence of 'a' in a string
+  // filled with 'a' characters. Iterate over the string putting
+  // non 'a' characters at the front of the string during each iteration
+  // and continue to verify that strchr can find the first occurrence
+  // properly. The idea is to cover all possible alignments of the location
+  // of the first occurrence of the 'a' character and which includes
+  // other 'a' characters close by.
+  for (size_t i = 0; i < sizeof(str) - 1; i++) {
+    EXPECT_EQ(&str[i], strchr(str, 'a'));
+    str[i] = 'b';
+  }
+}
+
 TEST(string, strchr) {
   int seek_char = random() & 255;
 
@@ -1235,3 +1253,29 @@
 TEST(string, memcmp_overread) {
   RunCmpBufferOverreadTest(DoMemcmpTest, DoMemcmpFailTest);
 }
+
+static void DoStrchrTest(uint8_t* buf, size_t len) {
+  if (len >= 1) {
+    char value = 32 + (len % 96);
+    char search_value = 33 + (len % 96);
+    memset(buf, value, len - 1);
+    buf[len-1] = '\0';
+    ASSERT_EQ(NULL, strchr(reinterpret_cast<char*>(buf), search_value));
+    ASSERT_EQ(reinterpret_cast<char*>(&buf[len-1]), strchr(reinterpret_cast<char*>(buf), '\0'));
+    if (len >= 2) {
+      buf[0] = search_value;
+      ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf), search_value));
+      buf[0] = value;
+      buf[len-2] = search_value;
+      ASSERT_EQ(reinterpret_cast<char*>(&buf[len-2]), strchr(reinterpret_cast<char*>(buf), search_value));
+    }
+  }
+}
+
+TEST(string, strchr_align) {
+  RunSingleBufferAlignTest(MEDIUM, DoStrchrTest);
+}
+
+TEST(string, strchr_overread) {
+  RunSingleBufferOverreadTest(DoStrchrTest);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6aa259a..58c9ad9 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -22,6 +22,7 @@
 #include <fcntl.h>
 #include <stdint.h>
 #include <unistd.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -379,3 +380,72 @@
 TEST(unistd, fsync) {
   TestFsyncFunction(fsync);
 }
+
+static void AssertGetPidCorrect() {
+  // The loop is just to make manual testing/debugging with strace easier.
+  pid_t getpid_syscall_result = syscall(__NR_getpid);
+  for (size_t i = 0; i < 128; ++i) {
+    ASSERT_EQ(getpid_syscall_result, getpid());
+  }
+}
+
+TEST(unistd, getpid_caching_and_fork) {
+  pid_t parent_pid = getpid();
+  ASSERT_EQ(syscall(__NR_getpid), parent_pid);
+
+  pid_t fork_result = fork();
+  ASSERT_NE(fork_result, -1);
+  if (fork_result == 0) {
+    // We're the child.
+    AssertGetPidCorrect();
+    ASSERT_EQ(parent_pid, getppid());
+    _exit(123);
+  } else {
+    // We're the parent.
+    ASSERT_EQ(parent_pid, getpid());
+
+    int status;
+    ASSERT_EQ(fork_result, waitpid(fork_result, &status, 0));
+    ASSERT_TRUE(WIFEXITED(status));
+    ASSERT_EQ(123, WEXITSTATUS(status));
+  }
+}
+
+static int GetPidCachingCloneStartRoutine(void*) {
+  AssertGetPidCorrect();
+  return 123;
+}
+
+TEST(unistd, getpid_caching_and_clone) {
+  pid_t parent_pid = getpid();
+  ASSERT_EQ(syscall(__NR_getpid), parent_pid);
+
+  void* child_stack[1024];
+  int clone_result = clone(GetPidCachingCloneStartRoutine, &child_stack[1024], CLONE_NEWNS | SIGCHLD, NULL);
+  ASSERT_NE(clone_result, -1);
+
+  ASSERT_EQ(parent_pid, getpid());
+
+  int status;
+  ASSERT_EQ(clone_result, waitpid(clone_result, &status, 0));
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(123, WEXITSTATUS(status));
+}
+
+static void* GetPidCachingPthreadStartRoutine(void*) {
+  AssertGetPidCorrect();
+  return NULL;
+}
+
+TEST(unistd, getpid_caching_and_pthread_create) {
+  pid_t parent_pid = getpid();
+
+  pthread_t t;
+  ASSERT_EQ(0, pthread_create(&t, NULL, GetPidCachingPthreadStartRoutine, NULL));
+
+  ASSERT_EQ(parent_pid, getpid());
+
+  void* result;
+  ASSERT_EQ(0, pthread_join(t, &result));
+  ASSERT_EQ(NULL, result);
+}