Merge "Reserve space for the future in statvfs(64)"
diff --git a/libc/Android.mk b/libc/Android.mk
index 8c2ebd6..2ec1281 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -223,11 +223,9 @@
     upstream-freebsd/lib/libc/stdio/fclose.c \
     upstream-freebsd/lib/libc/stdio/flags.c \
     upstream-freebsd/lib/libc/stdio/fopen.c \
-    upstream-freebsd/lib/libc/stdio/fwrite.c \
     upstream-freebsd/lib/libc/stdio/makebuf.c \
     upstream-freebsd/lib/libc/stdio/mktemp.c \
     upstream-freebsd/lib/libc/stdio/setvbuf.c \
-    upstream-freebsd/lib/libc/stdio/wsetup.c \
     upstream-freebsd/lib/libc/stdlib/abs.c \
     upstream-freebsd/lib/libc/stdlib/getopt_long.c \
     upstream-freebsd/lib/libc/stdlib/imaxabs.c \
@@ -388,6 +386,7 @@
     upstream-openbsd/lib/libc/stdio/fwalk.c \
     upstream-openbsd/lib/libc/stdio/fwide.c \
     upstream-openbsd/lib/libc/stdio/fwprintf.c \
+    upstream-openbsd/lib/libc/stdio/fwrite.c \
     upstream-openbsd/lib/libc/stdio/fwscanf.c \
     upstream-openbsd/lib/libc/stdio/getc.c \
     upstream-openbsd/lib/libc/stdio/getchar.c \
@@ -436,6 +435,7 @@
     upstream-openbsd/lib/libc/stdio/wbuf.c \
     upstream-openbsd/lib/libc/stdio/wprintf.c \
     upstream-openbsd/lib/libc/stdio/wscanf.c \
+    upstream-openbsd/lib/libc/stdio/wsetup.c \
     upstream-openbsd/lib/libc/stdlib/atoi.c \
     upstream-openbsd/lib/libc/stdlib/atol.c \
     upstream-openbsd/lib/libc/stdlib/atoll.c \
@@ -554,6 +554,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-c-files-under,tzcode)
+# tzcode doesn't include wcsftime, so we use the OpenBSD one.
+LOCAL_SRC_FILES += upstream-openbsd/lib/libc/time/wcsftime.c
 
 LOCAL_CFLAGS := $(libc_common_cflags)
 # Don't use ridiculous amounts of stack.
@@ -566,10 +568,11 @@
 LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\"
 # Include timezone and daylight globals.
 LOCAL_CFLAGS += -DUSG_COMPAT=1
+LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
-LOCAL_C_INCLUDES := $(libc_common_c_includes)
+LOCAL_C_INCLUDES := $(libc_common_c_includes) $(LOCAL_PATH)/tzcode/
 LOCAL_MODULE := libc_tzcode
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -616,6 +619,7 @@
 LOCAL_SRC_FILES := $(libc_upstream_freebsd_src_files)
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
+    -Wno-sign-compare -Wno-uninitialized \
     -I$(LOCAL_PATH)/upstream-freebsd/android/include \
     -I$(LOCAL_PATH)/upstream-freebsd/lib/libc/include \
     -include freebsd-compat.h
@@ -642,6 +646,7 @@
 LOCAL_SRC_FILES := $(libc_upstream_netbsd_src_files)
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
+    -Wno-sign-compare -Wno-uninitialized \
     -DPOSIX_MISTAKE \
     -I$(LOCAL_PATH)/upstream-netbsd/android/include \
     -I$(LOCAL_PATH)/upstream-netbsd/lib/libc/include \
@@ -669,8 +674,10 @@
 LOCAL_SRC_FILES := $(libc_upstream_openbsd_src_files)
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
+    -Wno-sign-compare -Wno-uninitialized \
     -I$(LOCAL_PATH)/upstream-openbsd/android/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
+    -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/gdtoa/ \
     -include openbsd-compat.h
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -696,6 +703,7 @@
 LOCAL_SRC_FILES_64 := $(libc_upstream_openbsd_gdtoa_src_files_64)
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
+    -Wno-sign-compare -Wno-uninitialized \
     -fvisibility=hidden \
     -I$(LOCAL_PATH)/upstream-openbsd/android/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
diff --git a/libc/NOTICE b/libc/NOTICE
index 82733a2..4334275 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -8,6 +8,38 @@
 
 -------------------------------------------------------------------
 
+Based on the UCB version with the ID appearing below.
+This is ANSIish only when "multibyte character == plain character".
+
+Copyright (c) 1989, 1993
+   The Regents of the University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
 Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 All rights reserved.
 
@@ -1201,35 +1233,6 @@
 -------------------------------------------------------------------
 
 Copyright (c) 1988, 1993
-    The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. Neither the name of the University nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988, 1993
    The Regents of the University of California.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -1804,6 +1807,38 @@
 
 Copyright (c) 1990, 1993
    The Regents of the University of California.  All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Donn Seeley at UUNET Technologies, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+4. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1990, 1993
+   The Regents of the University of California.  All rights reserved.
 (c) UNIX System Laboratories, Inc.
 All or some portions of this file are derived from material licensed
 to the University of California by American Telephone and Telegraph
@@ -2704,6 +2739,33 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 AUTHOR 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) 1997, 1998 The NetBSD Foundation, Inc.
 All rights reserved.
 
@@ -3378,6 +3440,32 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2002 Tim J. Robbins.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
 
 Permission to use, copy, modify, and distribute this software for any
@@ -3398,6 +3486,84 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2002, 2003 Tim J. Robbins.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 2002-2004 Tim J. Robbins
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 2002-2004 Tim J. Robbins.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
 
 Redistribution and use in source and binary forms, with or without
@@ -4057,6 +4223,32 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2011 David Chisnall
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 2011 Intel Corporation
 All rights reserved.
 
@@ -4421,6 +4613,32 @@
 
 -------------------------------------------------------------------
 
+Copyright (c)1999, 2000, 2001 Citrus 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:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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)2001 Citrus Project,
 All rights reserved.
 
diff --git a/libc/arch-arm/bionic/__bionic_clone.S b/libc/arch-arm/bionic/__bionic_clone.S
index 7b76f5e..7cc4db5 100644
--- a/libc/arch-arm/bionic/__bionic_clone.S
+++ b/libc/arch-arm/bionic/__bionic_clone.S
@@ -71,3 +71,4 @@
     ldr    r1, [sp, #-8]
     b      __bionic_clone_entry
 END(__bionic_clone)
+.hidden __bionic_clone
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 88da1f3..14cc3f4 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -55,4 +55,15 @@
 libc_crt_target_crtbegin_so_file_arm64 := \
     $(LOCAL_PATH)/arch-common/bionic/crtbegin_so.c
 
-include $(LOCAL_PATH)/arch-arm64/generic/generic.mk
+## CPU variant specific source files
+ifeq ($(strip $(TARGET_CPU_VARIANT)),)
+  $(warning TARGET_ARCH is arm64, but TARGET_CPU_VARIANT is not defined)
+endif
+cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
+ifeq ($(wildcard $(cpu_variant_mk)),)
+$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+endif
+include $(cpu_variant_mk)
+libc_common_additional_dependencies += $(cpu_variank_mk)
+
+cpu_variant_mk :=
diff --git a/libc/arch-arm64/bionic/__bionic_clone.S b/libc/arch-arm64/bionic/__bionic_clone.S
index 9790291..ddd8ee0 100644
--- a/libc/arch-arm64/bionic/__bionic_clone.S
+++ b/libc/arch-arm64/bionic/__bionic_clone.S
@@ -35,29 +35,34 @@
     mov     x29,  sp
     str     x8,       [sp, #-16]!
 
-    /* store thread pointer & args in child stack */
+    # Copy 'fn' and 'arg' onto the child stack.
     stp     x5, x6, [x1, #-16]
 
-    /* sys_clone */
+    # Zero out the top 32 bits of 'flags'. (Is this necessary?)
     uxtw    x0, w0
+
+    # Make the system call.
     mov     x8, __NR_clone
     svc     #0
 
-    /* check for child/parent */
-    cbz     x0,1f
+    # Are we the child?
+    cbz     x0, .L_bc_child
 
     ldr     x8,       [sp], #16
     ldp     x29, x30, [sp], #16
 
+    # Set errno if something went wrong.
     cmn     x0, #(MAX_ERRNO + 1)
     cneg    x0, x0, hi
     b.hi    __set_errno
 
     ret
 
-    /* thread initialization - set the end of the frame record chain */
-1:
+.L_bc_child:
+    # We're in the child now. Set the end of the frame record chain...
     mov     x29, xzr
+    # ...and call __bionic_clone_entry with the 'fn' and 'arg' we stored on the child stack.
     ldp     x0, x1, [sp, #-16]
     b       __bionic_clone_entry
 END(__bionic_clone)
+.hidden __bionic_clone
diff --git a/libc/arch-arm64/bionic/_setjmp.S b/libc/arch-arm64/bionic/_setjmp.S
index dfa861b..3836899 100644
--- a/libc/arch-arm64/bionic/_setjmp.S
+++ b/libc/arch-arm64/bionic/_setjmp.S
@@ -73,7 +73,7 @@
     ldr     w9, .L_setjmp_magic
     ldr     w10, [x0, #(_JB_MAGIC * 4)]
     cmp     w9, w10
-    b.ne    botch
+    b.ne    .L_fail
 
     /* restore core registers */
     ldp     x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
@@ -93,10 +93,10 @@
 
     /* validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0) */
     tst     x30, #3
-    b.ne    botch
+    b.ne    .L_fail
     mov     x10, sp
     tst     x10, #15
-    b.ne    botch
+    b.ne    .L_fail
 
     /* set return value */
     cmp     w1, wzr
@@ -104,7 +104,7 @@
     ret
 
     /* validation failed, die die die */
-botch:
+.L_fail:
     bl      PIC_SYM(longjmperror, PLT)
     bl      PIC_SYM(abort, PLT)
     b        . - 8       /* Cannot get here */
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index 9a68d86..f9d2266 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -85,7 +85,7 @@
     ldr     w9, .L_setjmp_magic
     ldr     w10, [x0, #(_JB_MAGIC * 4)]
     cmp     w9, w10
-    b.ne    botch
+    b.ne    .L_fail
 
     /* restore core registers */
     ldp     x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
@@ -105,10 +105,10 @@
 
     /* validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0) */
     tst     x30, #3
-    b.ne    botch
+    b.ne    .L_fail
     mov     x10, sp
     tst     x10, #15
-    b.ne    botch
+    b.ne    .L_fail
 
     /* set return value */
     cmp     w1, wzr
@@ -116,7 +116,7 @@
     ret
 
     /* validation failed, die die die */
-botch:
+.L_fail:
     bl      PIC_SYM(longjmperror, PLT)
     bl      PIC_SYM(abort, PLT)
     b       . - 8       /* Cannot get here */
diff --git a/libc/arch-arm64/generic-neon/bionic/memcpy.S b/libc/arch-arm64/generic-neon/bionic/memcpy.S
new file mode 100644
index 0000000..320f748
--- /dev/null
+++ b/libc/arch-arm64/generic-neon/bionic/memcpy.S
@@ -0,0 +1,179 @@
+/* Copyright (c) 2012, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the Linaro nor the
+         names of its contributors may be used to endorse or promote products
+         derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64
+ * Unaligned accesses
+ *
+ */
+
+#include <private/bionic_asm.h>
+
+#define dstin	x0
+#define src	x1
+#define count	x2
+#define tmp1	x3
+#define tmp1w	w3
+#define tmp2	x4
+#define tmp2w	w4
+#define tmp3	x5
+#define tmp3w	w5
+#define dst	x6
+
+#define A_l	x7
+#define A_h	x8
+#define B_l	x9
+#define B_h	x10
+#define C_l	x11
+#define C_h	x12
+#define D_l	x13
+#define D_h	x14
+
+#define QA_l q0
+#define QA_h q1
+#define QB_l q2
+#define QB_h q3
+
+ENTRY(memcpy)
+
+	mov	dst, dstin
+	cmp	count, #64
+	b.ge	.Lcpy_not_short
+	cmp	count, #15
+	b.le	.Ltail15tiny
+
+	/* Deal with small copies quickly by dropping straight into the
+	 * exit block.  */
+.Ltail63:
+	/* Copy up to 48 bytes of data.  At this point we only need the
+	 * bottom 6 bits of count to be accurate.  */
+	ands	tmp1, count, #0x30
+	b.eq	.Ltail15
+	add	dst, dst, tmp1
+	add	src, src, tmp1
+	cmp	tmp1w, #0x20
+	b.eq	1f
+	b.lt	2f
+	ldp	A_l, A_h, [src, #-48]
+	stp	A_l, A_h, [dst, #-48]
+1:
+	ldp	A_l, A_h, [src, #-32]
+	stp	A_l, A_h, [dst, #-32]
+2:
+	ldp	A_l, A_h, [src, #-16]
+	stp	A_l, A_h, [dst, #-16]
+
+.Ltail15:
+	ands	count, count, #15
+	beq	1f
+	add	src, src, count
+	ldp	A_l, A_h, [src, #-16]
+	add	dst, dst, count
+	stp	A_l, A_h, [dst, #-16]
+1:
+	ret
+
+.Ltail15tiny:
+	/* Copy up to 15 bytes of data.  Does not assume additional data
+	   being copied.  */
+	tbz	count, #3, 1f
+	ldr	tmp1, [src], #8
+	str	tmp1, [dst], #8
+1:
+	tbz	count, #2, 1f
+	ldr	tmp1w, [src], #4
+	str	tmp1w, [dst], #4
+1:
+	tbz	count, #1, 1f
+	ldrh	tmp1w, [src], #2
+	strh	tmp1w, [dst], #2
+1:
+	tbz	count, #0, 1f
+	ldrb	tmp1w, [src]
+	strb	tmp1w, [dst]
+1:
+	ret
+
+.Lcpy_not_short:
+	/* We don't much care about the alignment of DST, but we want SRC
+	 * to be 128-bit (16 byte) aligned so that we don't cross cache line
+	 * boundaries on both loads and stores.  */
+	neg	tmp2, src
+	ands	tmp2, tmp2, #15		/* Bytes to reach alignment.  */
+	b.eq	2f
+	sub	count, count, tmp2
+	/* Copy more data than needed; it's faster than jumping
+	 * around copying sub-Quadword quantities.  We know that
+	 * it can't overrun.  */
+	ldp	A_l, A_h, [src]
+	add	src, src, tmp2
+	stp	A_l, A_h, [dst]
+	add	dst, dst, tmp2
+	/* There may be less than 63 bytes to go now.  */
+	cmp	count, #63
+	b.le	.Ltail63
+2:
+	subs	count, count, #128
+	b.ge	.Lcpy_body_large
+	/* Less than 128 bytes to copy, so handle 64 here and then jump
+	 * to the tail.  */
+	ldp QA_l, QA_h, [src]
+	ldp QB_l, QB_h, [src, #32]
+	stp QA_l, QA_h, [dst]
+	stp QB_l, QB_h, [dst, #32]
+	tst	count, #0x3f
+	add	src, src, #64
+	add	dst, dst, #64
+	b.ne	.Ltail63
+	ret
+
+	/* Critical loop.  Start at a new cache line boundary.  Assuming
+	 * 64 bytes per line this ensures the entire loop is in one line.  */
+	.p2align 6
+.Lcpy_body_large:
+	/* There are at least 128 bytes to copy.  */
+	ldp QA_l, QA_h, [src, #0]
+	sub	dst, dst, #32		/* Pre-bias.  */
+	ldp QB_l, QB_h, [src, #32]!	/* src += 64 - Pre-bias.  */
+1:
+	stp QA_l, QA_h, [dst, #32]
+	ldp QA_l, QA_h, [src, #32]
+	stp QB_l, QB_h, [dst, #64]!
+	ldp QB_l, QB_h, [src, #64]!
+
+	subs	count, count, #64
+	b.ge	1b
+
+	stp QA_l, QA_h, [dst, #32]
+	stp QB_l, QB_h, [dst, #64]
+	add	src, src, #32
+	add	dst, dst, #64 + 32
+	tst	count, #0x3f
+	b.ne	.Ltail63
+	ret
+END(memcpy)
diff --git a/libc/arch-arm64/generic-neon/generic-neon.mk b/libc/arch-arm64/generic-neon/generic-neon.mk
new file mode 100644
index 0000000..2cbe3cf
--- /dev/null
+++ b/libc/arch-arm64/generic-neon/generic-neon.mk
@@ -0,0 +1,9 @@
+libc_bionic_src_files_arm64 += \
+    arch-arm64/generic/bionic/memcmp.S \
+    arch-arm64/generic/bionic/memmove.S \
+    arch-arm64/generic/bionic/memset.S \
+    arch-arm64/generic/bionic/strcmp.S \
+    arch-arm64/generic/bionic/strlen.S \
+    arch-arm64/generic/bionic/strncmp.S \
+    arch-arm64/generic/bionic/strnlen.S \
+    arch-arm64/generic-neon/bionic/memcpy.S \
diff --git a/libc/arch-common/bionic/atexit.h b/libc/arch-common/bionic/atexit.h
index 16ae7aa..90aa030 100644
--- a/libc/arch-common/bionic/atexit.h
+++ b/libc/arch-common/bionic/atexit.h
@@ -26,11 +26,20 @@
  * SUCH DAMAGE.
  */
 
+#include <stddef.h>
+
 extern void* __dso_handle;
 
 extern int __cxa_atexit(void (*)(void*), void*, void*);
 
 __attribute__ ((visibility ("hidden")))
+void __atexit_handler_wrapper(void* func) {
+  if (func != NULL) {
+    (*(void (*)(void))func)();
+  }
+}
+
+__attribute__ ((visibility ("hidden")))
 int atexit(void (*func)(void)) {
-  return (__cxa_atexit((void (*)(void*)) func, (void*) 0, &__dso_handle));
+  return (__cxa_atexit(&__atexit_handler_wrapper, func, &__dso_handle));
 }
diff --git a/libc/arch-mips/bionic/__bionic_clone.S b/libc/arch-mips/bionic/__bionic_clone.S
index 9273134..11d596b 100644
--- a/libc/arch-mips/bionic/__bionic_clone.S
+++ b/libc/arch-mips/bionic/__bionic_clone.S
@@ -66,3 +66,4 @@
 	la	t9,__set_errno
 	j	t9
 END(__bionic_clone)
+.hidden __bionic_clone
diff --git a/libc/arch-mips64/bionic/__bionic_clone.S b/libc/arch-mips64/bionic/__bionic_clone.S
index e1ade30..754861b 100644
--- a/libc/arch-mips64/bionic/__bionic_clone.S
+++ b/libc/arch-mips64/bionic/__bionic_clone.S
@@ -95,3 +95,4 @@
 	PTR_ADDU sp,FRAMESZ
 	j	t9
 	END(__bionic_clone)
+.hidden __bionic_clone
diff --git a/libc/arch-x86/bionic/__bionic_clone.S b/libc/arch-x86/bionic/__bionic_clone.S
index e6ddaaa..af6ef19 100644
--- a/libc/arch-x86/bionic/__bionic_clone.S
+++ b/libc/arch-x86/bionic/__bionic_clone.S
@@ -6,9 +6,12 @@
         pushl   %esi
         pushl   %edi
 
-        # Align child stack.
-        movl    20(%esp), %ecx
-        andl    $~15, %ecx
+        # Load system call arguments into registers.
+        movl    16(%esp), %ebx   # flags
+        movl    20(%esp), %ecx   # child_stack
+        movl    24(%esp), %edx   # parent_tid
+        movl    28(%esp), %esi   # tls
+        movl    32(%esp), %edi   # child_tid
 
         # Copy 'fn' and 'arg' onto the child stack
         movl    36(%esp), %eax   # Read 'fn'.
@@ -19,17 +22,12 @@
 
         # Make the system call.
         movl    $__NR_clone, %eax
-        movl    16(%esp), %ebx  # flags
-        #movl   %ecx, %ecx      # child stack (already there)
-        movl    24(%esp), %edx  # parent_tid
-        movl    28(%esp), %esi  # tls
-        movl    32(%esp), %edi  # child_tid
         int     $0x80
 
         # Check result.
         cmpl    $0, %eax
-        je      bc_child
-        jg      bc_parent
+        je      .L_bc_child
+        jg      .L_bc_parent
 
         # An error occurred, so set errno and return -1.
         negl    %eax
@@ -37,17 +35,18 @@
         call    __set_errno
         addl    $4, %esp
         orl     $-1, %eax
-        jmp     bc_return
+        jmp     .L_bc_return
 
-bc_child:
+.L_bc_child:
         call    __bionic_clone_entry
         hlt
 
-bc_parent:
+.L_bc_parent:
         # we're the parent; nothing to do.
-bc_return:
+.L_bc_return:
         popl    %edi
         popl    %esi
         popl    %ebx
         ret
 END(__bionic_clone)
+.hidden __bionic_clone
diff --git a/libc/arch-x86/bionic/__set_tls.c b/libc/arch-x86/bionic/__set_tls.c
index 7ed4b01..722ec6f 100644
--- a/libc/arch-x86/bionic/__set_tls.c
+++ b/libc/arch-x86/bionic/__set_tls.c
@@ -25,77 +25,50 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
+#include <limits.h>
 #include <pthread.h>
+#include <stdbool.h>
 
+#include <asm/ldt.h>
 
-struct user_desc {
-    unsigned int    entry_number;
-    unsigned long   base_addr;
-    unsigned int    limit;
-    unsigned int    seg_32bit:1;
-    unsigned int    contents:2;
-    unsigned int    read_exec_only:1;
-    unsigned int    limit_in_pages:1;
-    unsigned int    seg_not_present:1;
-    unsigned int    useable:1;
-    unsigned int    empty:25;
-};
+extern int __set_thread_area(struct user_desc*);
 
-extern int __set_thread_area(struct user_desc *u_info);
+__LIBC_HIDDEN__ void __init_user_desc(struct user_desc* result, bool allocate, void* base_addr) {
+  if (allocate) {
+    // Let the kernel choose.
+    result->entry_number = -1;
+  } else {
+    // Get the existing entry number from %gs.
+    uint32_t gs;
+    __asm__ __volatile__("movw %%gs, %w0" : "=q"(gs) /*output*/);
+    result->entry_number = (gs & 0xffff) >> 3;
+  }
 
-/* the following can't be const, since the first call will
- * update the 'entry_number' field
- */
-static struct user_desc  _tls_desc =
-{
-    -1,
-    0,
-    0x1000,
-    1,
-    0,
-    0,
-    1,
-    0,
-    1,
-    0
-};
+  result->base_addr = (uintptr_t) base_addr;
 
-static pthread_mutex_t  _tls_desc_lock = PTHREAD_MUTEX_INITIALIZER;
+  result->limit = PAGE_SIZE;
 
-struct _thread_area_head {
-    void *self;
-};
-
-/* we implement thread local storage through the gs: segment descriptor
- * we create a segment descriptor for the tls
- */
-int __set_tls(void *ptr)
-{
-    int   rc, segment;
-
-    pthread_mutex_lock(&_tls_desc_lock);
-    _tls_desc.base_addr = (unsigned long)ptr;
-
-    /* We also need to write the location of the tls to ptr[0] */
-    ((struct _thread_area_head *)ptr)->self = ptr;
-
-    rc = __set_thread_area( &_tls_desc );
-    if (rc != 0)
-    {
-        /* could not set thread local area */
-        pthread_mutex_unlock(&_tls_desc_lock);
-        return -1;
-    }
-
-    /* this weird computation comes from GLibc */
-    segment = _tls_desc.entry_number*8 + 3;
-    asm __volatile__ (
-        "   movw %w0, %%gs" :: "q"(segment)
-    );
-    pthread_mutex_unlock(&_tls_desc_lock);
-
-    return 0;
+  result->seg_32bit = 1;
+  result->contents = MODIFY_LDT_CONTENTS_DATA;
+  result->read_exec_only = 0;
+  result->limit_in_pages = 1;
+  result->seg_not_present = 0;
+  result->useable = 1;
 }
 
+int __set_tls(void* ptr) {
+  struct user_desc tls_descriptor;
+  __init_user_desc(&tls_descriptor, true, ptr);
 
+  int rc = __set_thread_area(&tls_descriptor);
+  if (rc != -1) {
+    // Change %gs to be new GDT entry.
+    uint16_t table_indicator = 0;  // GDT
+    uint16_t rpl = 3;  // Requested privilege level
+    uint16_t selector = (tls_descriptor.entry_number << 3) | table_indicator | rpl;
+    __asm__ __volatile__("movw %w0, %%gs" : /*output*/ : "q"(selector) /*input*/ : /*clobber*/);
+  }
 
+  return rc;
+}
diff --git a/libc/arch-x86_64/bionic/__bionic_clone.S b/libc/arch-x86_64/bionic/__bionic_clone.S
index cf98d76..db7d05c 100644
--- a/libc/arch-x86_64/bionic/__bionic_clone.S
+++ b/libc/arch-x86_64/bionic/__bionic_clone.S
@@ -30,9 +30,6 @@
 
 // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
 ENTRY(__bionic_clone)
-        # Enforce 16-byte alignment for child stack.
-        andq    $~15, %rsi
-
         # Copy 'fn' and 'arg' onto the child stack.
         movq    %r9, -16(%rsi)  # fn
         movq    8(%rsp), %rax   # Read 'arg'.
@@ -70,3 +67,4 @@
 2:
         ret
 END(__bionic_clone)
+.hidden __bionic_clone
diff --git a/libc/arch-x86_64/bionic/__set_tls.c b/libc/arch-x86_64/bionic/__set_tls.c
index 9a69449..cc7a5f4 100644
--- a/libc/arch-x86_64/bionic/__set_tls.c
+++ b/libc/arch-x86_64/bionic/__set_tls.c
@@ -32,7 +32,5 @@
 extern int __arch_prctl(int, unsigned long);
 
 int __set_tls(void* ptr) {
-  // We also need to write the location of the tls to ptr[0].
-  *(void**) ptr = ptr;
   return __arch_prctl(ARCH_SET_FS, (uintptr_t) ptr);
 }
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index 1d997fe..2c507c4 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -35,7 +35,7 @@
 extern "C" void __exit(int status);
 
 // Called from the __bionic_clone assembler to call the thread function then exit.
-extern "C" void __bionic_clone_entry(int (*fn)(void*), void* arg) {
+extern "C" __LIBC_HIDDEN__ void __bionic_clone_entry(int (*fn)(void*), void* arg) {
   int status = (*fn)(arg);
   __exit(status);
 }
@@ -59,5 +59,10 @@
   }
   va_end(args);
 
+  // Align 'child_stack' to 16 bytes.
+  uintptr_t child_stack_addr = reinterpret_cast<uintptr_t>(child_stack);
+  child_stack_addr &= ~0xf;
+  child_stack = reinterpret_cast<void*>(child_stack_addr);
+
   return __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
 }
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index c9c5d28..79472b3 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -495,7 +495,7 @@
   }
 
   iovec vec[6];
-  char log_id = LOG_ID_MAIN;
+  char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN;
   vec[0].iov_base = &log_id;
   vec[0].iov_len = sizeof(log_id);
   uint16_t tid = gettid();
@@ -614,7 +614,7 @@
   __libc_fatal("FORTIFY_SOURCE: %s. Calling abort().", msg);
 }
 
-static void __libc_fatal(const char* tag, const char* format, va_list args) {
+static void __libc_fatal(const char* format, va_list args) {
   char msg[1024];
   BufferOutputStream os(msg, sizeof(msg));
   out_vformat(os, format, args);
@@ -622,50 +622,53 @@
   // TODO: log to stderr for the benefit of "adb shell" users.
 
   // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
-  __libc_write_log(ANDROID_LOG_FATAL, tag, msg);
+  __libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
 
-  __libc_set_abort_message(msg);
+  __android_set_abort_message(msg);
 }
 
 void __libc_fatal_no_abort(const char* format, ...) {
   va_list args;
   va_start(args, format);
-  __libc_fatal("libc", format, args);
+  __libc_fatal(format, args);
   va_end(args);
 }
 
 void __libc_fatal(const char* format, ...) {
   va_list args;
   va_start(args, format);
-  __libc_fatal("libc", format, args);
+  __libc_fatal(format, args);
   va_end(args);
   abort();
 }
 
-// This is used by liblog to implement LOG_ALWAYS_FATAL and LOG_ALWAYS_FATAL_IF.
-void __android_fatal(const char* tag, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  __libc_fatal(tag, format, args);
-  va_end(args);
-  abort();
-}
+void __android_set_abort_message(const char* msg) {
+  ScopedPthreadMutexLocker locker(&gAbortMsgLock);
 
-void __libc_set_abort_message(const char* msg) {
+  if (__abort_message_ptr == NULL) {
+    // We must have crashed _very_ early.
+    return;
+  }
+
+  if (*__abort_message_ptr != NULL) {
+    // We already have an abort message.
+    // Assume that the first crash is the one most worth reporting.
+    return;
+  }
+
   size_t size = sizeof(abort_msg_t) + strlen(msg) + 1;
   void* map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
   if (map == MAP_FAILED) {
     return;
   }
 
-  if (__abort_message_ptr != NULL) {
-    ScopedPthreadMutexLocker locker(&gAbortMsgLock);
-    if (*__abort_message_ptr != NULL) {
-      munmap(*__abort_message_ptr, (*__abort_message_ptr)->size);
-    }
-    abort_msg_t* new_abort_message = reinterpret_cast<abort_msg_t*>(map);
-    new_abort_message->size = size;
-    strcpy(new_abort_message->msg, msg);
-    *__abort_message_ptr = new_abort_message;
+  // TODO: if we stick to the current "one-shot" scheme, we can remove this code and
+  // stop storing the size.
+  if (*__abort_message_ptr != NULL) {
+    munmap(*__abort_message_ptr, (*__abort_message_ptr)->size);
   }
+  abort_msg_t* new_abort_message = reinterpret_cast<abort_msg_t*>(map);
+  new_abort_message->size = size;
+  strcpy(new_abort_message->msg, msg);
+  *__abort_message_ptr = new_abort_message;
 }
diff --git a/libc/bionic/pthread_accessor.h b/libc/bionic/pthread_accessor.h
index 2a320f6..ccb71bb 100644
--- a/libc/bionic/pthread_accessor.h
+++ b/libc/bionic/pthread_accessor.h
@@ -19,6 +19,7 @@
 
 #include <pthread.h>
 
+#include "private/bionic_macros.h"
 #include "pthread_internal.h"
 
 class pthread_accessor {
@@ -57,9 +58,7 @@
     is_locked_ = true;
   }
 
-  // Disallow copy and assignment.
-  pthread_accessor(const pthread_accessor&);
-  void operator=(const pthread_accessor&);
+  DISALLOW_COPY_AND_ASSIGN(pthread_accessor);
 };
 
 #endif // PTHREAD_ACCESSOR_H
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 3d0daf7..f62dc15 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -39,9 +39,6 @@
 #include "private/ErrnoRestorer.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
-extern "C" pid_t __bionic_clone(uint32_t flags, void* child_stack, int* parent_tid, void* tls, int* child_tid, int (*fn)(void*), void* arg);
-extern "C" int __set_tls(void*);
-
 // Used by gdb to track thread creation. See libthread_db.
 #ifdef __i386__
 extern "C" __attribute__((noinline)) __attribute__((fastcall)) void _thread_created_hook(pid_t) {}
@@ -49,6 +46,12 @@
 extern "C" __attribute__((noinline)) void _thread_created_hook(pid_t) {}
 #endif
 
+// x86 uses segment descriptors rather than a direct pointer to TLS.
+#if __i386__
+#include <asm/ldt.h>
+extern "C" __LIBC_HIDDEN__ void __init_user_desc(struct user_desc*, int, void*);
+#endif
+
 static pthread_mutex_t gPthreadStackCreationLock = PTHREAD_MUTEX_INITIALIZER;
 
 static pthread_mutex_t gDebuggerNotificationLock = PTHREAD_MUTEX_INITIALIZER;
@@ -62,10 +65,6 @@
     thread->tls[i] = NULL;
   }
 
-#if defined(__i386__)
-  __set_tls(thread->tls);
-#endif
-
   // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
   thread->tls[TLS_SLOT_SELF] = thread->tls;
   thread->tls[TLS_SLOT_THREAD_ID] = thread;
@@ -148,8 +147,7 @@
   pthread_mutex_t* start_mutex = (pthread_mutex_t*) &thread->tls[TLS_SLOT_START_MUTEX];
   pthread_mutex_lock(start_mutex);
   pthread_mutex_destroy(start_mutex);
-
-  __init_tls(thread);
+  thread->tls[TLS_SLOT_START_MUTEX] = NULL;
 
   __init_alternate_signal_stack(thread);
 
@@ -208,6 +206,7 @@
   // At offsets < 0, we have the child stack.
   thread->tls = (void**)((uint8_t*)(thread->attr.stack_base) + thread->attr.stack_size - BIONIC_TLS_SLOTS * sizeof(void*));
   void* child_stack = thread->tls;
+  __init_tls(thread);
 
   // Create a mutex for the thread in TLS to wait on once it starts so we can keep
   // it from doing anything until after we notify the debugger about it
@@ -219,20 +218,20 @@
   pthread_mutex_init(start_mutex, NULL);
   pthread_mutex_lock(start_mutex);
 
-  thread->tls[TLS_SLOT_THREAD_ID] = thread;
-
   thread->start_routine = start_routine;
   thread->start_routine_arg = arg;
 
   int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
       CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
+  void* tls = thread->tls;
 #if defined(__i386__)
   // On x86 (but not x86-64), CLONE_SETTLS takes a pointer to a struct user_desc rather than
-  // a pointer to the TLS itself. Rather than try to deal with that here, we just let x86 set
-  // the TLS manually in __init_tls, like all architectures used to.
-  flags &= ~CLONE_SETTLS;
+  // a pointer to the TLS itself.
+  user_desc tls_descriptor;
+  __init_user_desc(&tls_descriptor, false, tls);
+  tls = &tls_descriptor;
 #endif
-  int rc = __bionic_clone(flags, child_stack, &(thread->tid), thread->tls, &(thread->tid), __pthread_start, thread);
+  int rc = clone(__pthread_start, child_stack, flags, thread, &(thread->tid), tls, &(thread->tid));
   if (rc == -1) {
     int clone_errno = errno;
     // We don't have to unlock the mutex at all because clone(2) failed so there's no child waiting to
diff --git a/libc/bionic/scandir.cpp b/libc/bionic/scandir.cpp
index 25d5200..9f731ab 100644
--- a/libc/bionic/scandir.cpp
+++ b/libc/bionic/scandir.cpp
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <stdlib.h>
 
+#include "private/bionic_macros.h"
 #include "private/ScopedReaddir.h"
 
 // A smart pointer to the scandir dirent**.
@@ -84,9 +85,7 @@
     return copy;
   }
 
-  // Disallow copy and assignment.
-  ScandirResult(const ScandirResult&);
-  void operator=(const ScandirResult&);
+  DISALLOW_COPY_AND_ASSIGN(ScandirResult);
 };
 
 int scandir(const char* dirname, dirent*** name_list,
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 2c2b74b..41ecd09 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -89,9 +89,11 @@
   // Copy the strings.
   snprintf(buf, byte_count, "%s%c%s%c%s", src->pw_name, 0, src->pw_dir, 0, src->pw_shell);
 
-  // pw_passwd is non-POSIX and unused (always NULL) in bionic.
-  // pw_gecos is non-POSIX and missing in bionic.
+  // pw_passwd and pw_gecos are non-POSIX and unused (always NULL) in bionic.
   dst->pw_passwd = NULL;
+#ifdef __LP64__
+  dst->pw_gecos = NULL;
+#endif
 
   // Copy the integral fields.
   dst->pw_gid = src->pw_gid;
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 4e4684a..ec3d04b 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -54,6 +54,7 @@
 #include <sys/atomics.h>
 
 #include "private/bionic_atomic_inline.h"
+#include "private/bionic_macros.h"
 
 #define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
 
@@ -100,9 +101,7 @@
     }
 
 private:
-    // Disallow copy and assign.
-    prop_bt(const prop_bt&);
-    prop_bt& operator=(const prop_bt&);
+    DISALLOW_COPY_AND_ASSIGN(prop_bt);
 };
 
 struct prop_area {
@@ -121,9 +120,7 @@
     }
 
 private:
-    // Disallow copy and assign.
-    prop_area(const prop_area&);
-    prop_area& operator=(const prop_area&);
+    DISALLOW_COPY_AND_ASSIGN(prop_area);
 };
 
 struct prop_info {
@@ -141,9 +138,7 @@
         ANDROID_MEMBAR_FULL();
     }
 private:
-    // Disallow copy and assign.
-    prop_info(const prop_info&);
-    prop_info& operator=(const prop_info&);
+    DISALLOW_COPY_AND_ASSIGN(prop_info);
 };
 
 struct find_nth_cookie {
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index 4fd590a..673402d 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -31,7 +31,7 @@
 #include <string.h>
 #include <wchar.h>
 
-// TODO: these only work for the ASCII range; rewrite to dlsym icu4c?
+// TODO: these only work for the ASCII range; rewrite to dlsym icu4c? http://b/14499654
 
 int iswalnum(wint_t wc) { return isalnum(wc); }
 int iswalpha(wint_t wc) { return isalpha(wc); }
@@ -48,18 +48,18 @@
 
 int iswctype(wint_t wc, wctype_t char_class) {
   switch (char_class) {
-    case WC_TYPE_ALNUM: return isalnum(wc);
-    case WC_TYPE_ALPHA: return isalpha(wc);
-    case WC_TYPE_BLANK: return isblank(wc);
-    case WC_TYPE_CNTRL: return iscntrl(wc);
-    case WC_TYPE_DIGIT: return isdigit(wc);
-    case WC_TYPE_GRAPH: return isgraph(wc);
-    case WC_TYPE_LOWER: return islower(wc);
-    case WC_TYPE_PRINT: return isprint(wc);
-    case WC_TYPE_PUNCT: return ispunct(wc);
-    case WC_TYPE_SPACE: return isspace(wc);
-    case WC_TYPE_UPPER: return isupper(wc);
-    case WC_TYPE_XDIGIT: return isxdigit(wc);
+    case WC_TYPE_ALNUM: return iswalnum(wc);
+    case WC_TYPE_ALPHA: return iswalpha(wc);
+    case WC_TYPE_BLANK: return iswblank(wc);
+    case WC_TYPE_CNTRL: return iswcntrl(wc);
+    case WC_TYPE_DIGIT: return iswdigit(wc);
+    case WC_TYPE_GRAPH: return iswgraph(wc);
+    case WC_TYPE_LOWER: return iswlower(wc);
+    case WC_TYPE_PRINT: return iswprint(wc);
+    case WC_TYPE_PUNCT: return iswpunct(wc);
+    case WC_TYPE_SPACE: return iswspace(wc);
+    case WC_TYPE_UPPER: return iswupper(wc);
+    case WC_TYPE_XDIGIT: return iswxdigit(wc);
     default: return 0;
   }
 }
@@ -84,8 +84,3 @@
 int wcwidth(wchar_t wc) {
   return (wc > 0);
 }
-
-// TODO: implement wcsftime.
-size_t wcsftime(wchar_t* wcs, size_t maxsize, const wchar_t* format,  const struct tm* timptr) {
-  abort();
-}
diff --git a/libc/dns/gethnamaddr.c b/libc/dns/gethnamaddr.c
index dbcadee..4da99b2 100644
--- a/libc/dns/gethnamaddr.c
+++ b/libc/dns/gethnamaddr.c
@@ -828,27 +828,27 @@
 
 	assert(addr != NULL);
 
-	if (af == AF_INET6 && len == IN6ADDRSZ &&
-	    (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) ||
-	     IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) {
+	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
+	    (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
+	     IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
 		h_errno = HOST_NOT_FOUND;
 		return NULL;
 	}
-	if (af == AF_INET6 && len == IN6ADDRSZ &&
-	    (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) ||
-	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) {
+	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
+	    (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
+	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
 		/* Unmap. */
-		addr += IN6ADDRSZ - INADDRSZ;
-		uaddr += IN6ADDRSZ - INADDRSZ;
+		uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
+		addr = uaddr;
 		af = AF_INET;
-		len = INADDRSZ;
+		len = NS_INADDRSZ;
 	}
 	switch (af) {
 	case AF_INET:
-		size = INADDRSZ;
+		size = NS_INADDRSZ;
 		break;
 	case AF_INET6:
-		size = IN6ADDRSZ;
+		size = NS_IN6ADDRSZ;
 		break;
 	default:
 		errno = EAFNOSUPPORT;
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 611fdfb..2d2f096 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -25,9 +25,14 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef ANDROID_API_LEVEL_H
 #define ANDROID_API_LEVEL_H
 
-#define __ANDROID_API__ 10
+/*
+ * Magic version number for a current development build, which has
+ * not yet turned into an official release.
+ */
+#define __ANDROID_API__ 10000
 
 #endif /* ANDROID_API_LEVEL_H */
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 3f59b91..7b8de81 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -91,7 +91,7 @@
 typedef long pthread_mutexattr_t;
 typedef long pthread_condattr_t;
 
-typedef int pthread_rwlockattr_t;
+typedef long pthread_rwlockattr_t;
 
 typedef struct {
   pthread_mutex_t lock;
diff --git a/libc/include/pwd.h b/libc/include/pwd.h
index 6f3fad5..6d483c0 100644
--- a/libc/include/pwd.h
+++ b/libc/include/pwd.h
@@ -100,12 +100,15 @@
 
 struct passwd
 {
-    char* pw_name;
-    char* pw_passwd;
-    uid_t pw_uid;
-    gid_t pw_gid;
-    char* pw_dir;
-    char* pw_shell;
+  char* pw_name;
+  char* pw_passwd;
+  uid_t pw_uid;
+  gid_t pw_gid;
+#ifdef __LP64__
+  char* pw_gecos;
+#endif
+  char* pw_dir;
+  char* pw_shell;
 };
 
 __BEGIN_DECLS
diff --git a/libc/include/semaphore.h b/libc/include/semaphore.h
index 30e3123..7ae3c3a 100644
--- a/libc/include/semaphore.h
+++ b/libc/include/semaphore.h
@@ -33,10 +33,13 @@
 __BEGIN_DECLS
 
 typedef struct {
-    volatile unsigned int  count;
+  volatile unsigned int count;
+#ifdef __LP64__
+  int __reserved[3];
+#endif
 } sem_t;
 
-#define  SEM_FAILED  NULL
+#define SEM_FAILED NULL
 
 extern int sem_init(sem_t *sem, int pshared, unsigned int value);
 
diff --git a/libc/include/sys/epoll.h b/libc/include/sys/epoll.h
index c06a081..4a5a37c 100644
--- a/libc/include/sys/epoll.h
+++ b/libc/include/sys/epoll.h
@@ -67,7 +67,11 @@
 struct epoll_event {
   uint32_t events;
   epoll_data_t data;
-};
+}
+#ifdef __x86_64__
+__packed
+#endif
+;
 
 int epoll_create(int);
 int epoll_create1(int);
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index dc847d2..9a76ad2 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -63,7 +63,7 @@
 typedef __kernel_key_t __key_t;
 typedef __key_t key_t;
 
-typedef uint32_t __ino_t;
+typedef __kernel_ino_t __ino_t;
 typedef __ino_t ino_t;
 
 typedef uint32_t __nlink_t;
@@ -72,9 +72,10 @@
 typedef void* __timer_t;
 typedef __timer_t timer_t;
 
-typedef int32_t __suseconds_t;
+typedef __kernel_suseconds_t __suseconds_t;
 typedef __suseconds_t suseconds_t;
 
+/* useconds_t is 32-bit on both LP32 and LP64. */
 typedef uint32_t __useconds_t;
 typedef __useconds_t useconds_t;
 
diff --git a/libc/include/time64.h b/libc/include/time64.h
index b4f1280..905669d 100644
--- a/libc/include/time64.h
+++ b/libc/include/time64.h
@@ -33,12 +33,7 @@
 
 #if defined(__LP64__)
 
-/* TODO: remove this when external/chromium_org is fixed. */
-#define time64_t time_t
-#define gmtime64_r gmtime_r
-#define localtime64_r localtime_r
-#define mktime64 mktime
-#define timegm64 timegm
+#error Your time_t is already 64-bit.
 
 #else
 
diff --git a/libc/include/utmp.h b/libc/include/utmp.h
index ffd3c92..d764227 100644
--- a/libc/include/utmp.h
+++ b/libc/include/utmp.h
@@ -36,9 +36,15 @@
 #define _PATH_WTMP      "/var/log/wtmp"
 #define _PATH_LASTLOG   "/var/log/lastlog"
 
-#define	UT_NAMESIZE	8
-#define	UT_LINESIZE	8
-#define	UT_HOSTSIZE	16
+#ifdef __LP64__
+#define UT_NAMESIZE 32
+#define UT_LINESIZE 32
+#define UT_HOSTSIZE 256
+#else
+#define UT_NAMESIZE 8
+#define UT_LINESIZE 8
+#define UT_HOSTSIZE 16
+#endif
 
 #define USER_PROCESS 7
 
diff --git a/libc/private/ErrnoRestorer.h b/libc/private/ErrnoRestorer.h
index ed6ab62..f467393 100644
--- a/libc/private/ErrnoRestorer.h
+++ b/libc/private/ErrnoRestorer.h
@@ -19,6 +19,8 @@
 
 #include <errno.h>
 
+#include "bionic_macros.h"
+
 class ErrnoRestorer {
  public:
   explicit ErrnoRestorer() : saved_errno_(errno) {
@@ -35,9 +37,7 @@
  private:
   int saved_errno_;
 
-  // Disallow copy and assignment.
-  ErrnoRestorer(const ErrnoRestorer&);
-  void operator=(const ErrnoRestorer&);
+  DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
 };
 
 #endif // ERRNO_RESTORER_H
diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h
index 4af52ab..c8ea497 100644
--- a/libc/private/KernelArgumentBlock.h
+++ b/libc/private/KernelArgumentBlock.h
@@ -22,6 +22,8 @@
 #include <stdint.h>
 #include <sys/auxv.h>
 
+#include "private/bionic_macros.h"
+
 struct abort_msg_t;
 
 // When the kernel starts the dynamic linker, it passes a pointer to a block
@@ -73,9 +75,7 @@
   abort_msg_t** abort_message_ptr;
 
  private:
-  // Disallow copy and assignment.
-  KernelArgumentBlock(const KernelArgumentBlock&);
-  void operator=(const KernelArgumentBlock&);
+  DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock);
 };
 
 #endif // KERNEL_ARGUMENT_BLOCK_H
diff --git a/libc/private/ScopedPthreadMutexLocker.h b/libc/private/ScopedPthreadMutexLocker.h
index 06b8e37..43dbdc1 100644
--- a/libc/private/ScopedPthreadMutexLocker.h
+++ b/libc/private/ScopedPthreadMutexLocker.h
@@ -19,6 +19,8 @@
 
 #include <pthread.h>
 
+#include "bionic_macros.h"
+
 class ScopedPthreadMutexLocker {
  public:
   explicit ScopedPthreadMutexLocker(pthread_mutex_t* mu) : mu_(mu) {
@@ -32,9 +34,7 @@
  private:
   pthread_mutex_t* mu_;
 
-  // Disallow copy and assignment.
-  ScopedPthreadMutexLocker(const ScopedPthreadMutexLocker&);
-  void operator=(const ScopedPthreadMutexLocker&);
+  DISALLOW_COPY_AND_ASSIGN(ScopedPthreadMutexLocker);
 };
 
 #endif // SCOPED_PTHREAD_MUTEX_LOCKER_H
diff --git a/libc/private/ScopedReaddir.h b/libc/private/ScopedReaddir.h
index 797809a..84c1b93 100644
--- a/libc/private/ScopedReaddir.h
+++ b/libc/private/ScopedReaddir.h
@@ -19,6 +19,8 @@
 
 #include <dirent.h>
 
+#include "private/bionic_macros.h"
+
 class ScopedReaddir {
  public:
   ScopedReaddir(const char* path) {
@@ -42,9 +44,7 @@
  private:
   DIR* dir_;
 
-  // Disallow copy and assignment.
-  ScopedReaddir(const ScopedReaddir&);
-  void operator=(const ScopedReaddir&);
+  DISALLOW_COPY_AND_ASSIGN(ScopedReaddir);
 };
 
 #endif // SCOPED_READDIR_H
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
new file mode 100644
index 0000000..34da501
--- /dev/null
+++ b/libc/private/bionic_macros.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_MACROS_H_
+#define _BIONIC_MACROS_H_
+
+// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
+// It goes in the private: declarations in a class.
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+  TypeName();                                    \
+  DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+#endif // _BIONIC_MACROS_H_
diff --git a/libc/private/libc_logging.h b/libc/private/libc_logging.h
index 54e050a..7dd97a4 100644
--- a/libc/private/libc_logging.h
+++ b/libc/private/libc_logging.h
@@ -53,14 +53,15 @@
 };
 
 enum {
-    LOG_ID_MIN = 0,
+  LOG_ID_MIN = 0,
 
-    LOG_ID_MAIN = 0,
-    LOG_ID_RADIO = 1,
-    LOG_ID_EVENTS = 2,
-    LOG_ID_SYSTEM = 3,
+  LOG_ID_MAIN = 0,
+  LOG_ID_RADIO = 1,
+  LOG_ID_EVENTS = 2,
+  LOG_ID_SYSTEM = 3,
+  LOG_ID_CRASH = 4,
 
-    LOG_ID_MAX
+  LOG_ID_MAX
 };
 
 struct abort_msg_t {
@@ -68,14 +69,13 @@
   char msg[0];
 };
 
-__LIBC_HIDDEN__ void __libc_set_abort_message(const char* msg);
+void __android_set_abort_message(const char* msg);
 
 //
 // Formats a message to the log (priority 'fatal'), then aborts.
 //
 
 __LIBC_HIDDEN__ __noreturn void __libc_fatal(const char* format, ...) __printflike(1, 2);
-__noreturn void __android_fatal(const char* tag, const char* format, ...) __printflike(2, 3);
 
 //
 // Formats a message to the log (priority 'fatal'), but doesn't abort.
diff --git a/libc/stdio/fileext.h b/libc/stdio/fileext.h
index fa6fed6..1f2a3a3 100644
--- a/libc/stdio/fileext.h
+++ b/libc/stdio/fileext.h
@@ -29,6 +29,9 @@
  * $Citrus$
  */
 
+#ifndef _FILEEXT_H_
+#define _FILEEXT_H_
+
 #include <pthread.h>
 
 /*
@@ -59,3 +62,5 @@
 	(f)->_ext._base = (unsigned char *)(fext); \
 	_FILEEXT_INIT(f); \
 } while (0)
+
+#endif /* _FILEEXT_H_ */
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 5fb2292..907fd21 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -102,6 +102,7 @@
 #define FLOATING_POINT
 #define PRINTF_WIDE_CHAR
 #define SCANF_WIDE_CHAR
+#define NO_PRINTF_PERCENT_N
 
 /* OpenBSD exposes these in <stdio.h>, but we only want them exposed to the implementation. */
 __BEGIN_DECLS
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 4e14434..b051e22 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -41,11 +41,52 @@
 struct atexit *__atexit;
 
 /*
+ * TODO: Read this before upstreaming:
+ *
+ * As of Apr 2014 there is a bug regaring function type detection logic in
+ * Free/Open/NetBSD implementations of __cxa_finalize().
+ *
+ * What it is about:
+ * First of all there are two kind of atexit handlers:
+ *  1) void handler(void) - this is the regular type
+ *     available for to user via atexit(.) function call.
+ *
+ *  2) void internal_handler(void*) - this is the type
+ *     __cxa_atexit() function expects. This handler is used
+ *     by C++ compiler to register static destructor calls.
+ *     Note that calling this function as the handler of type (1)
+ *     results in incorrect this pointer in static d-tors.
+ *
+ * What is wrong with BSD implementations:
+ *
+ *  They use dso argument to identify the handler type. The problem
+ *  with it is dso is also used to identify the handlers associated
+ *  with particular dynamic library and allow __cxa_finalize to call correct
+ *  set of functions on dlclose(). And it cannot identify both.
+ *
+ * What is correct way to identify function type?
+ *
+ *  Consider this:
+ *  1. __cxa_finalize and __cxa_atexit are part of libc and do not have access to hidden
+ *     &__dso_handle.
+ *  2. __cxa_atexit has only 3 arguments: function pointer, function argument, dso.
+ *     none of them can be reliably used to pass information about handler type.
+ *  3. following http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor (3.3.5.3 - B)
+ *     translation of user atexit -> __cxa_atexit(f, NULL, NULL) results in crashes
+ *     on exit() after dlclose() of a library with an atexit() call.
+ *
+ *  One way to resolve this is to always call second form of handler, which will
+ *  result in storing unused argument in register/stack depending on architecture
+ *  and should not present any problems.
+ *
+ *  Another way is to make them dso-local in one way or the other.
+ */
+
+/*
  * Function pointers are stored in a linked list of pages. The list
  * is initially empty, and pages are allocated on demand. The first
  * function pointer in the first allocated page (the last one in
  * the linked list) was reserved for the cleanup function.
- * TODO: switch to the regular FreeBSD/NetBSD atexit implementation.
  *
  * Outside the following functions, all pages are mprotect()'ed
  * to prevent unintentional/malicious corruption.
@@ -94,7 +135,7 @@
 			__atexit_invalid = 0;
 	}
 	fnp = &p->fns[p->ind++];
-	fnp->fn_ptr.cxa_func = func;
+	fnp->cxa_func = func;
 	fnp->fn_arg = arg;
 	fnp->fn_dso = dso;
 	if (mprotect(p, pgsize, PROT_READ))
@@ -113,57 +154,59 @@
 void
 __cxa_finalize(void *dso)
 {
-	struct atexit *p, *q;
+	struct atexit *p, *q, *original_atexit;
 	struct atexit_fn fn;
-	int n, pgsize = getpagesize();
+	int n, pgsize = getpagesize(), original_ind;
 	static int call_depth;
 
 	if (__atexit_invalid)
 		return;
-
 	_ATEXIT_LOCK();
 	call_depth++;
 
-	for (p = __atexit; p != NULL; p = p->next) {
-		for (n = p->ind; --n >= 0;) {
-			if (p->fns[n].fn_ptr.cxa_func == NULL)
-				continue;	/* already called */
-			if (dso != NULL && dso != p->fns[n].fn_dso)
-				continue;	/* wrong DSO */
-
+	p = original_atexit = __atexit;
+	n = original_ind = p != NULL ? p->ind : 0;
+	while (p != NULL) {
+		if (p->fns[n].cxa_func != NULL /* not called */
+				&& (dso == NULL || dso == p->fns[n].fn_dso)) { /* correct DSO */
 			/*
 			 * Mark handler as having been already called to avoid
 			 * dupes and loops, then call the appropriate function.
 			 */
 			fn = p->fns[n];
 			if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
-				p->fns[n].fn_ptr.cxa_func = NULL;
+				p->fns[n].cxa_func = NULL;
 				mprotect(p, pgsize, PROT_READ);
 			}
+
 			_ATEXIT_UNLOCK();
-#if ANDROID
-                        /* it looks like we should always call the function
-                         * with an argument, even if dso is not NULL. Otherwise
-                         * static destructors will not be called properly on
-                         * the ARM.
-                         */
-                        (*fn.fn_ptr.cxa_func)(fn.fn_arg);
-#else /* !ANDROID */
-			if (dso != NULL)
-				(*fn.fn_ptr.cxa_func)(fn.fn_arg);
-			else
-				(*fn.fn_ptr.std_func)();
-#endif /* !ANDROID */
+			(*fn.cxa_func)(fn.fn_arg);
 			_ATEXIT_LOCK();
+			// check for new atexit handlers
+			if ((__atexit->ind != original_ind) || (__atexit != original_atexit)) {
+				// need to restart now to preserve correct
+				// call order - LIFO
+				p = original_atexit = __atexit;
+				n = original_ind = p->ind;
+				continue;
+			}
+		}
+		if (n == 0) {
+			p = p->next;
+			n = p != NULL ? p->ind : 0;
+		} else {
+			--n;
 		}
 	}
 
+	--call_depth;
+
 	/*
 	 * If called via exit(), unmap the pages since we have now run
 	 * all the handlers.  We defer this until calldepth == 0 so that
 	 * we don't unmap things prematurely if called recursively.
 	 */
-	if (dso == NULL && --call_depth == 0) {
+	if (dso == NULL && call_depth == 0) {
 		for (p = __atexit; p != NULL; ) {
 			q = p;
 			p = p->next;
diff --git a/libc/stdlib/atexit.h b/libc/stdlib/atexit.h
index 4b3e5ab..2e88ad6 100644
--- a/libc/stdlib/atexit.h
+++ b/libc/stdlib/atexit.h
@@ -37,10 +37,7 @@
 	int ind;			/* next index in this table */
 	int max;			/* max entries >= ATEXIT_SIZE */
 	struct atexit_fn {
-		union {
-			void (*std_func)(void);
-			void (*cxa_func)(void *);
-		} fn_ptr;
+		void (*cxa_func)(void *);
 		void *fn_arg;		/* argument for CXA callback */
 		void *fn_dso;		/* shared module handle */
 	} fns[1];			/* the table itself */
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate-NOTICE.py
index 3fad656..6d4c761 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate-NOTICE.py
@@ -55,10 +55,13 @@
             break
         if "\tcitrus Id: " in lines[i]:
             break
-        if "\t$OpenBSD: " in lines[i] or " $FreeBSD: " in lines[i] or "\t$NetBSD: " in lines[i]:
+        if "\t$Citrus: " in lines[i] or "\t$OpenBSD: " in lines[i] or " $FreeBSD: " in lines[i] or "\t$NetBSD: " in lines[i]:
             break
         if "$FreeBSD$" in lines[i] or "$Citrus$" in lines[i]:
             break
+        # OpenBSD likes to say where stuff originally came from:
+        if "Original version ID:" in lines[i]:
+            break
         i += 1
 
     end = i
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 1164a13..967629d 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -37,7 +37,12 @@
 #include "fcntl.h"
 #include "locale.h"
 #include <ctype.h>
+#if defined(__LP64__)
+#define time64_t time_t
+#define mktime64 mktime
+#else
 #include <time64.h>
+#endif
 #include "private/bionic_time.h"  /* for strftime_tz */
 
 /* struct lc_time_T is now defined as strftime_locale
@@ -155,7 +160,7 @@
     tzset();
     warn = IN_NONE;
     p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, locale);
-#if 0  /* ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
+#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
     if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
         (void) fprintf(stderr, "\n");
         if (format == NULL)
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index b55f390..bacd1d7 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -17,7 +17,6 @@
 #ifndef _BIONIC_OPENBSD_COMPAT_H_included
 #define _BIONIC_OPENBSD_COMPAT_H_included
 
-#define _GNU_SOURCE
 #define __USE_BSD
 
 /* OpenBSD's <ctype.h> uses these names, which conflicted with stlport.
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index c3d1a3c..2c860f7 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fnmatch.c,v 1.16 2011/12/06 11:47:46 stsp Exp $	*/
+/*	$OpenBSD: fnmatch.c,v 1.17 2013/11/24 23:51:29 deraadt Exp $	*/
 
 /* Copyright (c) 2011, VMware, Inc.
  * All rights reserved.
@@ -214,10 +214,13 @@
                 /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
                 if ((**string >= *startch) && (**string <= **pattern))
                     result = 0;
-                else if (nocase && (isupper(**string) || isupper(*startch)
-                                                      || isupper(**pattern))
-                            && (tolower(**string) >= tolower(*startch)) 
-                            && (tolower(**string) <= tolower(**pattern)))
+                else if (nocase && (isupper((unsigned char)**string) ||
+			    isupper((unsigned char)*startch) ||
+                            isupper((unsigned char)**pattern))
+                            && (tolower((unsigned char)**string) >=
+			        tolower((unsigned char)*startch)) 
+                            && (tolower((unsigned char)**string) <=
+				tolower((unsigned char)**pattern)))
                     result = 0;
 
                 ++*pattern;
@@ -227,8 +230,10 @@
             /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
             if ((**string == **pattern))
                 result = 0;
-            else if (nocase && (isupper(**string) || isupper(**pattern))
-                            && (tolower(**string) == tolower(**pattern)))
+            else if (nocase && (isupper((unsigned char)**string) ||
+			    isupper((unsigned char)**pattern))
+                            && (tolower((unsigned char)**string) ==
+				tolower((unsigned char)**pattern)))
                 result = 0;
 
             ++*pattern;
@@ -254,8 +259,10 @@
     /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
     if (**string == **pattern)
         result = 0;
-    else if (nocase && (isupper(**string) || isupper(**pattern))
-                    && (tolower(**string) == tolower(**pattern)))
+    else if (nocase && (isupper((unsigned char)**string) ||
+		    isupper((unsigned char)**pattern))
+                    && (tolower((unsigned char)**string) ==
+			tolower((unsigned char)**pattern)))
         result = 0;
 
     /* Refuse to advance over trailing slash or nulls
diff --git a/libc/upstream-openbsd/lib/libc/gen/getprogname.c b/libc/upstream-openbsd/lib/libc/gen/getprogname.c
index 1cf498c88..17046ab 100644
--- a/libc/upstream-openbsd/lib/libc/gen/getprogname.c
+++ b/libc/upstream-openbsd/lib/libc/gen/getprogname.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getprogname.c,v 1.2 2013/05/31 21:19:01 tedu Exp $ */
+/* $OpenBSD: getprogname.c,v 1.3 2013/11/12 06:09:48 deraadt Exp $ */
 /*
  * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
  *
@@ -15,6 +15,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <stdlib.h>
+
 extern const char *__progname;
 
 const char *
diff --git a/libc/upstream-openbsd/lib/libc/gen/setprogname.c b/libc/upstream-openbsd/lib/libc/gen/setprogname.c
index 18b2ce0..089a15a 100644
--- a/libc/upstream-openbsd/lib/libc/gen/setprogname.c
+++ b/libc/upstream-openbsd/lib/libc/gen/setprogname.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: setprogname.c,v 1.3 2013/06/01 01:43:43 tedu Exp $ */
+/* $OpenBSD: setprogname.c,v 1.4 2013/11/12 06:09:48 deraadt Exp $ */
 /*
  * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
  *
@@ -16,6 +16,7 @@
  */
 
 #include <string.h>
+#include <stdlib.h>
 
 extern const char *__progname;
 
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
index 539b3c0..d0c0809 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fgetln.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
+/*	$OpenBSD: fgetln.c,v 1.12 2013/11/12 07:04:06 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -43,7 +43,7 @@
  * so we add 1 here.
 #endif
  */
-int
+static int
 __slbexpand(FILE *fp, size_t newsize)
 {
 	void *p;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputws.c b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
index c4c2d8e..108846e 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fputws.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fputws.c,v 1.6 2013/04/17 17:40:35 tedu Exp $	*/
+/*	$OpenBSD: fputws.c,v 1.7 2013/11/12 07:04:35 deraadt Exp $	*/
 /* $NetBSD: fputws.c,v 1.1 2003/03/07 07:11:37 tshiozak Exp $ */
 
 /*-
@@ -34,8 +34,7 @@
 #include <stdio.h>
 #include <wchar.h>
 #include "local.h"
-
-wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
+#include "fvwrite.h"
 
 int
 fputws(ws, fp)
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fread.c b/libc/upstream-openbsd/lib/libc/stdio/fread.c
index 430865d..8a592f6 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fread.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fread.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fread.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
+/*	$OpenBSD: fread.c,v 1.12 2014/05/01 16:40:36 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -33,8 +33,12 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdint.h>
+#include <errno.h>
 #include "local.h"
 
+#define MUL_NO_OVERFLOW	(1UL << (sizeof(size_t) * 4))
+
 size_t
 fread(void *buf, size_t size, size_t count, FILE *fp)
 {
@@ -44,6 +48,16 @@
 	size_t total;
 
 	/*
+	 * Extension:  Catch integer overflow
+	 */
+	if ((size >= MUL_NO_OVERFLOW || count >= MUL_NO_OVERFLOW) &&
+	    size > 0 && SIZE_MAX / size < count) {
+		errno = EOVERFLOW;
+		fp->_flags |= __SERR;
+		return (0);
+	}
+
+	/*
 	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
 	 */
 	if ((resid = count * size) == 0)
diff --git a/libc/stdio/fvwrite.h b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
similarity index 93%
rename from libc/stdio/fvwrite.h
rename to libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
index 96f65de..d3a309b 100644
--- a/libc/stdio/fvwrite.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $	*/
+/*	$OpenBSD: fvwrite.h,v 1.6 2013/11/12 07:04:35 deraadt Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -36,7 +36,7 @@
  * I/O descriptors for __sfvwrite().
  */
 struct __siov {
-	const void	*iov_base;
+	void	*iov_base;
 	size_t	iov_len;
 };
 struct __suio {
@@ -46,3 +46,4 @@
 };
 
 extern int __sfvwrite(FILE *, struct __suio *);
+wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
diff --git a/libc/upstream-freebsd/lib/libc/stdio/fwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
similarity index 74%
rename from libc/upstream-freebsd/lib/libc/stdio/fwrite.c
rename to libc/upstream-openbsd/lib/libc/stdio/fwrite.c
index 707d362..f0a17bf 100644
--- a/libc/upstream-freebsd/lib/libc/stdio/fwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: fwrite.c,v 1.11 2014/05/01 16:40:36 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,67 +31,58 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)fwrite.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "namespace.h"
-#include <errno.h>
-#include <stdint.h>
 #include <stdio.h>
-#include "un-namespace.h"
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
 #include "local.h"
 #include "fvwrite.h"
-#include "libc_private.h"
+
+#define MUL_NO_OVERFLOW	(1UL << (sizeof(size_t) * 4))
 
 /*
  * Write `count' objects (each size `size') from memory to the given file.
  * Return the number of whole objects written.
  */
 size_t
-fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
+fwrite(const void *buf, size_t size, size_t count, FILE *fp)
 {
 	size_t n;
 	struct __suio uio;
 	struct __siov iov;
+	int ret;
 
 	/*
-	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+	 * Extension:  Catch integer overflow
 	 */
-	if ((count == 0) || (size == 0))
-		return (0);
-
-	/*
-	 * Check for integer overflow.  As an optimization, first check that
-	 * at least one of {count, size} is at least 2^16, since if both
-	 * values are less than that, their product can't possible overflow
-	 * (size_t is always at least 32 bits on FreeBSD).
-	 */
-	if (((count | size) > 0xFFFF) &&
-	    (count > SIZE_MAX / size)) {
-		errno = EINVAL;
+	if ((size >= MUL_NO_OVERFLOW || count >= MUL_NO_OVERFLOW) &&
+	    size > 0 && SIZE_MAX / size < count) {
+		errno = EOVERFLOW;
 		fp->_flags |= __SERR;
 		return (0);
 	}
 
-	n = count * size;
+	/*
+	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+	 */
+	if ((n = count * size) == 0)
+		return (0);
 
 	iov.iov_base = (void *)buf;
 	uio.uio_resid = iov.iov_len = n;
 	uio.uio_iov = &iov;
 	uio.uio_iovcnt = 1;
 
-	FLOCKFILE(fp);
-	ORIENT(fp, -1);
 	/*
 	 * The usual case is success (__sfvwrite returns 0);
 	 * skip the divide if this happens, since divides are
 	 * generally slow and since this occurs whenever size==0.
 	 */
-	if (__sfvwrite(fp, &uio) != 0)
-	    count = (n - uio.uio_resid) / size;
+	FLOCKFILE(fp);
+	_SET_ORIENTATION(fp, -1);
+	ret = __sfvwrite(fp, &uio);
 	FUNLOCKFILE(fp);
-	return (count);
+	if (ret == 0)
+		return (count);
+	return ((n - uio.uio_resid) / size);
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
index b4f8f29..7f8ff31 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vfprintf.c,v 1.63 2013/03/02 19:40:08 guenther Exp $	*/
+/*	$OpenBSD: vfprintf.c,v 1.66 2014/05/03 12:36:45 deraadt Exp $	*/
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -216,11 +216,10 @@
 #include <locale.h>
 #include <math.h>
 #include "floatio.h"
+#include "gdtoa.h"
 
 #define	DEFPREC		6
 
-extern char *__dtoa(double, int, int, int *, int *, char **);
-extern void  __freedtoa(char *);
 static int exponent(char *, int, int);
 #endif /* FLOATING_POINT */
 
@@ -399,7 +398,7 @@
 	    flags&PTRINT ? GETARG(ptrdiff_t) : \
 	    flags&SIZEINT ? GETARG(ssize_t) : \
 	    flags&SHORTINT ? (short)GETARG(int) : \
-	    flags&CHARINT ? (__signed char)GETARG(int) : \
+	    flags&CHARINT ? (signed char)GETARG(int) : \
 	    GETARG(int)))
 #define	UARG() \
 	((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
@@ -802,6 +801,7 @@
 			}
 			break;
 #endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
 		case 'n':
 			if (flags & LLONGINT)
 				*GETARG(long long *) = ret;
@@ -810,7 +810,7 @@
 			else if (flags & SHORTINT)
 				*GETARG(short *) = ret;
 			else if (flags & CHARINT)
-				*GETARG(__signed char *) = ret;
+				*GETARG(signed char *) = ret;
 			else if (flags & PTRINT)
 				*GETARG(ptrdiff_t *) = ret;
 			else if (flags & SIZEINT)
@@ -820,6 +820,7 @@
 			else
 				*GETARG(int *) = ret;
 			continue;	/* no output */
+#endif /* NO_PRINTF_PERCENT_N */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
@@ -1318,6 +1319,7 @@
 				ADDTYPE(T_DOUBLE);
 			break;
 #endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
 		case 'n':
 			if (flags & LLONGINT)
 				ADDTYPE(TP_LLONG);
@@ -1334,6 +1336,7 @@
 			else
 				ADDTYPE(TP_INT);
 			continue;	/* no output */
+#endif /* NO_PRINTF_PERCENT_N */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c
index c2996a9..abefe32 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vfscanf.c,v 1.30 2013/04/17 17:40:35 tedu Exp $ */
+/*	$OpenBSD: vfscanf.c,v 1.31 2014/03/19 05:17:01 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -273,7 +273,7 @@
 			if (flags & SUPPRESS)
 				continue;
 			if (flags & SHORTSHORT)
-				*va_arg(ap, __signed char *) = nread;
+				*va_arg(ap, signed char *) = nread;
 			else if (flags & SHORT)
 				*va_arg(ap, short *) = nread;
 			else if (flags & LONG)
@@ -749,7 +749,7 @@
 				else if (flags & SHORT)
 					*va_arg(ap, short *) = res;
 				else if (flags & SHORTSHORT)
-					*va_arg(ap, __signed char *) = res;
+					*va_arg(ap, signed char *) = res;
 				else
 					*va_arg(ap, int *) = res;
 				nassigned++;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c
index f76eed3..745b4d9 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vfwprintf.c,v 1.6 2013/04/17 17:40:35 tedu Exp $ */
+/*	$OpenBSD: vfwprintf.c,v 1.10 2014/05/03 12:36:45 deraadt Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -54,8 +54,6 @@
 #include "local.h"
 #include "fvwrite.h"
 
-wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
-
 union arg {
 	int			intarg;
 	unsigned int		uintarg;
@@ -235,11 +233,10 @@
 #include <locale.h>
 #include <math.h>
 #include "floatio.h"
+#include "gdtoa.h"
 
 #define	DEFPREC		6
 
-extern char *__dtoa(double, int, int, int *, int *, char **);
-extern void  __freedtoa(char *);
 static int exponent(wchar_t *, int, int);
 #endif /* FLOATING_POINT */
 
@@ -392,7 +389,7 @@
 	    flags&PTRINT ? GETARG(ptrdiff_t) : \
 	    flags&SIZEINT ? GETARG(ssize_t) : \
 	    flags&SHORTINT ? (short)GETARG(int) : \
-	    flags&CHARINT ? (__signed char)GETARG(int) : \
+	    flags&CHARINT ? (signed char)GETARG(int) : \
 	    GETARG(int)))
 #define	UARG() \
 	((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
@@ -787,6 +784,7 @@
 			}
 			break;
 #endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
 		case 'n':
 			if (flags & LLONGINT)
 				*GETARG(long long *) = ret;
@@ -795,7 +793,7 @@
 			else if (flags & SHORTINT)
 				*GETARG(short *) = ret;
 			else if (flags & CHARINT)
-				*GETARG(__signed char *) = ret;
+				*GETARG(signed char *) = ret;
 			else if (flags & PTRINT)
 				*GETARG(ptrdiff_t *) = ret;
 			else if (flags & SIZEINT)
@@ -805,6 +803,7 @@
 			else
 				*GETARG(int *) = ret;
 			continue;	/* no output */
+#endif /* NO_PRINTF_PERCENT_N */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
@@ -1299,6 +1298,7 @@
 				ADDTYPE(T_DOUBLE);
 			break;
 #endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
 		case 'n':
 			if (flags & LLONGINT)
 				ADDTYPE(TP_LLONG);
@@ -1315,6 +1315,7 @@
 			else
 				ADDTYPE(TP_INT);
 			continue;	/* no output */
+#endif /* NO_PRINTF_PERCENT_N */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
index e5cf5e1..cbb36be 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vfwscanf.c,v 1.2 2012/01/18 17:23:11 chl Exp $ */
+/*	$OpenBSD: vfwscanf.c,v 1.4 2014/03/19 05:17:01 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -31,7 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#include <ctype.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <locale.h>
@@ -300,7 +299,7 @@
 			if (flags & SUPPRESS)
 				continue;
 			if (flags & SHORTSHORT)
-				*va_arg(ap, __signed char *) = nread;
+				*va_arg(ap, signed char *) = nread;
 			else if (flags & SHORT)
 				*va_arg(ap, short *) = nread;
 			else if (flags & LONG)
@@ -324,7 +323,7 @@
 			return (EOF);
 
 		default:	/* compat */
-			if (isupper(c))
+			if (iswupper(c))
 				flags |= LONG;
 			c = CT_INT;
 			base = 10;
@@ -672,7 +671,7 @@
 				else if (flags & SHORT)
 					*va_arg(ap, short *) = res;
 				else if (flags & SHORTSHORT)
-					*va_arg(ap, __signed char *) = res;
+					*va_arg(ap, signed char *) = res;
 				else
 					*va_arg(ap, int *) = res;
 				nassigned++;
diff --git a/libc/upstream-freebsd/lib/libc/stdio/wsetup.c b/libc/upstream-openbsd/lib/libc/stdio/wsetup.c
similarity index 87%
rename from libc/upstream-freebsd/lib/libc/stdio/wsetup.c
rename to libc/upstream-openbsd/lib/libc/stdio/wsetup.c
index 70f8247..0834223 100644
--- a/libc/upstream-freebsd/lib/libc/stdio/wsetup.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/wsetup.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: wsetup.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,13 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)wsetup.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "local.h"
@@ -44,7 +38,7 @@
 /*
  * Various output routines call wsetup to be sure it is safe to write,
  * because either _flags does not include __SWR, or _buf is NULL.
- * _wsetup returns 0 if OK to write; otherwise, it returns EOF and sets errno.
+ * _wsetup returns 0 if OK to write, nonzero otherwise.
  */
 int
 __swsetup(FILE *fp)
@@ -57,11 +51,8 @@
 	 * If we are not writing, we had better be reading and writing.
 	 */
 	if ((fp->_flags & __SWR) == 0) {
-		if ((fp->_flags & __SRW) == 0) {
-			errno = EBADF;
-			fp->_flags |= __SERR;
+		if ((fp->_flags & __SRW) == 0)
 			return (EOF);
-		}
 		if (fp->_flags & __SRD) {
 			/* clobber any ungetc data */
 			if (HASUB(fp))
@@ -76,8 +67,11 @@
 	/*
 	 * Make a buffer if necessary, then set _w.
 	 */
-	if (fp->_bf._base == NULL)
+	if (fp->_bf._base == NULL) {
+		if ((fp->_flags & (__SSTR | __SALC)) == __SSTR)
+			return (EOF);
 		__smakebuf(fp);
+	}
 	if (fp->_flags & __SLBF) {
 		/*
 		 * It is line buffered, so make _lbfsize be -_bufsize
diff --git a/libc/upstream-openbsd/lib/libc/string/strsep.c b/libc/upstream-openbsd/lib/libc/string/strsep.c
index bcca681..2ffc4b4 100644
--- a/libc/upstream-openbsd/lib/libc/string/strsep.c
+++ b/libc/upstream-openbsd/lib/libc/string/strsep.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strsep.c,v 1.7 2014/02/05 20:42:32 stsp Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -30,7 +30,6 @@
  */
 
 #include <string.h>
-#include <stdio.h>
 
 /*
  * Get next token from string *stringp, where tokens are possibly-empty
diff --git a/libc/upstream-openbsd/lib/libc/time/wcsftime.c b/libc/upstream-openbsd/lib/libc/time/wcsftime.c
new file mode 100644
index 0000000..21ccac7
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/time/wcsftime.c
@@ -0,0 +1,555 @@
+/*	$OpenBSD: wcsftime.c,v 1.3 2014/05/06 15:49:45 tedu Exp $ */
+#include "private.h"
+
+/*
+** Based on the UCB version with the ID appearing below.
+** This is ANSIish only when "multibyte character == plain character".
+**
+** Copyright (c) 1989, 1993
+**	The Regents of the University of California.  All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. Neither the name of the University nor the names of its contributors
+**    may be used to endorse or promote products derived from this software
+**    without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#include "tzfile.h"
+#include "fcntl.h"
+#include <locale.h>
+#include <wchar.h>
+
+struct lc_time_T {
+	const wchar_t *	mon[MONSPERYEAR];
+	const wchar_t *	month[MONSPERYEAR];
+	const wchar_t *	wday[DAYSPERWEEK];
+	const wchar_t *	weekday[DAYSPERWEEK];
+	const wchar_t *	X_fmt;
+	const wchar_t *	x_fmt;
+	const wchar_t *	c_fmt;
+	const wchar_t *	am;
+	const wchar_t *	pm;
+	const wchar_t *	date_fmt;
+};
+
+#define Locale	(&C_time_locale)
+
+static const struct lc_time_T	C_time_locale = {
+	{
+		L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
+		L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
+	}, {
+		L"January", L"February", L"March", L"April", L"May", L"June",
+		L"July", L"August", L"September", L"October", L"November", 
+		L"December"
+	}, {
+		L"Sun", L"Mon", L"Tue", L"Wed",
+		L"Thu", L"Fri", L"Sat"
+	}, {
+		L"Sunday", L"Monday", L"Tuesday", L"Wednesday",
+		L"Thursday", L"Friday", L"Saturday"
+	},
+
+	/* X_fmt */
+	L"%H:%M:%S",
+
+	/*
+	** x_fmt
+	** C99 requires this format.
+	** Using just numbers (as here) makes Quakers happier;
+	** it's also compatible with SVR4.
+	*/
+	L"%m/%d/%y",
+
+	/*
+	** c_fmt
+	** C99 requires this format.
+	** Previously this code used "%D %X", but we now conform to C99.
+	** Note that
+	**	"%a %b %d %H:%M:%S %Y"
+	** is used by Solaris 2.3.
+	*/
+	L"%a %b %e %T %Y",
+
+	/* am */
+	L"AM",
+
+	/* pm */
+	L"PM",
+
+	/* date_fmt */
+	L"%a %b %e %H:%M:%S %Z %Y"
+};
+
+#define UNKNOWN L"?"
+static wchar_t *	_add(const wchar_t *, wchar_t *, const wchar_t *);
+static wchar_t *	_sadd(const char *, wchar_t *, const wchar_t *);
+static wchar_t *	_conv(int, const wchar_t *, wchar_t *, const wchar_t *);
+static wchar_t *	_fmt(const wchar_t *, const struct tm *, wchar_t *, const wchar_t *,
+			int *);
+static wchar_t *	_yconv(int, int, int, int, wchar_t *, const wchar_t *);
+
+extern char *	tzname[];
+
+#define IN_NONE	0
+#define IN_SOME	1
+#define IN_THIS	2
+#define IN_ALL	3
+
+size_t
+wcsftime(wchar_t *__restrict s, size_t maxsize, 
+    const wchar_t *__restrict format, const struct tm *__restrict t)
+{
+	wchar_t *p;
+	int	warn;
+
+	tzset();
+	warn = IN_NONE;
+	p = _fmt(((format == NULL) ? L"%c" : format), t, s, s + maxsize, &warn);
+	if (p == s + maxsize) {
+		if (maxsize > 0)
+			s[maxsize - 1] = '\0';
+		return 0;
+	}
+	*p = L'\0';
+	return p - s;
+}
+
+static wchar_t *
+_fmt(const wchar_t *format, const struct tm *t, wchar_t *pt, 
+    const wchar_t *ptlim, int *warnp)
+{
+	for ( ; *format; ++format) {
+		if (*format != L'%') {
+			if (pt == ptlim)
+				break;
+			*pt++ = *format;
+			continue;
+		}
+label:
+		switch (*++format) {
+		case '\0':
+			--format;
+			break;
+		case 'A':
+			pt = _add((t->tm_wday < 0 ||
+				t->tm_wday >= DAYSPERWEEK) ?
+				UNKNOWN : Locale->weekday[t->tm_wday],
+				pt, ptlim);
+			continue;
+		case 'a':
+			pt = _add((t->tm_wday < 0 ||
+				t->tm_wday >= DAYSPERWEEK) ?
+				UNKNOWN : Locale->wday[t->tm_wday],
+				pt, ptlim);
+			continue;
+		case 'B':
+			pt = _add((t->tm_mon < 0 ||
+				t->tm_mon >= MONSPERYEAR) ?
+				UNKNOWN : Locale->month[t->tm_mon],
+				pt, ptlim);
+			continue;
+		case 'b':
+		case 'h':
+			pt = _add((t->tm_mon < 0 ||
+				t->tm_mon >= MONSPERYEAR) ?
+				UNKNOWN : Locale->mon[t->tm_mon],
+				pt, ptlim);
+			continue;
+		case 'C':
+			/*
+			** %C used to do a...
+			**	_fmt("%a %b %e %X %Y", t);
+			** ...whereas now POSIX 1003.2 calls for
+			** something completely different.
+			** (ado, 1993-05-24)
+			*/
+			pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+				pt, ptlim);
+			continue;
+		case 'c':
+			{
+			int warn2 = IN_SOME;
+
+			pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
+			if (warn2 == IN_ALL)
+				warn2 = IN_THIS;
+			if (warn2 > *warnp)
+				*warnp = warn2;
+			}
+			continue;
+		case 'D':
+			pt = _fmt(L"%m/%d/%y", t, pt, ptlim, warnp);
+			continue;
+		case 'd':
+			pt = _conv(t->tm_mday, L"%02d", pt, ptlim);
+			continue;
+		case 'E':
+		case 'O':
+			/*
+			** C99 locale modifiers.
+			** The sequences
+			**	%Ec %EC %Ex %EX %Ey %EY
+			**	%Od %oe %OH %OI %Om %OM
+			**	%OS %Ou %OU %OV %Ow %OW %Oy
+			** are supposed to provide alternate
+			** representations.
+			*/
+			goto label;
+		case 'e':
+			pt = _conv(t->tm_mday, L"%2d", pt, ptlim);
+			continue;
+		case 'F':
+			pt = _fmt(L"%Y-%m-%d", t, pt, ptlim, warnp);
+			continue;
+		case 'H':
+			pt = _conv(t->tm_hour, L"%02d", pt, ptlim);
+			continue;
+		case 'I':
+			pt = _conv((t->tm_hour % 12) ?
+				(t->tm_hour % 12) : 12,
+				L"%02d", pt, ptlim);
+			continue;
+		case 'j':
+			pt = _conv(t->tm_yday + 1, L"%03d", pt, ptlim);
+			continue;
+		case 'k':
+			/*
+			** This used to be...
+			**	_conv(t->tm_hour % 12 ?
+			**		t->tm_hour % 12 : 12, 2, ' ');
+			** ...and has been changed to the below to
+			** match SunOS 4.1.1 and Arnold Robbins'
+			** strftime version 3.0. That is, "%k" and
+			** "%l" have been swapped.
+			** (ado, 1993-05-24)
+			*/
+			pt = _conv(t->tm_hour, L"%2d", pt, ptlim);
+			continue;
+		case 'l':
+			/*
+			** This used to be...
+			**	_conv(t->tm_hour, 2, ' ');
+			** ...and has been changed to the below to
+			** match SunOS 4.1.1 and Arnold Robbin's
+			** strftime version 3.0. That is, "%k" and
+			** "%l" have been swapped.
+			** (ado, 1993-05-24)
+			*/
+			pt = _conv((t->tm_hour % 12) ?
+				(t->tm_hour % 12) : 12,
+				L"%2d", pt, ptlim);
+			continue;
+		case 'M':
+			pt = _conv(t->tm_min, L"%02d", pt, ptlim);
+			continue;
+		case 'm':
+			pt = _conv(t->tm_mon + 1, L"%02d", pt, ptlim);
+			continue;
+		case 'n':
+			pt = _add(L"\n", pt, ptlim);
+			continue;
+		case 'p':
+			pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
+				Locale->pm :
+				Locale->am,
+				pt, ptlim);
+			continue;
+		case 'R':
+			pt = _fmt(L"%H:%M", t, pt, ptlim, warnp);
+			continue;
+		case 'r':
+			pt = _fmt(L"%I:%M:%S %p", t, pt, ptlim, warnp);
+			continue;
+		case 'S':
+			pt = _conv(t->tm_sec, L"%02d", pt, ptlim);
+			continue;
+		case 's':
+			{
+				struct tm	tm;
+				wchar_t		buf[INT_STRLEN_MAXIMUM(
+							time_t) + 1];
+				time_t		mkt;
+
+				tm = *t;
+				mkt = mktime(&tm);
+				if (TYPE_SIGNED(time_t))
+					(void) swprintf(buf, 
+					    sizeof buf/sizeof buf[0],
+					    L"%ld", (long) mkt);
+				else	
+					(void) swprintf(buf, 
+					    sizeof buf/sizeof buf[0],
+					    L"%lu", (unsigned long) mkt);
+				pt = _add(buf, pt, ptlim);
+			}
+			continue;
+		case 'T':
+			pt = _fmt(L"%H:%M:%S", t, pt, ptlim, warnp);
+			continue;
+		case 't':
+			pt = _add(L"\t", pt, ptlim);
+			continue;
+		case 'U':
+			pt = _conv((t->tm_yday + DAYSPERWEEK -
+				t->tm_wday) / DAYSPERWEEK,
+				L"%02d", pt, ptlim);
+			continue;
+		case 'u':
+			/*
+			** From Arnold Robbins' strftime version 3.0:
+			** "ISO 8601: Weekday as a decimal number
+			** [1 (Monday) - 7]"
+			** (ado, 1993-05-24)
+			*/
+			pt = _conv((t->tm_wday == 0) ?
+				DAYSPERWEEK : t->tm_wday,
+				L"%d", pt, ptlim);
+			continue;
+		case 'V':	/* ISO 8601 week number */
+		case 'G':	/* ISO 8601 year (four digits) */
+		case 'g':	/* ISO 8601 year (two digits) */
+/*
+** From Arnold Robbins' strftime version 3.0: "the week number of the
+** year (the first Monday as the first day of week 1) as a decimal number
+** (01-53)."
+** (ado, 1993-05-24)
+**
+** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** "Week 01 of a year is per definition the first week which has the
+** Thursday in this year, which is equivalent to the week which contains
+** the fourth day of January. In other words, the first week of a new year
+** is the week which has the majority of its days in the new year. Week 01
+** might also contain days from the previous year and the week before week
+** 01 of a year is the last week (52 or 53) of the previous year even if
+** it contains days from the new year. A week starts with Monday (day 1)
+** and ends with Sunday (day 7). For example, the first week of the year
+** 1997 lasts from 1996-12-30 to 1997-01-05..."
+** (ado, 1996-01-02)
+*/
+			{
+			int	year;
+			int	base;
+			int	yday;
+			int	wday;
+			int	w;
+
+			year = t->tm_year;
+			base = TM_YEAR_BASE;
+			yday = t->tm_yday;
+			wday = t->tm_wday;
+			for ( ; ; ) {
+				int	len;
+				int	bot;
+				int	top;
+
+				len = isleap_sum(year, base) ?
+					DAYSPERLYEAR :
+					DAYSPERNYEAR;
+				/*
+				** What yday (-3 ... 3) does the ISO year 
+				** begin on?
+				*/
+				bot = ((yday + 11 - wday) % DAYSPERWEEK) - 3;
+				/*
+				** What yday does the NEXT ISO year begin on?
+				*/
+				top = bot - (len % DAYSPERWEEK);
+				if (top < -3)
+					top += DAYSPERWEEK;
+				top += len;
+				if (yday >= top) {
+					++base;
+					w = 1;
+					break;
+				}
+				if (yday >= bot) {
+					w = 1 + ((yday - bot) / DAYSPERWEEK);
+					break;
+				}
+				--base;
+				yday += isleap_sum(year, base) ?
+					DAYSPERLYEAR :
+					DAYSPERNYEAR;
+			}
+			if ((w == 52 && t->tm_mon == TM_JANUARY) ||
+				(w == 1 && t->tm_mon == TM_DECEMBER))
+					w = 53;
+			if (*format == 'V')
+				pt = _conv(w, L"%02d", pt, ptlim);
+			else if (*format == 'g') {
+				*warnp = IN_ALL;
+				pt = _yconv(year, base, 0, 1, pt, ptlim);
+			} else	
+				pt = _yconv(year, base, 1, 1, pt, ptlim);
+			}
+			continue;
+		case 'v':
+			/*
+			** From Arnold Robbins' strftime version 3.0:
+			** "date as dd-bbb-YYYY"
+			** (ado, 1993-05-24)
+			*/
+			pt = _fmt(L"%e-%b-%Y", t, pt, ptlim, warnp);
+			continue;
+		case 'W':
+			pt = _conv((t->tm_yday + DAYSPERWEEK -
+				(t->tm_wday ?
+				(t->tm_wday - 1) :
+				(DAYSPERWEEK - 1))) / DAYSPERWEEK,
+				L"%02d", pt, ptlim);
+			continue;
+		case 'w':
+			pt = _conv(t->tm_wday, L"%d", pt, ptlim);
+			continue;
+		case 'X':
+			pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
+			continue;
+		case 'x':
+			{
+			int	warn2 = IN_SOME;
+
+			pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
+			if (warn2 == IN_ALL)
+				warn2 = IN_THIS;
+			if (warn2 > *warnp)
+				*warnp = warn2;
+			}
+			continue;
+		case 'y':
+			*warnp = IN_ALL;
+			pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, pt, ptlim);
+			continue;
+		case 'Y':
+			pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, pt, ptlim);
+			continue;
+		case 'Z':
+			if (t->tm_zone != NULL)
+				pt = _sadd(t->TM_ZONE, pt, ptlim);
+			else
+				if (t->tm_isdst >= 0)
+					pt = _sadd(tzname[t->tm_isdst != 0], 
+					    pt, ptlim);
+			/*
+			** C99 says that %Z must be replaced by the
+			** empty string if the time zone is not
+			** determinable.
+			*/
+			continue;
+		case 'z':
+			{
+			int		diff;
+			wchar_t const *	sign;
+
+			if (t->tm_isdst < 0)
+				continue;
+			diff = t->tm_gmtoff;
+			if (diff < 0) {
+				sign = L"-";
+				diff = -diff;
+			} else	
+				sign = L"+";
+			pt = _add(sign, pt, ptlim);
+			diff /= SECSPERMIN;
+			diff = (diff / MINSPERHOUR) * 100 +
+				(diff % MINSPERHOUR);
+			pt = _conv(diff, L"%04d", pt, ptlim);
+			}
+			continue;
+		case '+':
+			pt = _fmt(Locale->date_fmt, t, pt, ptlim, warnp);
+			continue;
+		case '%':
+		/*
+		** X311J/88-090 (4.12.3.5): if conversion wchar_t is
+		** undefined, behavior is undefined. Print out the
+		** character itself as printf(3) also does.
+		*/
+		default:
+			if (pt != ptlim)
+				*pt++ = *format;
+			break;
+		}
+	}
+	return pt;
+}
+
+static wchar_t *
+_conv(int n, const wchar_t *format, wchar_t *pt, const wchar_t *ptlim)
+{
+	wchar_t	buf[INT_STRLEN_MAXIMUM(int) + 1];
+
+	(void) swprintf(buf, sizeof buf/sizeof buf[0], format, n);
+	return _add(buf, pt, ptlim);
+}
+
+static wchar_t *
+_add(const wchar_t *str, wchar_t *pt, const wchar_t *ptlim)
+{
+	while (pt < ptlim && (*pt = *str++) != L'\0')
+		++pt;
+	return pt;
+}
+
+static wchar_t *
+_sadd(const char *str, wchar_t *pt, const wchar_t *ptlim)
+{
+	while (pt < ptlim && (*pt = btowc(*str++)) != L'\0')
+		++pt;
+	return pt;
+}
+/*
+** POSIX and the C Standard are unclear or inconsistent about
+** what %C and %y do if the year is negative or exceeds 9999.
+** Use the convention that %C concatenated with %y yields the
+** same output as %Y, and that %Y contains at least 4 bytes,
+** with more only if necessary.
+*/
+
+static wchar_t *
+_yconv(int a, int b, int convert_top, int convert_yy, wchar_t *pt, 
+    const wchar_t *ptlim)
+{
+	register int	lead;
+	register int	trail;
+
+#define DIVISOR	100
+	trail = a % DIVISOR + b % DIVISOR;
+	lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
+	trail %= DIVISOR;
+	if (trail < 0 && lead > 0) {
+		trail += DIVISOR;
+		--lead;
+	} else if (lead < 0 && trail > 0) {
+		trail -= DIVISOR;
+		++lead;
+	}
+	if (convert_top) {
+		if (lead == 0 && trail < 0)
+			pt = _add(L"-0", pt, ptlim);
+		else	pt = _conv(lead, L"%02d", pt, ptlim);
+	}
+	if (convert_yy)
+		pt = _conv(((trail < 0) ? -trail : trail), L"%02d", pt, ptlim);
+	return pt;
+}
+
diff --git a/libm/Android.mk b/libm/Android.mk
index 5f69d1e..d7d8bc1 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -234,6 +234,11 @@
     -DFLT_EVAL_METHOD=0 \
     -std=c99 \
     -include $(LOCAL_PATH)/freebsd-compat.h \
+    -Wno-missing-braces \
+    -Wno-parentheses \
+    -Wno-sign-compare \
+    -Wno-uninitialized \
+    -Wno-unknown-pragmas \
 
 libm_common_includes := $(LOCAL_PATH)/upstream-freebsd/lib/msun/src/
 
diff --git a/libm/NOTICE b/libm/NOTICE
index 5a8e139..5be60db 100644
--- a/libm/NOTICE
+++ b/libm/NOTICE
@@ -155,6 +155,32 @@
 
 -------------------------------------------------------------------
 
+Copyright (C) 2014 The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 1985, 1993
    The Regents of the University of California.  All rights reserved.
 
@@ -312,32 +338,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 2003 Dag-Erling Smørgrav
 All rights reserved.
 
@@ -976,6 +976,32 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2013 David Chisnall
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+
+-------------------------------------------------------------------
+
 From: @(#)s_ilogb.c 5.1 93/09/24
 ====================================================
 Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
diff --git a/libm/include/math.h b/libm/include/math.h
index bd0241b..c264583 100644
--- a/libm/include/math.h
+++ b/libm/include/math.h
@@ -396,16 +396,23 @@
  * long double versions of ISO/POSIX math functions
  */
 #if __ISO_C_VISIBLE >= 1999
+long double	acoshl(long double);
 long double	acosl(long double);
+long double	asinhl(long double);
 long double	asinl(long double);
 long double	atan2l(long double, long double);
+long double	atanhl(long double);
 long double	atanl(long double);
 long double	cbrtl(long double);
 long double	ceill(long double);
 long double	copysignl(long double, long double) __pure2;
+long double	coshl(long double);
 long double	cosl(long double);
+long double	erfcl(long double);
+long double	erfl(long double);
 long double	exp2l(long double);
 long double	expl(long double);
+long double	expm1l(long double);
 long double	fabsl(long double) __pure2;
 long double	fdiml(long double, long double);
 long double	floorl(long double);
@@ -417,9 +424,14 @@
 long double	hypotl(long double, long double);
 int		ilogbl(long double) __pure2;
 long double	ldexpl(long double, int);
+long double	lgammal(long double);
 long long	llrintl(long double);
 long long	llroundl(long double);
+long double	log10l(long double);
+long double	log1pl(long double);
+long double	log2l(long double);
 long double	logbl(long double);
+long double	logl(long double);
 long		lrintl(long double);
 long		lroundl(long double);
 long double	modfl(long double, long double *); /* fundamentally !__pure2 */
@@ -429,53 +441,29 @@
 double		nexttoward(double, long double);
 float		nexttowardf(float, long double);
 long double	nexttowardl(long double, long double);
+long double	powl(long double, long double);
 long double	remainderl(long double, long double);
 long double	remquol(long double, long double, int *);
 long double	rintl(long double);
 long double	roundl(long double);
 long double	scalblnl(long double, long);
 long double	scalbnl(long double, int);
+long double	sinhl(long double);
 long double	sinl(long double);
 long double	sqrtl(long double);
+long double	tanhl(long double);
 long double	tanl(long double);
+long double	tgammal(long double);
 long double	truncl(long double);
 
 #endif /* __ISO_C_VISIBLE >= 1999 */
+
+#if defined(_GNU_SOURCE)
+void sincos(double, double*, double*);
+void sincosf(float, float*, float*);
+void sincosl(long double, long double*, long double*);
+#endif /* _GNU_SOURCE */
+
 __END_DECLS
 
 #endif /* !_MATH_H_ */
-
-/* separate header for cmath */
-#ifndef _MATH_EXTRA_H_
-#if __ISO_C_VISIBLE >= 1999
-#if _DECLARE_C99_LDBL_MATH
-
-#define _MATH_EXTRA_H_
-
-/*
- * extra long double versions of math functions for C99 and cmath
- */
-__BEGIN_DECLS
-
-long double	acoshl(long double);
-long double	asinhl(long double);
-long double	atanhl(long double);
-long double	coshl(long double);
-long double	erfcl(long double);
-long double	erfl(long double);
-long double	expm1l(long double);
-long double	lgammal(long double);
-long double	log10l(long double);
-long double	log1pl(long double);
-long double	log2l(long double);
-long double	logl(long double);
-long double	powl(long double, long double);
-long double	sinhl(long double);
-long double	tanhl(long double);
-long double	tgammal(long double);
-
-__END_DECLS
-
-#endif /* !_DECLARE_C99_LDBL_MATH */
-#endif /* __ISO_C_VISIBLE >= 1999 */
-#endif /* !_MATH_EXTRA_H_ */
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 4d8563e..1f32f6d 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -680,6 +680,9 @@
       return fd;
     }
     // ...but nvidia binary blobs (at least) rely on this behavior, so fall through for now.
+#if defined(__LP64__)
+    return -1;
+#endif
   }
 
   // Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
@@ -2068,6 +2071,12 @@
     si->dynamic = NULL;
     si->ref_count = 1;
 
+    ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
+    if (elf_hdr->e_type != ET_DYN) {
+        __libc_format_fd(2, "error: only position independent executables (PIE) are supported.\n");
+        exit(EXIT_FAILURE);
+    }
+
     // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
     parse_LD_LIBRARY_PATH(ldpath_env);
     parse_LD_PRELOAD(ldpreload_env);
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index cfeab96..12e9779 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -591,9 +591,12 @@
     return -1;
   }
   off_t file_size = file_stat.st_size;
-  void* temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
-  if (temp_mapping == MAP_FAILED) {
-    return -1;
+  void* temp_mapping = NULL;
+  if (file_size > 0) {
+    temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
+    if (temp_mapping == MAP_FAILED) {
+      return -1;
+    }
   }
   size_t file_offset = 0;
 
@@ -614,6 +617,13 @@
     size_t match_offset = 0;
     size_t size = seg_page_end - seg_page_start;
 
+    if (file_size - file_offset < size) {
+      // File is too short to compare to this segment. The contents are likely
+      // different as well (it's probably for a different library version) so
+      // just don't bother checking.
+      break;
+    }
+
     while (match_offset < size) {
       // Skip over dissimilar pages.
       while (match_offset < size &&
diff --git a/tests/Android.mk b/tests/Android.mk
index fccf3f1..10e288c 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -198,11 +198,14 @@
 endif
 
 # -----------------------------------------------------------------------------
-# Library used by dlext tests.
+# Library used by dlext tests - with/without GNU RELRO program header
 # -----------------------------------------------------------------------------
 libdlext_test_src_files := \
     dlext_test_library.cpp \
 
+libdlext_test_ldflags := \
+    -Wl,-z,relro \
+
 module := libdlext_test
 module_tag := optional
 build_type := target
@@ -210,6 +213,43 @@
 include $(LOCAL_PATH)/Android.build.mk
 
 # -----------------------------------------------------------------------------
+# create symlink to libdlext_test.so for symlink test
+# -----------------------------------------------------------------------------
+libdlext_origin := $(LOCAL_INSTALLED_MODULE)
+libdlext_sym := $(subst libdlext_test,libdlext_test_v2,$(libdlext_origin))
+$(libdlext_sym): $(libdlext_origin)
+	@echo "Symlink: $@ -> $(notdir $<)"
+	@mkdir -p $(dir $@)
+	$(hide) ln -sf $(notdir $<) $@
+
+ALL_MODULES := \
+  $(ALL_MODULES) $(libdlext_sym)
+
+libdlext_test_norelro_src_files := \
+    dlext_test_library.cpp \
+
+libdlext_test_norelro_ldflags := \
+    -Wl,-z,norelro \
+
+module := libdlext_test_norelro
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
+# Library used by atexit tests
+# -----------------------------------------------------------------------------
+
+libtest_atexit_src_files := \
+    atexit_testlib.cpp
+
+module := libtest_atexit
+build_type := target
+build_target := SHARED_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
 # Tests for the device using bionic's .so. Run with:
 #   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
 # -----------------------------------------------------------------------------
@@ -217,15 +257,23 @@
     libBionicTests \
 
 bionic-unit-tests_src_files := \
+    atexit_test.cpp \
     dlext_test.cpp \
     dlfcn_test.cpp \
 
+bionic-unit-tests_cppflags := \
+    $(test_cppflags)
+
 bionic-unit-tests_ldflags := \
     -Wl,--export-dynamic \
     -Wl,-u,DlSymTestFunction \
 
+bionic-unit-tests_c_includes := \
+    $(call include-path-for, libpagemap) \
+
 bionic-unit-tests_shared_libraries_target := \
     libdl \
+    libpagemap \
 
 module := bionic-unit-tests
 module_tag := optional
@@ -263,14 +311,21 @@
 
 ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
 
+bionic-unit-tests-glibc_src_files := \
+    atexit_test.cpp \
+
 bionic-unit-tests-glibc_whole_static_libraries := \
     libBionicStandardTests \
 
 bionic-unit-tests-glibc_ldlibs := \
-    -lrt \
+    -lrt -ldl \
+
+bionic-unit-tests-glibc_cppflags := \
+    $(test_cppflags)
 
 module := bionic-unit-tests-glibc
 module_tag := optional
+bionic-unit-tests-glibc_multilib := both
 build_type := host
 build_target := NATIVE_TEST
 include $(LOCAL_PATH)/Android.build.mk
diff --git a/tests/atexit_test.cpp b/tests/atexit_test.cpp
new file mode 100644
index 0000000..e01220e
--- /dev/null
+++ b/tests/atexit_test.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <dlfcn.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include <string>
+
+TEST(atexit, dlclose) {
+  std::string atexit_call_sequence;
+  bool valid_this_in_static_dtor = false;
+  void* handle = dlopen("libtest_atexit.so", RTLD_NOW);
+  ASSERT_TRUE(handle != NULL);
+
+  void* sym = dlsym(handle, "register_atexit");
+  ASSERT_TRUE(sym != NULL);
+  reinterpret_cast<void (*)(std::string*, bool*)>(sym)(&atexit_call_sequence, &valid_this_in_static_dtor);
+
+  ASSERT_EQ(0, dlclose(handle));
+  // this test verifies atexit call from atexit handler. as well as the order of calls
+  ASSERT_EQ("Humpty Dumpty sat on a wall", atexit_call_sequence);
+  ASSERT_TRUE(valid_this_in_static_dtor);
+}
+
+class TestMainStaticDtorClass {
+ public:
+  TestMainStaticDtorClass() {
+    expected_this = this;
+  }
+
+  ~TestMainStaticDtorClass() {
+    if (this != expected_this) {
+      fprintf(stderr, "\nerror: static d-tor called with incorrect this pointer: %p, expected: %p\n", this, expected_this);
+    } else {
+      fprintf(stderr, "6");
+    }
+  }
+ private:
+  static const TestMainStaticDtorClass* expected_this;
+};
+
+const TestMainStaticDtorClass* TestMainStaticDtorClass::expected_this = NULL;
+
+static void atexit_func5() {
+  fprintf(stderr, "5");
+}
+
+static void atexit_func4() {
+  fprintf(stderr, "4");
+}
+
+static void atexit_func3() {
+  fprintf(stderr, "3");
+  atexit(atexit_func4);
+}
+
+static void atexit_func2() {
+  fprintf(stderr, "2");
+}
+
+static void atexit_func1() {
+  fprintf(stderr, "1");
+}
+
+static void atexit_main() {
+  // This should result in "123456" output to stderr
+  static TestMainStaticDtorClass static_obj;
+  atexit(atexit_func5);
+  atexit(atexit_func3);
+  atexit(atexit_func2);
+  atexit(atexit_func1);
+  exit(0);
+}
+
+TEST(atexit, exit) {
+  ASSERT_EXIT(atexit_main(), testing::ExitedWithCode(0), "123456");
+}
+
diff --git a/tests/atexit_testlib.cpp b/tests/atexit_testlib.cpp
new file mode 100644
index 0000000..1fefdf0
--- /dev/null
+++ b/tests/atexit_testlib.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+
+// use external control number from main test
+static std::string* atexit_sequence = NULL;
+static bool* atexit_valid_this_in_static_dtor = NULL;
+
+static class AtExitStaticClass {
+ public:
+  AtExitStaticClass() { expected_this = this; }
+  ~AtExitStaticClass() {
+    if (atexit_valid_this_in_static_dtor) {
+      *atexit_valid_this_in_static_dtor = (expected_this == this);
+    }
+  }
+ private:
+  static const AtExitStaticClass* expected_this;
+
+} static_obj;
+
+const AtExitStaticClass* AtExitStaticClass::expected_this = NULL;
+
+// 4
+static void atexit_handler_from_atexit_from_atexit2() {
+  *atexit_sequence += " on";
+}
+
+// 3
+static void atexit_handler_from_atexit_from_atexit1() {
+  *atexit_sequence += " sat";
+}
+
+// 2
+static void atexit_handler_from_atexit() {
+  *atexit_sequence += " Dumpty";
+  // register 2 others
+  atexit(atexit_handler_from_atexit_from_atexit2);
+  atexit(atexit_handler_from_atexit_from_atexit1);
+}
+
+// 1
+static void atexit_handler_with_atexit() {
+  *atexit_sequence += "Humpty";
+  atexit(atexit_handler_from_atexit);
+}
+
+// last
+static void atexit_handler_regular() {
+  *atexit_sequence += " a wall";
+}
+
+extern "C" void register_atexit(std::string* sequence, bool* valid_this_in_static_dtor) {
+  atexit_sequence = sequence;
+  atexit_valid_this_in_static_dtor = valid_this_in_static_dtor;
+  atexit(atexit_handler_regular);
+  atexit(atexit_handler_with_atexit);
+  atexit(NULL);
+}
+
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 872cc5b..b56fc41 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -24,8 +24,11 @@
 #include <unistd.h>
 #include <android/dlext.h>
 #include <sys/mman.h>
+#include <sys/types.h>
 #include <sys/wait.h>
 
+#include <pagemap/pagemap.h>
+
 
 #define ASSERT_DL_NOTNULL(ptr) \
     ASSERT_TRUE(ptr != NULL) << "dlerror: " << dlerror()
@@ -39,6 +42,7 @@
 
 typedef int (*fn)(void);
 #define LIBNAME "libdlext_test.so"
+#define LIBNAME_NORELRO "libdlext_test_norelro.so"
 #define LIBSIZE 1024*1024 // how much address space to reserve for it
 
 
@@ -144,52 +148,208 @@
   EXPECT_EQ(4, f());
 }
 
-TEST_F(DlExtTest, RelroShareChildWrites) {
-  void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
-                     -1, 0);
-  ASSERT_TRUE(start != MAP_FAILED);
-  android_dlextinfo extinfo;
-  extinfo.reserved_addr = start;
-  extinfo.reserved_size = LIBSIZE;
+class DlExtRelroSharingTest : public DlExtTest {
+protected:
+  virtual void SetUp() {
+    DlExtTest::SetUp();
+    void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+                       -1, 0);
+    ASSERT_TRUE(start != MAP_FAILED);
+    extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
+    extinfo_.reserved_addr = start;
+    extinfo_.reserved_size = LIBSIZE;
+    extinfo_.relro_fd = -1;
 
-  int relro_fd;
-  char relro_file[PATH_MAX];
-  const char* android_data = getenv("ANDROID_DATA");
-  ASSERT_TRUE(android_data != NULL);
-  snprintf(relro_file, sizeof(relro_file), "%s/local/tmp/libdlext_test.relro", android_data);
-  relro_fd = open(relro_file, O_CREAT | O_RDWR | O_TRUNC, 0644);
-  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO;
-  ASSERT_NOERROR(relro_fd);
-  extinfo.relro_fd = relro_fd;
-
-  pid_t pid = fork();
-  if (pid == 0) {
-    // child process
-    void* handle = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
-    if (handle == NULL) {
-      fprintf(stderr, "in child: %s\n", dlerror());
-      exit(1);
-    }
-    exit(0);
+    const char* android_data = getenv("ANDROID_DATA");
+    ASSERT_TRUE(android_data != NULL);
+    snprintf(relro_file_, sizeof(relro_file_), "%s/local/tmp/libdlext_test.relro", android_data);
   }
 
-  // continuing in parent
-  ASSERT_NOERROR(close(relro_fd));
-  ASSERT_NOERROR(pid);
-  int status;
-  ASSERT_EQ(pid, waitpid(pid, &status, 0));
-  ASSERT_TRUE(WIFEXITED(status));
-  ASSERT_EQ(0, WEXITSTATUS(status));
+  virtual void TearDown() {
+    DlExtTest::TearDown();
+    if (extinfo_.relro_fd != -1) {
+      ASSERT_NOERROR(close(extinfo_.relro_fd));
+    }
+  }
 
-  relro_fd = open(relro_file, O_RDONLY);
+  void CreateRelroFile(const char* lib) {
+    int relro_fd = open(relro_file_, O_CREAT | O_RDWR | O_TRUNC, 0644);
+    ASSERT_NOERROR(relro_fd);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+      // child process
+      extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
+      extinfo_.relro_fd = relro_fd;
+      void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
+      if (handle == NULL) {
+        fprintf(stderr, "in child: %s\n", dlerror());
+        exit(1);
+      }
+      exit(0);
+    }
+
+    // continuing in parent
+    ASSERT_NOERROR(close(relro_fd));
+    ASSERT_NOERROR(pid);
+    int status;
+    ASSERT_EQ(pid, waitpid(pid, &status, 0));
+    ASSERT_TRUE(WIFEXITED(status));
+    ASSERT_EQ(0, WEXITSTATUS(status));
+
+    // reopen file for reading so it can be used
+    relro_fd = open(relro_file_, O_RDONLY);
+    ASSERT_NOERROR(relro_fd);
+    extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
+    extinfo_.relro_fd = relro_fd;
+  }
+
+  void TryUsingRelro(const char* lib) {
+    handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
+    ASSERT_DL_NOTNULL(handle_);
+    fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+    ASSERT_DL_NOTNULL(f);
+    EXPECT_EQ(4, f());
+  }
+
+  void SpawnChildrenAndMeasurePss(const char* lib, bool share_relro, size_t* pss_out);
+
+  android_dlextinfo extinfo_;
+  char relro_file_[PATH_MAX];
+};
+
+TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(LIBNAME));
+  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(LIBNAME));
+}
+
+TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(LIBNAME_NORELRO));
+  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(LIBNAME_NORELRO));
+}
+
+TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
+  int relro_fd = open(relro_file_, O_CREAT | O_RDWR | O_TRUNC, 0644);
   ASSERT_NOERROR(relro_fd);
-  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_USE_RELRO;
-  extinfo.relro_fd = relro_fd;
-  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
   ASSERT_NOERROR(close(relro_fd));
 
-  ASSERT_DL_NOTNULL(handle_);
-  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
-  ASSERT_DL_NOTNULL(f);
-  EXPECT_EQ(4, f());
+  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(LIBNAME));
+}
+
+TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(LIBNAME));
+  int relro_fd = open(relro_file_, O_RDONLY);
+  ASSERT_NOERROR(relro_fd);
+  extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
+  extinfo_.relro_fd = relro_fd;
+  int pipefd[2];
+  ASSERT_NOERROR(pipe(pipefd));
+
+  size_t without_sharing, with_sharing;
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(LIBNAME, false, &without_sharing));
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(LIBNAME, true, &with_sharing));
+
+  // We expect the sharing to save at least 10% of the total PSS. In practice
+  // it saves 40%+ for this test.
+  size_t expected_size = without_sharing - (without_sharing/10);
+  EXPECT_LT(with_sharing, expected_size);
+}
+
+void getPss(pid_t pid, size_t* pss_out) {
+  pm_kernel_t* kernel;
+  ASSERT_EQ(0, pm_kernel_create(&kernel));
+
+  pm_process_t* process;
+  ASSERT_EQ(0, pm_process_create(kernel, pid, &process));
+
+  pm_map_t** maps;
+  size_t num_maps;
+  ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
+
+  size_t total_pss = 0;
+  for (size_t i = 0; i < num_maps; i++) {
+    pm_memusage_t usage;
+    ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
+    total_pss += usage.pss;
+  }
+  *pss_out = total_pss;
+
+  free(maps);
+  pm_process_destroy(process);
+  pm_kernel_destroy(kernel);
+}
+
+void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, bool share_relro,
+                                                       size_t* pss_out) {
+  const int CHILDREN = 20;
+
+  // Create children
+  pid_t childpid[CHILDREN];
+  int childpipe[CHILDREN];
+  for (int i=0; i<CHILDREN; ++i) {
+    char read_buf;
+    int child_done_pipe[2], parent_done_pipe[2];
+    ASSERT_NOERROR(pipe(child_done_pipe));
+    ASSERT_NOERROR(pipe(parent_done_pipe));
+
+    pid_t child = fork();
+    if (child == 0) {
+      // close the 'wrong' ends of the pipes in the child
+      close(child_done_pipe[0]);
+      close(parent_done_pipe[1]);
+
+      // open the library
+      void* handle;
+      if (share_relro) {
+        handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
+      } else {
+        handle = dlopen(lib, RTLD_NOW);
+      }
+      if (handle == NULL) {
+        fprintf(stderr, "in child: %s\n", dlerror());
+        exit(1);
+      }
+
+      // close write end of child_done_pipe to signal the parent that we're done.
+      close(child_done_pipe[1]);
+
+      // wait for the parent to close parent_done_pipe, then exit
+      read(parent_done_pipe[0], &read_buf, 1);
+      exit(0);
+    }
+
+    ASSERT_NOERROR(child);
+
+    // close the 'wrong' ends of the pipes in the parent
+    close(child_done_pipe[1]);
+    close(parent_done_pipe[0]);
+
+    // wait for the child to be done
+    read(child_done_pipe[0], &read_buf, 1);
+    close(child_done_pipe[0]);
+
+    // save the child's pid and the parent_done_pipe
+    childpid[i] = child;
+    childpipe[i] = parent_done_pipe[1];
+  }
+
+  // Sum the PSS of all the children
+  size_t total_pss = 0;
+  for (int i=0; i<CHILDREN; ++i) {
+    size_t child_pss;
+    ASSERT_NO_FATAL_FAILURE(getPss(childpid[i], &child_pss));
+    total_pss += child_pss;
+  }
+  *pss_out = total_pss;
+
+  // Close pipes and wait for children to exit
+  for (int i=0; i<CHILDREN; ++i) {
+    ASSERT_NOERROR(close(childpipe[i]));
+  }
+  for (int i=0; i<CHILDREN; ++i) {
+    int status;
+    ASSERT_EQ(childpid[i], waitpid(childpid[i], &status, 0));
+    ASSERT_TRUE(WIFEXITED(status));
+    ASSERT_EQ(0, WEXITSTATUS(status));
+  }
 }
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index fc90dd9..1fdecdb 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -242,3 +242,11 @@
   void* addr = dlsym(RTLD_NEXT, "fopen");
   ASSERT_TRUE(addr != NULL);
 }
+
+TEST(dlfcn, dlopen_symlink) {
+  void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
+  void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW);
+  ASSERT_TRUE(handle1 != NULL);
+  ASSERT_TRUE(handle2 != NULL);
+  ASSERT_EQ(handle1, handle2);
+}
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 0b98e40..63ac719 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define _DECLARE_C99_LDBL_MATH 1
-
 // This include (and the associated definition of __test_capture_signbit)
 // must be placed before any files that include <cmath> (gtest.h in this case).
 //
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 9e7a9bc..6a5e4a6 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -256,22 +256,6 @@
   ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &original_set, NULL));
 }
 
-#if defined(__BIONIC__)
-extern "C" pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
-#endif // __BIONIC__
-
-TEST(pthread, __bionic_clone) {
-#if defined(__BIONIC__)
-  // Check that our hand-written clone assembler sets errno correctly on failure.
-  uintptr_t fake_child_stack[16];
-  errno = 0;
-  ASSERT_EQ(-1, __bionic_clone(CLONE_THREAD, &fake_child_stack[16], NULL, NULL, NULL, NULL, NULL));
-  ASSERT_EQ(EINVAL, errno);
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
-
 TEST(pthread, pthread_setname_np__too_long) {
 #if defined(__BIONIC__) // Not all build servers have a new enough glibc? TODO: remove when they're on gprecise.
   ASSERT_EQ(ERANGE, pthread_setname_np(pthread_self(), "this name is far too long for linux"));
diff --git a/tests/sched_test.cpp b/tests/sched_test.cpp
index 8dba948..7c19962 100644
--- a/tests/sched_test.cpp
+++ b/tests/sched_test.cpp
@@ -51,6 +51,14 @@
 }
 #endif
 
+TEST(sched, clone_errno) {
+  // Check that our hand-written clone assembler sets errno correctly on failure.
+  uintptr_t fake_child_stack[16];
+  errno = 0;
+  ASSERT_EQ(-1, clone(NULL, &fake_child_stack[16], CLONE_THREAD, NULL));
+  ASSERT_EQ(EINVAL, errno);
+}
+
 TEST(sched, cpu_set) {
   cpu_set_t set;
 
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index d825c14..73e9dcd 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -220,11 +220,16 @@
 }
 
 TEST(stdio, snprintf_n) {
+#if !defined(__GLIBC__)
+  // http://b/14492135
   char buf[32];
-  int i = 0;
-  EXPECT_EQ(4, snprintf(buf, sizeof(buf), "a %n b", &i));
-  EXPECT_EQ(2, i);
-  EXPECT_STREQ("a  b", buf);
+  int i = 1234;
+  EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
+  EXPECT_EQ(1234, i);
+  EXPECT_STREQ("a n b", buf);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(stdio, snprintf_smoke) {
@@ -436,3 +441,45 @@
   ASSERT_EQ(123, i1);
   ASSERT_DOUBLE_EQ(1.23, d1);
 }
+
+TEST(stdio, cantwrite_EBADF) {
+  // If we open a file read-only...
+  FILE* fp = fopen("/proc/version", "r");
+
+  // ...all attempts to write to that file should return failure.
+
+  // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
+  // glibc gets the wide-character functions wrong.
+
+  errno = 0;
+  EXPECT_EQ(EOF, putc('x', fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(EOF, fprintf(fp, "hello"));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
+#if !defined(__GLIBC__)
+  EXPECT_EQ(EBADF, errno);
+#endif
+
+  errno = 0;
+  EXPECT_EQ(EOF, putw(1234, fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(EOF, fputs("hello", fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(WEOF, fputwc(L'x', fp));
+#if !defined(__GLIBC__)
+  EXPECT_EQ(EBADF, errno);
+#endif
+}
diff --git a/tests/stubs_test.cpp b/tests/stubs_test.cpp
index 7d70aa6..9b0c231 100644
--- a/tests/stubs_test.cpp
+++ b/tests/stubs_test.cpp
@@ -41,6 +41,10 @@
   EXPECT_STREQ(username, pwd->pw_name);
   EXPECT_EQ(uid, pwd->pw_uid);
   EXPECT_EQ(uid, pwd->pw_gid);
+  ASSERT_EQ(NULL, pwd->pw_passwd);
+#ifdef __LP64__
+  ASSERT_EQ(NULL, pwd->pw_gecos);
+#endif
 
   if (uid_type == TYPE_SYSTEM) {
     EXPECT_STREQ("/", pwd->pw_dir);
diff --git a/tests/sys_epoll_test.cpp b/tests/sys_epoll_test.cpp
index daa064a..6e7a807 100644
--- a/tests/sys_epoll_test.cpp
+++ b/tests/sys_epoll_test.cpp
@@ -17,8 +17,10 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #include <signal.h>
 #include <sys/epoll.h>
+#include <unistd.h>
 
 TEST(sys_epoll, smoke) {
   int epoll_fd = epoll_create(1);
@@ -37,3 +39,30 @@
   sigaddset(&ss, SIGPIPE);
   ASSERT_EQ(0, epoll_pwait(epoll_fd, events, 1, 1, &ss));
 }
+
+TEST(sys_epoll, epoll_event_data) {
+  int epoll_fd = epoll_create(1);
+  ASSERT_NE(-1, epoll_fd) << strerror(errno);
+
+  int fds[2];
+  ASSERT_NE(-1, pipe(fds));
+
+  const uint64_t expected = 0x123456789abcdef0;
+
+  // Get ready to poll on read end of pipe.
+  epoll_event ev;
+  ev.events = EPOLLIN;
+  ev.data.u64 = expected;
+  ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
+
+  // Ensure there's something in the pipe.
+  ASSERT_EQ(1, write(fds[1], "\n", 1));
+
+  // Poll.
+  epoll_event events[1];
+  ASSERT_EQ(1, epoll_wait(epoll_fd, events, 1, 1));
+  ASSERT_EQ(expected, events[0].data.u64);
+
+  close(fds[0]);
+  close(fds[1]);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index ce0beba..2b51aad 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -275,3 +275,46 @@
 
   EXPECT_EQ(0, unsetenv("test-variable"));
 }
+
+static void TestFsyncFunction(int (*fn)(int)) {
+  int fd;
+
+  // Can't sync an invalid fd.
+  errno = 0;
+  EXPECT_EQ(-1, fn(-1));
+  EXPECT_EQ(EBADF, errno);
+
+  // It doesn't matter whether you've opened a file for write or not.
+  TemporaryFile tf;
+  ASSERT_NE(-1, tf.fd);
+
+  EXPECT_EQ(0, fn(tf.fd));
+
+  ASSERT_NE(-1, fd = open(tf.filename, O_RDONLY));
+  EXPECT_EQ(0, fn(fd));
+  close(fd);
+
+  ASSERT_NE(-1, fd = open(tf.filename, O_RDWR));
+  EXPECT_EQ(0, fn(fd));
+  close(fd);
+
+  // The fd can even be a directory.
+  ASSERT_NE(-1, fd = open("/", O_RDONLY));
+  EXPECT_EQ(0, fn(fd));
+  close(fd);
+
+  // But some file systems may choose to be fussy...
+  errno = 0;
+  ASSERT_NE(-1, fd = open("/proc/version", O_RDONLY));
+  EXPECT_EQ(-1, fn(fd));
+  EXPECT_EQ(EINVAL, errno);
+  close(fd);
+}
+
+TEST(unistd, fdatasync) {
+  TestFsyncFunction(fdatasync);
+}
+
+TEST(unistd, fsync) {
+  TestFsyncFunction(fsync);
+}
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 468f09f..0d15f21 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -250,13 +250,13 @@
   ASSERT_EQ(L'a', out[0]);
   // 2-byte UTF-8.
   ASSERT_EQ(2U, mbrtowc(out, "\xc2\xa2" "cdef", 6, NULL));
-  ASSERT_EQ(0x00a2, out[0]);
+  ASSERT_EQ(static_cast<wchar_t>(0x00a2), out[0]);
   // 3-byte UTF-8.
   ASSERT_EQ(3U, mbrtowc(out, "\xe2\x82\xac" "def", 6, NULL));
-  ASSERT_EQ(0x20ac, out[0]);
+  ASSERT_EQ(static_cast<wchar_t>(0x20ac), out[0]);
   // 4-byte UTF-8.
   ASSERT_EQ(4U, mbrtowc(out, "\xf0\xa4\xad\xa2" "ef", 6, NULL));
-  ASSERT_EQ(0x24b62, out[0]);
+  ASSERT_EQ(static_cast<wchar_t>(0x24b62), out[0]);
 #if __BIONIC__ // glibc allows this.
   // Illegal 5-byte UTF-8.
   ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf8\xa1\xa2\xa3\xa4" "f", 6, NULL));
@@ -319,3 +319,18 @@
   ASSERT_EQ(L'l', dst[2]);
   ASSERT_EQ(&s[3], src);
 }
+
+TEST(wchar, wcsftime) {
+  setenv("TZ", "UTC", 1);
+
+  struct tm t;
+  memset(&t, 0, sizeof(tm));
+  t.tm_year = 200;
+  t.tm_mon = 2;
+  t.tm_mday = 10;
+
+  wchar_t buf[64];
+
+  EXPECT_EQ(24U, wcsftime(buf, sizeof(buf), L"%c", &t));
+  EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
+}