Merge "Add marking of DNS sockets for mark based routing"
diff --git a/libc/Android.mk b/libc/Android.mk
index 11ae09b..73aa2e6 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -9,7 +9,6 @@
 	unistd/alarm.c \
 	unistd/exec.c \
 	unistd/fnmatch.c \
-	unistd/getopt_long.c \
 	unistd/syslog.c \
 	unistd/system.c \
 	unistd/time.c \
@@ -150,6 +149,7 @@
 	bionic/strntoumax.c \
 	bionic/strtotimeval.c \
 	bionic/system_properties.c \
+	bionic/system_properties_compat.c \
 	bionic/tcgetpgrp.c \
 	bionic/tcsetpgrp.c \
 	bionic/thread_atexit.c \
@@ -225,6 +225,7 @@
     bionic/setlocale.cpp \
     bionic/signalfd.cpp \
     bionic/sigwait.cpp \
+    bionic/statvfs.cpp \
     bionic/__strcat_chk.cpp \
     bionic/__strchr_chk.cpp \
     bionic/__strcpy_chk.cpp \
@@ -279,6 +280,7 @@
     upstream-freebsd/lib/libc/stdio/tempnam.c \
     upstream-freebsd/lib/libc/stdio/tmpnam.c \
     upstream-freebsd/lib/libc/stdio/wsetup.c \
+    upstream-freebsd/lib/libc/stdlib/getopt_long.c \
     upstream-freebsd/lib/libc/stdlib/qsort.c \
     upstream-freebsd/lib/libc/stdlib/realpath.c \
     upstream-freebsd/lib/libc/string/wcpcpy.c \
diff --git a/libc/NOTICE b/libc/NOTICE
index 2937518..8ed455c 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3060,13 +3060,6 @@
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-       This product includes software developed by the NetBSD
-       Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -4116,6 +4109,38 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2013, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+     Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+     Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+     Neither the name of Linaro Limited 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.
+
+-------------------------------------------------------------------
+
 Copyright (c)1999 Citrus Project,
 All rights reserved.
 
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index ac04e51..88c980f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -201,6 +201,8 @@
 int     lremovexattr(const char *, const char *) 1
 int     __statfs64:statfs64(const char *, size_t, struct statfs *)  1
 long    unshare(unsigned long)  1
+int     swapon(const char *, int) 1
+int     swapoff(const char *) 1
 
 # time
 int           pause ()                       1
diff --git a/libc/arch-arm/bionic/memcpy.a9.S b/libc/arch-arm/bionic/memcpy.a9.S
new file mode 100644
index 0000000..2ba1ff5
--- /dev/null
+++ b/libc/arch-arm/bionic/memcpy.a9.S
@@ -0,0 +1,614 @@
+/* Copyright (c) 2013, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+      * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+      * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+      * Neither the name of Linaro Limited 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.
+
+ */
+
+/*
+   This memcpy routine is optimised for Cortex-A15 cores and takes advantage
+   of VFP or NEON when built with the appropriate flags.
+
+   Assumptions:
+
+    ARMv6 (ARMv7-a if using Neon)
+    ARM state
+    Unaligned accesses
+    LDRD/STRD support unaligned word accesses
+
+ */
+
+#include <machine/cpu-features.h>
+#include <machine/asm.h>
+
+	.syntax unified
+	/* This implementation requires ARM state.  */
+	.arm
+
+#ifdef __ARM_NEON__
+
+	.fpu	neon
+	.arch	armv7-a
+# define FRAME_SIZE	4
+# define USE_VFP
+# define USE_NEON
+
+#elif !defined (__SOFTFP__)
+
+	.arch	armv6
+	.fpu	vfpv2
+# define FRAME_SIZE	32
+# define USE_VFP
+
+#else
+	.arch	armv6
+# define FRAME_SIZE    32
+
+#endif
+
+/* Old versions of GAS incorrectly implement the NEON align semantics.  */
+#ifdef BROKEN_ASM_NEON_ALIGN
+#define ALIGN(addr, align) addr,:align
+#else
+#define ALIGN(addr, align) addr:align
+#endif
+
+#define PC_OFFSET	8	/* PC pipeline compensation.  */
+#define INSN_SIZE	4
+
+/* Call parameters.  */
+#define dstin	r0
+#define src	r1
+#define count	r2
+
+/* Locals.  */
+#define tmp1	r3
+#define dst	ip
+#define tmp2	r10
+
+#ifndef USE_NEON
+/* For bulk copies using GP registers.  */
+#define	A_l	r2		/* Call-clobbered.  */
+#define	A_h	r3		/* Call-clobbered.  */
+#define	B_l	r4
+#define	B_h	r5
+#define	C_l	r6
+#define	C_h	r7
+#define	D_l	r8
+#define	D_h	r9
+#endif
+
+/* Number of lines ahead to pre-fetch data.  If you change this the code
+   below will need adjustment to compensate.  */
+
+#define prefetch_lines	5
+
+#ifdef USE_VFP
+	.macro	cpy_line_vfp vreg, base
+	vstr	\vreg, [dst, #\base]
+	vldr	\vreg, [src, #\base]
+	vstr	d0, [dst, #\base + 8]
+	vldr	d0, [src, #\base + 8]
+	vstr	d1, [dst, #\base + 16]
+	vldr	d1, [src, #\base + 16]
+	vstr	d2, [dst, #\base + 24]
+	vldr	d2, [src, #\base + 24]
+	vstr	\vreg, [dst, #\base + 32]
+	vldr	\vreg, [src, #\base + prefetch_lines * 64 - 32]
+	vstr	d0, [dst, #\base + 40]
+	vldr	d0, [src, #\base + 40]
+	vstr	d1, [dst, #\base + 48]
+	vldr	d1, [src, #\base + 48]
+	vstr	d2, [dst, #\base + 56]
+	vldr	d2, [src, #\base + 56]
+	.endm
+
+	.macro	cpy_tail_vfp vreg, base
+	vstr	\vreg, [dst, #\base]
+	vldr	\vreg, [src, #\base]
+	vstr	d0, [dst, #\base + 8]
+	vldr	d0, [src, #\base + 8]
+	vstr	d1, [dst, #\base + 16]
+	vldr	d1, [src, #\base + 16]
+	vstr	d2, [dst, #\base + 24]
+	vldr	d2, [src, #\base + 24]
+	vstr	\vreg, [dst, #\base + 32]
+	vstr	d0, [dst, #\base + 40]
+	vldr	d0, [src, #\base + 40]
+	vstr	d1, [dst, #\base + 48]
+	vldr	d1, [src, #\base + 48]
+	vstr	d2, [dst, #\base + 56]
+	vldr	d2, [src, #\base + 56]
+	.endm
+#endif
+
+	.p2align 6
+ENTRY(memcpy)
+
+	mov	dst, dstin	/* Preserve dstin, we need to return it.  */
+	cmp	count, #64
+	bge	.Lcpy_not_short
+	/* Deal with small copies quickly by dropping straight into the
+	   exit block.  */
+
+.Ltail63unaligned:
+#ifdef USE_NEON
+	and	tmp1, count, #0x38
+	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
+	add	pc, pc, tmp1
+	vld1.8	{d0}, [src]!	/* 14 words to go.  */
+	vst1.8	{d0}, [dst]!
+	vld1.8	{d0}, [src]!	/* 12 words to go.  */
+	vst1.8	{d0}, [dst]!
+	vld1.8	{d0}, [src]!	/* 10 words to go.  */
+	vst1.8	{d0}, [dst]!
+	vld1.8	{d0}, [src]!	/* 8 words to go.  */
+	vst1.8	{d0}, [dst]!
+	vld1.8	{d0}, [src]!	/* 6 words to go.  */
+	vst1.8	{d0}, [dst]!
+	vld1.8	{d0}, [src]!	/* 4 words to go.  */
+	vst1.8	{d0}, [dst]!
+	vld1.8	{d0}, [src]!	/* 2 words to go.  */
+	vst1.8	{d0}, [dst]!
+
+	tst	count, #4
+	ldrne	tmp1, [src], #4
+	strne	tmp1, [dst], #4
+#else
+	/* Copy up to 15 full words of data.  May not be aligned.  */
+	/* Cannot use VFP for unaligned data.  */
+	and	tmp1, count, #0x3c
+	add	dst, dst, tmp1
+	add	src, src, tmp1
+	rsb	tmp1, tmp1, #(60 - PC_OFFSET/2 + INSN_SIZE/2)
+	/* Jump directly into the sequence below at the correct offset.  */
+	add	pc, pc, tmp1, lsl #1
+
+	ldr	tmp1, [src, #-60]	/* 15 words to go.  */
+	str	tmp1, [dst, #-60]
+
+	ldr	tmp1, [src, #-56]	/* 14 words to go.  */
+	str	tmp1, [dst, #-56]
+	ldr	tmp1, [src, #-52]
+	str	tmp1, [dst, #-52]
+
+	ldr	tmp1, [src, #-48]	/* 12 words to go.  */
+	str	tmp1, [dst, #-48]
+	ldr	tmp1, [src, #-44]
+	str	tmp1, [dst, #-44]
+
+	ldr	tmp1, [src, #-40]	/* 10 words to go.  */
+	str	tmp1, [dst, #-40]
+	ldr	tmp1, [src, #-36]
+	str	tmp1, [dst, #-36]
+
+	ldr	tmp1, [src, #-32]	/* 8 words to go.  */
+	str	tmp1, [dst, #-32]
+	ldr	tmp1, [src, #-28]
+	str	tmp1, [dst, #-28]
+
+	ldr	tmp1, [src, #-24]	/* 6 words to go.  */
+	str	tmp1, [dst, #-24]
+	ldr	tmp1, [src, #-20]
+	str	tmp1, [dst, #-20]
+
+	ldr	tmp1, [src, #-16]	/* 4 words to go.  */
+	str	tmp1, [dst, #-16]
+	ldr	tmp1, [src, #-12]
+	str	tmp1, [dst, #-12]
+
+	ldr	tmp1, [src, #-8]	/* 2 words to go.  */
+	str	tmp1, [dst, #-8]
+	ldr	tmp1, [src, #-4]
+	str	tmp1, [dst, #-4]
+#endif
+
+	lsls	count, count, #31
+	ldrhcs	tmp1, [src], #2
+	ldrbne	src, [src]		/* Src is dead, use as a scratch.  */
+	strhcs	tmp1, [dst], #2
+	strbne	src, [dst]
+	bx	lr
+
+.Lcpy_not_short:
+	/* At least 64 bytes to copy, but don't know the alignment yet.  */
+	str	tmp2, [sp, #-FRAME_SIZE]!
+	and	tmp2, src, #7
+	and	tmp1, dst, #7
+	cmp	tmp1, tmp2
+	bne	.Lcpy_notaligned
+
+#ifdef USE_VFP
+	/* Magic dust alert!  Force VFP on Cortex-A9.  Experiments show
+	   that the FP pipeline is much better at streaming loads and
+	   stores.  This is outside the critical loop.  */
+	vmov.f32	s0, s0
+#endif
+
+	/* SRC and DST have the same mutual 32-bit alignment, but we may
+	   still need to pre-copy some bytes to get to natural alignment.
+	   We bring DST into full 64-bit alignment.  */
+	lsls	tmp2, dst, #29
+	beq	1f
+	rsbs	tmp2, tmp2, #0
+	sub	count, count, tmp2, lsr #29
+	ldrmi	tmp1, [src], #4
+	strmi	tmp1, [dst], #4
+	lsls	tmp2, tmp2, #2
+	ldrhcs	tmp1, [src], #2
+	ldrbne	tmp2, [src], #1
+	strhcs	tmp1, [dst], #2
+	strbne	tmp2, [dst], #1
+
+1:
+	subs	tmp2, count, #64	/* Use tmp2 for count.  */
+	blt	.Ltail63aligned
+
+	cmp	tmp2, #512
+	bge	.Lcpy_body_long
+
+.Lcpy_body_medium:			/* Count in tmp2.  */
+#ifdef USE_VFP
+1:
+	vldr	d0, [src, #0]
+	subs	tmp2, tmp2, #64
+	vldr	d1, [src, #8]
+	vstr	d0, [dst, #0]
+	vldr	d0, [src, #16]
+	vstr	d1, [dst, #8]
+	vldr	d1, [src, #24]
+	vstr	d0, [dst, #16]
+	vldr	d0, [src, #32]
+	vstr	d1, [dst, #24]
+	vldr	d1, [src, #40]
+	vstr	d0, [dst, #32]
+	vldr	d0, [src, #48]
+	vstr	d1, [dst, #40]
+	vldr	d1, [src, #56]
+	vstr	d0, [dst, #48]
+	add	src, src, #64
+	vstr	d1, [dst, #56]
+	add	dst, dst, #64
+	bge	1b
+	tst	tmp2, #0x3f
+	beq	.Ldone
+
+.Ltail63aligned:			/* Count in tmp2.  */
+	and	tmp1, tmp2, #0x38
+	add	dst, dst, tmp1
+	add	src, src, tmp1
+	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
+	add	pc, pc, tmp1
+
+	vldr	d0, [src, #-56]	/* 14 words to go.  */
+	vstr	d0, [dst, #-56]
+	vldr	d0, [src, #-48]	/* 12 words to go.  */
+	vstr	d0, [dst, #-48]
+	vldr	d0, [src, #-40]	/* 10 words to go.  */
+	vstr	d0, [dst, #-40]
+	vldr	d0, [src, #-32]	/* 8 words to go.  */
+	vstr	d0, [dst, #-32]
+	vldr	d0, [src, #-24]	/* 6 words to go.  */
+	vstr	d0, [dst, #-24]
+	vldr	d0, [src, #-16]	/* 4 words to go.  */
+	vstr	d0, [dst, #-16]
+	vldr	d0, [src, #-8]	/* 2 words to go.  */
+	vstr	d0, [dst, #-8]
+#else
+	sub	src, src, #8
+	sub	dst, dst, #8
+1:
+	ldrd	A_l, A_h, [src, #8]
+	strd	A_l, A_h, [dst, #8]
+	ldrd	A_l, A_h, [src, #16]
+	strd	A_l, A_h, [dst, #16]
+	ldrd	A_l, A_h, [src, #24]
+	strd	A_l, A_h, [dst, #24]
+	ldrd	A_l, A_h, [src, #32]
+	strd	A_l, A_h, [dst, #32]
+	ldrd	A_l, A_h, [src, #40]
+	strd	A_l, A_h, [dst, #40]
+	ldrd	A_l, A_h, [src, #48]
+	strd	A_l, A_h, [dst, #48]
+	ldrd	A_l, A_h, [src, #56]
+	strd	A_l, A_h, [dst, #56]
+	ldrd	A_l, A_h, [src, #64]!
+	strd	A_l, A_h, [dst, #64]!
+	subs	tmp2, tmp2, #64
+	bge	1b
+	tst	tmp2, #0x3f
+	bne	1f
+	ldr	tmp2,[sp], #FRAME_SIZE
+	bx	lr
+1:
+	add	src, src, #8
+	add	dst, dst, #8
+
+.Ltail63aligned:			/* Count in tmp2.  */
+	/* Copy up to 7 d-words of data.  Similar to Ltail63unaligned, but
+	   we know that the src and dest are 32-bit aligned so we can use
+	   LDRD/STRD to improve efficiency.  */
+	/* TMP2 is now negative, but we don't care about that.  The bottom
+	   six bits still tell us how many bytes are left to copy.  */
+
+	and	tmp1, tmp2, #0x38
+	add	dst, dst, tmp1
+	add	src, src, tmp1
+	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
+	add	pc, pc, tmp1
+	ldrd	A_l, A_h, [src, #-56]	/* 14 words to go.  */
+	strd	A_l, A_h, [dst, #-56]
+	ldrd	A_l, A_h, [src, #-48]	/* 12 words to go.  */
+	strd	A_l, A_h, [dst, #-48]
+	ldrd	A_l, A_h, [src, #-40]	/* 10 words to go.  */
+	strd	A_l, A_h, [dst, #-40]
+	ldrd	A_l, A_h, [src, #-32]	/* 8 words to go.  */
+	strd	A_l, A_h, [dst, #-32]
+	ldrd	A_l, A_h, [src, #-24]	/* 6 words to go.  */
+	strd	A_l, A_h, [dst, #-24]
+	ldrd	A_l, A_h, [src, #-16]	/* 4 words to go.  */
+	strd	A_l, A_h, [dst, #-16]
+	ldrd	A_l, A_h, [src, #-8]	/* 2 words to go.  */
+	strd	A_l, A_h, [dst, #-8]
+
+#endif
+	tst	tmp2, #4
+	ldrne	tmp1, [src], #4
+	strne	tmp1, [dst], #4
+	lsls	tmp2, tmp2, #31		/* Count (tmp2) now dead. */
+	ldrhcs	tmp1, [src], #2
+	ldrbne	tmp2, [src]
+	strhcs	tmp1, [dst], #2
+	strbne	tmp2, [dst]
+
+.Ldone:
+	ldr	tmp2, [sp], #FRAME_SIZE
+	bx	lr
+
+.Lcpy_body_long:			/* Count in tmp2.  */
+
+	/* Long copy.  We know that there's at least (prefetch_lines * 64)
+	   bytes to go.  */
+#ifdef USE_VFP
+	/* Don't use PLD.  Instead, read some data in advance of the current
+	   copy position into a register.  This should act like a PLD
+	   operation but we won't have to repeat the transfer.  */
+
+	vldr	d3, [src, #0]
+	vldr	d4, [src, #64]
+	vldr	d5, [src, #128]
+	vldr	d6, [src, #192]
+	vldr	d7, [src, #256]
+
+	vldr	d0, [src, #8]
+	vldr	d1, [src, #16]
+	vldr	d2, [src, #24]
+	add	src, src, #32
+
+	subs	tmp2, tmp2, #prefetch_lines * 64 * 2
+	blt	2f
+1:
+	cpy_line_vfp	d3, 0
+	cpy_line_vfp	d4, 64
+	cpy_line_vfp	d5, 128
+	add	dst, dst, #3 * 64
+	add	src, src, #3 * 64
+	cpy_line_vfp	d6, 0
+	cpy_line_vfp	d7, 64
+	add	dst, dst, #2 * 64
+	add	src, src, #2 * 64
+	subs	tmp2, tmp2, #prefetch_lines * 64
+	bge	1b
+
+2:
+	cpy_tail_vfp	d3, 0
+	cpy_tail_vfp	d4, 64
+	cpy_tail_vfp	d5, 128
+	add	src, src, #3 * 64
+	add	dst, dst, #3 * 64
+	cpy_tail_vfp	d6, 0
+	vstr	d7, [dst, #64]
+	vldr	d7, [src, #64]
+	vstr	d0, [dst, #64 + 8]
+	vldr	d0, [src, #64 + 8]
+	vstr	d1, [dst, #64 + 16]
+	vldr	d1, [src, #64 + 16]
+	vstr	d2, [dst, #64 + 24]
+	vldr	d2, [src, #64 + 24]
+	vstr	d7, [dst, #64 + 32]
+	add	src, src, #96
+	vstr	d0, [dst, #64 + 40]
+	vstr	d1, [dst, #64 + 48]
+	vstr	d2, [dst, #64 + 56]
+	add	dst, dst, #128
+	add	tmp2, tmp2, #prefetch_lines * 64
+	b	.Lcpy_body_medium
+#else
+	/* Long copy.  Use an SMS style loop to maximize the I/O
+	   bandwidth of the core.  We don't have enough spare registers
+	   to synthesise prefetching, so use PLD operations.  */
+	/* Pre-bias src and dst.  */
+	sub	src, src, #8
+	sub	dst, dst, #8
+	pld	[src, #8]
+	pld	[src, #72]
+	subs	tmp2, tmp2, #64
+	pld	[src, #136]
+	ldrd	A_l, A_h, [src, #8]
+	strd	B_l, B_h, [sp, #8]
+	ldrd	B_l, B_h, [src, #16]
+	strd	C_l, C_h, [sp, #16]
+	ldrd	C_l, C_h, [src, #24]
+	strd	D_l, D_h, [sp, #24]
+	pld	[src, #200]
+	ldrd	D_l, D_h, [src, #32]!
+	b	1f
+	.p2align	6
+2:
+	pld	[src, #232]
+	strd	A_l, A_h, [dst, #40]
+	ldrd	A_l, A_h, [src, #40]
+	strd	B_l, B_h, [dst, #48]
+	ldrd	B_l, B_h, [src, #48]
+	strd	C_l, C_h, [dst, #56]
+	ldrd	C_l, C_h, [src, #56]
+	strd	D_l, D_h, [dst, #64]!
+	ldrd	D_l, D_h, [src, #64]!
+	subs	tmp2, tmp2, #64
+1:
+	strd	A_l, A_h, [dst, #8]
+	ldrd	A_l, A_h, [src, #8]
+	strd	B_l, B_h, [dst, #16]
+	ldrd	B_l, B_h, [src, #16]
+	strd	C_l, C_h, [dst, #24]
+	ldrd	C_l, C_h, [src, #24]
+	strd	D_l, D_h, [dst, #32]
+	ldrd	D_l, D_h, [src, #32]
+	bcs	2b
+	/* Save the remaining bytes and restore the callee-saved regs.  */
+	strd	A_l, A_h, [dst, #40]
+	add	src, src, #40
+	strd	B_l, B_h, [dst, #48]
+	ldrd	B_l, B_h, [sp, #8]
+	strd	C_l, C_h, [dst, #56]
+	ldrd	C_l, C_h, [sp, #16]
+	strd	D_l, D_h, [dst, #64]
+	ldrd	D_l, D_h, [sp, #24]
+	add	dst, dst, #72
+	tst	tmp2, #0x3f
+	bne	.Ltail63aligned
+	ldr	tmp2, [sp], #FRAME_SIZE
+	bx	lr
+#endif
+
+.Lcpy_notaligned:
+	pld	[src]
+	pld	[src, #64]
+	/* There's at least 64 bytes to copy, but there is no mutual
+	   alignment.  */
+	/* Bring DST to 64-bit alignment.  */
+	lsls	tmp2, dst, #29
+	pld	[src, #(2 * 64)]
+	beq	1f
+	rsbs	tmp2, tmp2, #0
+	sub	count, count, tmp2, lsr #29
+	ldrmi	tmp1, [src], #4
+	strmi	tmp1, [dst], #4
+	lsls	tmp2, tmp2, #2
+	ldrbne	tmp1, [src], #1
+	ldrhcs	tmp2, [src], #2
+	strbne	tmp1, [dst], #1
+	strhcs	tmp2, [dst], #2
+1:
+	pld	[src, #(3 * 64)]
+	subs	count, count, #64
+	ldrmi	tmp2, [sp], #FRAME_SIZE
+	bmi	.Ltail63unaligned
+	pld	[src, #(4 * 64)]
+
+#ifdef USE_NEON
+	vld1.8	{d0-d3}, [src]!
+	vld1.8	{d4-d7}, [src]!
+	subs	count, count, #64
+	bmi	2f
+1:
+	pld	[src, #(4 * 64)]
+	vst1.8	{d0-d3}, [ALIGN (dst, 64)]!
+	vld1.8	{d0-d3}, [src]!
+	vst1.8	{d4-d7}, [ALIGN (dst, 64)]!
+	vld1.8	{d4-d7}, [src]!
+	subs	count, count, #64
+	bpl	1b
+2:
+	vst1.8	{d0-d3}, [ALIGN (dst, 64)]!
+	vst1.8	{d4-d7}, [ALIGN (dst, 64)]!
+	ands	count, count, #0x3f
+#else
+	/* Use an SMS style loop to maximize the I/O bandwidth.  */
+	sub	src, src, #4
+	sub	dst, dst, #8
+	subs	tmp2, count, #64	/* Use tmp2 for count.  */
+	ldr	A_l, [src, #4]
+	ldr	A_h, [src, #8]
+	strd	B_l, B_h, [sp, #8]
+	ldr	B_l, [src, #12]
+	ldr	B_h, [src, #16]
+	strd	C_l, C_h, [sp, #16]
+	ldr	C_l, [src, #20]
+	ldr	C_h, [src, #24]
+	strd	D_l, D_h, [sp, #24]
+	ldr	D_l, [src, #28]
+	ldr	D_h, [src, #32]!
+	b	1f
+	.p2align	6
+2:
+	pld	[src, #(5 * 64) - (32 - 4)]
+	strd	A_l, A_h, [dst, #40]
+	ldr	A_l, [src, #36]
+	ldr	A_h, [src, #40]
+	strd	B_l, B_h, [dst, #48]
+	ldr	B_l, [src, #44]
+	ldr	B_h, [src, #48]
+	strd	C_l, C_h, [dst, #56]
+	ldr	C_l, [src, #52]
+	ldr	C_h, [src, #56]
+	strd	D_l, D_h, [dst, #64]!
+	ldr	D_l, [src, #60]
+	ldr	D_h, [src, #64]!
+	subs	tmp2, tmp2, #64
+1:
+	strd	A_l, A_h, [dst, #8]
+	ldr	A_l, [src, #4]
+	ldr	A_h, [src, #8]
+	strd	B_l, B_h, [dst, #16]
+	ldr	B_l, [src, #12]
+	ldr	B_h, [src, #16]
+	strd	C_l, C_h, [dst, #24]
+	ldr	C_l, [src, #20]
+	ldr	C_h, [src, #24]
+	strd	D_l, D_h, [dst, #32]
+	ldr	D_l, [src, #28]
+	ldr	D_h, [src, #32]
+	bcs	2b
+
+	/* Save the remaining bytes and restore the callee-saved regs.  */
+	strd	A_l, A_h, [dst, #40]
+	add	src, src, #36
+	strd	B_l, B_h, [dst, #48]
+	ldrd	B_l, B_h, [sp, #8]
+	strd	C_l, C_h, [dst, #56]
+	ldrd	C_l, C_h, [sp, #16]
+	strd	D_l, D_h, [dst, #64]
+	ldrd	D_l, D_h, [sp, #24]
+	add	dst, dst, #72
+	ands	count, tmp2, #0x3f
+#endif
+	ldr	tmp2, [sp], #FRAME_SIZE
+	bne	.Ltail63unaligned
+	bx	lr
+END(memcpy)
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 3c8f204..252a428 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -126,6 +126,8 @@
 syscall_src += arch-arm/syscalls/lremovexattr.S
 syscall_src += arch-arm/syscalls/__statfs64.S
 syscall_src += arch-arm/syscalls/unshare.S
+syscall_src += arch-arm/syscalls/swapon.S
+syscall_src += arch-arm/syscalls/swapoff.S
 syscall_src += arch-arm/syscalls/pause.S
 syscall_src += arch-arm/syscalls/gettimeofday.S
 syscall_src += arch-arm/syscalls/settimeofday.S
diff --git a/libc/arch-arm/syscalls/swapoff.S b/libc/arch-arm/syscalls/swapoff.S
new file mode 100644
index 0000000..070d160
--- /dev/null
+++ b/libc/arch-arm/syscalls/swapoff.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(swapoff)
+    mov     ip, r7
+    ldr     r7, =__NR_swapoff
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(swapoff)
diff --git a/libc/arch-arm/syscalls/swapon.S b/libc/arch-arm/syscalls/swapon.S
new file mode 100644
index 0000000..a77e0cd
--- /dev/null
+++ b/libc/arch-arm/syscalls/swapon.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(swapon)
+    mov     ip, r7
+    ldr     r7, =__NR_swapon
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(swapon)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index d3096bc..23393a2 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -129,6 +129,8 @@
 syscall_src += arch-mips/syscalls/lremovexattr.S
 syscall_src += arch-mips/syscalls/__statfs64.S
 syscall_src += arch-mips/syscalls/unshare.S
+syscall_src += arch-mips/syscalls/swapon.S
+syscall_src += arch-mips/syscalls/swapoff.S
 syscall_src += arch-mips/syscalls/pause.S
 syscall_src += arch-mips/syscalls/gettimeofday.S
 syscall_src += arch-mips/syscalls/settimeofday.S
diff --git a/libc/arch-mips/syscalls/swapoff.S b/libc/arch-mips/syscalls/swapoff.S
new file mode 100644
index 0000000..4f204c9
--- /dev/null
+++ b/libc/arch-mips/syscalls/swapoff.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+    .text
+    .globl swapoff
+    .align 4
+    .ent swapoff
+
+swapoff:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_swapoff
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end swapoff
diff --git a/libc/arch-mips/syscalls/swapon.S b/libc/arch-mips/syscalls/swapon.S
new file mode 100644
index 0000000..af3dda6
--- /dev/null
+++ b/libc/arch-mips/syscalls/swapon.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+    .text
+    .globl swapon
+    .align 4
+    .ent swapon
+
+swapon:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_swapon
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end swapon
diff --git a/libc/arch-x86/include/machine/endian.h b/libc/arch-x86/include/machine/endian.h
index e7ad257..e1506b1 100644
--- a/libc/arch-x86/include/machine/endian.h
+++ b/libc/arch-x86/include/machine/endian.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: endian.h,v 1.14 2005/12/13 00:35:23 millert Exp $	*/
+/*	$OpenBSD: endian.h,v 1.17 2011/03/12 04:03:04 guenther Exp $	*/
 
 /*-
  * Copyright (c) 1997 Niklas Hallqvist.  All rights reserved.
@@ -24,38 +24,28 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef _I386_ENDIAN_H_
-#define _I386_ENDIAN_H_
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_ENDIAN_H_
 
 #ifdef __GNUC__
 
-#if defined(_KERNEL) && !defined(I386_CPU)
-#define	__swap32md(x) ({						\
+#define	__swap32md(x) __statement({					\
 	uint32_t __swap32md_x = (x);					\
 									\
-	__asm ("bswap %1" : "+r" (__swap32md_x));			\
+	__asm ("bswap %0" : "+r" (__swap32md_x));			\
 	__swap32md_x;							\
 })
-#else
-#define	__swap32md(x) ({						\
-	uint32_t __swap32md_x = (x);					\
-									\
-	__asm ("rorw $8, %w1; rorl $16, %1; rorw $8, %w1" :		\
-	    "+r" (__swap32md_x));					\
-	__swap32md_x;							\
-})
-#endif	/* _KERNEL && !I386_CPU */
 
-#define	__swap64md(x) ({						\
+#define	__swap64md(x) __statement({					\
 	uint64_t __swap64md_x = (x);					\
 									\
 	(uint64_t)__swap32md(__swap64md_x >> 32) |			\
 	    (uint64_t)__swap32md(__swap64md_x & 0xffffffff) << 32;	\
 })
-#define	__swap16md(x) ({						\
+#define	__swap16md(x) __statement({					\
 	uint16_t __swap16md_x = (x);					\
 									\
-	__asm ("rorw $8, %w1" : "+r" (__swap16md_x));			\
+	__asm ("rorw $8, %w0" : "+r" (__swap16md_x));			\
 	__swap16md_x;							\
 })
 
@@ -68,4 +58,4 @@
 #include <sys/types.h>
 #include <sys/endian.h>
 
-#endif /* _I386_ENDIAN_H_ */
+#endif /* _MACHINE_ENDIAN_H_ */
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 31eb930..11573de 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -130,6 +130,8 @@
 syscall_src += arch-x86/syscalls/lremovexattr.S
 syscall_src += arch-x86/syscalls/__statfs64.S
 syscall_src += arch-x86/syscalls/unshare.S
+syscall_src += arch-x86/syscalls/swapon.S
+syscall_src += arch-x86/syscalls/swapoff.S
 syscall_src += arch-x86/syscalls/pause.S
 syscall_src += arch-x86/syscalls/gettimeofday.S
 syscall_src += arch-x86/syscalls/settimeofday.S
diff --git a/libc/arch-x86/syscalls/swapoff.S b/libc/arch-x86/syscalls/swapoff.S
new file mode 100644
index 0000000..f2d6ddb
--- /dev/null
+++ b/libc/arch-x86/syscalls/swapoff.S
@@ -0,0 +1,21 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(swapoff)
+    pushl   %ebx
+    mov     8(%esp), %ebx
+    movl    $__NR_swapoff, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %ebx
+    ret
+END(swapoff)
diff --git a/libc/arch-x86/syscalls/swapon.S b/libc/arch-x86/syscalls/swapon.S
new file mode 100644
index 0000000..08602fb
--- /dev/null
+++ b/libc/arch-x86/syscalls/swapon.S
@@ -0,0 +1,24 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(swapon)
+    pushl   %ebx
+    pushl   %ecx
+    mov     12(%esp), %ebx
+    mov     16(%esp), %ecx
+    movl    $__NR_swapon, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %ecx
+    popl    %ebx
+    ret
+END(swapon)
diff --git a/libc/bionic/dl_iterate_phdr_static.c b/libc/bionic/dl_iterate_phdr_static.c
index 90ed1b7..fc79ce5 100644
--- a/libc/bionic/dl_iterate_phdr_static.c
+++ b/libc/bionic/dl_iterate_phdr_static.c
@@ -27,39 +27,56 @@
  */
 
 #include <elf.h>
+#include <sys/auxv.h>
 #include <sys/types.h>
 #include <link.h>
 
-/* Dynamic binaries get this from the dynamic linker (system/linker), which
- * we don't pull in for static bins. We also don't have a list of so's to
- * iterate over, since there's really only a single monolithic blob of
- * code/data.
- *
- * All we need to do is to find where the executable is in memory, and grab the
- * phdr and phnum from there.
- */
-
 /* ld provides this to us in the default link script */
-extern void *__executable_start;
+extern void* __executable_start;
 
-int
-dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),
-                void *data)
-{
-    struct dl_phdr_info dl_info;
-    Elf32_Ehdr *ehdr = (Elf32_Ehdr *) &__executable_start;
-    Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned long)ehdr + ehdr->e_phoff);
+int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
+    Elf32_Ehdr* ehdr = (Elf32_Ehdr*) &__executable_start;
 
-    /* TODO: again, copied from linker.c. Find a better home for this
-     * later. */
+    // TODO: again, copied from linker.c. Find a better home for this later.
     if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
     if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
     if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
     if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
 
-    dl_info.dlpi_addr = 0;
-    dl_info.dlpi_name = NULL;
-    dl_info.dlpi_phdr = phdr;
-    dl_info.dlpi_phnum = ehdr->e_phnum;
-    return cb(&dl_info, sizeof (struct dl_phdr_info), data);
+    // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but
+    // static binaries get this. We don't have a list of shared objects to
+    // iterate over, since there's really only a single monolithic blob of
+    // code/data, plus optionally a VDSO.
+
+    struct dl_phdr_info exe_info;
+    exe_info.dlpi_addr = 0;
+    exe_info.dlpi_name = NULL;
+    exe_info.dlpi_phdr = (Elf32_Phdr*) ((unsigned long) ehdr + ehdr->e_phoff);
+    exe_info.dlpi_phnum = ehdr->e_phnum;
+
+#ifdef AT_SYSINFO_EHDR
+    // Try the executable first.
+    int rc = cb(&exe_info, sizeof(exe_info), data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    // Try the VDSO if that didn't work.
+    Elf32_Ehdr* ehdr_vdso = (Elf32_Ehdr*) getauxval(AT_SYSINFO_EHDR);
+    struct dl_phdr_info vdso_info;
+    vdso_info.dlpi_addr = 0;
+    vdso_info.dlpi_name = NULL;
+    vdso_info.dlpi_phdr = (Elf32_Phdr*) ((char*) ehdr_vdso + ehdr_vdso->e_phoff);
+    vdso_info.dlpi_phnum = ehdr_vdso->e_phnum;
+    for (size_t i = 0; i < vdso_info.dlpi_phnum; ++i) {
+        if (vdso_info.dlpi_phdr[i].p_type == PT_LOAD) {
+            vdso_info.dlpi_addr = (Elf32_Addr) ehdr_vdso - vdso_info.dlpi_phdr[i].p_vaddr;
+            break;
+        }
+    }
+    return cb(&vdso_info, sizeof(vdso_info), data);
+#else
+    // There's only the executable to try.
+    return cb(&exe_info, sizeof(exe_info), data);
+#endif
 }
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index ffc5335..6bf7415 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -42,7 +42,6 @@
 #include <unistd.h>
 
 static pthread_mutex_t gAbortMsgLock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t gLogInitializationLock = PTHREAD_MUTEX_INITIALIZER;
 
 __LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
 
@@ -421,13 +420,9 @@
 }
 
 static int __libc_write_log(int priority, const char* tag, const char* msg) {
-  static int main_log_fd = -1;
+  int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
   if (main_log_fd == -1) {
-    ScopedPthreadMutexLocker locker(&gLogInitializationLock);
-    main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
-    if (main_log_fd == -1) {
-      return -1;
-    }
+    return -1;
   }
 
   iovec vec[3];
@@ -438,7 +433,9 @@
   vec[2].iov_base = const_cast<char*>(msg);
   vec[2].iov_len = strlen(msg) + 1;
 
-  return TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3));
+  int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3));
+  close(main_log_fd);
+  return result;
 }
 
 int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) {
@@ -465,12 +462,13 @@
   vec[2].iov_base = const_cast<void*>(payload);
   vec[2].iov_len = len;
 
-  static int event_log_fd = -1;
+  int event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
   if (event_log_fd == -1) {
-    ScopedPthreadMutexLocker locker(&gLogInitializationLock);
-    event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
+    return -1;
   }
-  return TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3));
+  int result = TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3));
+  close(event_log_fd);
+  return result;
 }
 
 void __libc_android_log_event_int(int32_t tag, int value) {
diff --git a/libc/bionic/mmap.c b/libc/bionic/mmap.c
index e097086..36aee85 100644
--- a/libc/bionic/mmap.c
+++ b/libc/bionic/mmap.c
@@ -43,8 +43,9 @@
 
     ret = __mmap2(addr, size, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT);
 
-    if (ret && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)))
-	    madvise(ret, size, MADV_MERGEABLE);
+    if ((ret != MAP_FAILED) && (flags & (MAP_PRIVATE | MAP_ANONYMOUS))) {
+        madvise(ret, size, MADV_MERGEABLE);
+    }
 
     return ret;
 }
diff --git a/libc/bionic/statvfs.cpp b/libc/bionic/statvfs.cpp
new file mode 100644
index 0000000..5d42aaa
--- /dev/null
+++ b/libc/bionic/statvfs.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/statvfs.h>
+
+#include <sys/statfs.h>
+
+extern "C" int __statfs64(const char*, size_t, struct statfs*);
+extern "C" int __fstatfs64(int, size_t, struct statfs*);
+
+#define ST_VALID 0x0020
+
+#if defined(__mips__)
+#define __val val
+#endif
+
+static void __statfs_to_statvfs(const struct statfs& in, struct statvfs* out) {
+  out->f_bsize = in.f_bsize;
+  out->f_frsize = in.f_frsize;
+  out->f_blocks = in.f_blocks;
+  out->f_bfree = in.f_bfree;
+  out->f_bavail = in.f_bavail;
+  out->f_files = in.f_files;
+  out->f_ffree = in.f_ffree;
+  out->f_favail = in.f_ffree;
+  out->f_fsid = in.f_fsid.__val[0] | (static_cast<uint64_t>(in.f_fsid.__val[1]) << 32);
+  out->f_flag = in.f_flags & ~ST_VALID;
+  out->f_namemax = in.f_namelen;
+}
+
+int statvfs(const char* path, struct statvfs* result) {
+  struct statfs tmp;
+  int rc = __statfs64(path, sizeof(tmp), &tmp);
+  if (rc != 0) {
+    return rc;
+  }
+  __statfs_to_statvfs(tmp, result);
+  return 0;
+}
+
+int fstatvfs(int fd, struct statvfs* result) {
+  struct statfs tmp;
+  int rc = __fstatfs64(fd, sizeof(tmp), &tmp);
+  if (rc != 0) {
+    return rc;
+  }
+  __statfs_to_statvfs(tmp, result);
+  return 0;
+}
diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c
index 800c8b8..4c2e5a2 100644
--- a/libc/bionic/system_properties.c
+++ b/libc/bionic/system_properties.c
@@ -34,6 +34,7 @@
 #include <poll.h>
 #include <fcntl.h>
 #include <stdbool.h>
+#include <string.h>
 
 #include <sys/mman.h>
 
@@ -49,29 +50,71 @@
 #include <sys/_system_properties.h>
 
 #include <sys/atomics.h>
+#include <bionic_atomic_inline.h>
+
+#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
 
 struct prop_area {
-    unsigned volatile count;
+    unsigned bytes_used;
     unsigned volatile serial;
     unsigned magic;
     unsigned version;
-    unsigned toc[1];
+    unsigned reserved[28];
+    char data[0];
 };
 
 typedef struct prop_area prop_area;
 
 struct prop_info {
-    char name[PROP_NAME_MAX];
     unsigned volatile serial;
     char value[PROP_VALUE_MAX];
+    char name[0];
 };
 
 typedef struct prop_info prop_info;
 
+/*
+ * Properties are stored in a hybrid trie/binary tree structure.
+ * Each property's name is delimited at '.' characters, and the tokens are put
+ * into a trie structure.  Siblings at each level of the trie are stored in a
+ * binary tree.  For instance, "ro.secure"="1" could be stored as follows:
+ *
+ * +-----+   children    +----+   children    +--------+
+ * |     |-------------->| ro |-------------->| secure |
+ * +-----+               +----+               +--------+
+ *                       /    \                /   |
+ *                 left /      \ right   left /    |  prop   +===========+
+ *                     v        v            v     +-------->| ro.secure |
+ *                  +-----+   +-----+     +-----+            +-----------+
+ *                  | net |   | sys |     | com |            |     1     |
+ *                  +-----+   +-----+     +-----+            +===========+
+ */
+
+typedef volatile uint32_t prop_off_t;
+struct prop_bt {
+    uint8_t namelen;
+    uint8_t reserved[3];
+
+    prop_off_t prop;
+
+    prop_off_t left;
+    prop_off_t right;
+
+    prop_off_t children;
+
+    char name[0];
+};
+
+typedef struct prop_bt prop_bt;
+
 static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
 static char property_filename[PATH_MAX] = PROP_FILENAME;
+static bool compat_mode = false;
 
-prop_area *__system_property_regions__[PA_REGION_COUNT] = { NULL, };
+prop_area *__system_property_area__ = NULL;
+
+size_t pa_data_size;
+size_t pa_size;
 
 static int get_fd_from_env(void)
 {
@@ -84,20 +127,17 @@
     return atoi(env);
 }
 
-static int map_prop_region_rw(size_t region)
+static int map_prop_area_rw()
 {
     prop_area *pa;
     int fd;
-    size_t offset = region * PA_SIZE;
-
-    if (__system_property_regions__[region]) {
-        return 0;
-    }
+    int ret;
 
     /* dev is a tmpfs that we can use to carve a shared workspace
      * out of, so let's do that...
      */
-    fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW, 0644);
+    fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC |
+            O_EXCL, 0444);
     if (fd < 0) {
         if (errno == EACCES) {
             /* for consistency with the case where the process has already
@@ -108,19 +148,29 @@
         return -1;
     }
 
-    if (ftruncate(fd, offset + PA_SIZE) < 0)
+    ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+    if (ret < 0)
         goto out;
 
-    pa = mmap(NULL, PA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
+    if (ftruncate(fd, PA_SIZE) < 0)
+        goto out;
+
+    pa_size = PA_SIZE;
+    pa_data_size = pa_size - sizeof(prop_area);
+    compat_mode = false;
+
+    pa = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if(pa == MAP_FAILED)
         goto out;
 
-    memset(pa, 0, PA_SIZE);
+    memset(pa, 0, pa_size);
     pa->magic = PROP_AREA_MAGIC;
     pa->version = PROP_AREA_VERSION;
+    /* reserve root node */
+    pa->bytes_used = sizeof(prop_bt);
 
     /* plug into the lib property services */
-    __system_property_regions__[region] = pa;
+    __system_property_area__ = pa;
 
     close(fd);
     return 0;
@@ -142,22 +192,24 @@
 
 int __system_property_area_init()
 {
-    return map_prop_region_rw(0);
+    return map_prop_area_rw();
 }
 
-static int map_prop_region(size_t region)
+static int map_prop_area()
 {
     bool fromFile = true;
-    bool swapped;
-    size_t offset = region * PA_SIZE;
     int result = -1;
+    int fd;
+    int ret;
 
-    if(__system_property_regions__[region]) {
-        return 0;
+    fd = open(property_filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+    if (fd >= 0) {
+        /* For old kernels that don't support O_CLOEXEC */
+        ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+        if (ret < 0)
+            goto cleanup;
     }
 
-    int fd = open(property_filename, O_RDONLY | O_NOFOLLOW);
-
     if ((fd < 0) && (errno == ENOENT)) {
         /*
          * For backwards compatibility, if the file doesn't
@@ -184,33 +236,32 @@
     if ((fd_stat.st_uid != 0)
             || (fd_stat.st_gid != 0)
             || ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0)
-            || (fd_stat.st_size < offset + PA_SIZE) ) {
+            || (fd_stat.st_size < sizeof(prop_area)) ) {
         goto cleanup;
     }
 
-    prop_area *pa = mmap(NULL, PA_SIZE, PROT_READ, MAP_SHARED, fd, offset);
+    pa_size = fd_stat.st_size;
+    pa_data_size = pa_size - sizeof(prop_area);
+    prop_area *pa = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0);
 
     if (pa == MAP_FAILED) {
         goto cleanup;
     }
 
-    if((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION)) {
-        munmap(pa, PA_SIZE);
+    if((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION &&
+                pa->version != PROP_AREA_VERSION_COMPAT)) {
+        munmap(pa, pa_size);
         goto cleanup;
     }
 
-    result = 0;
-    swapped = __sync_bool_compare_and_swap(&__system_property_regions__[region],
-            NULL, pa);
-    if (!swapped) {
-        /**
-         * In the event of a race either mapping is equally good, so
-         * the thread that lost can just throw its mapping away and proceed as
-         * normal.
-         */
-        munmap(pa, PA_SIZE);
+    if (pa->version == PROP_AREA_VERSION_COMPAT) {
+        compat_mode = true;
     }
 
+    result = 0;
+
+    __system_property_area__ = pa;
+
 cleanup:
     if (fromFile) {
         close(fd);
@@ -221,92 +272,180 @@
 
 int __system_properties_init()
 {
-    return map_prop_region(0);
+    return map_prop_area();
 }
 
-int __system_property_foreach(
-        void (*propfn)(const prop_info *pi, void *cookie),
-        void *cookie)
+static void *new_prop_obj(size_t size, prop_off_t *off)
 {
-    size_t region;
+    prop_area *pa = __system_property_area__;
+    size = ALIGN(size, sizeof(uint32_t));
 
-    for (region = 0; region < PA_REGION_COUNT; region++) {
-        prop_area *pa;
-        unsigned i;
+    if (pa->bytes_used + size > pa_data_size)
+        return NULL;
 
-        int err = map_prop_region(region);
-        if (err < 0)
-            break;
-        pa = __system_property_regions__[region];
+    *off = pa->bytes_used;
+    __system_property_area__->bytes_used += size;
+    return __system_property_area__->data + *off;
+}
 
-        for (i = 0; i < pa->count; i++) {
-            unsigned entry = pa->toc[i];
-            prop_info *pi = TOC_TO_INFO(pa, entry);
-            propfn(pi, cookie);
-        }
+static prop_bt *new_prop_bt(const char *name, uint8_t namelen, prop_off_t *off)
+{
+    prop_off_t off_tmp;
+    prop_bt *bt = new_prop_obj(sizeof(prop_bt) + namelen + 1, &off_tmp);
+    if (bt) {
+        memcpy(bt->name, name, namelen);
+        bt->name[namelen] = '\0';
+        bt->namelen = namelen;
+        ANDROID_MEMBAR_FULL();
+        *off = off_tmp;
     }
 
-    return 0;
+    return bt;
 }
 
-const prop_info *__system_property_find_nth(unsigned n)
+static prop_info *new_prop_info(const char *name, uint8_t namelen,
+        const char *value, uint8_t valuelen, prop_off_t *off)
 {
-    size_t region = n / PA_COUNT_MAX;
-    prop_area *pa;
+    prop_off_t off_tmp;
+    prop_info *info = new_prop_obj(sizeof(prop_info) + namelen + 1, &off_tmp);
+    if (info) {
+        memcpy(info->name, name, namelen);
+        info->name[namelen] = '\0';
+        info->serial = (valuelen << 24);
+        memcpy(info->value, value, valuelen);
+        info->value[valuelen] = '\0';
+        ANDROID_MEMBAR_FULL();
+        *off = off_tmp;
+    }
 
-    int err = map_prop_region(region);
-    if (err < 0)
+    return info;
+}
+
+static void *to_prop_obj(prop_off_t off)
+{
+    if (off > pa_data_size)
         return NULL;
-    pa = __system_property_regions__[region];
 
-    if((n % PA_COUNT_MAX) >= pa->count) {
-        return 0;
+    return __system_property_area__->data + off;
+}
+
+static prop_bt *root_node()
+{
+    return to_prop_obj(0);
+}
+
+static int cmp_prop_name(const char *one, uint8_t one_len, const char *two,
+        uint8_t two_len)
+{
+    if (one_len < two_len)
+        return -1;
+    else if (one_len > two_len)
+        return 1;
+    else
+        return strncmp(one, two, one_len);
+}
+
+static prop_bt *find_prop_bt(prop_bt *bt, const char *name, uint8_t namelen,
+        bool alloc_if_needed)
+{
+    while (true) {
+        int ret;
+        if (!bt)
+            return bt;
+        ret = cmp_prop_name(name, namelen, bt->name, bt->namelen);
+
+        if (ret == 0) {
+            return bt;
+        } else if (ret < 0) {
+            if (bt->left) {
+                bt = to_prop_obj(bt->left);
+            } else {
+                if (!alloc_if_needed)
+                   return NULL;
+
+                bt = new_prop_bt(name, namelen, &bt->left);
+            }
+        } else {
+            if (bt->right) {
+                bt = to_prop_obj(bt->right);
+            } else {
+                if (!alloc_if_needed)
+                   return NULL;
+
+                bt = new_prop_bt(name, namelen, &bt->right);
+            }
+        }
+    }
+}
+
+static const prop_info *find_property(prop_bt *trie, const char *name,
+        uint8_t namelen, const char *value, uint8_t valuelen,
+        bool alloc_if_needed)
+{
+    const char *remaining_name = name;
+
+    while (true) {
+        char *sep = strchr(remaining_name, '.');
+        bool want_subtree = (sep != NULL);
+        uint8_t substr_size;
+
+        prop_bt *root;
+
+        if (want_subtree) {
+            substr_size = sep - remaining_name;
+        } else {
+            substr_size = strlen(remaining_name);
+        }
+
+        if (!substr_size)
+            return NULL;
+
+        if (trie->children) {
+            root = to_prop_obj(trie->children);
+        } else if (alloc_if_needed) {
+            root = new_prop_bt(remaining_name, substr_size, &trie->children);
+        } else {
+            root = NULL;
+        }
+
+        if (!root)
+            return NULL;
+
+        trie = find_prop_bt(root, remaining_name, substr_size, alloc_if_needed);
+        if (!trie)
+            return NULL;
+
+        if (!want_subtree)
+            break;
+
+        remaining_name = sep + 1;
+    }
+
+    if (trie->prop) {
+        return to_prop_obj(trie->prop);
+    } else if (alloc_if_needed) {
+        return new_prop_info(name, namelen, value, valuelen, &trie->prop);
     } else {
-        return TOC_TO_INFO(pa, pa->toc[n]);
+        return NULL;
     }
 }
 
 const prop_info *__system_property_find(const char *name)
 {
-    unsigned len = strlen(name);
-    size_t region;
-
-    if (len >= PROP_NAME_MAX)
-        return 0;
-    if (len < 1)
-        return 0;
-
-    for (region = 0; region < PA_REGION_COUNT; region++) {
-        prop_area *pa;
-        unsigned count;
-        unsigned *toc;
-        prop_info *pi;
-
-        int err = map_prop_region(region);
-        if (err < 0)
-            return 0;
-        pa = __system_property_regions__[region];
-        count = pa->count;
-        toc = pa->toc;
-
-        while(count--) {
-            unsigned entry = *toc++;
-            if(TOC_NAME_LEN(entry) != len) continue;
-
-            pi = TOC_TO_INFO(pa, entry);
-            if(memcmp(name, pi->name, len)) continue;
-
-            return pi;
-        }
+    if (__predict_false(compat_mode)) {
+        return __system_property_find_compat(name);
     }
-
-    return 0;
+    return find_property(root_node(), name, strlen(name), NULL, 0, false);
 }
 
 int __system_property_read(const prop_info *pi, char *name, char *value)
 {
     unsigned serial, len;
 
+    if (__predict_false(compat_mode)) {
+        return __system_property_read_compat(pi, name, value);
+    }
+
     for(;;) {
         serial = pi->serial;
         while(SERIAL_DIRTY(serial)) {
@@ -315,6 +454,7 @@
         }
         len = SERIAL_VALUE_LEN(serial);
         memcpy(value, pi->value, len + 1);
+        ANDROID_MEMBAR_FULL();
         if(serial == pi->serial) {
             if(name != 0) {
                 strcpy(name, pi->name);
@@ -424,7 +564,7 @@
 {
     unsigned n;
     if(pi == 0) {
-        prop_area *pa = __system_property_regions__[0];
+        prop_area *pa = __system_property_area__;
         n = pa->serial;
         do {
             __futex_wait(&pa->serial, n, 0);
@@ -440,13 +580,15 @@
 
 int __system_property_update(prop_info *pi, const char *value, unsigned int len)
 {
-    prop_area *pa = __system_property_regions__[0];
+    prop_area *pa = __system_property_area__;
 
     if (len >= PROP_VALUE_MAX)
         return -1;
 
     pi->serial = pi->serial | 1;
+    ANDROID_MEMBAR_FULL();
     memcpy(pi->value, value, len + 1);
+    ANDROID_MEMBAR_FULL();
     pi->serial = (len << 24) | ((pi->serial + 1) & 0xffffff);
     __futex_wake(&pi->serial, INT32_MAX);
 
@@ -459,10 +601,8 @@
 int __system_property_add(const char *name, unsigned int namelen,
             const char *value, unsigned int valuelen)
 {
-    prop_area *pa;
-    prop_info *pa_info_array;
-    prop_info *pi;
-    size_t region;
+    prop_area *pa = __system_property_area__;
+    const prop_info *pi;
 
     if (namelen >= PROP_NAME_MAX)
         return -1;
@@ -471,33 +611,12 @@
     if (namelen < 1)
         return -1;
 
-    for (region = 0; region < PA_REGION_COUNT; region++)
-    {
-        int err = map_prop_region_rw(region);
-        if (err < 0)
-            return -1;
-
-        pa = __system_property_regions__[region];
-
-        if (pa->count < PA_COUNT_MAX)
-            break;
-    }
-
-    if (region == PA_REGION_COUNT)
+    pi = find_property(root_node(), name, namelen, value, valuelen, true);
+    if (!pi)
         return -1;
 
-    pa_info_array = (void*) (((char*) pa) + PA_INFO_START);
-    pi = pa_info_array + pa->count;
-    pi->serial = (valuelen << 24);
-    memcpy(pi->name, name, namelen + 1);
-    memcpy(pi->value, value, valuelen + 1);
-
-    pa->toc[pa->count] = (namelen << 24) | (((unsigned) pi) - ((unsigned) pa));
-
-    pa->count++;
     pa->serial++;
     __futex_wake(&pa->serial, INT32_MAX);
-
     return 0;
 }
 
@@ -508,7 +627,7 @@
 
 unsigned int __system_property_wait_any(unsigned int serial)
 {
-    prop_area *pa = __system_property_regions__[0];
+    prop_area *pa = __system_property_area__;
 
     do {
         __futex_wait(&pa->serial, serial, 0);
@@ -516,3 +635,75 @@
 
     return pa->serial;
 }
+
+struct find_nth_cookie {
+    unsigned count;
+    unsigned n;
+    const prop_info *pi;
+};
+
+static void find_nth_fn(const prop_info *pi, void *ptr)
+{
+    struct find_nth_cookie *cookie = ptr;
+
+    if (cookie->n == cookie->count)
+        cookie->pi = pi;
+
+    cookie->count++;
+}
+
+const prop_info *__system_property_find_nth(unsigned n)
+{
+    struct find_nth_cookie cookie;
+    int err;
+
+    memset(&cookie, 0, sizeof(cookie));
+    cookie.n = n;
+
+    err = __system_property_foreach(find_nth_fn, &cookie);
+    if (err < 0)
+        return NULL;
+
+    return cookie.pi;
+}
+
+static int foreach_property(prop_off_t off,
+        void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
+{
+    prop_bt *trie = to_prop_obj(off);
+    if (!trie)
+        return -1;
+
+    if (trie->left) {
+        int err = foreach_property(trie->left, propfn, cookie);
+        if (err < 0)
+            return -1;
+    }
+    if (trie->prop) {
+        prop_info *info = to_prop_obj(trie->prop);
+        if (!info)
+            return -1;
+        propfn(info, cookie);
+    }
+    if (trie->children) {
+        int err = foreach_property(trie->children, propfn, cookie);
+        if (err < 0)
+            return -1;
+    }
+    if (trie->right) {
+        int err = foreach_property(trie->right, propfn, cookie);
+        if (err < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie),
+        void *cookie)
+{
+    if (__predict_false(compat_mode)) {
+        return __system_property_foreach_compat(propfn, cookie);
+	}
+    return foreach_property(0, propfn, cookie);
+}
diff --git a/libc/bionic/system_properties_compat.c b/libc/bionic/system_properties_compat.c
new file mode 100644
index 0000000..6dbc4cc
--- /dev/null
+++ b/libc/bionic/system_properties_compat.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * This file is only used to provide backwards compatibility to property areas
+ * created by old versions of init, which occurs when an ota runs.  The updater
+ * binary is compiled statically against the newest bionic, but the recovery
+ * ramdisk may be using an old version of init.  This can all be removed once
+ * OTAs from pre-K versions are no longer supported.
+ */
+
+#include <string.h>
+#include <sys/atomics.h>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#define TOC_NAME_LEN(toc)       ((toc) >> 24)
+#define TOC_TO_INFO(area, toc)  ((prop_info_compat*) (((char*) area) + ((toc) & 0xFFFFFF)))
+
+struct prop_area_compat {
+    unsigned volatile count;
+    unsigned volatile serial;
+    unsigned magic;
+    unsigned version;
+    unsigned toc[1];
+};
+
+typedef struct prop_area_compat prop_area_compat;
+
+struct prop_area;
+typedef struct prop_area prop_area;
+
+struct prop_info_compat {
+    char name[PROP_NAME_MAX];
+    unsigned volatile serial;
+    char value[PROP_VALUE_MAX];
+};
+
+typedef struct prop_info_compat prop_info_compat;
+
+extern prop_area *__system_property_area__;
+
+const prop_info *__system_property_find_compat(const char *name)
+{
+    prop_area_compat *pa = (prop_area_compat *)__system_property_area__;
+    unsigned count = pa->count;
+    unsigned *toc = pa->toc;
+    unsigned len = strlen(name);
+    prop_info_compat *pi;
+
+    if (len >= PROP_NAME_MAX)
+        return 0;
+    if (len < 1)
+        return 0;
+
+    while(count--) {
+        unsigned entry = *toc++;
+        if(TOC_NAME_LEN(entry) != len) continue;
+
+        pi = TOC_TO_INFO(pa, entry);
+        if(memcmp(name, pi->name, len)) continue;
+
+        return (const prop_info *)pi;
+    }
+
+    return 0;
+}
+
+int __system_property_read_compat(const prop_info *_pi, char *name, char *value)
+{
+    unsigned serial, len;
+    const prop_info_compat *pi = (const prop_info_compat *)_pi;
+
+    for(;;) {
+        serial = pi->serial;
+        while(SERIAL_DIRTY(serial)) {
+            __futex_wait((volatile void *)&pi->serial, serial, 0);
+            serial = pi->serial;
+        }
+        len = SERIAL_VALUE_LEN(serial);
+        memcpy(value, pi->value, len + 1);
+        if(serial == pi->serial) {
+            if(name != 0) {
+                strcpy(name, pi->name);
+            }
+            return len;
+        }
+    }
+}
+
+int __system_property_foreach_compat(
+        void (*propfn)(const prop_info *pi, void *cookie),
+        void *cookie)
+{
+    prop_area_compat *pa = (prop_area_compat *)__system_property_area__;
+    unsigned i;
+
+    for (i = 0; i < pa->count; i++) {
+        unsigned entry = pa->toc[i];
+        prop_info_compat *pi = TOC_TO_INFO(pa, entry);
+        propfn((const prop_info *)pi, cookie);
+    }
+
+    return 0;
+}
diff --git a/libc/include/getopt.h b/libc/include/getopt.h
index 56f1983..4451941 100644
--- a/libc/include/getopt.h
+++ b/libc/include/getopt.h
@@ -1,5 +1,5 @@
-/*	$OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $	*/
 /*	$NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $	*/
+/*	$FreeBSD$ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -16,13 +16,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -43,7 +36,8 @@
 #include <sys/cdefs.h>
 
 /*
- * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
+ * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
+ * getopt() is declared here too for GNU programs.
  */
 #define no_argument        0
 #define required_argument  1
@@ -64,26 +58,20 @@
 };
 
 __BEGIN_DECLS
-int	 getopt_long(int, char * const *, const char *,
-	    const struct option *, int *);
-int	 getopt_long_only(int, char * const *, const char *,
-	    const struct option *, int *);
-#ifndef _GETOPT_DEFINED_
-#define _GETOPT_DEFINED_
-int	 getopt(int, char * const *, const char *);
+int	getopt_long(int, char * const *, const char *,
+	const struct option *, int *);
+int	getopt_long_only(int, char * const *, const char *,
+	const struct option *, int *);
+#ifndef _GETOPT_DECLARED
+#define	_GETOPT_DECLARED
+int	 getopt(int, char * const [], const char *);
 
-
-extern   char *optarg;                  /* getopt(3) external variables */
-extern   int opterr;
-extern   int optind;
-extern   int optopt;
-extern   int optreset;
-
-#if 0 /* MISSING FROM BIONIC */
-int       getsubopt(char **, char * const *, char **);
-extern   char *suboptarg;               /* getsubopt(3) external variable */
-#endif /* MISSING */
-
+extern char *optarg;			/* getopt(3) external variables */
+extern int optind, opterr, optopt;
+#endif
+#ifndef _OPTRESET_DECLARED
+#define	_OPTRESET_DECLARED
+extern int optreset;			/* getopt(3) external variable */
 #endif
 __END_DECLS
  
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 81d2315..73b22db 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -56,7 +56,7 @@
 #define	PRIdFAST64		"lld"		/* int_fast64_t */
 
 #define	PRIdMAX			"jd"		/* intmax_t */
-#define	PRIdPTR			"ld"		/* intptr_t */
+#define	PRIdPTR			"d"		/* intptr_t */
 
 #define	PRIi8			"i"		/* int8_t */
 #define	PRIi16			"i"		/* int16_t */
@@ -74,7 +74,7 @@
 #define	PRIiFAST64		"lli"		/* int_fast64_t */
 
 #define	PRIiMAX			"ji"		/* intmax_t */
-#define	PRIiPTR			"li"		/* intptr_t */
+#define	PRIiPTR			"i"		/* intptr_t */
 
 /* fprintf macros for unsigned integers */
 #define	PRIo8			"o"		/* int8_t */
@@ -93,7 +93,7 @@
 #define	PRIoFAST64		"llo"		/* int_fast64_t */
 
 #define	PRIoMAX			"jo"		/* intmax_t */
-#define	PRIoPTR			"lo"		/* intptr_t */
+#define	PRIoPTR			"o"		/* intptr_t */
 
 #define	PRIu8			"u"		/* uint8_t */
 #define	PRIu16			"u"		/* uint16_t */
@@ -111,7 +111,7 @@
 #define	PRIuFAST64		"llu"		/* uint_fast64_t */
 
 #define	PRIuMAX			"ju"		/* uintmax_t */
-#define	PRIuPTR			"lu"		/* uintptr_t */
+#define	PRIuPTR			"u"		/* uintptr_t */
 
 #define	PRIx8			"x"		/* uint8_t */
 #define	PRIx16			"x"		/* uint16_t */
@@ -129,7 +129,7 @@
 #define	PRIxFAST64		"llx"		/* uint_fast64_t */
 
 #define	PRIxMAX			"jx"		/* uintmax_t */
-#define	PRIxPTR			"lx"		/* uintptr_t */
+#define	PRIxPTR			"x"		/* uintptr_t */
 
 #define	PRIX8			"X"		/* uint8_t */
 #define	PRIX16			"X"		/* uint16_t */
@@ -147,7 +147,7 @@
 #define	PRIXFAST64		"llX"		/* uint_fast64_t */
 
 #define	PRIXMAX			"jX"		/* uintmax_t */
-#define	PRIXPTR			"lX"		/* uintptr_t */
+#define	PRIXPTR			"X"		/* uintptr_t */
 
 /* fscanf macros for signed integers */
 #define	SCNd8			"hhd"		/* int8_t */
@@ -166,7 +166,7 @@
 #define	SCNdFAST64		"lld"		/* int_fast64_t */
 
 #define	SCNdMAX			"jd"		/* intmax_t */
-#define	SCNdPTR			"ld"		/* intptr_t */
+#define	SCNdPTR			"d"		/* intptr_t */
 
 #define	SCNi8			"hhi"		/* int8_t */
 #define	SCNi16			"hi"		/* int16_t */
@@ -184,7 +184,7 @@
 #define	SCNiFAST64		"lli"		/* int_fast64_t */
 
 #define	SCNiMAX			"ji"		/* intmax_t */
-#define	SCNiPTR			"li"		/* intptr_t */
+#define	SCNiPTR			"i"		/* intptr_t */
 
 /* fscanf macros for unsigned integers */
 #define	SCNo8			"hho"		/* uint8_t */
@@ -203,7 +203,7 @@
 #define	SCNoFAST64		"llo"		/* uint_fast64_t */
 
 #define	SCNoMAX			"jo"		/* uintmax_t */
-#define	SCNoPTR			"lo"		/* uintptr_t */
+#define	SCNoPTR			"o"		/* uintptr_t */
 
 #define	SCNu8			"hhu"		/* uint8_t */
 #define	SCNu16			"hu"		/* uint16_t */
@@ -221,7 +221,7 @@
 #define	SCNuFAST64		"llu"		/* uint_fast64_t */
 
 #define	SCNuMAX			"ju"		/* uintmax_t */
-#define	SCNuPTR			"lu"		/* uintptr_t */
+#define	SCNuPTR			"u"		/* uintptr_t */
 
 #define	SCNx8			"hhx"		/* uint8_t */
 #define	SCNx16			"hx"		/* uint16_t */
@@ -239,7 +239,7 @@
 #define	SCNxFAST64		"llx"		/* uint_fast64_t */
 
 #define	SCNxMAX			"jx"		/* uintmax_t */
-#define	SCNxPTR			"lx"		/* uintptr_t */
+#define	SCNxPTR			"x"		/* uintptr_t */
 
 #endif /* __cplusplus || __STDC_FORMAT_MACROS */
 
diff --git a/libc/include/netinet/icmp6.h b/libc/include/netinet/icmp6.h
index fbc8234..6625712 100644
--- a/libc/include/netinet/icmp6.h
+++ b/libc/include/netinet/icmp6.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: icmp6.h,v 1.40 2009/10/31 22:32:17 christos Exp $	*/
+/*	$NetBSD: icmp6.h,v 1.47 2013/07/01 12:43:15 christos Exp $	*/
 /*	$KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $	*/
 
 
@@ -65,6 +65,8 @@
 #ifndef _NETINET_ICMP6_H_
 #define _NETINET_ICMP6_H_
 
+#include <netinet/in.h> /* android-added: glibc source compatibility. */
+
 #define ICMPV6_PLD_MAXLEN	1232	/* IPV6_MMTU - sizeof(struct ip6_hdr)
 					   - sizeof(struct icmp6_hdr) */
 
@@ -98,6 +100,7 @@
 #define MLD_LISTENER_QUERY		130 	/* multicast listener query */
 #define MLD_LISTENER_REPORT		131	/* multicast listener report */
 #define MLD_LISTENER_DONE		132	/* multicast listener done */
+#define MLD_LISTENER_REDUCTION MLD_LISTENER_DONE /* RFC3542 definition */
 
 /* RFC2292 decls */
 #define ICMP6_MEMBERSHIP_QUERY		130	/* group membership query */
@@ -125,6 +128,7 @@
 #define ICMP6_FQDN_REPLY		140	/* FQDN reply */
 #define ICMP6_NI_QUERY			139	/* node information request */
 #define ICMP6_NI_REPLY			140	/* node information reply */
+#define MLDV2_LISTENER_REPORT		143	/* RFC3810 listener report */
 
 /* The definitions below are experimental. TBA */
 #define MLD_MTRACE_RESP			200	/* mtrace response(to sender) */
@@ -144,6 +148,9 @@
 #define ICMP6_DST_UNREACH_BEYONDSCOPE	2	/* beyond scope of source address */
 #define ICMP6_DST_UNREACH_ADDR		3	/* address unreachable */
 #define ICMP6_DST_UNREACH_NOPORT	4	/* port unreachable */
+#define ICMP6_DST_UNREACH_POLICY	5	/* source address failed ingress/egress policy */
+#define ICMP6_DST_UNREACH_REJROUTE	6	/* reject route to destination */
+#define ICMP6_DST_UNREACH_SOURCERT	7	/* error in source routing header */
 
 #define ICMP6_TIME_EXCEED_TRANSIT 	0	/* ttl==0 in transit */
 #define ICMP6_TIME_EXCEED_REASSEMBLY	1	/* ttl==0 in reass */
@@ -229,7 +236,7 @@
 #define ND_RA_FLAG_HOME_AGENT	0x20
 
 /*
- * Router preference values based on RFC4199.
+ * Router preference values based on RFC4191.
  */
 #define ND_RA_FLAG_RTPREF_MASK	0x18 /* 00011000 */
 
@@ -300,11 +307,10 @@
 #define ND_OPT_HOMEAGENT_INFO		8
 #define ND_OPT_SOURCE_ADDRLIST		9
 #define ND_OPT_TARGET_ADDRLIST		10
-#define ND_OPT_RDNSS			25
-/* draft-ietf-ipngwg-router-preference, not officially assigned yet */
-#define ND_OPT_ROUTE_INFO		200
-/* draft-ietf-mobileip-hmipv6, not officially assigned yet */
-#define ND_OPT_MAP			201
+#define ND_OPT_MAP			23	/* RFC 5380 */
+#define ND_OPT_ROUTE_INFO		24	/* RFC 4191 */
+#define ND_OPT_RDNSS			25	/* RFC 6016 */
+#define ND_OPT_DNSSL			31	/* RFC 6016 */
 
 struct nd_opt_route_info {	/* route info */
 	u_int8_t	nd_opt_rti_type;
@@ -344,7 +350,7 @@
 	u_int32_t	nd_opt_mtu_mtu;
 } __packed;
 
-struct nd_opt_rdnss {		/* RDNSS option RFC 5006 */
+struct nd_opt_rdnss {		/* RDNSS option RFC 6106 */
 	u_int8_t	nd_opt_rdnss_type;
 	u_int8_t	nd_opt_rdnss_len;
 	u_int16_t	nd_opt_rdnss_reserved;
@@ -352,6 +358,14 @@
 	/* followed by list of IP prefixes */
 } __packed;
 
+struct nd_opt_dnssl {		/* DNSSL option RFC 6106 */
+	u_int8_t	nd_opt_dnssl_type;
+	u_int8_t	nd_opt_dnssl_len;
+	u_int16_t	nd_opt_dnssl_reserved;
+	u_int32_t	nd_opt_dnssl_lifetime;
+	/* followed by list of IP prefixes */
+} __packed;
+
 /*
  * icmp6 namelookup
  */
@@ -376,11 +390,15 @@
 	/* could be followed by reply data */
 } __packed;
 
+/*
+ * BEGIN android-removed: glibc doesn't have these, and external/ping declares them itself.
 #define ni_type		icmp6_ni_hdr.icmp6_type
 #define ni_code		icmp6_ni_hdr.icmp6_code
 #define ni_cksum	icmp6_ni_hdr.icmp6_cksum
 #define ni_qtype	icmp6_ni_hdr.icmp6_data16[0]
 #define ni_flags	icmp6_ni_hdr.icmp6_data16[1]
+ * END android-removed
+ */
 
 #define NI_QTYPE_NOOP		0 /* NOOP  */
 #define NI_QTYPE_SUPTYPES	1 /* Supported Qtypes */
@@ -521,18 +539,28 @@
 	u_int32_t icmp6_filt[8];
 };
 
+/*
+ * BEGIN android-changed
+ * Linux and *BSD kernels use opposite values to indicate pass/block in ICMPv6
+ * filters, and assign a different value to the ICMP6_FILTER sockopt.
+ */
+#define ICMP6_FILTER 1
+
 #define	ICMP6_FILTER_SETPASSALL(filterp) \
-	(void)memset(filterp, 0xff, sizeof(struct icmp6_filter))
-#define	ICMP6_FILTER_SETBLOCKALL(filterp) \
 	(void)memset(filterp, 0x00, sizeof(struct icmp6_filter))
+#define	ICMP6_FILTER_SETBLOCKALL(filterp) \
+	(void)memset(filterp, 0xff, sizeof(struct icmp6_filter))
 #define	ICMP6_FILTER_SETPASS(type, filterp) \
-	(((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
-#define	ICMP6_FILTER_SETBLOCK(type, filterp) \
 	(((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))
+#define	ICMP6_FILTER_SETBLOCK(type, filterp) \
+	(((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
 #define	ICMP6_FILTER_WILLPASS(type, filterp) \
-	((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
-#define	ICMP6_FILTER_WILLBLOCK(type, filterp) \
 	((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
+#define	ICMP6_FILTER_WILLBLOCK(type, filterp) \
+	((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
+/*
+ * END android-changed
+ */
 
 /*
  * Variables related to this implementation
@@ -569,8 +597,9 @@
 #define	ICMP6_STAT_BADRS	538	/* bad router solicitiation */
 #define	ICMP6_STAT_BADRA	539	/* bad router advertisement */
 #define	ICMP6_STAT_BADREDIRECT	540	/* bad redirect message */
+#define ICMP6_STAT_DROPPED_RAROUTE 541	/* discarded routes from router advertisement */
 
-#define	ICMP6_NSTATS		541
+#define	ICMP6_NSTATS		542
 
 #define	ICMP6_ERRSTAT_DST_UNREACH_NOROUTE	0
 #define	ICMP6_ERRSTAT_DST_UNREACH_ADMIN		1
@@ -640,8 +669,6 @@
 	{ "nd6_maxqueuelen", CTLTYPE_INT }, \
 }
 
-#define RTF_PROBEMTU	RTF_PROTO1
-
 #ifdef _KERNEL
 struct	rtentry;
 struct	rttimer;
@@ -727,4 +754,41 @@
 extern int	icmp6_redirtimeout;	/* cache time for redirect routes */
 #endif /* _KERNEL */
 
+#ifdef ICMP6_STRINGS
+/* Info: http://www.iana.org/assignments/icmpv6-parameters */
+
+static const char * const icmp6_type_err[] = {
+	"reserved0", "unreach", "packet_too_big", "timxceed", "paramprob",
+	NULL
+};
+
+static const char * const icmp6_type_info[] = {
+	"echo", "echoreply",
+	"mcastlistenq", "mcastlistenrep", "mcastlistendone",
+	"rtsol", "rtadv", "neighsol", "neighadv", "redirect",
+	"routerrenum", "nodeinfoq", "nodeinfor", "invneighsol", "invneighrep",
+	"mcastlistenrep2", "haad_req", "haad_rep",
+	"mobile_psol", "mobile_padv", "cga_sol", "cga_adv",
+	"experimental150", "mcast_rtadv", "mcast_rtsol", "mcast_rtterm",
+	"fmipv6_msg", "rpl_control", NULL
+};
+
+static const char * const icmp6_code_none[] = { "none", NULL };
+
+static const char * const icmp6_code_unreach[] = {
+	"noroute", "admin", "beyondscope", "addr", "port",
+	"srcaddr_policy", "reject_route", "source_route_err", NULL
+};
+
+static const char * const icmp6_code_timxceed[] = {
+	"intrans", "reass", NULL
+};
+
+static const char * const icmp6_code_paramprob[] = {
+	"hdr_field", "nxthdr_type", "option", NULL
+};      
+
+/* not all informational icmps that have codes have a names array */
+#endif
+
 #endif /* !_NETINET_ICMP6_H_ */
diff --git a/libc/include/resolv.h b/libc/include/resolv.h
index 7c34012..36b93ee 100644
--- a/libc/include/resolv.h
+++ b/libc/include/resolv.h
@@ -43,12 +43,14 @@
 extern struct __res_state *__res_state(void);
 #define _res (*__res_state())
 
-/* Base-64 functions - because some code expects it there */
+#define b64_ntop __b64_ntop
+#define b64_pton __b64_pton
+extern int b64_ntop(u_char const*, size_t, char*, size_t);
+extern int b64_pton(char const*, u_char*, size_t);
 
-#define b64_ntop        __b64_ntop
-#define b64_pton        __b64_pton
-extern int   b64_ntop(u_char const *, size_t, char *, size_t);
-extern int   b64_pton(char const *, u_char *, size_t);
+#define dn_comp __dn_comp
+extern int dn_comp(const char*, u_char*, int, u_char**, u_char**);
+extern int dn_expand(const u_char*, const u_char*, const u_char*, char*, int);
 
 __END_DECLS
 
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 511bcd2..23fc944 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -450,7 +450,7 @@
 __END_DECLS
 #endif /* _GNU_SOURCE */
 
-#if defined(__BIONIC_FORTIFY) && !defined(__clang__)
+#if defined(__BIONIC_FORTIFY)
 
 __BEGIN_DECLS
 
@@ -468,14 +468,21 @@
     return __builtin___vsprintf_chk(dest, 0, __bos(dest), format, ap);
 }
 
+#if defined(__clang__)
+#define snprintf(dest, size, ...) __builtin___snprintf_chk(dest, size, 0, __bos(dest), __VA_ARGS__)
+#else
 __BIONIC_FORTIFY_INLINE
 __printflike(3, 4)
-int snprintf(char *str, size_t size, const char *format, ...)
+int snprintf(char *dest, size_t size, const char *format, ...)
 {
-    return __builtin___snprintf_chk(str, size, 0,
-        __bos(str), format, __builtin_va_arg_pack());
+    return __builtin___snprintf_chk(dest, size, 0,
+        __bos(dest), format, __builtin_va_arg_pack());
 }
+#endif
 
+#if defined(__clang__)
+#define sprintf(dest, ...) __builtin___sprintf_chk(dest, 0, __bos(dest), __VA_ARGS__)
+#else
 __BIONIC_FORTIFY_INLINE
 __printflike(2, 3)
 int sprintf(char *dest, const char *format, ...)
@@ -483,7 +490,9 @@
     return __builtin___sprintf_chk(dest, 0,
         __bos(dest), format, __builtin_va_arg_pack());
 }
+#endif
 
+#if !defined(__clang__)
 extern char *__fgets_real(char *, int, FILE *)
     __asm__(__USER_LABEL_PREFIX__ "fgets");
 __errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
@@ -521,8 +530,10 @@
     return __fgets_chk(dest, size, stream, bos);
 }
 
+#endif /* !defined(__clang__) */
+
 __END_DECLS
 
-#endif /* defined(__BIONIC_FORTIFY) && !defined(__clang__) */
+#endif /* defined(__BIONIC_FORTIFY) */
 
 #endif /* _STDIO_H_ */
diff --git a/libc/include/string.h b/libc/include/string.h
index 2b7d47c..7801ee9 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -175,7 +175,6 @@
     return __strlcpy_chk(dest, src, size, bos);
 }
 
-#if !defined(__clang__)
 extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t)
     __asm__(__USER_LABEL_PREFIX__ "strlcat");
 __errordecl(__strlcat_error, "strlcat called with size bigger than buffer");
@@ -186,6 +185,7 @@
 size_t strlcat(char* __restrict dest, const char* __restrict src, size_t size) {
     size_t bos = __bos(dest);
 
+#if !defined(__clang__)
     // Compiler doesn't know destination size. Don't call __strlcat_chk
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __strlcat_real(dest, src, size);
@@ -202,10 +202,10 @@
     if (__builtin_constant_p(size) && (size > bos)) {
         __strlcat_error();
     }
+#endif /* !defined(__clang__) */
 
     return __strlcat_chk(dest, src, size, bos);
 }
-#endif /* !defined(__clang__) */
 
 __BIONIC_FORTIFY_INLINE
 size_t strlen(const char *s) {
diff --git a/libc/include/strings.h b/libc/include/strings.h
index faa12a4..e72798b 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -50,12 +50,12 @@
 int	 strcasecmp(const char *, const char *);
 int	 strncasecmp(const char *, const char *, size_t);
 
-#if defined(__BIONIC_FORTIFY) && !defined(__clang__)
+#if defined(__BIONIC_FORTIFY)
 __BIONIC_FORTIFY_INLINE
 void bzero (void *s, size_t n) {
     __builtin___memset_chk(s, '\0', n, __builtin_object_size (s, 0));
 }
-#endif /* defined(__BIONIC_FORTIFY) && !defined(__clang__) */
+#endif /* defined(__BIONIC_FORTIFY) */
 
 __END_DECLS
 
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index 4971a4c..5eee7f0 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -37,21 +37,13 @@
 typedef struct prop_msg prop_msg;
 
 #define PROP_AREA_MAGIC   0x504f5250
-#define PROP_AREA_VERSION 0x45434f76
+#define PROP_AREA_VERSION 0xfc6ed0ab
+#define PROP_AREA_VERSION_COMPAT 0x45434f76
 
 #define PROP_SERVICE_NAME "property_service"
 #define PROP_FILENAME "/dev/__properties__"
 
-/* (4 header words + 28 toc words) = 128 bytes */
-/* 128 bytes header and toc + 28 prop_infos @ 128 bytes = 3712 bytes */
-
-#define PA_COUNT_MAX    28
-#define PA_REGION_COUNT 128
-#define PA_INFO_START   128
-#define PA_SIZE         4096
-
-#define TOC_NAME_LEN(toc)       ((toc) >> 24)
-#define TOC_TO_INFO(area, toc)  ((prop_info*) (((char*) area) + ((toc) & 0xFFFFFF)))
+#define PA_SIZE         (128 * 1024)
 
 #define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
 #define SERIAL_DIRTY(serial) ((serial) & 1)
@@ -84,11 +76,6 @@
 **   1. pi->serial = pi->serial | 1
 **   2. memcpy(pi->value, local_value, value_len)
 **   3. pi->serial = (value_len << 24) | ((pi->serial + 1) & 0xffffff)
-**
-** Improvements:
-** - maintain the toc sorted by pi->name to allow lookup
-**   by binary search
-**
 */
 
 #define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
@@ -143,6 +130,15 @@
 ** successive call. */
 unsigned int __system_property_wait_any(unsigned int serial);
 
+/*  Compatibility functions to support using an old init with a new libc,
+ ** mostly for the OTA updater binary.  These can be deleted once OTAs from
+ ** a pre-K release no longer needed to be supported. */
+const prop_info *__system_property_find_compat(const char *name);
+int __system_property_read_compat(const prop_info *pi, char *name, char *value);
+int __system_property_foreach_compat(
+        void (*propfn)(const prop_info *pi, void *cookie),
+        void *cookie);
+
 __END_DECLS
 
 #endif
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index c7fb9de..a4c1aff 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -211,8 +211,10 @@
 #define __statement(x)	(x)
 #endif
 
-#define __printflike(x, y) __attribute__((__format__(printf, x, y))) __attribute__((__nonnull__(x)))
-#define __scanflike(x, y) __attribute__((__format__(scanf, x, y))) __attribute__((__nonnull__(x)))
+#define __nonnull(args) __attribute__((__nonnull__ args))
+
+#define __printflike(x, y) __attribute__((__format__(printf, x, y))) __nonnull((x))
+#define __scanflike(x, y) __attribute__((__format__(scanf, x, y))) __nonnull((x))
 
 /*
  * C99 defines the restrict type qualifier keyword, which was made available
diff --git a/libc/include/sys/ioctl.h b/libc/include/sys/ioctl.h
index 9f68510..49d452c 100644
--- a/libc/include/sys/ioctl.h
+++ b/libc/include/sys/ioctl.h
@@ -30,6 +30,11 @@
 
 #include <sys/cdefs.h>
 #include <linux/ioctl.h>
+/*
+ * NetBSD and glibc's <sys/ioctl.h> provide some of the
+ * terminal-related ioctl data structures such as struct winsize.
+ */
+#include <linux/termios.h>
 #include <asm/ioctls.h>
 #include <asm/termbits.h>
 #include <sys/ioctl_compat.h>
diff --git a/libc/include/sys/mount.h b/libc/include/sys/mount.h
index 207527e..3c35d31 100644
--- a/libc/include/sys/mount.h
+++ b/libc/include/sys/mount.h
@@ -30,75 +30,18 @@
 
 #include <sys/cdefs.h>
 #include <sys/ioctl.h>
+#include <linux/fs.h>
 
 __BEGIN_DECLS
 
-/*
- * These are the fs-independent mount-flags: up to 32 flags are supported
- */
-#define MS_RDONLY        1      /* Mount read-only */
-#define MS_NOSUID        2      /* Ignore suid and sgid bits */
-#define MS_NODEV         4      /* Disallow access to device special files */
-#define MS_NOEXEC        8      /* Disallow program execution */
-#define MS_SYNCHRONOUS  16      /* Writes are synced at once */
-#define MS_REMOUNT      32      /* Alter flags of a mounted FS */
-#define MS_MANDLOCK     64      /* Allow mandatory locks on an FS */
-#define MS_DIRSYNC      128     /* Directory modifications are synchronous */
-#define MS_NOATIME      1024    /* Do not update access times. */
-#define MS_NODIRATIME   2048    /* Do not update directory access times */
-#define MS_BIND         4096
-#define MS_MOVE         8192
-#define MS_REC          16384
-#define MS_VERBOSE      32768
-#define MS_POSIXACL     (1<<16) /* VFS does not apply the umask */
-#define MS_UNBINDABLE   (1<<17) /* change to unbindable */
-#define MS_PRIVATE      (1<<18) /* change to private */
-#define MS_SLAVE        (1<<19) /* change to slave */
-#define MS_SHARED       (1<<20) /* change to shared */
-#define MS_ACTIVE       (1<<30)
-#define MS_NOUSER       (1<<31)
-
-/*
- * Superblock flags that can be altered by MS_REMOUNT
- */
-#define MS_RMT_MASK     (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME)
-
-/*
- * Old magic mount flag and mask
- */
-#define MS_MGC_VAL 0xC0ED0000
-#define MS_MGC_MSK 0xffff0000
-
-/*
- * umount2() flags
- */
+/* umount2 flags. */
 #define MNT_FORCE	1	/* Forcibly unmount */
 #define MNT_DETACH	2	/* Detach from tree only */
 #define MNT_EXPIRE	4	/* Mark for expiry */
 
-/*
- * Block device ioctls
- */
-#define BLKROSET   _IO(0x12, 93) /* Set device read-only (0 = read-write).  */
-#define BLKROGET   _IO(0x12, 94) /* Get read-only status (0 = read_write).  */
-#define BLKRRPART  _IO(0x12, 95) /* Re-read partition table.  */
-#define BLKGETSIZE _IO(0x12, 96) /* Return device size.  */
-#define BLKFLSBUF  _IO(0x12, 97) /* Flush buffer cache.  */
-#define BLKRASET   _IO(0x12, 98) /* Set read ahead for block device.  */
-#define BLKRAGET   _IO(0x12, 99) /* Get current read ahead setting.  */
-
-/*
- * Prototypes
- */
-extern int mount(const char *, const char *,
-		   const char *, unsigned long,
-		   const void *);
-extern int umount(const char *);
-extern int umount2(const char *, int);
-
-#if 0 /* MISSING FROM BIONIC */
-extern int pivot_root(const char *, const char *);
-#endif /* MISSING */
+extern int mount(const char*, const char*, const char*, unsigned long, const void*);
+extern int umount(const char*);
+extern int umount2(const char*, int);
 
 __END_DECLS
 
diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h
index a249d65..2537ab9 100644
--- a/libc/include/sys/signalfd.h
+++ b/libc/include/sys/signalfd.h
@@ -35,7 +35,7 @@
 
 __BEGIN_DECLS
 
-extern int signalfd(int fd, const sigset_t* mask, int flags) __attribute__((__nonnull__(2)));
+extern int signalfd(int fd, const sigset_t* mask, int flags) __nonnull((2));
 
 __END_DECLS
 
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index c9ad23d..c7715a3 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -129,7 +129,7 @@
 extern int    mknod(const char *, mode_t, dev_t);
 extern mode_t umask(mode_t);
 
-#if defined(__BIONIC_FORTIFY) && !defined(__clang__)
+#if defined(__BIONIC_FORTIFY)
 
 extern mode_t __umask_chk(mode_t);
 extern mode_t __umask_real(mode_t)
@@ -138,15 +138,17 @@
 
 __BIONIC_FORTIFY_INLINE
 mode_t umask(mode_t mode) {
+#if !defined(__clang__)
   if (__builtin_constant_p(mode)) {
     if ((mode & 0777) != mode) {
       __umask_invalid_mode();
     }
     return __umask_real(mode);
   }
+#endif
   return __umask_chk(mode);
 }
-#endif /* defined(__BIONIC_FORTIFY) && !defined(__clang__) */
+#endif /* defined(__BIONIC_FORTIFY) */
 
 
 #define  stat64    stat
diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h
new file mode 100644
index 0000000..e910c03
--- /dev/null
+++ b/libc/include/sys/statvfs.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 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 _SYS_STATVFS_H_
+#define _SYS_STATVFS_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+struct statvfs {
+  unsigned long f_bsize;
+  unsigned long f_frsize;
+  fsblkcnt_t    f_blocks;
+  fsblkcnt_t    f_bfree;
+  fsblkcnt_t    f_bavail;
+  fsfilcnt_t    f_files;
+  fsfilcnt_t    f_ffree;
+  fsfilcnt_t    f_favail;
+  unsigned long f_fsid;
+  unsigned long f_flag;
+  unsigned long f_namemax;
+};
+
+#define ST_RDONLY      0x0001
+#define ST_NOSUID      0x0002
+#define ST_NODEV       0x0004
+#define ST_NOEXEC      0x0008
+#define ST_SYNCHRONOUS 0x0010
+#define ST_MANDLOCK    0x0040
+#define ST_NOATIME     0x0400
+#define ST_NODIRATIME  0x0800
+#define ST_RELATIME    0x1000
+
+extern int statvfs(const char* __restrict, struct statvfs* __restrict) __nonnull((1, 2));
+extern int fstatvfs(int, struct statvfs*) __nonnull((2));
+
+__END_DECLS
+
+#endif /* _SYS_STATVFS_H_ */
diff --git a/libc/include/sys/swap.h b/libc/include/sys/swap.h
new file mode 100644
index 0000000..97a6f36
--- /dev/null
+++ b/libc/include/sys/swap.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _SYS_SWAP_H_
+#define _SYS_SWAP_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+extern int swapon(const char*, int) __nonnull((1));
+extern int swapoff(const char*) __nonnull((1));
+
+__END_DECLS
+
+#endif /* _SYS_SWAP_H_ */
diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h
index d14944d..6a55c99 100644
--- a/libc/include/sys/vfs.h
+++ b/libc/include/sys/vfs.h
@@ -34,7 +34,7 @@
 
 __BEGIN_DECLS
 
-/* note: this corresponds to the kernel's statfs64 type */
+/* These correspond to the kernel's statfs64 type. */
 #ifdef __mips__
 struct statfs {
     uint32_t        f_type;
@@ -48,7 +48,8 @@
     uint64_t        f_bavail;
     __kernel_fsid_t f_fsid;
     uint32_t        f_namelen;
-    uint32_t        f_spare[6];
+    uint32_t        f_flags;
+    uint32_t        f_spare[5];
 };
 #else
 struct statfs {
@@ -62,7 +63,8 @@
     __kernel_fsid_t f_fsid;
     uint32_t        f_namelen;
     uint32_t        f_frsize;
-    uint32_t        f_spare[5];
+    uint32_t        f_flags;
+    uint32_t        f_spare[4];
 };
 #endif
 
diff --git a/libc/kernel/common/linux/fs.h b/libc/kernel/common/linux/fs.h
index 6b7e6b8..538d0e4 100644
--- a/libc/kernel/common/linux/fs.h
+++ b/libc/kernel/common/linux/fs.h
@@ -33,190 +33,195 @@
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define SEEK_CUR 1
 #define SEEK_END 2
-#define SEEK_MAX SEEK_END
-struct fstrim_range {
+#define SEEK_DATA 3
+#define SEEK_HOLE 4
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SEEK_MAX SEEK_HOLE
+struct fstrim_range {
  __u64 start;
  __u64 len;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u64 minlen;
 };
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 struct files_stat_struct {
  unsigned long nr_files;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  unsigned long nr_free_files;
  unsigned long max_files;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
 struct inodes_stat_t {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int nr_inodes;
  int nr_unused;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int dummy[5];
 };
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define NR_FILE 8192
-#define MAY_EXEC 1
+#define MAY_EXEC 0x00000001
+#define MAY_WRITE 0x00000002
+#define MAY_READ 0x00000004
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MAY_WRITE 2
-#define MAY_READ 4
-#define MAY_APPEND 8
-#define MAY_ACCESS 16
+#define MAY_APPEND 0x00000008
+#define MAY_ACCESS 0x00000010
+#define MAY_OPEN 0x00000020
+#define MAY_CHDIR 0x00000040
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MAY_OPEN 32
-#define MAY_CHDIR 64
+#define MAY_NOT_BLOCK 0x00000080
 #define FMODE_READ ((__force fmode_t)0x1)
 #define FMODE_WRITE ((__force fmode_t)0x2)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FMODE_LSEEK ((__force fmode_t)0x4)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FMODE_PREAD ((__force fmode_t)0x8)
 #define FMODE_PWRITE ((__force fmode_t)0x10)
 #define FMODE_EXEC ((__force fmode_t)0x20)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FMODE_NDELAY ((__force fmode_t)0x40)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FMODE_EXCL ((__force fmode_t)0x80)
 #define FMODE_WRITE_IOCTL ((__force fmode_t)0x100)
-#define FMODE_NOCMTIME ((__force fmode_t)0x800)
+#define FMODE_32BITHASH ((__force fmode_t)0x200)
+#define FMODE_64BITHASH ((__force fmode_t)0x400)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FMODE_NOCMTIME ((__force fmode_t)0x800)
 #define FMODE_RANDOM ((__force fmode_t)0x1000)
 #define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000)
 #define FMODE_PATH ((__force fmode_t)0x4000)
-#define FMODE_NONOTIFY ((__force fmode_t)0x1000000)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FMODE_NONOTIFY ((__force fmode_t)0x1000000)
 #define RW_MASK REQ_WRITE
 #define RWA_MASK REQ_RAHEAD
 #define READ 0
-#define WRITE RW_MASK
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WRITE RW_MASK
 #define READA RWA_MASK
 #define READ_SYNC (READ | REQ_SYNC)
-#define READ_META (READ | REQ_META)
 #define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define WRITE_ODIRECT (WRITE | REQ_SYNC)
-#define WRITE_META (WRITE | REQ_META)
 #define WRITE_FLUSH (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH)
 #define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define SEL_IN 1
 #define SEL_OUT 2
 #define SEL_EX 4
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FS_REQUIRES_DEV 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FS_BINARY_MOUNTDATA 2
 #define FS_HAS_SUBTYPE 4
 #define FS_REVAL_DOT 16384
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FS_RENAME_DOES_D_MOVE 32768
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_RDONLY 1
 #define MS_NOSUID 2
 #define MS_NODEV 4
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_NOEXEC 8
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_SYNCHRONOUS 16
 #define MS_REMOUNT 32
 #define MS_MANDLOCK 64
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_DIRSYNC 128
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_NOATIME 1024
 #define MS_NODIRATIME 2048
 #define MS_BIND 4096
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_MOVE 8192
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_REC 16384
 #define MS_VERBOSE 32768
 #define MS_SILENT 32768
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_POSIXACL (1<<16)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_UNBINDABLE (1<<17)
 #define MS_PRIVATE (1<<18)
 #define MS_SLAVE (1<<19)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_SHARED (1<<20)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_RELATIME (1<<21)
 #define MS_KERNMOUNT (1<<22)
 #define MS_I_VERSION (1<<23)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_STRICTATIME (1<<24)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_NOSEC (1<<28)
 #define MS_BORN (1<<29)
 #define MS_ACTIVE (1<<30)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_NOUSER (1<<31)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION)
 #define MS_MGC_VAL 0xC0ED0000
 #define MS_MGC_MSK 0xffff0000
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define S_SYNC 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define S_NOATIME 2
 #define S_APPEND 4
 #define S_IMMUTABLE 8
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define S_DEAD 16
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define S_NOQUOTA 32
 #define S_DIRSYNC 64
 #define S_NOCMTIME 128
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define S_SWAPFILE 256
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define S_PRIVATE 512
 #define S_IMA 1024
 #define S_AUTOMOUNT 2048
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define S_NOSEC 4096
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg))
 #define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
 #define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) ||   ((inode)->i_flags & S_SYNC))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_DIRSYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) ||   ((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK)
 #define IS_NOATIME(inode) __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
 #define IS_I_VERSION(inode) __IS_FLG(inode, MS_I_VERSION)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
 #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
 #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
 #define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
 #define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_IMA(inode) ((inode)->i_flags & S_IMA)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT)
 #define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC)
 #define BLKROSET _IO(0x12,93)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKROGET _IO(0x12,94)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKRRPART _IO(0x12,95)
 #define BLKGETSIZE _IO(0x12,96)
 #define BLKFLSBUF _IO(0x12,97)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKRASET _IO(0x12,98)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKRAGET _IO(0x12,99)
 #define BLKFRASET _IO(0x12,100)
 #define BLKFRAGET _IO(0x12,101)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKSECTSET _IO(0x12,102)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKSECTGET _IO(0x12,103)
 #define BLKSSZGET _IO(0x12,104)
 #define BLKBSZGET _IOR(0x12,112,size_t)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKBSZSET _IOW(0x12,113,size_t)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
 #define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup)
 #define BLKTRACESTART _IO(0x12,116)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKTRACESTOP _IO(0x12,117)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKTRACETEARDOWN _IO(0x12,118)
 #define BLKDISCARD _IO(0x12,119)
 #define BLKIOMIN _IO(0x12,120)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKIOOPT _IO(0x12,121)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKALIGNOFF _IO(0x12,122)
 #define BLKPBSZGET _IO(0x12,123)
 #define BLKDISCARDZEROES _IO(0x12,124)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BLKSECDISCARD _IO(0x12,125)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define BLKROTATIONAL _IO(0x12,126)
 #define BMAP_IOCTL 1
 #define FIBMAP _IO(0x00,1)
 #define FIGETBSZ _IO(0x00,2)
diff --git a/libc/kernel/common/linux/types.h b/libc/kernel/common/linux/types.h
index 90b0f6b..b40959c 100644
--- a/libc/kernel/common/linux/types.h
+++ b/libc/kernel/common/linux/types.h
@@ -33,12 +33,14 @@
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 typedef __u64 __bitwise __be64;
 #endif
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 struct ustat {
  __kernel_daddr_t f_tfree;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __kernel_ino_t f_tinode;
  char f_fname[6];
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  char f_fpack[6];
 };
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
diff --git a/libc/private/bionic_atomic_arm.h b/libc/private/bionic_atomic_arm.h
index 275c1c9..3bb639e 100644
--- a/libc/private/bionic_atomic_arm.h
+++ b/libc/private/bionic_atomic_arm.h
@@ -70,10 +70,6 @@
  *        code is going to run on a single or multi-core device, so we
  *        need to be cautious.
  *
- *        Fortunately, we can use the kernel helper function that is
- *        mapped at address 0xffff0fa0 in all user process, and that
- *        provides a device-specific barrier operation.
- *
  *        I.e. on single-core devices, the helper immediately returns,
  *        on multi-core devices, it uses "dmb" or any other means to
  *        perform a full-memory barrier.
@@ -82,7 +78,7 @@
  *
  *    - multi-core ARMv7-A       => use the 'dmb' hardware instruction
  *    - multi-core ARMv6         => use the coprocessor
- *    - single core ARMv5TE/6/7  => do not use any hardware barrier
+ *    - single core ARMv6+       => do not use any hardware barrier
  */
 #if defined(ANDROID_SMP) && ANDROID_SMP == 1
 
@@ -124,18 +120,14 @@
 }
 #endif /* !ANDROID_SMP */
 
+#ifndef __ARM_HAVE_LDREX_STREX
+#error Only ARM devices which have LDREX / STREX are supported
+#endif
+
 /* Compare-and-swap, without any explicit barriers. Note that this functions
  * returns 0 on success, and 1 on failure. The opposite convention is typically
  * used on other platforms.
- *
- * There are two cases to consider:
- *
- *     - ARMv6+  => use LDREX/STREX instructions
- *     - < ARMv6 => use kernel helper function mapped at 0xffff0fc0
- *
- * LDREX/STREX are only available starting from ARMv6
  */
-#ifdef __ARM_HAVE_LDREX_STREX
 __ATOMIC_INLINE__ int
 __bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
 {
@@ -157,32 +149,8 @@
     } while (__builtin_expect(status != 0, 0));
     return prev != old_value;
 }
-#  else /* !__ARM_HAVE_LDREX_STREX */
 
-/* Use the handy kernel helper function mapped at 0xffff0fc0 */
-typedef int (kernel_cmpxchg)(int32_t, int32_t, volatile int32_t *);
-
-__ATOMIC_INLINE__ int
-__kernel_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
-{
-    /* Note: the kernel function returns 0 on success too */
-    return (*(kernel_cmpxchg *)0xffff0fc0)(old_value, new_value, ptr);
-}
-
-__ATOMIC_INLINE__ int
-__bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
-{
-    return __kernel_cmpxchg(old_value, new_value, ptr);
-}
-#endif /* !__ARM_HAVE_LDREX_STREX */
-
-/* Swap operation, without any explicit barriers.
- * There are again two similar cases to consider:
- *
- *   ARMv6+ => use LDREX/STREX
- *   < ARMv6 => use SWP instead.
- */
-#ifdef __ARM_HAVE_LDREX_STREX
+/* Swap operation, without any explicit barriers. */
 __ATOMIC_INLINE__ int32_t
 __bionic_swap(int32_t new_value, volatile int32_t* ptr)
 {
@@ -199,24 +167,10 @@
     } while (__builtin_expect(status != 0, 0));
     return prev;
 }
-#else /* !__ARM_HAVE_LDREX_STREX */
-__ATOMIC_INLINE__ int32_t
-__bionic_swap(int32_t new_value, volatile int32_t* ptr)
-{
-    int32_t prev;
-    /* NOTE: SWP is available in Thumb-1 too */
-    __asm__ __volatile__ ("swp %0, %2, [%3]"
-                          : "=&r" (prev), "+m" (*ptr)
-                          : "r" (new_value), "r" (ptr)
-                          : "cc");
-    return prev;
-}
-#endif /* !__ARM_HAVE_LDREX_STREX */
 
 /* Atomic increment - without any barriers
  * This returns the old value
  */
-#ifdef __ARM_HAVE_LDREX_STREX
 __ATOMIC_INLINE__ int32_t
 __bionic_atomic_inc(volatile int32_t* ptr)
 {
@@ -234,23 +188,10 @@
     } while (__builtin_expect(status != 0, 0));
     return prev;
 }
-#else
-__ATOMIC_INLINE__ int32_t
-__bionic_atomic_inc(volatile int32_t* ptr)
-{
-    int32_t  prev, status;
-    do {
-        prev = *ptr;
-        status = __kernel_cmpxchg(prev, prev+1, ptr);
-    } while (__builtin_expect(status != 0, 0));
-    return prev;
-}
-#endif
 
 /* Atomic decrement - without any barriers
  * This returns the old value.
  */
-#ifdef __ARM_HAVE_LDREX_STREX
 __ATOMIC_INLINE__ int32_t
 __bionic_atomic_dec(volatile int32_t* ptr)
 {
@@ -268,17 +209,5 @@
     } while (__builtin_expect(status != 0, 0));
     return prev;
 }
-#else
-__ATOMIC_INLINE__ int32_t
-__bionic_atomic_dec(volatile int32_t* ptr)
-{
-    int32_t  prev, status;
-    do {
-        prev = *ptr;
-        status = __kernel_cmpxchg(prev, prev-1, ptr);
-    } while (__builtin_expect(status != 0, 0));
-    return prev;
-}
-#endif
 
 #endif /* SYS_ATOMICS_ARM_H */
diff --git a/libc/private/resolv_private.h b/libc/private/resolv_private.h
index 61db8c8..c7bcb89 100644
--- a/libc/private/resolv_private.h
+++ b/libc/private/resolv_private.h
@@ -346,12 +346,9 @@
 extern const struct res_sym __p_rcode_syms[];
 #endif /* SHARED_LIBBIND */
 
-#ifndef ADNROID_CHANGES
-#define b64_ntop		__b64_ntop
-#define b64_pton		__b64_pton
-#endif
-
+#ifndef ANDROID_CHANGES
 #define dn_comp			__dn_comp
+#endif
 #define dn_count_labels		__dn_count_labels
 #define dn_skipname		__dn_skipname
 #define fp_resstat		__fp_resstat
@@ -446,9 +443,6 @@
 const char *	p_option(u_long);
 char *		p_secstodate(u_long);
 int		dn_count_labels(const char *);
-int		dn_comp(const char *, u_char *, int, u_char **, u_char **);
-int		dn_expand(const u_char *, const u_char *, const u_char *,
-			       char *, int);
 u_int		res_randomid(void);
 int		res_nameinquery(const char *, int, int, const u_char *,
 				     const u_char *);
diff --git a/libc/upstream-freebsd/freebsd-compat.h b/libc/upstream-freebsd/freebsd-compat.h
index 5298663..8030eea 100644
--- a/libc/upstream-freebsd/freebsd-compat.h
+++ b/libc/upstream-freebsd/freebsd-compat.h
@@ -18,6 +18,7 @@
 #define _BIONIC_FREEBSD_COMPAT_H_included
 
 #define __USE_BSD
+#define REPLACE_GETOPT
 
 #define _close close
 #define _fcntl fcntl
diff --git a/libc/unistd/getopt_long.c b/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c
similarity index 79%
rename from libc/unistd/getopt_long.c
rename to libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c
index dbdf01a..9f7f6d5 100644
--- a/libc/unistd/getopt_long.c
+++ b/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: getopt_long.c,v 1.20 2005/10/25 15:49:37 jmc Exp $	*/
+/*	$OpenBSD: getopt_long.c,v 1.22 2006/10/04 21:29:04 jmc Exp $	*/
 /*	$NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $	*/
 
 /*
@@ -35,13 +35,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -56,22 +49,33 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <err.h>
 #include <errno.h>
 #include <getopt.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 
+#define GNU_COMPATIBLE		/* Be more compatible, configure's use us! */
+
+#if 0				/* we prefer to keep our getopt(3) */
 #define	REPLACE_GETOPT		/* use this getopt as the system getopt(3) */
+#endif
 
 #ifdef REPLACE_GETOPT
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
+int	optreset;		/* reset getopt */
 char    *optarg;		/* argument associated with option */
 #endif
-int	optreset;		/* reset getopt */
 
 #define PRINT_ERROR	((opterr) && (*options != ':'))
 
@@ -86,10 +90,17 @@
 
 #define	EMSG		""
 
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX	(-1)
+#define D_PREFIX	0
+#define DD_PREFIX	1
+#define W_PREFIX	2
+#endif
+
 static int getopt_internal(int, char * const *, const char *,
 			   const struct option *, int *, int);
 static int parse_long_options(char * const *, const char *,
-			      const struct option *, int *, int);
+			      const struct option *, int *, int, int);
 static int gcd(int, int);
 static void permute_args(int, int, int, char * const *);
 
@@ -101,11 +112,21 @@
 
 /* Error messages */
 static const char recargchar[] = "option requires an argument -- %c";
+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c";
+
+static const char recargstring[] = "option `%s%s' requires an argument";
+static const char ambig[] = "option `%s%.*s' is ambiguous";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
+static const char illoptstring[] = "unrecognized option `%s%s'";
+#else
 static const char recargstring[] = "option requires an argument -- %s";
 static const char ambig[] = "ambiguous option -- %.*s";
 static const char noarg[] = "option doesn't take an argument -- %.*s";
-static const char illoptchar[] = "unknown option -- %c";
 static const char illoptstring[] = "unknown option -- %s";
+#endif
 
 /*
  * Compute the greatest common divisor of a and b.
@@ -169,14 +190,35 @@
  */
 static int
 parse_long_options(char * const *nargv, const char *options,
-	const struct option *long_options, int *idx, int short_too)
+	const struct option *long_options, int *idx, int short_too, int flags)
 {
 	char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+	char *current_dash;
+#endif
 	size_t current_argv_len;
-	int i, match;
+	int i, match, exact_match, second_partial_match;
 
 	current_argv = place;
+#ifdef GNU_COMPATIBLE
+	switch (dash_prefix) {
+		case D_PREFIX:
+			current_dash = "-";
+			break;
+		case DD_PREFIX:
+			current_dash = "--";
+			break;
+		case W_PREFIX:
+			current_dash = "-W ";
+			break;
+		default:
+			current_dash = "";
+			break;
+	}
+#endif
 	match = -1;
+	exact_match = 0;
+	second_partial_match = 0;
 
 	optind++;
 
@@ -196,6 +238,7 @@
 		if (strlen(long_options[i].name) == current_argv_len) {
 			/* exact match */
 			match = i;
+			exact_match = 1;
 			break;
 		}
 		/*
@@ -205,25 +248,37 @@
 		if (short_too && current_argv_len == 1)
 			continue;
 
-		if (match == -1)	/* partial match */
+		if (match == -1)        /* first partial match */
 			match = i;
-		else {
-			/* ambiguous abbreviation */
-			if (PRINT_ERROR)
-				fprintf(stderr, 
-                        ambig, (int)current_argv_len,
-                        current_argv);
-			optopt = 0;
-			return (BADCH);
-		}
+		else if ((flags & FLAG_LONGONLY) ||
+			 long_options[i].has_arg !=
+			     long_options[match].has_arg ||
+			 long_options[i].flag != long_options[match].flag ||
+			 long_options[i].val != long_options[match].val)
+			second_partial_match = 1;
+	}
+	if (!exact_match && second_partial_match) {
+		/* ambiguous abbreviation */
+		if (PRINT_ERROR)
+			warnx(ambig,
+#ifdef GNU_COMPATIBLE
+			     current_dash,
+#endif
+			     (int)current_argv_len,
+			     current_argv);
+		optopt = 0;
+		return (BADCH);
 	}
 	if (match != -1) {		/* option found */
 		if (long_options[match].has_arg == no_argument
 		    && has_equal) {
 			if (PRINT_ERROR)
-				fprintf(stderr,
-                        noarg, (int)current_argv_len,
-                        current_argv);
+				warnx(noarg,
+#ifdef GNU_COMPATIBLE
+				     current_dash,
+#endif
+				     (int)current_argv_len,
+				     current_argv);
 			/*
 			 * XXX: GNU sets optopt to val regardless of flag
 			 */
@@ -231,7 +286,11 @@
 				optopt = long_options[match].val;
 			else
 				optopt = 0;
+#ifdef GNU_COMPATIBLE
+			return (BADCH);
+#else
 			return (BADARG);
+#endif
 		}
 		if (long_options[match].has_arg == required_argument ||
 		    long_options[match].has_arg == optional_argument) {
@@ -252,9 +311,11 @@
 			 * should be generated.
 			 */
 			if (PRINT_ERROR)
-				fprintf(stderr, 
-                        recargstring,
-                        current_argv);
+				warnx(recargstring,
+#ifdef GNU_COMPATIBLE
+				    current_dash,
+#endif
+				    current_argv);
 			/*
 			 * XXX: GNU sets optopt to val regardless of flag
 			 */
@@ -271,7 +332,11 @@
 			return (-1);
 		}
 		if (PRINT_ERROR)
-			fprintf(stderr, illoptstring, current_argv);
+			warnx(illoptstring,
+#ifdef GNU_COMPATIBLE
+			      current_dash,
+#endif
+			      current_argv);
 		optopt = 0;
 		return (BADCH);
 	}
@@ -294,7 +359,7 @@
 {
 	char *oli;				/* option letter list index */
 	int optchar, short_too;
-	static int posixly_correct = -1;
+	int posixly_correct;	/* no static, can be changed on the fly */
 
 	if (options == NULL)
 		return (-1);
@@ -303,12 +368,18 @@
 	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
 	 * string begins with a '+'.
 	 */
-	if (posixly_correct == -1)
-		posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+	posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+	if (*options == '-')
+		flags |= FLAG_ALLARGS;
+	else if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
+#else
 	if (posixly_correct || *options == '+')
 		flags &= ~FLAG_PERMUTE;
 	else if (*options == '-')
 		flags |= FLAG_ALLARGS;
+#endif
 	if (*options == '+' || *options == '-')
 		options++;
 
@@ -344,7 +415,11 @@
 			return (-1);
 		}
 		if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+		    place[1] == '\0') {
+#else
 		    (place[1] == '\0' && strchr(options, '-') == NULL)) {
+#endif
 			place = EMSG;		/* found non-option */
 			if (flags & FLAG_ALLARGS) {
 				/*
@@ -407,20 +482,26 @@
 	if (long_options != NULL && place != nargv[optind] &&
 	    (*place == '-' || (flags & FLAG_LONGONLY))) {
 		short_too = 0;
-		if (*place == '-')
+#ifdef GNU_COMPATIBLE
+		dash_prefix = D_PREFIX;
+#endif
+		if (*place == '-') {
 			place++;		/* --foo long option */
-		else if (*place != ':' && strchr(options, *place) != NULL)
+#ifdef GNU_COMPATIBLE
+			dash_prefix = DD_PREFIX;
+#endif
+		} else if (*place != ':' && strchr(options, *place) != NULL)
 			short_too = 1;		/* could be short option too */
 
 		optchar = parse_long_options(nargv, options, long_options,
-		    idx, short_too);
+		    idx, short_too, flags);
 		if (optchar != -1) {
 			place = EMSG;
 			return (optchar);
 		}
 	}
 
-	if (((optchar = (int)*place++) == (int)':') ||
+	if ((optchar = (int)*place++) == (int)':' ||
 	    (optchar == (int)'-' && *place != '\0') ||
 	    (oli = strchr(options, optchar)) == NULL) {
 		/*
@@ -432,8 +513,14 @@
 			return (-1);
 		if (!*place)
 			++optind;
+#ifdef GNU_COMPATIBLE
 		if (PRINT_ERROR)
-			fprintf(stderr, illoptchar, optchar);
+			warnx(posixly_correct ? illoptchar : gnuoptchar,
+			      optchar);
+#else
+		if (PRINT_ERROR)
+			warnx(illoptchar, optchar);
+#endif
 		optopt = optchar;
 		return (BADCH);
 	}
@@ -444,13 +531,16 @@
 		else if (++optind >= nargc) {	/* no arg */
 			place = EMSG;
 			if (PRINT_ERROR)
-				fprintf(stderr, recargchar, optchar);
+				warnx(recargchar, optchar);
 			optopt = optchar;
 			return (BADARG);
 		} else				/* white space */
 			place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+		dash_prefix = W_PREFIX;
+#endif
 		optchar = parse_long_options(nargv, options, long_options,
-		    idx, 0);
+		    idx, 0, flags);
 		place = EMSG;
 		return (optchar);
 	}
@@ -461,24 +551,15 @@
 		optarg = NULL;
 		if (*place)			/* no white space */
 			optarg = place;
-		/* XXX: disable test for :: if PC? (GNU doesn't) */
 		else if (oli[1] != ':') {	/* arg not optional */
 			if (++optind >= nargc) {	/* no arg */
 				place = EMSG;
 				if (PRINT_ERROR)
-					fprintf(stderr, recargchar, optchar);
+					warnx(recargchar, optchar);
 				optopt = optchar;
 				return (BADARG);
 			} else
 				optarg = nargv[optind];
-		} else if (!(flags & FLAG_PERMUTE)) {
-			/*
-			 * If permutation is disabled, we can accept an
-			 * optional arg separated by whitespace so long
-			 * as it does not start with a dash (-).
-			 */
-			if (optind + 1 < nargc && *nargv[optind + 1] != '-')
-				optarg = nargv[++optind];
 		}
 		place = EMSG;
 		++optind;
@@ -516,7 +597,7 @@
  */
 int
 getopt_long(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx)
+	const struct option *long_options, int *idx)
 {
 
 	return (getopt_internal(nargc, nargv, options, long_options, idx,
@@ -529,7 +610,7 @@
  */
 int
 getopt_long_only(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx)
+	const struct option *long_options, int *idx)
 {
 
 	return (getopt_internal(nargc, nargv, options, long_options, idx,
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index 9594284..bce6e50 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ
diff --git a/linker/linker.cpp b/linker/linker.cpp
index c53d52f..386f6dc 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1533,6 +1533,8 @@
          * phdr_table_protect_segments() after all of them are applied
          * and all constructors are run.
          */
+        DL_WARN("%s has text relocations. This is wasting memory and is "
+                "a security risk. Please fix.", si->name);
         if (phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias) < 0) {
             DL_ERR("can't unprotect loadable segments for \"%s\": %s",
                    si->name, strerror(errno));
@@ -1584,6 +1586,28 @@
 }
 
 /*
+ * This function add vdso to internal dso list.
+ * It helps to stack unwinding through signal handlers.
+ * Also, it makes bionic more like glibc.
+ */
+static void add_vdso(KernelArgumentBlock& args UNUSED) {
+#ifdef AT_SYSINFO_EHDR
+    Elf32_Ehdr* ehdr_vdso = reinterpret_cast<Elf32_Ehdr*>(args.getauxval(AT_SYSINFO_EHDR));
+
+    soinfo* si = soinfo_alloc("[vdso]");
+    si->phdr = reinterpret_cast<Elf32_Phdr*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff);
+    si->phnum = ehdr_vdso->e_phnum;
+    si->link_map.l_name = si->name;
+    for (size_t i = 0; i < si->phnum; ++i) {
+        if (si->phdr[i].p_type == PT_LOAD) {
+            si->link_map.l_addr = reinterpret_cast<Elf32_Addr>(ehdr_vdso) - si->phdr[i].p_vaddr;
+            break;
+        }
+    }
+#endif
+}
+
+/*
  * This code is called after the linker has linked itself and
  * fixed it's own GOT. It is safe to make references to externs
  * and other non-local data at this point.
@@ -1708,6 +1732,8 @@
         exit(EXIT_FAILURE);
     }
 
+    add_vdso(args);
+
     si->CallPreInitConstructors();
 
     for (size_t i = 0; gLdPreloads[i] != NULL; ++i) {
diff --git a/tests/Android.mk b/tests/Android.mk
index fe794c4..efee17b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -61,10 +61,9 @@
     dirent_test.cpp \
     eventfd_test.cpp \
     fenv_test.cpp \
-    fortify1_test.cpp \
-    fortify2_test.cpp \
     getauxval_test.cpp \
     getcwd_test.cpp \
+    inttypes_test.cpp \
     libc_logging_test.cpp \
     libgen_test.cpp \
     malloc_test.cpp \
@@ -74,6 +73,8 @@
     regex_test.cpp \
     signal_test.cpp \
     stack_protector_test.cpp \
+    stack_unwinding_test.cpp \
+    statvfs_test.cpp \
     stdio_test.cpp \
     stdlib_test.cpp \
     string_test.cpp \
@@ -87,6 +88,21 @@
 test_dynamic_src_files = \
     dlfcn_test.cpp \
 
+test_fortify_static_libraries = \
+    fortify1-tests-gcc fortify2-tests-gcc fortify1-tests-clang fortify2-tests-clang
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := bionic-unit-tests-unwind-test-impl
+LOCAL_CFLAGS += $(test_c_flags) -fexceptions -fnon-call-exceptions
+LOCAL_SRC_FILES := stack_unwinding_test_impl.c
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := bionic-unit-tests-unwind-test-impl-host
+LOCAL_CFLAGS += $(test_c_flags) -fexceptions -fnon-call-exceptions
+LOCAL_SRC_FILES := stack_unwinding_test_impl.c
+include $(BUILD_HOST_STATIC_LIBRARY)
+
 # Build tests for the device (with bionic's .so). Run with:
 #   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
 include $(CLEAR_VARS)
@@ -96,7 +112,8 @@
 LOCAL_LDFLAGS += $(test_dynamic_ldflags)
 LOCAL_SHARED_LIBRARIES += libdl
 LOCAL_SRC_FILES := $(test_src_files) $(test_dynamic_src_files)
-LOCAL_WHOLE_STATIC_LIBRARIES := bionic-unit-tests-clang
+LOCAL_WHOLE_STATIC_LIBRARIES := $(test_fortify_static_libraries)
+LOCAL_STATIC_LIBRARIES += bionic-unit-tests-unwind-test-impl
 include $(BUILD_NATIVE_TEST)
 
 # Build tests for the device (with bionic's .a). Run with:
@@ -107,8 +124,8 @@
 LOCAL_CFLAGS += $(test_c_flags)
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_STATIC_LIBRARIES += libstlport_static libstdc++ libm libc
-LOCAL_WHOLE_STATIC_LIBRARIES := bionic-unit-tests-clang
+LOCAL_STATIC_LIBRARIES += libstlport_static libstdc++ libm libc bionic-unit-tests-unwind-test-impl
+LOCAL_WHOLE_STATIC_LIBRARIES := $(test_fortify_static_libraries)
 include $(BUILD_NATIVE_TEST)
 
 # -----------------------------------------------------------------------------
@@ -142,29 +159,59 @@
 LOCAL_LDFLAGS += -lpthread -ldl
 LOCAL_LDFLAGS += $(test_dynamic_ldflags)
 LOCAL_SRC_FILES := $(test_src_files) $(test_dynamic_src_files)
+LOCAL_STATIC_LIBRARIES += bionic-unit-tests-unwind-test-impl-host
 include $(BUILD_HOST_NATIVE_TEST)
 endif
 
 # -----------------------------------------------------------------------------
-# Unit tests which depend on clang as the compiler
+# FORTIFY_SOURCE tests
 # -----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := fortify1_test_clang.cpp fortify2_test_clang.cpp
-LOCAL_MODULE := bionic-unit-tests-clang
-LOCAL_CLANG := true
+
+fortify_c_includes = \
+    bionic \
+    bionic/libstdc++/include \
+    external/stlport/stlport \
+    external/gtest/include
+fortify_test_files = fortify_test.cpp
 
 # -Wno-error=unused-parameter needed as
 # external/stlport/stlport/stl/_threads.c (included from
 # external/gtest/include/gtest/gtest.h) does not compile cleanly under
 # clang. TODO: fix this.
-LOCAL_CFLAGS += $(test_c_flags) -Wno-error=unused-parameter
+fortify_c_flags = $(test_c_flags) -Wno-error=unused-parameter
 
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify1-tests-gcc
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DTEST_NAME=Fortify1_Gcc
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_C_INCLUDES += bionic \
-                    bionic/libstdc++/include \
-                    external/stlport/stlport \
-                    external/gtest/include
+LOCAL_C_INCLUDES += $(fortify_c_includes)
+include $(BUILD_STATIC_LIBRARY)
 
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify2-tests-gcc
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -DTEST_NAME=Fortify2_Gcc
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_C_INCLUDES += $(fortify_c_includes)
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify1-tests-clang
+LOCAL_CLANG := true
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DTEST_NAME=Fortify1_Clang
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_C_INCLUDES += $(fortify_c_includes)
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify2-tests-clang
+LOCAL_CLANG := true
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -DTEST_NAME=Fortify2_Clang
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_C_INCLUDES += $(fortify_c_includes)
 include $(BUILD_STATIC_LIBRARY)
 
 endif # !BUILD_TINY_ANDROID
diff --git a/tests/fortify1_test.cpp b/tests/fortify1_test.cpp
deleted file mode 100644
index b8751bb..0000000
--- a/tests/fortify1_test.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 1
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-#if __BIONIC__
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-
-// multibyte target where we over fill (should fail)
-TEST(Fortify1_DeathTest, strcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  char *orig = strdup("0123456789");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify1_DeathTest, strcpy2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify1_DeathTest, strcpy3_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("1");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify1_DeathTest, strcpy4_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[1];
-  char *orig = strdup("12");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-TEST(Fortify1_DeathTest, strlen_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strrchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strlcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[15];
-  char bufb[10];
-  strcpy(bufa, "01234567890123");
-  size_t n = strlen(bufa);
-  ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify1_DeathTest, sprintf_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  char source_buf[15];
-  memcpy(source_buf, "12345678901234", 15);
-  ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strncat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  size_t n = atoi("10"); // avoid compiler optimizations
-  strncpy(buf, "012345678", n);
-  ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strncat2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  buf[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
-  ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strcat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char src[11];
-  strcpy(src, "0123456789");
-  char buf[10];
-  buf[0] = '\0';
-  ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, memmove_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[20];
-  strcpy(buf, "0123456789");
-  size_t n = atoi("10");
-  ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, memcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[10];
-  char bufb[10];
-  strcpy(bufa, "012345678");
-  size_t n = atoi("11");
-  ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strncpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[15];
-  char bufb[10];
-  strcpy(bufa, "01234567890123");
-  size_t n = strlen(bufa);
-  ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
-extern "C" char* __strcat_chk(char*, const char*, size_t);
-
-TEST(Fortify1, strncat) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "01234", sizeof(buf) - strlen(buf) - 1, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('\0', buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1, strncat2) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('\0', buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1, strncat3) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = '\0';
-  char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('0',  buf[0]);
-  ASSERT_EQ('1',  buf[1]);
-  ASSERT_EQ('2',  buf[2]);
-  ASSERT_EQ('3',  buf[3]);
-  ASSERT_EQ('4',  buf[4]);
-  ASSERT_EQ('\0', buf[5]);
-  ASSERT_EQ('A',  buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1, strncat4) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[9] = '\0';
-  char* res = __strncat_chk(buf, "", 5, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('A',  buf[0]);
-  ASSERT_EQ('A',  buf[1]);
-  ASSERT_EQ('A',  buf[2]);
-  ASSERT_EQ('A',  buf[3]);
-  ASSERT_EQ('A',  buf[4]);
-  ASSERT_EQ('A',  buf[5]);
-  ASSERT_EQ('A',  buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('\0', buf[9]);
-}
-
-TEST(Fortify1, strncat5) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "01234567", 8, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('5', buf[6]);
-  ASSERT_EQ('6',  buf[7]);
-  ASSERT_EQ('7',  buf[8]);
-  ASSERT_EQ('\0',  buf[9]);
-}
-
-TEST(Fortify1, strncat6) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "01234567", 9, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('5', buf[6]);
-  ASSERT_EQ('6',  buf[7]);
-  ASSERT_EQ('7',  buf[8]);
-  ASSERT_EQ('\0',  buf[9]);
-}
-
-
-TEST(Fortify1, strcat) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strcat_chk(buf, "01234", sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('\0', buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1, strcat2) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strcat_chk(buf, "01234567", sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('5', buf[6]);
-  ASSERT_EQ('6',  buf[7]);
-  ASSERT_EQ('7',  buf[8]);
-  ASSERT_EQ('\0',  buf[9]);
-}
diff --git a/tests/fortify1_test_clang.cpp b/tests/fortify1_test_clang.cpp
deleted file mode 100644
index fed9f13..0000000
--- a/tests/fortify1_test_clang.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 1
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-#if __BIONIC__
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-
-// multibyte target where we over fill (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  char *orig = strdup("0123456789");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy3_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("1");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy4_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[1];
-  char *orig = strdup("12");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-TEST(Fortify1_Clang_DeathTest, strlen_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strrchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strlcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[15];
-  char bufb[10];
-  strcpy(bufa, "01234567890123");
-  size_t n = strlen(bufa);
-  ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify1_Clang_DeathTest, strncat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  size_t n = atoi("10"); // avoid compiler optimizations
-  strncpy(buf, "012345678", n);
-  ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strncat2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  buf[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
-  ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strcat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char src[11];
-  strcpy(src, "0123456789");
-  char buf[10];
-  buf[0] = '\0';
-  ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, memmove_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[20];
-  strcpy(buf, "0123456789");
-  size_t n = atoi("10");
-  ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, memcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[10];
-  char bufb[10];
-  strcpy(bufa, "012345678");
-  size_t n = atoi("11");
-  ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strncpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[15];
-  char bufb[10];
-  strcpy(bufa, "01234567890123");
-  size_t n = strlen(bufa);
-  ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
-extern "C" char* __strcat_chk(char*, const char*, size_t);
-
-TEST(Fortify1_Clang, strncat) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "01234", sizeof(buf) - strlen(buf) - 1, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('\0', buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat2) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('\0', buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat3) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = '\0';
-  char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('0',  buf[0]);
-  ASSERT_EQ('1',  buf[1]);
-  ASSERT_EQ('2',  buf[2]);
-  ASSERT_EQ('3',  buf[3]);
-  ASSERT_EQ('4',  buf[4]);
-  ASSERT_EQ('\0', buf[5]);
-  ASSERT_EQ('A',  buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat4) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[9] = '\0';
-  char* res = __strncat_chk(buf, "", 5, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('A',  buf[0]);
-  ASSERT_EQ('A',  buf[1]);
-  ASSERT_EQ('A',  buf[2]);
-  ASSERT_EQ('A',  buf[3]);
-  ASSERT_EQ('A',  buf[4]);
-  ASSERT_EQ('A',  buf[5]);
-  ASSERT_EQ('A',  buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('\0', buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat5) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "01234567", 8, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('5', buf[6]);
-  ASSERT_EQ('6',  buf[7]);
-  ASSERT_EQ('7',  buf[8]);
-  ASSERT_EQ('\0',  buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat6) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strncat_chk(buf, "01234567", 9, sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('5', buf[6]);
-  ASSERT_EQ('6',  buf[7]);
-  ASSERT_EQ('7',  buf[8]);
-  ASSERT_EQ('\0',  buf[9]);
-}
-
-
-TEST(Fortify1_Clang, strcat) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strcat_chk(buf, "01234", sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('\0', buf[6]);
-  ASSERT_EQ('A',  buf[7]);
-  ASSERT_EQ('A',  buf[8]);
-  ASSERT_EQ('A',  buf[9]);
-}
-
-TEST(Fortify1_Clang, strcat2) {
-  char buf[10];
-  memset(buf, 'A', sizeof(buf));
-  buf[0] = 'a';
-  buf[1] = '\0';
-  char* res = __strcat_chk(buf, "01234567", sizeof(buf));
-  ASSERT_EQ(buf, res);
-  ASSERT_EQ('a',  buf[0]);
-  ASSERT_EQ('0',  buf[1]);
-  ASSERT_EQ('1',  buf[2]);
-  ASSERT_EQ('2',  buf[3]);
-  ASSERT_EQ('3',  buf[4]);
-  ASSERT_EQ('4',  buf[5]);
-  ASSERT_EQ('5', buf[6]);
-  ASSERT_EQ('6',  buf[7]);
-  ASSERT_EQ('7',  buf[8]);
-  ASSERT_EQ('\0',  buf[9]);
-}
-
-__BIONIC_FORTIFY_INLINE
-size_t test_fortify_inline(char* buf) {
-  return __bos(buf);
-}
-
-TEST(Fortify1_Clang, fortify_inline) {
-  char buf[1024];
-  // no-op. Prints nothing. Needed to prevent the compiler
-  // from optimizing out buf.
-  buf[0] = '\0';
-  printf("%s", buf);
-  ASSERT_EQ(sizeof(buf), test_fortify_inline(buf));
-}
diff --git a/tests/fortify2_test.cpp b/tests/fortify2_test.cpp
deleted file mode 100644
index b6f6661..0000000
--- a/tests/fortify2_test.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 2
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-struct foo {
-  char empty[0];
-  char one[1];
-  char a[10];
-  char b[10];
-};
-
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-TEST(Fortify2_DeathTest, strncpy_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  int copy_amt = atoi("11");
-  ASSERT_EXIT(strncpy(myfoo.a, "01234567890", copy_amt),
-              testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, sprintf_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  char source_buf[15];
-  memcpy(source_buf, "12345678901234", 15);
-  ASSERT_EXIT(sprintf(myfoo.a, "%s", source_buf),
-              testing::KilledBySignal(SIGABRT), "");
-}
-
-#if __BIONIC__
-// zero sized target with "\0" source (should fail)
-TEST(Fortify2_DeathTest, strcpy_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  char* src = strdup("");
-  ASSERT_EXIT(strcpy(myfoo.empty, src),
-              testing::KilledBySignal(SIGABRT), "");
-  free(src);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy2_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  char* src = strdup("1");
-  ASSERT_EXIT(strcpy(myfoo.empty, src),
-              testing::KilledBySignal(SIGABRT), "");
-  free(src);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy3_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  char* src = strdup("12");
-  ASSERT_EXIT(strcpy(myfoo.one, src),
-              testing::KilledBySignal(SIGABRT), "");
-  free(src);
-}
-
-TEST(Fortify2_DeathTest, strchr_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
-  myfoo.b[0] = '\0';
-  ASSERT_EXIT(printf("%s", strchr(myfoo.a, 'a')),
-              testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strrchr_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  memcpy(myfoo.a, "0123456789", 10);
-  memcpy(myfoo.b, "01234", 6);
-  ASSERT_EXIT(printf("%s", strrchr(myfoo.a, 'a')),
-              testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strlcpy_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  strcpy(myfoo.a, "01");
-  size_t n = strlen(myfoo.a);
-  ASSERT_EXIT(strlcpy(myfoo.one, myfoo.a, n),
-              testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify2_DeathTest, strncat_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  size_t n = atoi("10"); // avoid compiler optimizations
-  strncpy(myfoo.a, "012345678", n);
-  ASSERT_EXIT(strncat(myfoo.a, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat2_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  myfoo.a[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
-  ASSERT_EXIT(strncat(myfoo.a, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat3_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
-  myfoo.b[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
-  ASSERT_EXIT(strncat(myfoo.b, myfoo.a, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strcat_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char src[11];
-  strcpy(src, "0123456789");
-  foo myfoo;
-  myfoo.a[0] = '\0';
-  ASSERT_EXIT(strcat(myfoo.a, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strcat2_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
-  myfoo.b[0] = '\0';
-  ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
-}
-
-/***********************************************************/
-/* TESTS BELOW HERE DUPLICATE TESTS FROM fortify1_test.cpp */
-/***********************************************************/
-
-#if __BIONIC__
-// multibyte target where we over fill (should fail)
-TEST(Fortify2_DeathTest, strcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  char *orig = strdup("0123456789");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify2_DeathTest, strcpy2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy3_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("1");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy4_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[1];
-  char *orig = strdup("12");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-TEST(Fortify2_DeathTest, strlen_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strrchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strlcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[15];
-  char bufb[10];
-  strcpy(bufa, "01234567890123");
-  size_t n = strlen(bufa);
-  ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify2_DeathTest, sprintf_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  char source_buf[15];
-  memcpy(source_buf, "12345678901234", 15);
-  ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  size_t n = atoi("10"); // avoid compiler optimizations
-  strncpy(buf, "012345678", n);
-  ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  buf[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
-  ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strcat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char src[11];
-  strcpy(src, "0123456789");
-  char buf[10];
-  buf[0] = '\0';
-  ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, memmove_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[20];
-  strcpy(buf, "0123456789");
-  size_t n = atoi("10");
-  ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, memcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[10];
-  char bufb[10];
-  strcpy(bufa, "012345678");
-  size_t n = atoi("11");
-  ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[15];
-  char bufb[10];
-  strcpy(bufa, "01234567890123");
-  size_t n = strlen(bufa);
-  ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
diff --git a/tests/fortify2_test_clang.cpp b/tests/fortify2_test_clang.cpp
deleted file mode 100644
index d8a0ba6..0000000
--- a/tests/fortify2_test_clang.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 2
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-struct foo {
-  char empty[0];
-  char one[1];
-  char a[10];
-  char b[10];
-};
-
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-TEST(Fortify2_Clang_DeathTest, strncat3_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
-  myfoo.b[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
-  ASSERT_EXIT(strncat(myfoo.b, myfoo.a, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strcat2_fortified2) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  foo myfoo;
-  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
-  myfoo.b[0] = '\0';
-  ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
-}
-
-/*****************************************************************/
-/* TESTS BELOW HERE DUPLICATE TESTS FROM fortify1_test_clang.cpp */
-/*****************************************************************/
-
-#if __BIONIC__
-// multibyte target where we over fill (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  char *orig = strdup("0123456789");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy3_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[0];
-  char *orig = strdup("1");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy4_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[1];
-  char *orig = strdup("12");
-  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
-  free(orig);
-}
-
-TEST(Fortify2_Clang_DeathTest, strlen_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strrchr_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  memcpy(buf, "0123456789", sizeof(buf));
-  ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-#endif
-
-TEST(Fortify2_Clang_DeathTest, strncat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  size_t n = atoi("10"); // avoid compiler optimizations
-  strncpy(buf, "012345678", n);
-  ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strncat2_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[10];
-  buf[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
-  ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strcat_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char src[11];
-  strcpy(src, "0123456789");
-  char buf[10];
-  buf[0] = '\0';
-  ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, memmove_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char buf[20];
-  strcpy(buf, "0123456789");
-  size_t n = atoi("10");
-  ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, memcpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[10];
-  char bufb[10];
-  strcpy(bufa, "012345678");
-  size_t n = atoi("11");
-  ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strncpy_fortified) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-  char bufa[15];
-  char bufb[10];
-  strcpy(bufa, "01234567890123");
-  size_t n = strlen(bufa);
-  ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-__BIONIC_FORTIFY_INLINE
-size_t test_fortify2_inline(char* buf) {
-  return __bos(buf);
-}
-
-TEST(Fortify2_Clang, fortify_inline) {
-  char buf[1024];
-  // no-op. Prints nothing. Needed to prevent the compiler
-  // from optimizing out buf.
-  buf[0] = '\0';
-  printf("%s", buf);
-  ASSERT_EQ(sizeof(buf), test_fortify2_inline(buf));
-}
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
new file mode 100644
index 0000000..d8f0e76
--- /dev/null
+++ b/tests/fortify_test.cpp
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// We have to say "DeathTest" here so gtest knows to run this test (which exits)
+// in its own process. Unfortunately, the C preprocessor doesn't give us an
+// easy way to concatenate strings, so we need to use the complicated method
+// below. *sigh*
+#define DEATHTEST_PASTER(name) name##_DeathTest
+#define DEATHTEST_EVALUATOR(name) DEATHTEST_PASTER(name)
+#define DEATHTEST DEATHTEST_EVALUATOR(TEST_NAME)
+
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE == 2
+struct foo {
+  char empty[0];
+  char one[1];
+  char a[10];
+  char b[10];
+};
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strncpy_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  int copy_amt = atoi("11");
+  ASSERT_EXIT(strncpy(myfoo.a, "01234567890", copy_amt),
+              testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, sprintf_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  char source_buf[15];
+  memcpy(source_buf, "12345678901234", 15);
+  ASSERT_EXIT(sprintf(myfoo.a, "%s", source_buf),
+              testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, sprintf2_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  ASSERT_EXIT(sprintf(myfoo.a, "0123456789"),
+              testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// These tests are disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+static int vsprintf_helper2(const char *fmt, ...) {
+  foo myfoo;
+  va_list va;
+  int result;
+
+  va_start(va, fmt);
+  result = vsprintf(myfoo.a, fmt, va); // should crash here
+  va_end(va);
+  return result;
+}
+
+TEST(DEATHTEST, vsprintf_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsprintf2_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// These tests are disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+static int vsnprintf_helper2(const char *fmt, ...) {
+  foo myfoo;
+  va_list va;
+  int result;
+  size_t size = atoi("11");
+
+  va_start(va, fmt);
+  result = vsnprintf(myfoo.a, size, fmt, va); // should crash here
+  va_end(va);
+  return result;
+}
+
+TEST(DEATHTEST, vsnprintf_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsnprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsnprintf2_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsnprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#if __BIONIC__
+
+#ifndef __clang__
+// zero sized target with "\0" source (should fail)
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strcpy_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  char* src = strdup("");
+  ASSERT_EXIT(strcpy(myfoo.empty, src),
+              testing::KilledBySignal(SIGABRT), "");
+  free(src);
+}
+#endif
+
+#ifndef __clang__
+// zero sized target with longer source (should fail)
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strcpy2_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  char* src = strdup("1");
+  ASSERT_EXIT(strcpy(myfoo.empty, src),
+              testing::KilledBySignal(SIGABRT), "");
+  free(src);
+}
+#endif
+
+#ifndef __clang__
+// one byte target with longer source (should fail)
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strcpy3_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  char* src = strdup("12");
+  ASSERT_EXIT(strcpy(myfoo.one, src),
+              testing::KilledBySignal(SIGABRT), "");
+  free(src);
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strchr_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
+  myfoo.b[0] = '\0';
+  ASSERT_EXIT(printf("%s", strchr(myfoo.a, 'a')),
+              testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strrchr_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  memcpy(myfoo.a, "0123456789", 10);
+  memcpy(myfoo.b, "01234", 6);
+  ASSERT_EXIT(printf("%s", strrchr(myfoo.a, 'a')),
+              testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strlcpy_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  strcpy(myfoo.a, "01");
+  size_t n = strlen(myfoo.a);
+  ASSERT_EXIT(strlcpy(myfoo.one, myfoo.a, n),
+              testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strlcat_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  strcpy(myfoo.a, "01");
+  myfoo.one[0] = '\0';
+  size_t n = strlen(myfoo.a);
+  ASSERT_EXIT(strlcat(myfoo.one, myfoo.a, n),
+              testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#endif /* __BIONIC__ */
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strncat_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  size_t n = atoi("10"); // avoid compiler optimizations
+  strncpy(myfoo.a, "012345678", n);
+  ASSERT_EXIT(strncat(myfoo.a, "9", n), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strncat2_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  myfoo.a[0] = '\0';
+  size_t n = atoi("10"); // avoid compiler optimizations
+  ASSERT_EXIT(strncat(myfoo.a, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+TEST(DEATHTEST, strncat3_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
+  myfoo.b[0] = '\0';
+  size_t n = atoi("10"); // avoid compiler optimizations
+  ASSERT_EXIT(strncat(myfoo.b, myfoo.a, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strcat_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char src[11];
+  strcpy(src, "0123456789");
+  foo myfoo;
+  myfoo.a[0] = '\0';
+  ASSERT_EXIT(strcat(myfoo.a, src), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+TEST(DEATHTEST, strcat2_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
+  myfoo.b[0] = '\0';
+  ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, snprintf_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  strcpy(myfoo.a, "012345678");
+  size_t n = strlen(myfoo.a) + 2;
+  ASSERT_EXIT(snprintf(myfoo.b, n, "a%s", myfoo.a), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, bzero_fortified2) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  foo myfoo;
+  memcpy(myfoo.b, "0123456789", sizeof(myfoo.b));
+  size_t n = atoi("11");
+  ASSERT_EXIT(bzero(myfoo.b, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+#endif /* defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE=2 */
+
+#if __BIONIC__
+// multibyte target where we over fill (should fail)
+TEST(DEATHTEST, strcpy_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  char *orig = strdup("0123456789");
+  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+  free(orig);
+}
+
+// zero sized target with "\0" source (should fail)
+TEST(DEATHTEST, strcpy2_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[0];
+  char *orig = strdup("");
+  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+  free(orig);
+}
+
+// zero sized target with longer source (should fail)
+TEST(DEATHTEST, strcpy3_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[0];
+  char *orig = strdup("1");
+  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+  free(orig);
+}
+
+// one byte target with longer source (should fail)
+TEST(DEATHTEST, strcpy4_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[1];
+  char *orig = strdup("12");
+  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+  free(orig);
+}
+
+TEST(DEATHTEST, strlen_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  memcpy(buf, "0123456789", sizeof(buf));
+  ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strchr_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  memcpy(buf, "0123456789", sizeof(buf));
+  ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strrchr_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  memcpy(buf, "0123456789", sizeof(buf));
+  ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strlcpy_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char bufa[15];
+  char bufb[10];
+  strcpy(bufa, "01234567890123");
+  size_t n = strlen(bufa);
+  ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strlcat_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char bufa[15];
+  char bufb[10];
+  bufb[0] = '\0';
+  strcpy(bufa, "01234567890123");
+  size_t n = strlen(bufa);
+  ASSERT_EXIT(strlcat(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+#endif
+
+TEST(DEATHTEST, sprintf_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  char source_buf[15];
+  memcpy(source_buf, "12345678901234", 15);
+  ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, sprintf2_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[5];
+  ASSERT_EXIT(sprintf(buf, "aaaaa"), testing::KilledBySignal(SIGABRT), "");
+}
+
+static int vsprintf_helper(const char *fmt, ...) {
+  char buf[10];
+  va_list va;
+  int result;
+
+  va_start(va, fmt);
+  result = vsprintf(buf, fmt, va); // should crash here
+  va_end(va);
+  return result;
+}
+
+TEST(DEATHTEST, vsprintf_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsprintf2_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+static int vsnprintf_helper(const char *fmt, ...) {
+  char buf[10];
+  va_list va;
+  int result;
+  size_t size = atoi("11");
+
+  va_start(va, fmt);
+  result = vsnprintf(buf, size, fmt, va); // should crash here
+  va_end(va);
+  return result;
+}
+
+TEST(DEATHTEST, vsnprintf_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsnprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsnprintf2_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(vsnprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strncat_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  size_t n = atoi("10"); // avoid compiler optimizations
+  strncpy(buf, "012345678", n);
+  ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strncat2_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  buf[0] = '\0';
+  size_t n = atoi("10"); // avoid compiler optimizations
+  ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strcat_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char src[11];
+  strcpy(src, "0123456789");
+  char buf[10];
+  buf[0] = '\0';
+  ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, memmove_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[20];
+  strcpy(buf, "0123456789");
+  size_t n = atoi("10");
+  ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, memcpy_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char bufa[10];
+  char bufb[10];
+  strcpy(bufa, "012345678");
+  size_t n = atoi("11");
+  ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strncpy_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char bufa[15];
+  char bufb[10];
+  strcpy(bufa, "01234567890123");
+  size_t n = strlen(bufa);
+  ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, snprintf_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char bufa[15];
+  char bufb[10];
+  strcpy(bufa, "0123456789");
+  size_t n = strlen(bufa) + 1;
+  ASSERT_EXIT(snprintf(bufb, n, "%s", bufa), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, bzero_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  memcpy(buf, "0123456789", sizeof(buf));
+  size_t n = atoi("11");
+  ASSERT_EXIT(bzero(buf, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, umask_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  mode_t mask = atoi("1023");  // 01777 in octal
+  ASSERT_EXIT(umask(mask), testing::KilledBySignal(SIGABRT), "");
+}
+
+extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
+extern "C" char* __strcat_chk(char*, const char*, size_t);
+
+TEST(TEST_NAME, strncat) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[0] = 'a';
+  buf[1] = '\0';
+  char* res = __strncat_chk(buf, "01234", sizeof(buf) - strlen(buf) - 1, sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('a',  buf[0]);
+  ASSERT_EQ('0',  buf[1]);
+  ASSERT_EQ('1',  buf[2]);
+  ASSERT_EQ('2',  buf[3]);
+  ASSERT_EQ('3',  buf[4]);
+  ASSERT_EQ('4',  buf[5]);
+  ASSERT_EQ('\0', buf[6]);
+  ASSERT_EQ('A',  buf[7]);
+  ASSERT_EQ('A',  buf[8]);
+  ASSERT_EQ('A',  buf[9]);
+}
+
+TEST(TEST_NAME, strncat2) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[0] = 'a';
+  buf[1] = '\0';
+  char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('a',  buf[0]);
+  ASSERT_EQ('0',  buf[1]);
+  ASSERT_EQ('1',  buf[2]);
+  ASSERT_EQ('2',  buf[3]);
+  ASSERT_EQ('3',  buf[4]);
+  ASSERT_EQ('4',  buf[5]);
+  ASSERT_EQ('\0', buf[6]);
+  ASSERT_EQ('A',  buf[7]);
+  ASSERT_EQ('A',  buf[8]);
+  ASSERT_EQ('A',  buf[9]);
+}
+
+TEST(TEST_NAME, strncat3) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[0] = '\0';
+  char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('0',  buf[0]);
+  ASSERT_EQ('1',  buf[1]);
+  ASSERT_EQ('2',  buf[2]);
+  ASSERT_EQ('3',  buf[3]);
+  ASSERT_EQ('4',  buf[4]);
+  ASSERT_EQ('\0', buf[5]);
+  ASSERT_EQ('A',  buf[6]);
+  ASSERT_EQ('A',  buf[7]);
+  ASSERT_EQ('A',  buf[8]);
+  ASSERT_EQ('A',  buf[9]);
+}
+
+TEST(TEST_NAME, strncat4) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[9] = '\0';
+  char* res = __strncat_chk(buf, "", 5, sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('A',  buf[0]);
+  ASSERT_EQ('A',  buf[1]);
+  ASSERT_EQ('A',  buf[2]);
+  ASSERT_EQ('A',  buf[3]);
+  ASSERT_EQ('A',  buf[4]);
+  ASSERT_EQ('A',  buf[5]);
+  ASSERT_EQ('A',  buf[6]);
+  ASSERT_EQ('A',  buf[7]);
+  ASSERT_EQ('A',  buf[8]);
+  ASSERT_EQ('\0', buf[9]);
+}
+
+TEST(TEST_NAME, strncat5) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[0] = 'a';
+  buf[1] = '\0';
+  char* res = __strncat_chk(buf, "01234567", 8, sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('a',  buf[0]);
+  ASSERT_EQ('0',  buf[1]);
+  ASSERT_EQ('1',  buf[2]);
+  ASSERT_EQ('2',  buf[3]);
+  ASSERT_EQ('3',  buf[4]);
+  ASSERT_EQ('4',  buf[5]);
+  ASSERT_EQ('5', buf[6]);
+  ASSERT_EQ('6',  buf[7]);
+  ASSERT_EQ('7',  buf[8]);
+  ASSERT_EQ('\0',  buf[9]);
+}
+
+TEST(TEST_NAME, strncat6) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[0] = 'a';
+  buf[1] = '\0';
+  char* res = __strncat_chk(buf, "01234567", 9, sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('a',  buf[0]);
+  ASSERT_EQ('0',  buf[1]);
+  ASSERT_EQ('1',  buf[2]);
+  ASSERT_EQ('2',  buf[3]);
+  ASSERT_EQ('3',  buf[4]);
+  ASSERT_EQ('4',  buf[5]);
+  ASSERT_EQ('5', buf[6]);
+  ASSERT_EQ('6',  buf[7]);
+  ASSERT_EQ('7',  buf[8]);
+  ASSERT_EQ('\0',  buf[9]);
+}
+
+
+TEST(TEST_NAME, strcat) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[0] = 'a';
+  buf[1] = '\0';
+  char* res = __strcat_chk(buf, "01234", sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('a',  buf[0]);
+  ASSERT_EQ('0',  buf[1]);
+  ASSERT_EQ('1',  buf[2]);
+  ASSERT_EQ('2',  buf[3]);
+  ASSERT_EQ('3',  buf[4]);
+  ASSERT_EQ('4',  buf[5]);
+  ASSERT_EQ('\0', buf[6]);
+  ASSERT_EQ('A',  buf[7]);
+  ASSERT_EQ('A',  buf[8]);
+  ASSERT_EQ('A',  buf[9]);
+}
+
+TEST(TEST_NAME, strcat2) {
+  char buf[10];
+  memset(buf, 'A', sizeof(buf));
+  buf[0] = 'a';
+  buf[1] = '\0';
+  char* res = __strcat_chk(buf, "01234567", sizeof(buf));
+  ASSERT_EQ(buf, res);
+  ASSERT_EQ('a',  buf[0]);
+  ASSERT_EQ('0',  buf[1]);
+  ASSERT_EQ('1',  buf[2]);
+  ASSERT_EQ('2',  buf[3]);
+  ASSERT_EQ('3',  buf[4]);
+  ASSERT_EQ('4',  buf[5]);
+  ASSERT_EQ('5', buf[6]);
+  ASSERT_EQ('6',  buf[7]);
+  ASSERT_EQ('7',  buf[8]);
+  ASSERT_EQ('\0',  buf[9]);
+}
diff --git a/tests/inttypes_test.cpp b/tests/inttypes_test.cpp
new file mode 100644
index 0000000..ec4a104
--- /dev/null
+++ b/tests/inttypes_test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#define __STDC_FORMAT_MACROS // Otherwise not available in C++.
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#if defined(__BIONIC__) // Doesn't work on glibc because we use -m32.
+TEST(inttypes, misc) {
+  char buf[512];
+
+  intptr_t i = 0;
+  uintptr_t u = 0;
+
+  snprintf(buf, sizeof(buf), "%08" PRIdPTR, i);
+  snprintf(buf, sizeof(buf), "%08" PRIiPTR, i);
+  snprintf(buf, sizeof(buf), "%08" PRIoPTR, i);
+  snprintf(buf, sizeof(buf), "%08" PRIuPTR, u);
+  snprintf(buf, sizeof(buf), "%08" PRIxPTR, u);
+  snprintf(buf, sizeof(buf), "%08" PRIXPTR, u);
+
+  sscanf(buf, "%08" SCNdPTR, &i);
+  sscanf(buf, "%08" SCNiPTR, &i);
+  sscanf(buf, "%08" SCNoPTR, &u);
+  sscanf(buf, "%08" SCNuPTR, &u);
+  sscanf(buf, "%08" SCNxPTR, &u);
+}
+#endif
diff --git a/tests/property_benchmark.cpp b/tests/property_benchmark.cpp
index 7266bd0..d10be91 100644
--- a/tests/property_benchmark.cpp
+++ b/tests/property_benchmark.cpp
@@ -23,7 +23,7 @@
 #include <vector>
 #include <string>
 
-extern void *__system_property_regions__[PA_REGION_COUNT];
+extern void *__system_property_area__;
 
 #define TEST_NUM_PROPS \
     Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)
@@ -39,10 +39,8 @@
             return;
         }
 
-        for (size_t i = 0; i < PA_REGION_COUNT; i++) {
-            old_pa[i] = __system_property_regions__[i];
-            __system_property_regions__[i] = NULL;
-        }
+        old_pa = __system_property_area__;
+        __system_property_area__ = NULL;
 
         pa_dirname = dirname;
         pa_filename = pa_dirname + "/__properties__";
@@ -79,9 +77,7 @@
         if (!valid)
             return;
 
-        for (size_t i = 0; i < PA_REGION_COUNT; i++) {
-            __system_property_regions__[i] = old_pa[i];
-        }
+        __system_property_area__ = old_pa;
 
         __system_property_set_filename(PROP_FILENAME);
         unlink(pa_filename.c_str());
@@ -107,7 +103,7 @@
 private:
     std::string pa_dirname;
     std::string pa_filename;
-    void *old_pa[PA_REGION_COUNT];
+    void *old_pa;
 };
 
 static void BM_property_get(int iters, int nprops)
diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
new file mode 100644
index 0000000..3b18daa
--- /dev/null
+++ b/tests/stack_unwinding_test.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#include <gtest/gtest.h>
+
+#if defined(i386) // Only our x86 unwinding is good enough. Switch to libunwind?
+
+extern "C" {
+  void do_test();
+}
+
+// We have to say "DeathTest" here so gtest knows to run this test (which exits)
+// in its own process.
+TEST(stack_unwinding_DeathTest, unwinding_through_signal_frame) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(do_test(), ::testing::ExitedWithCode(42), "");
+}
+
+#endif
diff --git a/tests/stack_unwinding_test_impl.c b/tests/stack_unwinding_test_impl.c
new file mode 100644
index 0000000..b0099f0
--- /dev/null
+++ b/tests/stack_unwinding_test_impl.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unwind.h>
+
+#define noinline __attribute__((__noinline__))
+#define unused __attribute__((__unused__))
+
+static noinline _Unwind_Reason_Code stop_fn(int a unused,
+    _Unwind_Action action,
+    _Unwind_Exception_Class b unused, struct _Unwind_Exception* c unused,
+    struct _Unwind_Context* d unused, void* e unused) {
+  if ((action & _UA_END_OF_STACK) != 0) {
+    // We reached the end of the stack without executing foo_cleanup. Test failed.
+    abort();
+  }
+  return _URC_NO_REASON;
+}
+
+static void noinline foo_cleanup(char* param unused) {
+  exit(42);
+}
+
+static void noinline do_crash() {
+  char* ptr = NULL;
+  *ptr = 0; // Deliberately cause a SIGSEGV.
+}
+
+static void noinline foo() {
+  char c1 __attribute__((cleanup(foo_cleanup)));
+  do_crash();
+}
+
+// It's SEGSEGV handler. We start forced stack unwinding here.
+// If libgcc don't find dso for signal frame stack unwinding will be finished.
+// libgcc pass to stop_fn _UA_END_OF_STACK flag.
+// Test pass condition: stack unwinding through signal frame and foo1_handler execution.
+static void noinline sigsegv_handler(int param unused) {
+  struct _Unwind_Exception* exception = (struct _Unwind_Exception*) malloc(sizeof(*exception));
+  memset(&exception->exception_class, 0, sizeof(exception->exception_class));
+  exception->exception_cleanup = 0;
+  _Unwind_ForcedUnwind(exception, stop_fn, 0);
+}
+
+void do_test() {
+  signal(SIGSEGV, &sigsegv_handler);
+  foo();
+}
diff --git a/tests/statvfs_test.cpp b/tests/statvfs_test.cpp
new file mode 100644
index 0000000..8afc6fd
--- /dev/null
+++ b/tests/statvfs_test.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <sys/statvfs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+TEST(statvfs, statvfs) {
+  struct statvfs sb;
+  memset(&sb, 0, sizeof(sb));
+
+  ASSERT_EQ(0, statvfs("/", &sb));
+#if __BIONIC__
+  ASSERT_EQ(0U, sb.f_bfree);
+  ASSERT_EQ(0U, sb.f_ffree);
+  ASSERT_EQ(0U, sb.f_fsid);
+  ASSERT_TRUE((sb.f_flag & ST_RDONLY) != 0);
+#endif
+
+#if __BIONIC__
+  ASSERT_EQ(0, statvfs("/data/data", &sb));
+  ASSERT_NE(0U, sb.f_bfree);
+  ASSERT_NE(0U, sb.f_ffree);
+  ASSERT_NE(0U, sb.f_fsid);
+  ASSERT_FALSE((sb.f_flag & ST_RDONLY) != 0);
+  ASSERT_TRUE((sb.f_flag & ST_NOSUID) != 0);
+#endif
+}
+
+TEST(statvfs, fstatvfs) {
+  struct statvfs sb;
+  memset(&sb, 0, sizeof(sb));
+
+  int fd = open("/", O_RDONLY);
+  ASSERT_EQ(0, fstatvfs(fd, &sb));
+  close(fd);
+#if __BIONIC__
+  ASSERT_EQ(0U, sb.f_bfree);
+  ASSERT_EQ(0U, sb.f_ffree);
+  ASSERT_EQ(0U, sb.f_fsid);
+  ASSERT_TRUE((sb.f_flag & ST_RDONLY) != 0);
+#endif
+
+#if __BIONIC__
+  fd = open("/data/data", O_RDONLY);
+  ASSERT_EQ(0, fstatvfs(fd, &sb));
+  close(fd);
+  ASSERT_NE(0U, sb.f_bfree);
+  ASSERT_NE(0U, sb.f_ffree);
+  ASSERT_NE(0U, sb.f_fsid);
+  ASSERT_FALSE((sb.f_flag & ST_RDONLY) != 0);
+  ASSERT_TRUE((sb.f_flag & ST_NOSUID) != 0);
+#endif
+}
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index 50bdfdf..b9256c6 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -24,7 +24,7 @@
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
-extern void *__system_property_regions__[PA_REGION_COUNT];
+extern void *__system_property_area__;
 
 struct LocalPropertyTestState {
     LocalPropertyTestState() : valid(false) {
@@ -35,10 +35,8 @@
             return;
         }
 
-        for (size_t i = 0; i < PA_REGION_COUNT; i++) {
-            old_pa[i] = __system_property_regions__[i];
-            __system_property_regions__[i] = NULL;
-        }
+        old_pa = __system_property_area__;
+        __system_property_area__ = NULL;
 
         pa_dirname = dirname;
         pa_filename = pa_dirname + "/__properties__";
@@ -52,9 +50,7 @@
         if (!valid)
             return;
 
-        for (size_t i = 0; i < PA_REGION_COUNT; i++) {
-            __system_property_regions__[i] = old_pa[i];
-        }
+        __system_property_area__ = old_pa;
 
         __system_property_set_filename(PROP_FILENAME);
         unlink(pa_filename.c_str());
@@ -65,7 +61,7 @@
 private:
     std::string pa_dirname;
     std::string pa_filename;
-    void *old_pa[PA_REGION_COUNT];
+    void *old_pa;
 };
 
 TEST(properties, add) {
@@ -202,6 +198,84 @@
     ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(247));
 }
 
+static void hierarchical_test_callback(const prop_info *pi, void *cookie) {
+    bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie);
+
+    char name[PROP_NAME_MAX];
+    char value[PROP_VALUE_MAX];
+
+    __system_property_read(pi, name, value);
+
+    int name_i, name_j, name_k;
+    int value_i, value_j, value_k;
+    ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k));
+    ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k));
+    ASSERT_EQ(name_i, value_i);
+    ASSERT_GE(name_i, 0);
+    ASSERT_LT(name_i, 8);
+    ASSERT_EQ(name_j, value_j);
+    ASSERT_GE(name_j, 0);
+    ASSERT_LT(name_j, 8);
+    ASSERT_EQ(name_k, value_k);
+    ASSERT_GE(name_k, 0);
+    ASSERT_LT(name_k, 8);
+
+    ok[name_i][name_j][name_k] = true;
+}
+
+TEST(properties, fill_hierarchical) {
+    LocalPropertyTestState pa;
+    ASSERT_TRUE(pa.valid);
+    char prop_name[PROP_NAME_MAX];
+    char prop_value[PROP_VALUE_MAX];
+    char prop_value_ret[PROP_VALUE_MAX];
+    int ret;
+
+    for (int i = 0; i < 8; i++) {
+        for (int j = 0; j < 8; j++) {
+            for (int k = 0; k < 8; k++) {
+                ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
+                memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
+                ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
+                memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
+                prop_name[PROP_NAME_MAX - 1] = 0;
+                prop_value[PROP_VALUE_MAX - 1] = 0;
+
+                ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1));
+            }
+        }
+    }
+
+    for (int i = 0; i < 8; i++) {
+        for (int j = 0; j < 8; j++) {
+            for (int k = 0; k < 8; k++) {
+                ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
+                memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
+                ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
+                memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
+                prop_name[PROP_NAME_MAX - 1] = 0;
+                prop_value[PROP_VALUE_MAX - 1] = 0;
+                memset(prop_value_ret, '\0', PROP_VALUE_MAX);
+
+                ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret));
+                ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
+            }
+        }
+    }
+
+    bool ok[8][8][8];
+    memset(ok, 0, sizeof(ok));
+    __system_property_foreach(hierarchical_test_callback, ok);
+
+    for (int i = 0; i < 8; i++) {
+        for (int j = 0; j < 8; j++) {
+            for (int k = 0; k < 8; k++) {
+                ASSERT_TRUE(ok[i][j][k]);
+            }
+        }
+    }
+}
+
 TEST(properties, errors) {
     LocalPropertyTestState pa;
     ASSERT_TRUE(pa.valid);