Merge "Remove SHA1 from LP64 in favor of libcrypto."
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 37f3059..1b3965e 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 \
@@ -500,7 +501,7 @@
 
 ifeq ($(MALLOC_IMPL),jemalloc)
   libc_common_cflags += -DUSE_JEMALLOC
-  libc_malloc_src := bionic/jemalloc.cpp
+  libc_malloc_src := bionic/jemalloc_wrapper.cpp
 else
   libc_common_cflags += -DUSE_DLMALLOC
   libc_malloc_src := bionic/dlmalloc.c
@@ -584,7 +585,10 @@
 # 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 \
+    -Werror \
+
 # Don't use ridiculous amounts of stack.
 LOCAL_CFLAGS += -DALL_STATE
 # Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
@@ -596,6 +600,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)
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 369b23c..839cfb7 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
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-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 2d34f52..e44ee31 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -57,7 +57,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..36146bf
--- /dev/null
+++ b/libc/arch-arm64/denver64/denver64.mk
@@ -0,0 +1,10 @@
+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/strcmp.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/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-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-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-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_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/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/getpid.cpp b/libc/bionic/getpid.cpp
new file mode 100644
index 0000000..a3d5b35
--- /dev/null
+++ b/libc/bionic/getpid.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include <unistd.h>
+
+#include "pthread_internal.h"
+
+extern "C" pid_t __getpid();
+
+pid_t getpid() {
+  pthread_internal_t* self = __get_thread();
+
+  // Do we have a valid cached pid?
+  pid_t cached_pid;
+  if (__predict_true(self->get_cached_pid(&cached_pid))) {
+    return cached_pid;
+  }
+
+  // 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/jemalloc.cpp b/libc/bionic/jemalloc_wrapper.cpp
similarity index 77%
rename from libc/bionic/jemalloc.cpp
rename to libc/bionic/jemalloc_wrapper.cpp
index 625d789..d1fe960 100644
--- a/libc/bionic/jemalloc.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/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_common.h b/libc/bionic/malloc_debug_common.h
index a0f9972..fb2f03d 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -37,6 +37,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+#include "private/bionic_config.h"
 #include "private/libc_logging.h"
 
 #define HASHTABLE_SIZE      1543
@@ -61,12 +62,6 @@
 #define Malloc(function)  dl ## function
 #endif
 
-// valloc(3) and pvalloc(3) were removed from POSIX 2004. We do not include them
-// for LP64, but the symbols remain in LP32 for binary compatibility.
-#ifndef __LP64__
-#define HAVE_DEPRECATED_MALLOC_FUNCS 1
-#endif
-
 // =============================================================================
 // Structures
 // =============================================================================
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/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/include/stdio.h b/libc/include/stdio.h
index 62acb3a..e532de4 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -254,7 +254,9 @@
 int vdprintf(int, const char * __restrict, __va_list) __printflike(2, 0);
 
 #ifndef __AUDIT__
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
 char* gets(char*) __warnattr("gets is very unsafe; consider using fgets");
+#endif
 int sprintf(char* __restrict, const char* __restrict, ...)
     __printflike(2, 3) __warnattr("sprintf is often misused; please use snprintf");
 char* tmpnam(char*) __warnattr("tmpnam possibly used unsafely; consider using mkstemp");
diff --git a/libc/include/sys/ioctl.h b/libc/include/sys/ioctl.h
index 49d452c..a1014dc 100644
--- a/libc/include/sys/ioctl.h
+++ b/libc/include/sys/ioctl.h
@@ -38,6 +38,7 @@
 #include <asm/ioctls.h>
 #include <asm/termbits.h>
 #include <sys/ioctl_compat.h>
+#include <linux/tty.h>
 
 __BEGIN_DECLS
 
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/bionic_config.h b/libc/private/bionic_config.h
new file mode 100644
index 0000000..0c9811c
--- /dev/null
+++ b/libc/private/bionic_config.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef _BIONIC_CONFIG_H_
+#define _BIONIC_CONFIG_H_
+
+// valloc(3) and pvalloc(3) were removed from POSIX 2004. We do not include them
+// for LP64, but the symbols remain in LP32 for binary compatibility.
+#if !defined(__LP64__)
+#define HAVE_DEPRECATED_MALLOC_FUNCS 1
+#endif
+
+#endif // _BIONIC_CONFIG_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/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/libm/Android.mk b/libm/Android.mk
index b67395f..90b4906 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -1,3 +1,4 @@
+ifneq ($(TARGET_USE_PRIVATE_LIBM),true)
 LOCAL_PATH:= $(call my-dir)
 
 # TODO: this comes from from upstream's libc, not libm, but it's an
@@ -291,3 +292,4 @@
 LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 LOCAL_WHOLE_STATIC_LIBRARIES := libm
 include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/libstdc++/include/cstdio b/libstdc++/include/cstdio
index 3c8b5c6..2948d85 100644
--- a/libstdc++/include/cstdio
+++ b/libstdc++/include/cstdio
@@ -63,7 +63,9 @@
 using ::fwrite;
 using ::getc;
 using ::getchar;
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
 using ::gets;
+#endif
 using ::perror;
 using ::printf;
 using ::putc;
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 6d63ad6..0b60ef5 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -118,7 +118,7 @@
   if (sym != NULL) {
     unsigned bind = ELF_ST_BIND(sym->st_info);
 
-    if (bind == STB_GLOBAL && sym->st_shndx != 0) {
+    if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
       return reinterpret_cast<void*>(sym->st_value + found->load_bias);
     }
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index a22233d..e202aaf 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -59,6 +59,7 @@
  *
  * open issues / todo:
  *
+ * - are we doing everything we should for ARM_COPY relocations?
  * - cleaner error reporting
  * - after linking, set as much stuff as possible to READONLY
  *   and NOEXEC
@@ -1037,17 +1038,52 @@
         break;
 
     case R_AARCH64_COPY:
-        /*
-         * ET_EXEC is not supported so this should not happen.
-         *
-         * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
-         *
-         * Section 4.7.1.10 "Dynamic relocations"
-         * R_AARCH64_COPY may only appear in executable objects where e_type is
-         * set to ET_EXEC.
-         */
-        DL_ERR("%s R_AARCH64_COPY relocations are not supported", si->name);
-        return -1;
+        if ((si->flags & FLAG_EXE) == 0) {
+            /*
+              * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+              *
+              * Section 4.7.1.10 "Dynamic relocations"
+              * R_AARCH64_COPY may only appear in executable objects where e_type is
+              * set to ET_EXEC.
+              *
+              * FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+              * We should explicitly disallow ET_DYN executables from having
+              * R_AARCH64_COPY relocations.
+              */
+            DL_ERR("%s R_AARCH64_COPY relocations only supported for ET_EXEC", si->name);
+            return -1;
+        }
+        count_relocation(kRelocCopy);
+        MARK(rela->r_offset);
+        TRACE_TYPE(RELO, "RELO COPY %16llx <- %lld @ %16llx %s\n",
+                   reloc,
+                   s->st_size,
+                   (sym_addr + rela->r_addend),
+                   sym_name);
+        if (reloc == (sym_addr + rela->r_addend)) {
+            ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
+
+            if (src == NULL) {
+                DL_ERR("%s R_AARCH64_COPY relocation source cannot be resolved", si->name);
+                return -1;
+            }
+            if (lsi->has_DT_SYMBOLIC) {
+                DL_ERR("%s invalid R_AARCH64_COPY relocation against DT_SYMBOLIC shared "
+                       "library %s (built with -Bsymbolic?)", si->name, lsi->name);
+                return -1;
+            }
+            if (s->st_size < src->st_size) {
+                DL_ERR("%s R_AARCH64_COPY relocation size mismatch (%lld < %lld)",
+                       si->name, s->st_size, src->st_size);
+                return -1;
+            }
+            memcpy(reinterpret_cast<void*>(reloc),
+                   reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
+        } else {
+            DL_ERR("%s R_AARCH64_COPY relocation target cannot be resolved", si->name);
+            return -1;
+        }
+        break;
     case R_AARCH64_TLS_TPREL64:
         TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
                    reloc, (sym_addr + rela->r_addend), rela->r_offset);
@@ -1225,17 +1261,48 @@
             *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
             break;
         case R_ARM_COPY:
-            /*
-             * ET_EXEC is not supported so this should not happen.
-             *
-             * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
-             *
-             * Section 4.7.1.10 "Dynamic relocations"
-             * R_ARM_COPY may only appear in executable objects where e_type is
-             * set to ET_EXEC.
-             */
-            DL_ERR("%s R_ARM_COPY relocations are not supported", si->name);
-            return -1;
+            if ((si->flags & FLAG_EXE) == 0) {
+                /*
+                 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+                 *
+                 * Section 4.7.1.10 "Dynamic relocations"
+                 * R_ARM_COPY may only appear in executable objects where e_type is
+                 * set to ET_EXEC.
+                 *
+                 * TODO: FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+                 * We should explicitly disallow ET_DYN executables from having
+                 * R_ARM_COPY relocations.
+                 */
+                DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", si->name);
+                return -1;
+            }
+            count_relocation(kRelocCopy);
+            MARK(rel->r_offset);
+            TRACE_TYPE(RELO, "RELO %08x <- %d @ %08x %s", reloc, s->st_size, sym_addr, sym_name);
+            if (reloc == sym_addr) {
+                ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
+
+                if (src == NULL) {
+                    DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", si->name);
+                    return -1;
+                }
+                if (lsi->has_DT_SYMBOLIC) {
+                    DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
+                           "library %s (built with -Bsymbolic?)", si->name, lsi->name);
+                    return -1;
+                }
+                if (s->st_size < src->st_size) {
+                    DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
+                           si->name, s->st_size, src->st_size);
+                    return -1;
+                }
+                memcpy(reinterpret_cast<void*>(reloc),
+                       reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
+            } else {
+                DL_ERR("%s R_ARM_COPY relocation target cannot be resolved", si->name);
+                return -1;
+            }
+            break;
 #elif defined(__i386__)
         case R_386_JMP_SLOT:
             count_relocation(kRelocAbsolute);
@@ -2105,11 +2172,13 @@
     si->dynamic = NULL;
     si->ref_count = 1;
 
+#if defined(__LP64__)
     ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
     if (elf_hdr->e_type != ET_DYN) {
         __libc_format_fd(2, "error: only position independent executables (PIE) are supported.\n");
         exit(EXIT_FAILURE);
     }
+#endif
 
     // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
     parse_LD_LIBRARY_PATH(ldpath_env);
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index e65ec16..6433d55 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -36,10 +36,6 @@
 
 LOCAL_FORCE_STATIC_EXECUTABLE := $($(module)_force_static_executable)
 
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-    $(LOCAL_PATH)/Android.mk \
-    $(LOCAL_PATH)/Android.build.mk \
-
 LOCAL_CFLAGS := \
     $(common_cflags) \
     $($(module)_cflags) \
diff --git a/tests/Android.mk b/tests/Android.mk
index ce0c5f2..47e6272 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -233,88 +233,6 @@
 include $(LOCAL_PATH)/Android.build.mk
 
 # -----------------------------------------------------------------------------
-# Library used by dlfcn tests.
-# -----------------------------------------------------------------------------
-ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64))
-no-elf-hash-table-library_src_files := \
-    empty.cpp \
-
-no-elf-hash-table-library_ldflags := \
-    -Wl,--hash-style=gnu \
-
-module := no-elf-hash-table-library
-module_tag := optional
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-endif
-
-# -----------------------------------------------------------------------------
-# Library used by dlext tests - with/without GNU RELRO program header
-# -----------------------------------------------------------------------------
-libdlext_test_src_files := \
-    dlext_test_library.cpp \
-
-libdlext_test_ldflags := \
-    -Wl,-z,relro \
-
-module := libdlext_test
-module_tag := optional
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-
-# -----------------------------------------------------------------------------
-# create symlink to libdlext_test.so for symlink test
-# -----------------------------------------------------------------------------
-# Use = instead of := to defer the evaluation of $@
-$(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD = \
-    $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
-ifneq ($(TARGET_2ND_ARCH),)
-# link 64 bit .so
-$(TARGET_OUT)/lib64/libdlext_test.so: PRIVATE_POST_INSTALL_CMD = \
-    $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
-endif
-
-libdlext_test_norelro_src_files := \
-    dlext_test_library.cpp \
-
-libdlext_test_norelro_ldflags := \
-    -Wl,-z,norelro \
-
-module := libdlext_test_norelro
-module_tag := optional
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-
-# -----------------------------------------------------------------------------
-# Library used by dlfcn tests
-# -----------------------------------------------------------------------------
-libtest_simple_src_files := \
-    dlopen_testlib_simple.cpp
-
-module := libtest_simple
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-
-
-# -----------------------------------------------------------------------------
-# Library used by atexit tests
-# -----------------------------------------------------------------------------
-
-libtest_atexit_src_files := \
-    atexit_testlib.cpp
-
-module := libtest_atexit
-build_target := SHARED_LIBRARY
-build_type := target
-include $(LOCAL_PATH)/Android.build.mk
-build_type := host
-include $(LOCAL_PATH)/Android.build.mk
-
-# -----------------------------------------------------------------------------
 # Tests for the device using bionic's .so. Run with:
 #   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
 # -----------------------------------------------------------------------------
@@ -438,4 +356,5 @@
 
 endif # linux-x86
 
+include $(call first-makefiles-under,$(LOCAL_PATH))
 endif # !BUILD_TINY_ANDROID
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 49cbb7d..8b89183 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -254,6 +254,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/libs/Android.mk b/tests/libs/Android.mk
new file mode 100644
index 0000000..67ea562
--- /dev/null
+++ b/tests/libs/Android.mk
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2012 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+TEST_PATH := $(LOCAL_PATH)/..
+
+# -----------------------------------------------------------------------------
+# Library used by dlfcn tests.
+# -----------------------------------------------------------------------------
+ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64))
+no-elf-hash-table-library_src_files := \
+    empty.cpp \
+
+no-elf-hash-table-library_ldflags := \
+    -Wl,--hash-style=gnu \
+
+module := no-elf-hash-table-library
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+endif
+
+# -----------------------------------------------------------------------------
+# Library used by dlext tests - with GNU RELRO program header
+# -----------------------------------------------------------------------------
+libdlext_test_src_files := \
+    dlext_test_library.cpp \
+
+libdlext_test_ldflags := \
+    -Wl,-z,relro \
+
+module := libdlext_test
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
+# create symlink to libdlext_test.so for symlink test
+# -----------------------------------------------------------------------------
+# Use = instead of := to defer the evaluation of $@
+$(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD = \
+    $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
+
+ifneq ($(TARGET_2ND_ARCH),)
+# link 64 bit .so
+$(TARGET_OUT)/lib64/libdlext_test.so: PRIVATE_POST_INSTALL_CMD = \
+    $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
+endif
+
+# -----------------------------------------------------------------------------
+# Library used by dlext tests - without GNU RELRO program header
+# -----------------------------------------------------------------------------
+libdlext_test_norelro_src_files := \
+    dlext_test_library.cpp \
+
+libdlext_test_norelro_ldflags := \
+    -Wl,-z,norelro \
+
+module := libdlext_test_norelro
+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 := \
+    dlopen_testlib_simple.cpp
+
+module := libtest_simple
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+
+# -----------------------------------------------------------------------------
+# Library used by atexit tests
+# -----------------------------------------------------------------------------
+
+libtest_atexit_src_files := \
+    atexit_testlib.cpp
+
+module := libtest_atexit
+build_target := SHARED_LIBRARY
+build_type := target
+include $(TEST_PATH)/Android.build.mk
+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/tests/atexit_testlib.cpp b/tests/libs/atexit_testlib.cpp
similarity index 100%
rename from tests/atexit_testlib.cpp
rename to tests/libs/atexit_testlib.cpp
diff --git a/tests/dlext_test_library.cpp b/tests/libs/dlext_test_library.cpp
similarity index 100%
rename from tests/dlext_test_library.cpp
rename to tests/libs/dlext_test_library.cpp
diff --git a/tests/dlopen_testlib_simple.cpp b/tests/libs/dlopen_testlib_simple.cpp
similarity index 100%
rename from tests/dlopen_testlib_simple.cpp
rename to tests/libs/dlopen_testlib_simple.cpp
diff --git a/tests/libs/dlsym_weak_function.cpp b/tests/libs/dlsym_weak_function.cpp
new file mode 100644
index 0000000..e38f2b8
--- /dev/null
+++ b/tests/libs/dlsym_weak_function.cpp
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+extern "C" int __attribute__((weak)) weak_func() {
+  return 42;
+}
+
diff --git a/tests/empty.cpp b/tests/libs/empty.cpp
similarity index 100%
rename from tests/empty.cpp
rename to tests/libs/empty.cpp
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index d701364..6b7a28b 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -22,9 +22,7 @@
 #include <malloc.h>
 #include <unistd.h>
 
-#if defined(__BIONIC__)
-#include <libc/bionic/malloc_debug_common.h>
-#endif
+#include "private/bionic_config.h"
 
 TEST(malloc, malloc_std) {
   // Simple malloc test.
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6aa259a..95e63b3 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,47 @@
 TEST(unistd, fsync) {
   TestFsyncFunction(fsync);
 }
+
+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.
+    ASSERT_EQ(syscall(__NR_getpid), getpid());
+    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 void GetPidCachingHelperHelper() {
+  ASSERT_EQ(syscall(__NR_getpid), getpid());
+}
+
+static void* GetPidCachingHelper(void*) {
+  GetPidCachingHelperHelper(); // Can't assert in a non-void function.
+  return NULL;
+}
+
+TEST(unistd, getpid_caching_and_pthread_create) {
+  pid_t parent_pid = getpid();
+
+  pthread_t t;
+  ASSERT_EQ(0, pthread_create(&t, NULL, GetPidCachingHelper, NULL));
+
+  ASSERT_EQ(parent_pid, getpid());
+
+  void* result;
+  ASSERT_EQ(0, pthread_join(t, &result));
+  ASSERT_EQ(NULL, result);
+}