Merge "Update kernel headers to v3.14."
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 0b0c47f..f330d7e 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -183,3 +183,29 @@
     delete[] pinfo;
 }
 BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
+
+static void BM_property_serial(int iters, int nprops)
+{
+    StopBenchmarkTiming();
+
+    LocalPropertyTestState pa(nprops);
+
+    if (!pa.valid)
+        return;
+
+    srandom(iters * nprops);
+    const prop_info** pinfo = new const prop_info*[iters];
+
+    for (int i = 0; i < iters; i++) {
+        pinfo[i] = __system_property_find(pa.names[random() % nprops]);
+    }
+
+    StartBenchmarkTiming();
+    for (int i = 0; i < iters; i++) {
+        __system_property_serial(pinfo[i]);
+    }
+    StopBenchmarkTiming();
+
+    delete[] pinfo;
+}
+BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
diff --git a/libc/Android.mk b/libc/Android.mk
index 078be59..5acdd6b 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -107,8 +107,9 @@
     bionic/clearenv.cpp \
     bionic/clock.cpp \
     bionic/clone.cpp \
-    bionic/cmsg_nxthdr.cpp \
+    bionic/__cmsg_nxthdr.cpp \
     bionic/connect.cpp \
+    bionic/ctype.cpp \
     bionic/__cxa_guard.cpp \
     bionic/__cxa_pure_virtual.cpp \
     bionic/dirent.cpp \
@@ -205,10 +206,16 @@
     bionic/socket.cpp \
     bionic/stat.cpp \
     bionic/statvfs.cpp \
+    bionic/strcoll_l.cpp \
     bionic/strerror.cpp \
     bionic/strerror_r.cpp \
+    bionic/strftime_l.cpp \
     bionic/strsignal.cpp \
     bionic/strtold.cpp \
+    bionic/strtold_l.cpp \
+    bionic/strtoll_l.cpp \
+    bionic/strtoull_l.cpp \
+    bionic/strxfrm_l.cpp \
     bionic/stubs.cpp \
     bionic/symlink.cpp \
     bionic/sysconf.cpp \
@@ -491,6 +498,12 @@
     -D_LIBC=1 \
     -Wall -Wextra -Wunused \
 
+ifneq ($(TARGET_USES_LOGD),false)
+libc_common_cflags += -DTARGET_USES_LOGD
+endif
+
+use_clang := false
+
 # Try to catch typical 32-bit assumptions that break with 64-bit pointers.
 libc_common_cflags += \
     -Werror=pointer-to-int-cast \
@@ -571,6 +584,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_stack_protector
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -608,6 +622,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes) $(LOCAL_PATH)/tzcode/
 LOCAL_MODULE := libc_tzcode
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -642,6 +657,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_dns
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -670,6 +686,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_freebsd
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -699,6 +716,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_netbsd
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -729,6 +747,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_openbsd
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -759,6 +778,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_gdtoa
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -780,13 +800,10 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_bionic
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
-ifneq ($(TARGET_USES_LOGD),false)
-LOCAL_CFLAGS += -DTARGET_USES_LOGD
-endif
-
 $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 $(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files))
 include $(BUILD_STATIC_LIBRARY)
@@ -803,6 +820,7 @@
 LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) := $(call all-S-files-under,arch-$(TARGET_2ND_ARCH)/syscalls)
 endif
 LOCAL_MODULE := libc_syscalls
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
@@ -810,6 +828,24 @@
 
 
 # ========================================================
+# libc_aeabi.a
+# This is an LP32 ARM-only library that needs to be built with -fno-builtin
+# to avoid infinite recursion. For the other architectures we just build an
+# empty library to keep this makefile simple.
+# ========================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES_arm := arch-arm/bionic/__aeabi.c
+LOCAL_MODULE := libc_aeabi
+LOCAL_CLANG := $(use_clang)
+LOCAL_CFLAGS := $(libc_common_cflags) -fno-builtin
+LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
+LOCAL_SYSTEM_SHARED_LIBRARIES :=
+
+include $(BUILD_STATIC_LIBRARY)
+
+# ========================================================
 # libc_common.a
 # ========================================================
 
@@ -821,6 +857,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_common
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_WHOLE_STATIC_LIBRARIES := \
     libc_bionic \
@@ -834,6 +871,8 @@
     libc_syscalls \
     libc_tzcode \
 
+LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
+
 ifeq ($(MALLOC_IMPL),jemalloc)
 LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
 endif
@@ -874,6 +913,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 
 LOCAL_MODULE := libc_nomalloc
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -896,6 +936,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_malloc
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 include $(BUILD_STATIC_LIBRARY)
 
@@ -918,6 +959,7 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -946,6 +988,7 @@
     bionic/NetdClient.cpp \
 
 LOCAL_MODULE := libc
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_REQUIRED_MODULES := tzdata
 
@@ -1011,14 +1054,15 @@
 LOCAL_SRC_FILES := \
     bionic/debug_mapinfo.cpp \
     bionic/debug_stacktrace.cpp \
+    bionic/libc_logging.cpp \
     bionic/malloc_debug_leak.cpp \
     bionic/malloc_debug_check.cpp \
 
 LOCAL_MODULE := libc_malloc_debug_leak
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 
 LOCAL_SHARED_LIBRARIES := libc libdl
-LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
 
@@ -1044,13 +1088,14 @@
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 
 LOCAL_SRC_FILES := \
-    bionic/malloc_debug_qemu.cpp
+    bionic/libc_logging.cpp \
+    bionic/malloc_debug_qemu.cpp \
 
 LOCAL_MODULE := libc_malloc_debug_qemu
+LOCAL_CLANG := $(use_clang)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 
 LOCAL_SHARED_LIBRARIES := libc libdl
-LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
 # Don't install on release build
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 47e436c..00be4ae 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -52,7 +52,6 @@
     arch-arm/bionic/abort_arm.S \
     arch-arm/bionic/atomics_arm.c \
     arch-arm/bionic/__bionic_clone.S \
-    arch-arm/bionic/eabi.c \
     arch-arm/bionic/_exit_with_stack_teardown.S \
     arch-arm/bionic/__get_sp.S \
     arch-arm/bionic/libgcc_compat.c \
diff --git a/libc/arch-arm/bionic/eabi.c b/libc/arch-arm/bionic/__aeabi.c
similarity index 84%
rename from libc/arch-arm/bionic/eabi.c
rename to libc/arch-arm/bionic/__aeabi.c
index 5511ddd..3254f64 100644
--- a/libc/arch-arm/bionic/eabi.c
+++ b/libc/arch-arm/bionic/__aeabi.c
@@ -25,10 +25,19 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
+#if defined(__clang__)
+// clang interprets -fno-builtin more loosely than you might expect,
+// and thinks it's okay to still substitute builtins as long as they're
+// named __aeabi_* rather than __builtin_*, which causes infinite
+// recursion if we have the fortified memcpy visible in this file.
+#undef _FORTIFY_SOURCE
+#endif
+
 #include <stddef.h>
 #include <string.h>
 
-extern int  __cxa_atexit(void (*)(void*), void*, void* );
+extern int __cxa_atexit(void (*)(void*), void*, void*);
 
 /* The "C++ ABI for ARM" document states that static C++ constructors,
  * which are called from the .init_array, should manually call
@@ -38,11 +47,9 @@
  * variable from the shared object that contains the constructor/destructor
  */
 
-/* Make this a weak symbol to avoid a multiple definition error when linking
- * with libstdc++-v3.  */
+// Make this a weak symbol to avoid a multiple definition error when linking with libstdc++-v3.
 int __attribute__((weak))
-__aeabi_atexit (void *object, void (*destructor) (void *), void *dso_handle)
-{
+__aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle) {
     return __cxa_atexit(destructor, object, dso_handle);
 }
 
@@ -73,10 +80,10 @@
 }
 
 /*
- * __aeabi_memset has the order of its second and third arguments reversed. 
+ * __aeabi_memset has the order of its second and third arguments reversed.
  *  This allows __aeabi_memclr to tail-call __aeabi_memset
  */
- 
+
 void __aeabi_memset8(void *dest, size_t n, int c) {
     memset(dest, c, n);
 }
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/__cmsg_nxthdr.cpp
similarity index 95%
rename from libc/bionic/cmsg_nxthdr.cpp
rename to libc/bionic/__cmsg_nxthdr.cpp
index 8a2b33e..f962788 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/__cmsg_nxthdr.cpp
@@ -37,6 +37,3 @@
   }
   return ptr;
 }
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/ctype.cpp
similarity index 61%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/ctype.cpp
index 8a2b33e..3960d9d 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/ctype.cpp
@@ -26,17 +26,64 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/socket.h>
+#include <ctype.h>
 
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
-  cmsghdr* ptr;
-  ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
-  size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
-  if (len > msg->msg_controllen) {
-    return NULL;
-  }
-  return ptr;
+int isalnum_l(int c, locale_t) {
+  return isalnum(c);
 }
 
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
+int isalpha_l(int c, locale_t) {
+  return isalpha(c);
+}
+
+int isascii_l(int c, locale_t) {
+  return isascii(c);
+}
+
+int isblank_l(int c, locale_t) {
+  return isblank(c);
+}
+
+int iscntrl_l(int c, locale_t) {
+  return iscntrl(c);
+}
+
+int isdigit_l(int c, locale_t) {
+  return isdigit(c);
+}
+
+int isgraph_l(int c, locale_t) {
+  return isgraph(c);
+}
+
+int islower_l(int c, locale_t) {
+  return islower(c);
+}
+
+int isprint_l(int c, locale_t) {
+  return isprint(c);
+}
+
+int ispunct_l(int c, locale_t) {
+  return ispunct(c);
+}
+
+int isspace_l(int c, locale_t) {
+  return isspace(c);
+}
+
+int isupper_l(int c, locale_t) {
+  return isupper(c);
+}
+
+int isxdigit_l(int c, locale_t) {
+  return isxdigit(c);
+}
+
+int toupper_l(int c, locale_t) {
+  return toupper(c);
+}
+
+int tolower_l(int c, locale_t) {
+  return tolower(c);
+}
diff --git a/libc/bionic/dlmalloc.h b/libc/bionic/dlmalloc.h
index e065687..46efa91 100644
--- a/libc/bionic/dlmalloc.h
+++ b/libc/bionic/dlmalloc.h
@@ -32,6 +32,8 @@
 #define USE_SPIN_LOCKS 0
 #define DEFAULT_MMAP_THRESHOLD (64U * 1024U)
 
+#define malloc_getpagesize getpagesize()
+
 /* Export two symbols used by the VM. */
 __BEGIN_DECLS
 int dlmalloc_trim(size_t) __LIBC_ABI_PUBLIC__;
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index d1fe960..e33d560 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -21,7 +21,7 @@
 #include "private/bionic_macros.h"
 
 void* je_pvalloc(size_t bytes) {
-  size_t pagesize = sysconf(_SC_PAGESIZE);
+  size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) {
     return NULL;
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index e4e4c2e..1c63d4d 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -123,6 +123,7 @@
 static unsigned g_malloc_debug_backlog = 100;
 
 __LIBC_HIDDEN__ HashTable* g_hash_table;
+__LIBC_HIDDEN__ const MallocDebug* g_malloc_dispatch;
 
 static inline void init_front_guard(hdr_t* hdr) {
     memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
@@ -324,7 +325,7 @@
     while (backlog_num > g_malloc_debug_backlog) {
         hdr_t* gone = backlog_tail;
         del_from_backlog_locked(gone);
-        Malloc(free)(gone->base);
+        g_malloc_dispatch->free(gone->base);
     }
 }
 
@@ -336,7 +337,7 @@
         errno = ENOMEM;
         return NULL;
     }
-    hdr_t* hdr = static_cast<hdr_t*>(Malloc(malloc)(size));
+    hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->malloc(size));
     if (hdr) {
         hdr->base = hdr;
         hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -364,7 +365,7 @@
         return NULL;
     }
 
-    void* base = Malloc(malloc)(sizeof(hdr_t) + size + sizeof(ftr_t));
+    void* base = g_malloc_dispatch->malloc(sizeof(hdr_t) + size + sizeof(ftr_t));
     if (base != NULL) {
         // Check that the actual pointer that will be returned is aligned
         // properly.
@@ -461,7 +462,7 @@
                        user(hdr), bytes);
             log_backtrace(bt, depth);
             // just get a whole new allocation and leak the old one
-            return Malloc(realloc)(0, bytes);
+            return g_malloc_dispatch->realloc(0, bytes);
             // return realloc(user(hdr), bytes); // assuming it was allocated externally
         }
     }
@@ -474,15 +475,15 @@
     if (hdr->base != hdr) {
         // An allocation from memalign, so create another allocation and
         // copy the data out.
-        void* newMem = Malloc(malloc)(size);
+        void* newMem = g_malloc_dispatch->malloc(size);
         if (newMem == NULL) {
             return NULL;
         }
         memcpy(newMem, hdr, sizeof(hdr_t) + hdr->size);
-        Malloc(free)(hdr->base);
+        g_malloc_dispatch->free(hdr->base);
         hdr = static_cast<hdr_t*>(newMem);
     } else {
-        hdr = static_cast<hdr_t*>(Malloc(realloc)(hdr, size));
+        hdr = static_cast<hdr_t*>(g_malloc_dispatch->realloc(hdr, size));
     }
     if (hdr) {
         hdr->base = hdr;
@@ -501,7 +502,7 @@
         errno = ENOMEM;
         return NULL;
     }
-    hdr_t* hdr = static_cast<hdr_t*>(Malloc(calloc)(1, size));
+    hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->calloc(1, size));
     if (hdr) {
         hdr->base = hdr;
         hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -524,7 +525,7 @@
 }
 
 extern "C" struct mallinfo chk_mallinfo() {
-  return Malloc(mallinfo)();
+  return g_malloc_dispatch->mallinfo();
 }
 
 extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -538,7 +539,7 @@
 }
 
 extern "C" void* chk_pvalloc(size_t bytes) {
-  size_t pagesize = sysconf(_SC_PAGESIZE);
+  size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     return NULL;
@@ -547,7 +548,7 @@
 }
 
 extern "C" void* chk_valloc(size_t size) {
-  return chk_memalign(sysconf(_SC_PAGESIZE), size);
+  return chk_memalign(getpagesize(), size);
 }
 
 static void ReportMemoryLeaks() {
@@ -584,8 +585,9 @@
   }
 }
 
-extern "C" bool malloc_debug_initialize(HashTable* hash_table) {
+extern "C" bool malloc_debug_initialize(HashTable* hash_table, const MallocDebug* malloc_dispatch) {
   g_hash_table = hash_table;
+  g_malloc_dispatch = malloc_dispatch;
 
   char debug_backlog[PROP_VALUE_MAX];
   if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 9399237..be16625 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -46,6 +46,16 @@
 
 #include "private/ScopedPthreadMutexLocker.h"
 
+#if defined(USE_JEMALLOC)
+#include "jemalloc.h"
+#define Malloc(function)  je_ ## function
+#elif defined(USE_DLMALLOC)
+#include "dlmalloc.h"
+#define Malloc(function)  dl ## function
+#else
+#error "Either one of USE_DLMALLOC or USE_JEMALLOC must be defined."
+#endif
+
 // In a VM process, this is set to 1 after fork()ing out of zygote.
 int gMallocLeakZygoteChild = 0;
 
@@ -408,7 +418,7 @@
     dlclose(malloc_impl_handle);
     return;
   }
-  if (!malloc_debug_initialize(&g_hash_table)) {
+  if (!malloc_debug_initialize(&g_hash_table, &__libc_malloc_default_dispatch)) {
     dlclose(malloc_impl_handle);
     return;
   }
diff --git a/libc/bionic/malloc_debug_common.h b/libc/bionic/malloc_debug_common.h
index fb2f03d..5c73da3 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -51,17 +51,6 @@
 #define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
 #endif
 
-#ifdef USE_JEMALLOC
-#include "jemalloc.h"
-#define Malloc(function)  je_ ## function
-#else
-#ifndef USE_DLMALLOC
-#error "Either one of USE_DLMALLOC or USE_JEMALLOC must be defined."
-#endif
-#include "dlmalloc.h"
-#define Malloc(function)  dl ## function
-#endif
-
 // =============================================================================
 // Structures
 // =============================================================================
@@ -116,7 +105,7 @@
 #endif
 };
 
-typedef bool (*MallocDebugInit)(HashTable*);
+typedef bool (*MallocDebugInit)(HashTable*, const MallocDebug*);
 typedef void (*MallocDebugFini)(int);
 
 // =============================================================================
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 308d40b..d9824f0 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -62,6 +62,7 @@
 
 extern int gMallocLeakZygoteChild;
 extern HashTable* g_hash_table;
+extern const MallocDebug* g_malloc_dispatch;
 
 // =============================================================================
 // stack trace functions
@@ -143,7 +144,7 @@
         entry->allocations++;
     } else {
         // create a new entry
-        entry = static_cast<HashEntry*>(Malloc(malloc)(sizeof(HashEntry) + numEntries*sizeof(uintptr_t)));
+        entry = static_cast<HashEntry*>(g_malloc_dispatch->malloc(sizeof(HashEntry) + numEntries*sizeof(uintptr_t)));
         if (!entry) {
             return NULL;
         }
@@ -208,11 +209,11 @@
 #define CHK_SENTINEL_VALUE      0xeb
 
 extern "C" void* fill_calloc(size_t n_elements, size_t elem_size) {
-    return Malloc(calloc)(n_elements, elem_size);
+    return g_malloc_dispatch->calloc(n_elements, elem_size);
 }
 
 extern "C" void* fill_malloc(size_t bytes) {
-    void* buffer = Malloc(malloc)(bytes);
+    void* buffer = g_malloc_dispatch->malloc(bytes);
     if (buffer) {
         memset(buffer, CHK_SENTINEL_VALUE, bytes);
     }
@@ -220,17 +221,17 @@
 }
 
 extern "C" void fill_free(void* mem) {
-    size_t bytes = Malloc(malloc_usable_size)(mem);
+    size_t bytes = g_malloc_dispatch->malloc_usable_size(mem);
     memset(mem, CHK_FILL_FREE, bytes);
-    Malloc(free)(mem);
+    g_malloc_dispatch->free(mem);
 }
 
 extern "C" void* fill_realloc(void* mem, size_t bytes) {
-    size_t oldSize = Malloc(malloc_usable_size)(mem);
-    void* newMem = Malloc(realloc)(mem, bytes);
+    size_t oldSize = g_malloc_dispatch->malloc_usable_size(mem);
+    void* newMem = g_malloc_dispatch->realloc(mem, bytes);
     if (newMem) {
         // If this is larger than before, fill the extra with our pattern.
-        size_t newSize = Malloc(malloc_usable_size)(newMem);
+        size_t newSize = g_malloc_dispatch->malloc_usable_size(newMem);
         if (newSize > oldSize) {
             memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(newMem)+oldSize), CHK_FILL_FREE, newSize-oldSize);
         }
@@ -239,7 +240,7 @@
 }
 
 extern "C" void* fill_memalign(size_t alignment, size_t bytes) {
-    void* buffer = Malloc(memalign)(alignment, bytes);
+    void* buffer = g_malloc_dispatch->memalign(alignment, bytes);
     if (buffer) {
         memset(buffer, CHK_SENTINEL_VALUE, bytes);
     }
@@ -249,11 +250,11 @@
 extern "C" size_t fill_malloc_usable_size(const void* mem) {
     // Since we didn't allocate extra bytes before or after, we can
     // report the normal usable size here.
-    return Malloc(malloc_usable_size)(mem);
+    return g_malloc_dispatch->malloc_usable_size(mem);
 }
 
 extern "C" struct mallinfo fill_mallinfo() {
-  return Malloc(mallinfo)();
+  return g_malloc_dispatch->mallinfo();
 }
 
 extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -267,7 +268,7 @@
 }
 
 extern "C" void* fill_pvalloc(size_t bytes) {
-  size_t pagesize = sysconf(_SC_PAGESIZE);
+  size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     return NULL;
@@ -276,7 +277,7 @@
 }
 
 extern "C" void* fill_valloc(size_t size) {
-  return fill_memalign(sysconf(_SC_PAGESIZE), size);
+  return fill_memalign(getpagesize(), size);
 }
 
 // =============================================================================
@@ -298,7 +299,7 @@
         return NULL;
     }
 
-    void* base = Malloc(malloc)(size);
+    void* base = g_malloc_dispatch->malloc(size);
     if (base != NULL) {
         ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 
@@ -342,11 +343,11 @@
     entry->allocations--;
     if (entry->allocations <= 0) {
       remove_entry(entry);
-      Malloc(free)(entry);
+      g_malloc_dispatch->free(entry);
     }
 
     // now free the memory!
-    Malloc(free)(header);
+    g_malloc_dispatch->free(header);
   } else {
     debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
               header->guard, header->entry);
@@ -452,7 +453,7 @@
             return 0;
         }
 
-        size_t ret = Malloc(malloc_usable_size)(header);
+        size_t ret = g_malloc_dispatch->malloc_usable_size(header);
         if (ret != 0) {
             // The usable area starts at 'mem' and stops at 'header+ret'.
             return reinterpret_cast<uintptr_t>(header) + ret - reinterpret_cast<uintptr_t>(mem);
@@ -462,7 +463,7 @@
 }
 
 extern "C" struct mallinfo leak_mallinfo() {
-  return Malloc(mallinfo)();
+  return g_malloc_dispatch->mallinfo();
 }
 
 extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -476,7 +477,7 @@
 }
 
 extern "C" void* leak_pvalloc(size_t bytes) {
-  size_t pagesize = sysconf(_SC_PAGESIZE);
+  size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     return NULL;
@@ -485,5 +486,5 @@
 }
 
 extern "C" void* leak_valloc(size_t size) {
-  return leak_memalign(sysconf(_SC_PAGESIZE), size);
+  return leak_memalign(getpagesize(), size);
 }
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index fd5161a..b3b604d 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -336,6 +336,9 @@
 // Static data
 // =============================================================================
 
+// The underlying malloc implementation to use to get memory.
+static const MallocDebug* g_malloc_dispatch = NULL;
+
 /* Emulator's magic page address.
  * This page (mapped on /dev/qemu_trace device) is used to fire up events
  * in the emulator. */
@@ -595,7 +598,9 @@
  * Return:
  *  0 on success, or -1 on failure.
 */
-extern "C" bool malloc_debug_initialize(HashTable*) {
+extern "C" bool malloc_debug_initialize(HashTable*, const MallocDebug* malloc_dispatch) {
+    g_malloc_dispatch = malloc_dispatch;
+
     /* We will be using emulator's magic page to report memory allocation
      * activities. In essence, what magic page does, it translates writes to
      * the memory mapped spaces into writes to an I/O port that emulator
@@ -693,7 +698,7 @@
         errno = ENOMEM;
         return NULL;
     }
-    desc.ptr = Malloc(malloc)(size);
+    desc.ptr = g_malloc_dispatch->malloc(size);
     if (desc.ptr == NULL) {
         qemu_error_log("<libc_pid=%03u, pid=%03u> malloc(%zu): malloc(%zu) failed.",
                        malloc_pid, getpid(), bytes, size);
@@ -704,7 +709,7 @@
     if (notify_qemu_malloc(&desc)) {
         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: malloc: notify_malloc failed for ",
                   malloc_pid, getpid());
-        Malloc(free)(desc.ptr);
+        g_malloc_dispatch->free(desc.ptr);
         errno = ENOMEM;
         return NULL;
     } else {
@@ -726,7 +731,7 @@
 
     if (mem == NULL) {
         // Just let go NULL free
-        Malloc(free)(mem);
+        g_malloc_dispatch->free(mem);
         return;
     }
 
@@ -757,7 +762,7 @@
     } else {
         log_mdesc(info, &desc, "--- <libc_pid=%03u, pid=%03u> free(%p) -> ",
                   malloc_pid, getpid(), mem);
-        Malloc(free)(desc.ptr);
+        g_malloc_dispatch->free(desc.ptr);
     }
 }
 
@@ -816,7 +821,7 @@
         total_elements++;
         desc.suffix_size += (elem_size - total_size);
     }
-    desc.ptr = Malloc(calloc)(total_elements, elem_size);
+    desc.ptr = g_malloc_dispatch->calloc(total_elements, elem_size);
     if (desc.ptr == NULL) {
         error_log("<libc_pid=%03u, pid=%03u> calloc: calloc(%zu(%zu), %zu) (prx=%u, sfx=%u) failed.",
                    malloc_pid, getpid(), n_elements, total_elements, elem_size,
@@ -827,7 +832,7 @@
     if (notify_qemu_malloc(&desc)) {
         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: calloc(%zu(%zu), %zu): notify_malloc failed for ",
                   malloc_pid, getpid(), n_elements, total_elements, elem_size);
-        Malloc(free)(desc.ptr);
+        g_malloc_dispatch->free(desc.ptr);
         errno = ENOMEM;
         return NULL;
     } else {
@@ -905,7 +910,7 @@
         errno = ENOMEM;
         return NULL;
     }
-    new_desc.ptr = Malloc(malloc)(new_size);
+    new_desc.ptr = g_malloc_dispatch->malloc(new_size);
     if (new_desc.ptr == NULL) {
         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu): malloc(%zu) failed on ",
                   malloc_pid, getpid(), mem, bytes, new_size);
@@ -924,7 +929,7 @@
         log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu) notify_malloc failed -> ",
                   malloc_pid, getpid(), mem, bytes);
         log_mdesc(error, &cur_desc, "                                                                <- ");
-        Malloc(free)(new_desc.ptr);
+        g_malloc_dispatch->free(new_desc.ptr);
         errno = ENOMEM;
         return NULL;
     }
@@ -940,11 +945,11 @@
         /* Since we registered new decriptor with the emulator, we need
          * to unregister it before freeing newly allocated block. */
         notify_qemu_free(mallocdesc_user_ptr(&new_desc));
-        Malloc(free)(new_desc.ptr);
+        g_malloc_dispatch->free(new_desc.ptr);
         errno = ENOMEM;
         return NULL;
     }
-    Malloc(free)(cur_desc.ptr);
+    g_malloc_dispatch->free(cur_desc.ptr);
 
     log_mdesc(info, &new_desc, "=== <libc_pid=%03u, pid=%03u>: realloc(%p, %zu) -> ",
               malloc_pid, getpid(), mem, bytes);
@@ -985,7 +990,7 @@
 
         return NULL;
     }
-    desc.ptr = Malloc(memalign)(desc.prefix_size, size);
+    desc.ptr = g_malloc_dispatch->memalign(desc.prefix_size, size);
     if (desc.ptr == NULL) {
         error_log("<libc_pid=%03u, pid=%03u> memalign(%zx, %zu): malloc(%zu) failed.",
                   malloc_pid, getpid(), alignment, bytes, size);
@@ -994,7 +999,7 @@
     if (notify_qemu_malloc(&desc)) {
         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: memalign(%zx, %zu): notify_malloc failed for ",
                   malloc_pid, getpid(), alignment, bytes);
-        Malloc(free)(desc.ptr);
+        g_malloc_dispatch->free(desc.ptr);
         return NULL;
     }
 
@@ -1032,7 +1037,7 @@
 }
 
 extern "C" struct mallinfo qemu_instrumented_mallinfo() {
-  return Malloc(mallinfo)();
+  return g_malloc_dispatch->mallinfo();
 }
 
 extern "C" int qemu_instrumented_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -1048,7 +1053,7 @@
 }
 
 extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
-  size_t pagesize = sysconf(_SC_PAGESIZE);
+  size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
     qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
@@ -1059,5 +1064,5 @@
 }
 
 extern "C" void* qemu_instrumented_valloc(size_t size) {
-  return qemu_instrumented_memalign(sysconf(_SC_PAGESIZE), size);
+  return qemu_instrumented_memalign(getpagesize(), size);
 }
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 2ded22b..174e308 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -41,23 +41,12 @@
 #include "private/ErrnoRestorer.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
-// Used by gdb to track thread creation. See libthread_db.
-#ifdef __i386__
-extern "C" __attribute__((noinline)) __attribute__((fastcall)) void _thread_created_hook(pid_t) {}
-#else
-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 g_pthread_stack_creation_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static pthread_mutex_t g_debugger_notification_lock = PTHREAD_MUTEX_INITIALIZER;
-
 extern "C" int __isthreaded;
 
 // This code is used both by each new pthread and the code that initializes the main thread.
@@ -113,8 +102,6 @@
 }
 
 static void* __create_thread_stack(pthread_internal_t* thread) {
-  ScopedPthreadMutexLocker lock(&g_pthread_stack_creation_lock);
-
   // Create a new private anonymous map.
   int prot = PROT_READ | PROT_WRITE;
   int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
@@ -258,12 +245,6 @@
     return init_errno;
   }
 
-  // Notify any debuggers about the new thread.
-  {
-    ScopedPthreadMutexLocker debugger_locker(&g_debugger_notification_lock);
-    _thread_created_hook(thread->tid);
-  }
-
   // Publish the pthread_t and unlock the mutex to let the new thread start running.
   *thread_out = reinterpret_cast<pthread_t>(thread);
   pthread_mutex_unlock(&thread->startup_handshake_mutex);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strcoll_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strcoll_l.cpp
index 8a2b33e..7d7c28b 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strcoll_l.cpp
@@ -26,17 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/socket.h>
+#include <string.h>
 
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
-  cmsghdr* ptr;
-  ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
-  size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
-  if (len > msg->msg_controllen) {
-    return NULL;
-  }
-  return ptr;
+int strcoll_l(const char *s1, const char *s2, locale_t) {
+  return strcoll(s1, s2);
 }
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/strerror_r.cpp b/libc/bionic/strerror_r.cpp
index 5f2d362..1e57cc0 100644
--- a/libc/bionic/strerror_r.cpp
+++ b/libc/bionic/strerror_r.cpp
@@ -8,6 +8,7 @@
 #include <string.h>
 
 #include "private/ErrnoRestorer.h"
+#include "private/libc_logging.h"
 
 struct Pair {
   int code;
@@ -49,9 +50,9 @@
 
   const char* error_name = __strerror_lookup(error_number);
   if (error_name != NULL) {
-    length = snprintf(buf, buf_len, "%s", error_name);
+    length = strlcpy(buf, error_name, buf_len);
   } else {
-    length = snprintf(buf, buf_len, "Unknown error %d", error_number);
+    length = __libc_format_buffer(buf, buf_len, "Unknown error %d", error_number);
   }
   if (length >= buf_len) {
     errno_restorer.override(ERANGE);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strftime_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strftime_l.cpp
index 8a2b33e..fb01da5 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strftime_l.cpp
@@ -26,17 +26,9 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/socket.h>
+#include <time.h>
 
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
-  cmsghdr* ptr;
-  ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
-  size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
-  if (len > msg->msg_controllen) {
-    return NULL;
-  }
-  return ptr;
+size_t strftime_l(char *s, size_t max, const char *format, const struct tm *tm,
+                  locale_t) {
+  return strftime(s, max, format, tm);
 }
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strtold_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strtold_l.cpp
index 8a2b33e..4b230b9 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strtold_l.cpp
@@ -26,17 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/socket.h>
+#include <stdlib.h>
 
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
-  cmsghdr* ptr;
-  ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
-  size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
-  if (len > msg->msg_controllen) {
-    return NULL;
-  }
-  return ptr;
+long double strtold_l(const char *nptr, char **endptr, locale_t) {
+  return strtold(nptr, endptr);
 }
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strtoll_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strtoll_l.cpp
index 8a2b33e..05fb760 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strtoll_l.cpp
@@ -26,17 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/socket.h>
+#include <stdlib.h>
 
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
-  cmsghdr* ptr;
-  ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
-  size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
-  if (len > msg->msg_controllen) {
-    return NULL;
-  }
-  return ptr;
+long long strtoll_l(const char *nptr, char **endptr, size_t base, locale_t) {
+  return strtoll(nptr, endptr, base);
 }
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strtoull_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strtoull_l.cpp
index 8a2b33e..ba0bc6a 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strtoull_l.cpp
@@ -26,17 +26,9 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/socket.h>
+#include <stdlib.h>
 
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
-  cmsghdr* ptr;
-  ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
-  size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
-  if (len > msg->msg_controllen) {
-    return NULL;
-  }
-  return ptr;
+unsigned long long strtoull_l(const char *nptr, char **endptr, size_t base,
+                              locale_t) {
+  return strtoull(nptr, endptr, base);
 }
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strxfrm_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strxfrm_l.cpp
index 8a2b33e..afe3b96 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strxfrm_l.cpp
@@ -26,17 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/socket.h>
+#include <string.h>
 
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
-  cmsghdr* ptr;
-  ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
-  size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
-  if (len > msg->msg_controllen) {
-    return NULL;
-  }
-  return ptr;
+size_t strxfrm_l(char *dest, const char *src, size_t n, locale_t) {
+  return strxfrm(dest, src, n);
 }
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 9b025df..0937e9c 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -469,5 +469,6 @@
 
 // Portable code should use sysconf(_SC_PAGE_SIZE) directly instead.
 int getpagesize() {
-  return sysconf(_SC_PAGE_SIZE);
+  // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat.
+  return PAGE_SIZE;
 }
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index acb2761..ecb8b33 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -219,3 +219,25 @@
 size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps) {
   return wcsnrtombs(dst, src, SIZE_MAX, len, ps);
 }
+
+int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
+  return wcscoll(ws1, ws2);
+}
+
+size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) {
+  return wcsxfrm(dest, src, n);
+}
+
+long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, size_t base,
+                    locale_t) {
+  return wcstoll(nptr, endptr, base);
+}
+
+unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
+                              size_t base, locale_t) {
+  return wcstoull(nptr, endptr, base);
+}
+
+long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) {
+  return wcstold(nptr, endptr);
+}
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index 673402d..f2d7861 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
+#include <wctype.h>
 
 // TODO: these only work for the ASCII range; rewrite to dlsym icu4c? http://b/14499654
 
@@ -46,6 +47,19 @@
 int iswupper(wint_t wc) { return isupper(wc); }
 int iswxdigit(wint_t wc) { return isxdigit(wc); }
 
+int iswalnum_l(wint_t c, locale_t) { return iswalnum(c); }
+int iswalpha_l(wint_t c, locale_t) { return iswalpha(c); }
+int iswblank_l(wint_t c, locale_t) { return iswblank(c); }
+int iswcntrl_l(wint_t c, locale_t) { return iswcntrl(c); }
+int iswdigit_l(wint_t c, locale_t) { return iswdigit(c); }
+int iswgraph_l(wint_t c, locale_t) { return iswgraph(c); }
+int iswlower_l(wint_t c, locale_t) { return iswlower(c); }
+int iswprint_l(wint_t c, locale_t) { return iswprint(c); }
+int iswpunct_l(wint_t c, locale_t) { return iswpunct(c); }
+int iswspace_l(wint_t c, locale_t) { return iswspace(c); }
+int iswupper_l(wint_t c, locale_t) { return iswupper(c); }
+int iswxdigit_l(wint_t c, locale_t) { return iswxdigit(c); }
+
 int iswctype(wint_t wc, wctype_t char_class) {
   switch (char_class) {
     case WC_TYPE_ALNUM: return iswalnum(wc);
@@ -64,9 +78,16 @@
   }
 }
 
+int iswctype_l(wint_t wc, wctype_t char_class, locale_t) {
+  return iswctype(wc, char_class);
+}
+
 wint_t towlower(wint_t wc) { return tolower(wc); }
 wint_t towupper(wint_t wc) { return toupper(wc); }
 
+int towupper_l(int c, locale_t) { return towupper(c); }
+int towlower_l(int c, locale_t) { return towlower(c); }
+
 wctype_t wctype(const char* property) {
   static const char* const  properties[WC_TYPE_MAX] = {
     "<invalid>",
@@ -81,6 +102,10 @@
   return static_cast<wctype_t>(0);
 }
 
+wctype_t wctype_l(const char* property, locale_t) {
+  return wctype(property);
+}
+
 int wcwidth(wchar_t wc) {
   return (wc > 0);
 }
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index 6e97326..19b1adf 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -41,6 +41,7 @@
 #define _CTYPE_H_
 
 #include <sys/cdefs.h>
+#include <xlocale.h>
 
 #define	_CTYPE_U	0x01
 #define	_CTYPE_L	0x02
@@ -72,6 +73,22 @@
 int	tolower(int);
 int	toupper(int);
 
+int isalnum_l(int, locale_t);
+int isalpha_l(int, locale_t);
+int isascii_l(int, locale_t);
+int isblank_l(int, locale_t);
+int iscntrl_l(int, locale_t);
+int isdigit_l(int, locale_t);
+int isgraph_l(int, locale_t);
+int islower_l(int, locale_t);
+int isprint_l(int, locale_t);
+int ispunct_l(int, locale_t);
+int isspace_l(int, locale_t);
+int isupper_l(int, locale_t);
+int isxdigit_l(int, locale_t);
+int tolower_l(int, locale_t);
+int toupper_l(int, locale_t);
+
 #if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE > 200112 \
     || __XPG_VISIBLE > 600
 int	isblank(int);
diff --git a/libc/include/err.h b/libc/include/err.h
index aad1f59..ca62c9e 100644
--- a/libc/include/err.h
+++ b/libc/include/err.h
@@ -33,50 +33,25 @@
  */
 
 #ifndef _ERR_H_
-#define	_ERR_H_
+#define _ERR_H_
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
-__noreturn void	err(int, const char *, ...)
-			__printflike(2, 3);
-__noreturn void	verr(int, const char *, __va_list)
-			__printflike(2, 0);
-__noreturn void	errx(int, const char *, ...)
-			__printflike(2, 3);
-__noreturn void	verrx(int, const char *, __va_list)
-			__printflike(2, 0);
-void		warn(const char *, ...)
-			__printflike(1, 2);
-void		vwarn(const char *, __va_list)
-			__printflike(1, 0);
-void		warnx(const char *, ...)
-			__printflike(1, 2);
-void		vwarnx(const char *, __va_list)
-			__printflike(1, 0);
+/* printf's format string isn't nullable; the err family's one is,
+ * so we can't use __errlike here. */
+#define __errlike(x, y) __attribute__((__format__(printf, x, y)))
 
-/*
- * The _* versions are for use in library functions so user-defined
- * versions of err*,warn* do not get used.
- */
-__noreturn void	_err(int, const char *, ...)
-			__printflike(2, 3);
-__noreturn void	_verr(int, const char *, __va_list)
-			__printflike(2, 0);
-__noreturn void	_errx(int, const char *, ...)
-			__printflike(2, 3);
-__noreturn void	_verrx(int, const char *, __va_list)
-			__printflike(2, 0);
-void		_warn(const char *, ...)
-			__printflike(1, 2);
-void		_vwarn(const char *, __va_list)
-			__printflike(1, 0);
-void		_warnx(const char *, ...)
-			__printflike(1, 2);
-void		_vwarnx(const char *, __va_list)
-			__printflike(1, 0);
+__noreturn void err(int, const char *, ...) __errlike(2, 3);
+__noreturn void verr(int, const char *, __va_list) __errlike(2, 0);
+__noreturn void errx(int, const char *, ...) __errlike(2, 3);
+__noreturn void verrx(int, const char *, __va_list) __errlike(2, 0);
+void warn(const char *, ...) __errlike(1, 2);
+void vwarn(const char *, __va_list) __errlike(1, 0);
+void warnx(const char *, ...) __errlike(1, 2);
+void vwarnx(const char *, __va_list) __errlike(1, 0);
 
 __END_DECLS
 
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 62b7a67..0dac650 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -75,6 +75,10 @@
 extern float strtof(const char*, char**) __LIBC_ABI_PUBLIC__;
 extern long double strtold(const char*, char**) __LIBC_ABI_PUBLIC__;
 
+extern long double strtold_l(const char *, char **, locale_t) __LIBC_ABI_PUBLIC__;
+extern long long strtoll_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
+extern unsigned long long strtoull_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
+
 extern int atoi(const char*) __purefunc;
 extern long atol(const char*) __purefunc;
 extern long long atoll(const char*) __purefunc;
diff --git a/libc/include/string.h b/libc/include/string.h
index 7727c0e..af1c0c1 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -31,6 +31,7 @@
 #include <sys/cdefs.h>
 #include <stddef.h>
 #include <malloc.h>
+#include <xlocale.h>
 
 __BEGIN_DECLS
 
@@ -88,6 +89,9 @@
 extern int    strcoll(const char *, const char *) __purefunc;
 extern size_t strxfrm(char* __restrict, const char* __restrict, size_t);
 
+extern int    strcoll_l(const char *, const char *, locale_t) __purefunc;
+extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t);
+
 #if defined(__BIONIC_FORTIFY)
 
 __errordecl(__memcpy_dest_size_error, "memcpy: prevented write past end of buffer");
diff --git a/libc/include/time.h b/libc/include/time.h
index 0587a2d..34a53b2 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -31,6 +31,7 @@
 
 #include <sys/cdefs.h>
 #include <sys/time.h>
+#include <xlocale.h>
 
 __BEGIN_DECLS
 
@@ -75,6 +76,7 @@
 
 extern char* strptime(const char*, const char*, struct tm*) __LIBC_ABI_PUBLIC__;
 extern size_t strftime(char*, size_t, const char*, const struct tm*) __LIBC_ABI_PUBLIC__;
+extern size_t strftime_l(char *, size_t, const char *, const struct tm *, locale_t) __LIBC_ABI_PUBLIC__;
 
 extern char* ctime(const time_t*) __LIBC_ABI_PUBLIC__;
 extern char* ctime_r(const time_t*, char*) __LIBC_ABI_PUBLIC__;
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 014fed3..1898c7e 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -151,6 +151,13 @@
 extern int               wprintf(const wchar_t *, ...);
 extern int               wscanf(const wchar_t *, ...);
 
+extern long long          wcstoll_l(const wchar_t *, wchar_t **, size_t, locale_t);
+extern unsigned long long wcstoull_l(const wchar_t *, wchar_t **, size_t, locale_t);
+extern long double        wcstold_l(const wchar_t *, wchar_t **, locale_t );
+
+extern int    wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
+extern size_t wcsxfrm_l(wchar_t *, const wchar_t *, size_t, locale_t);
+
 extern size_t wcslcat(wchar_t*, const wchar_t*, size_t);
 extern size_t wcslcpy(wchar_t*, const wchar_t*, size_t);
 
diff --git a/libc/include/wctype.h b/libc/include/wctype.h
index b5f18a0..1a4a05e 100644
--- a/libc/include/wctype.h
+++ b/libc/include/wctype.h
@@ -1 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _WCTYPE_H_
+#define _WCTYPE_H_
+
 #include <wchar.h>
+
+__BEGIN_DECLS
+
+extern int iswalnum_l(wint_t, locale_t);
+extern int iswalpha_l(wint_t, locale_t);
+extern int iswblank_l(wint_t, locale_t);
+extern int iswcntrl_l(wint_t, locale_t);
+extern int iswdigit_l(wint_t, locale_t);
+extern int iswgraph_l(wint_t, locale_t);
+extern int iswlower_l(wint_t, locale_t);
+extern int iswprint_l(wint_t, locale_t);
+extern int iswpunct_l(wint_t, locale_t);
+extern int iswspace_l(wint_t, locale_t);
+extern int iswupper_l(wint_t, locale_t);
+extern int iswxdigit_l(wint_t, locale_t);
+extern int towlower_l(int, locale_t);
+extern int towupper_l(int, locale_t);
+
+extern int iswctype_l(wint_t, wctype_t, locale_t);
+extern wctype_t wctype_l(const char*, locale_t);
+
+__END_DECLS
+
+#endif /* _WCTYPE_H_ */
diff --git a/libc/private/libc_logging.h b/libc/private/libc_logging.h
index 7dd97a4..35c756b 100644
--- a/libc/private/libc_logging.h
+++ b/libc/private/libc_logging.h
@@ -88,7 +88,7 @@
 
 //
 // Formatting routines for the C library's internal debugging.
-// Unlike the usual alternatives, these don't allocate.
+// Unlike the usual alternatives, these don't allocate, and they don't drag in all of stdio.
 //
 
 __LIBC_HIDDEN__ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...)
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 05f2faa..e10238b 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -103,7 +103,7 @@
 {
 	struct atexit *p = __atexit;
 	struct atexit_fn *fnp;
-	size_t pgsize = sysconf(_SC_PAGESIZE);
+	size_t pgsize = getpagesize();
 	int ret = -1;
 
 	if (pgsize < sizeof(*p))
@@ -219,7 +219,7 @@
 __atexit_register_cleanup(void (*func)(void))
 {
         struct atexit *p;
-        size_t pgsize = sysconf(_SC_PAGESIZE);
+        size_t pgsize = getpagesize();
 
         if (pgsize < sizeof(*p))
                 return;
@@ -248,4 +248,3 @@
 unlock:
         _ATEXIT_UNLOCK();
 }
-
diff --git a/libc/tools/zoneinfo/update-tzdata.py b/libc/tools/zoneinfo/update-tzdata.py
index 3dcb210..6b69a5a 100755
--- a/libc/tools/zoneinfo/update-tzdata.py
+++ b/libc/tools/zoneinfo/update-tzdata.py
@@ -31,8 +31,8 @@
 print 'Found bionic in %s ...' % bionic_dir
 
 # Find the icu4c directory.
-icu_dir = os.path.realpath('%s/../external/icu4c' % bionic_dir)
-CheckDirExists(icu_dir, 'external/icu4c')
+icu_dir = os.path.realpath('%s/../external/icu/icu4c/source' % bionic_dir)
+CheckDirExists(icu_dir, 'external/icu/icu4c/source')
 print 'Found icu in %s ...' % icu_dir