Merge "[MIPSR6] Use C-coded string ops on mips32r6/mips64r6"
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 0a146ae..22f6e8e 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -19,26 +19,6 @@
 #include <sys/syscall.h>
 #include <time.h>
 
-#if defined(__BIONIC__)
-
-// Used by the horrible android.text.format.Time class, which is used by Calendar. http://b/8270865.
-extern "C" void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz);
-
-static void BM_time_localtime_tz(int iters) {
-  StartBenchmarkTiming();
-
-  time_t now(time(NULL));
-  tm broken_down_time;
-  for (int i = 0; i < iters; ++i) {
-    localtime_tz(&now, &broken_down_time, "Europe/Berlin");
-  }
-
-  StopBenchmarkTiming();
-}
-BENCHMARK(BM_time_localtime_tz);
-
-#endif
-
 static void BM_time_clock_gettime(int iters) {
   StartBenchmarkTiming();
 
diff --git a/libc/Android.mk b/libc/Android.mk
index 0bdf1a5..9554e18 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -45,7 +45,6 @@
     bionic/fts.c \
     bionic/gethostname.c \
     bionic/getpriority.c \
-    bionic/getpt.c \
     bionic/if_indextoname.c \
     bionic/if_nametoindex.c \
     bionic/initgroups.c \
@@ -53,8 +52,6 @@
     bionic/isatty.c \
     bionic/memmem.c \
     bionic/pathconf.c \
-    bionic/ptsname.c \
-    bionic/ptsname_r.c \
     bionic/pututline.c \
     bionic/sched_cpualloc.c \
     bionic/sched_cpucount.c \
@@ -63,7 +60,6 @@
     bionic/siginterrupt.c \
     bionic/sigsetmask.c \
     bionic/system_properties_compat.c \
-    bionic/unlockpt.c \
     stdio/snprintf.c\
     stdio/sprintf.c \
 
@@ -94,6 +90,7 @@
     bionic/access.cpp \
     bionic/assert.cpp \
     bionic/atof.cpp \
+    bionic/bionic_systrace.cpp \
     bionic/bionic_time_conversions.cpp \
     bionic/brk.cpp \
     bionic/c16rtomb.cpp \
@@ -174,6 +171,7 @@
     bionic/pthread_setschedparam.cpp \
     bionic/pthread_sigmask.cpp \
     bionic/ptrace.cpp \
+    bionic/pty.cpp \
     bionic/raise.cpp \
     bionic/rand.cpp \
     bionic/readlink.cpp \
@@ -287,20 +285,18 @@
     upstream-netbsd/lib/libc/stdlib/div.c \
     upstream-netbsd/lib/libc/stdlib/drand48.c \
     upstream-netbsd/lib/libc/stdlib/erand48.c \
+    upstream-netbsd/lib/libc/stdlib/insque.c \
     upstream-netbsd/lib/libc/stdlib/jrand48.c \
     upstream-netbsd/lib/libc/stdlib/ldiv.c \
     upstream-netbsd/lib/libc/stdlib/lldiv.c \
     upstream-netbsd/lib/libc/stdlib/lrand48.c \
-    upstream-netbsd/lib/libc/stdlib/lsearch.c \
     upstream-netbsd/lib/libc/stdlib/mrand48.c \
     upstream-netbsd/lib/libc/stdlib/nrand48.c \
     upstream-netbsd/lib/libc/stdlib/_rand48.c \
     upstream-netbsd/lib/libc/stdlib/rand_r.c \
+    upstream-netbsd/lib/libc/stdlib/remque.c \
     upstream-netbsd/lib/libc/stdlib/seed48.c \
     upstream-netbsd/lib/libc/stdlib/srand48.c \
-    upstream-netbsd/lib/libc/stdlib/tdelete.c \
-    upstream-netbsd/lib/libc/stdlib/tfind.c \
-    upstream-netbsd/lib/libc/stdlib/tsearch.c \
     upstream-netbsd/lib/libc/string/memccpy.c \
     upstream-netbsd/lib/libc/string/strcasestr.c \
     upstream-netbsd/lib/libc/string/strcoll.c \
@@ -469,6 +465,7 @@
     upstream-openbsd/lib/libc/stdlib/atoll.c \
     upstream-openbsd/lib/libc/stdlib/exit.c \
     upstream-openbsd/lib/libc/stdlib/getenv.c \
+    upstream-openbsd/lib/libc/stdlib/lsearch.c \
     upstream-openbsd/lib/libc/stdlib/setenv.c \
     upstream-openbsd/lib/libc/stdlib/strtoimax.c \
     upstream-openbsd/lib/libc/stdlib/strtol.c \
@@ -477,6 +474,8 @@
     upstream-openbsd/lib/libc/stdlib/strtoull.c \
     upstream-openbsd/lib/libc/stdlib/strtoumax.c \
     upstream-openbsd/lib/libc/stdlib/system.c \
+    upstream-openbsd/lib/libc/stdlib/tfind.c \
+    upstream-openbsd/lib/libc/stdlib/tsearch.c \
     upstream-openbsd/lib/libc/string/strcasecmp.c \
     upstream-openbsd/lib/libc/string/strcspn.c \
     upstream-openbsd/lib/libc/string/strdup.c \
@@ -981,8 +980,6 @@
     $(libc_arch_dynamic_src_files) \
     $(libc_static_common_src_files) \
     bionic/malloc_debug_common.cpp \
-    bionic/debug_mapinfo.cpp \
-    bionic/debug_stacktrace.cpp \
     bionic/libc_init_dynamic.cpp \
     bionic/NetdClient.cpp \
 
@@ -1048,7 +1045,10 @@
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 
-LOCAL_C_INCLUDES := $(libc_common_c_includes)
+# Make sure that unwind.h comes from libunwind.
+LOCAL_C_INCLUDES := \
+    external/libunwind/include \
+    $(libc_common_c_includes) \
 
 LOCAL_SRC_FILES := \
     bionic/debug_mapinfo.cpp \
@@ -1063,6 +1063,7 @@
 
 LOCAL_SHARED_LIBRARIES := libc libdl
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
+LOCAL_WHOLE_STATIC_LIBRARIES := libunwindbacktrace
 LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
 
 # Don't install on release build
diff --git a/libc/NOTICE b/libc/NOTICE
index afbaecf..80d9a27 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3,12 +3,12 @@
 
    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
+       * 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
+       * 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
+       * 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.
 
@@ -34,12 +34,12 @@
 
    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
+       * 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
+       * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
-      Neither the name of the company nor the names of its contributors
+       * Neither the name of the company nor the names of its contributors
          may be used to endorse or promote products derived from this
          software without specific prior written permission.
 
@@ -57,6 +57,34 @@
 
 -------------------------------------------------------------------
 
+ Copyright (c) 1993 John Brezak
+ 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 be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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) 1993 by Sun Microsystems, Inc. All rights reserved.
 
@@ -184,9 +212,9 @@
 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
+ * 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
+ * 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.
@@ -228,9 +256,9 @@
 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
+ * 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
+ * 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.
@@ -257,9 +285,9 @@
 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
+ * 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
+ * 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.
@@ -285,9 +313,9 @@
 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
+ * 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
+ * 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.
@@ -329,9 +357,9 @@
 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
+ * 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
+ * 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.
@@ -373,9 +401,9 @@
 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
+ * 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
+ * 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.
@@ -448,9 +476,9 @@
 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
+ * 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
+ * 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.
@@ -492,9 +520,9 @@
 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
+ * 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
+ * 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.
@@ -536,9 +564,9 @@
 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
+ * 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
+ * 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.
@@ -565,9 +593,9 @@
 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
+ * 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
+ * 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.
@@ -594,9 +622,9 @@
 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
+ * 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
+ * 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.
@@ -638,9 +666,9 @@
 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
+ * 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
+ * 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.
@@ -804,35 +832,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 1983, 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) 1983, 1989
    The Regents of the University of California.  All rights reserved.
 
@@ -3164,35 +3163,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 1999 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Michael Graff.
-
-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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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) 2000 Ben Harris.
 Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 All rights reserved.
@@ -4132,6 +4102,22 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
 Copyright (c) 2009
      MIPS Technologies, Inc., California.
 
@@ -4253,13 +4239,13 @@
 modification, are permitted provided that the following conditions
 are met:
 
-    Redistributions of source code must retain the above copyright
+     * 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
+     * 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 MIPS Technologies Inc. nor the names of its
+     * Neither the name of MIPS Technologies Inc. nor the names of its
        contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
 
@@ -4299,16 +4285,16 @@
 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 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.
+    * 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 Intel Corporation nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
+    * Neither the name of Intel Corporation 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
@@ -4329,16 +4315,16 @@
 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 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.
+    * 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 Intel Corporation nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
+    * Neither the name of Intel Corporation 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
@@ -4412,16 +4398,16 @@
 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 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.
+    * 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 Intel Corporation nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
+    * Neither the name of Intel Corporation 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
@@ -4471,16 +4457,16 @@
 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 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.
+    * 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 Intel Corporation nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
+    * Neither the name of Intel Corporation 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
@@ -4501,16 +4487,16 @@
 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 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.
+    * 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 Intel Corporation nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
+    * Neither the name of Intel Corporation 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
@@ -4530,12 +4516,12 @@
 
 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
+    * 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
+    * 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 VMware, Inc. nor the names of its contributors
+    * Neither the name of the VMware, Inc. nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission.
 
@@ -4557,12 +4543,12 @@
 
    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
+       * 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
+       * 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
+       * 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.
 
@@ -4586,12 +4572,12 @@
 
    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
+       * 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
+       * 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
+       * 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.
 
@@ -4660,14 +4646,14 @@
    modification, are permitted provided that the following conditions
    are met:
 
-     Redistributions of source code must retain the above copyright
+      * 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
+      * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
 
-     Neither the name of Linaro Limited nor the names of its
+      * Neither the name of Linaro Limited nor the names of its
       contributors may be used to endorse or promote products derived
       from this software without specific prior written permission.
 
@@ -4685,22 +4671,42 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+Copyright (c) 2014 Bob Beck <beck@obtuse.com>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Emulation of getentropy(2) as documented at:
+http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
+
+-------------------------------------------------------------------
+
 Copyright (c) 2014, Intel Corporation
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
-   Redistributions of source code must retain the above copyright notice,
-   this list of conditions and the following disclaimer.
+    * Redistributions 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.
+    * 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 Intel Corporation nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
+    * Neither the name of Intel Corporation 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
@@ -4720,12 +4726,12 @@
 
    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
+       * 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
+       * 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
+       * 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.
 
@@ -5149,3 +5155,34 @@
 
 -------------------------------------------------------------------
 
+memchr - find a character in a memory zone
+
+Copyright (c) 2014, ARM Limited
+All rights Reserved.
+Copyright (c) 2014, Linaro Ltd.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the company nor the names of its contributors
+      may be used to endorse or promote products derived from this
+      software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
diff --git a/libc/arch-mips/bionic/_setjmp.S b/libc/arch-mips/bionic/_setjmp.S
index 4465cd2..d237e6d 100644
--- a/libc/arch-mips/bionic/_setjmp.S
+++ b/libc/arch-mips/bionic/_setjmp.S
@@ -44,17 +44,6 @@
 FRAMESZ= MKFSIZ(0,4)
 GPOFF= FRAMESZ-2*REGSZ
 
-#define FPREG64_S(FPR, OFF, BASE)       \
-        swc1    FPR, OFF(BASE)  ;       \
-        mfhc1   t0, FPR         ;       \
-        sw      t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE)       \
-        lw      t0, OFF+4(BASE) ;       \
-        lw      t1, OFF(BASE)   ;       \
-        mtc1    t1, FPR         ;       \
-        mthc1   t0, FPR         ;       \
-
 LEAF(_setjmp, FRAMESZ)
 	PTR_SUBU sp, FRAMESZ
 	SETUP_GP64(GPOFF, _setjmp)
@@ -85,32 +74,19 @@
 	li	v0, 1				# be nice if we could tell
 	REG_S	v0, SC_FPUSED(a0)		# sc_fpused = 1
 	cfc1	v0, $31
+	s.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	s.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	s.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	s.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	s.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	s.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        swc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        swc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        swc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        swc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        swc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        swc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        swc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        swc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        swc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        swc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        swc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        swc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	s.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	s.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	s.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	s.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	s.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	s.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 	REG_S	v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
 #endif /* !SOFTFLOAT */
@@ -142,32 +118,19 @@
 	REG_L	sp, SC_REGS+SP*REGSZ(a0)
 #if !defined(SOFTFLOAT)
 	ctc1	v0, $31
+	l.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	l.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	l.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	l.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	l.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	l.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        lwc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        lwc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        lwc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        lwc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        lwc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        lwc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        lwc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        lwc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        lwc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        lwc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        lwc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        lwc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	l.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	l.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	l.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	l.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	l.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	l.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 #endif /* !SOFTFLOAT */
 	bne	a1, zero, 1f
diff --git a/libc/arch-mips/bionic/setjmp.S b/libc/arch-mips/bionic/setjmp.S
index 2af1fbd..31786be 100644
--- a/libc/arch-mips/bionic/setjmp.S
+++ b/libc/arch-mips/bionic/setjmp.S
@@ -45,17 +45,6 @@
 GPOFF= FRAMESZ-2*REGSZ
 RAOFF= FRAMESZ-1*REGSZ
 
-#define FPREG64_S(FPR, OFF, BASE)       \
-        swc1    FPR, OFF(BASE)  ;       \
-        mfhc1   t0, FPR         ;       \
-        sw      t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE)       \
-        lw      t0, OFF+4(BASE) ;       \
-        lw      t1, OFF(BASE)   ;       \
-        mtc1    t1, FPR         ;       \
-        mthc1   t0, FPR         ;       \
-
 NON_LEAF(setjmp, FRAMESZ, ra)
 	.mask	0x80000000, RAOFF
 	PTR_SUBU sp, FRAMESZ			# allocate stack frame
@@ -98,32 +87,19 @@
 	li	v0, 1				# be nice if we could tell
 	REG_S	v0, SC_FPUSED(a0)		# sc_fpused = 1
 	cfc1	v0, $31
+	s.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	s.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	s.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	s.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	s.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	s.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        swc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        swc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        swc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        swc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        swc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        swc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        swc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        swc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        swc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        swc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        swc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        swc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	s.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	s.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	s.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	s.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	s.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	s.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 	REG_S	v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
 #endif /* !SOFTFLOAT */
@@ -173,32 +149,19 @@
 #if !defined(SOFTFLOAT)
 	REG_L	v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
 	ctc1	v0, $31
+	l.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	l.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	l.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	l.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	l.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	l.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        lwc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        lwc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        lwc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        lwc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        lwc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        lwc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        lwc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        lwc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        lwc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        lwc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        lwc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        lwc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	l.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	l.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	l.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	l.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	l.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	l.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 #endif /* !SOFTFLOAT */
 	bne	a1, zero, 1f
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index e244f88..bf3b8ae 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -47,11 +47,6 @@
     bionic/__strcat_chk.cpp \
 
 
-ifneq ($(ARCH_MIPS_HAS_FPU),true)
-libc_common_cflags_mips := \
-    -DSOFTFLOAT
-endif
-
 ##########################################
 ### CPU specific source files
 libc_bionic_src_files_mips += \
@@ -94,3 +89,6 @@
 
 libc_crt_target_so_cflags_mips := \
     -fPIC
+
+libc_crt_target_ldflags_mips := \
+    -melf32ltsmip
diff --git a/libc/arch-mips64/bionic/_setjmp.S b/libc/arch-mips64/bionic/_setjmp.S
index 4465cd2..d237e6d 100644
--- a/libc/arch-mips64/bionic/_setjmp.S
+++ b/libc/arch-mips64/bionic/_setjmp.S
@@ -44,17 +44,6 @@
 FRAMESZ= MKFSIZ(0,4)
 GPOFF= FRAMESZ-2*REGSZ
 
-#define FPREG64_S(FPR, OFF, BASE)       \
-        swc1    FPR, OFF(BASE)  ;       \
-        mfhc1   t0, FPR         ;       \
-        sw      t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE)       \
-        lw      t0, OFF+4(BASE) ;       \
-        lw      t1, OFF(BASE)   ;       \
-        mtc1    t1, FPR         ;       \
-        mthc1   t0, FPR         ;       \
-
 LEAF(_setjmp, FRAMESZ)
 	PTR_SUBU sp, FRAMESZ
 	SETUP_GP64(GPOFF, _setjmp)
@@ -85,32 +74,19 @@
 	li	v0, 1				# be nice if we could tell
 	REG_S	v0, SC_FPUSED(a0)		# sc_fpused = 1
 	cfc1	v0, $31
+	s.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	s.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	s.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	s.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	s.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	s.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        swc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        swc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        swc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        swc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        swc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        swc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        swc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        swc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        swc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        swc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        swc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        swc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	s.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	s.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	s.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	s.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	s.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	s.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 	REG_S	v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
 #endif /* !SOFTFLOAT */
@@ -142,32 +118,19 @@
 	REG_L	sp, SC_REGS+SP*REGSZ(a0)
 #if !defined(SOFTFLOAT)
 	ctc1	v0, $31
+	l.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	l.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	l.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	l.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	l.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	l.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        lwc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        lwc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        lwc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        lwc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        lwc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        lwc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        lwc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        lwc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        lwc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        lwc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        lwc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        lwc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	l.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	l.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	l.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	l.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	l.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	l.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 #endif /* !SOFTFLOAT */
 	bne	a1, zero, 1f
diff --git a/libc/arch-mips64/bionic/setjmp.S b/libc/arch-mips64/bionic/setjmp.S
index 2af1fbd..31786be 100644
--- a/libc/arch-mips64/bionic/setjmp.S
+++ b/libc/arch-mips64/bionic/setjmp.S
@@ -45,17 +45,6 @@
 GPOFF= FRAMESZ-2*REGSZ
 RAOFF= FRAMESZ-1*REGSZ
 
-#define FPREG64_S(FPR, OFF, BASE)       \
-        swc1    FPR, OFF(BASE)  ;       \
-        mfhc1   t0, FPR         ;       \
-        sw      t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE)       \
-        lw      t0, OFF+4(BASE) ;       \
-        lw      t1, OFF(BASE)   ;       \
-        mtc1    t1, FPR         ;       \
-        mthc1   t0, FPR         ;       \
-
 NON_LEAF(setjmp, FRAMESZ, ra)
 	.mask	0x80000000, RAOFF
 	PTR_SUBU sp, FRAMESZ			# allocate stack frame
@@ -98,32 +87,19 @@
 	li	v0, 1				# be nice if we could tell
 	REG_S	v0, SC_FPUSED(a0)		# sc_fpused = 1
 	cfc1	v0, $31
+	s.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	s.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	s.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	s.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	s.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	s.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        swc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        swc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        swc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        swc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        swc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        swc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        swc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        swc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        swc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        swc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        swc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        swc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	s.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	s.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	s.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	s.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	s.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	s.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 	REG_S	v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
 #endif /* !SOFTFLOAT */
@@ -173,32 +149,19 @@
 #if !defined(SOFTFLOAT)
 	REG_L	v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
 	ctc1	v0, $31
+	l.d	$f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+	l.d	$f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+	l.d	$f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+	l.d	$f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+	l.d	$f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+	l.d	$f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
 #if _MIPS_FPSET == 32
-        FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
-        FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
-        FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
-        FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
-        FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
-        FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
-        FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
-        FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
-        FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
-        FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
-        FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
-        FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
-        lwc1    $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
-        lwc1    $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
-        lwc1    $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
-        lwc1    $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
-        lwc1    $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
-        lwc1    $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
-        lwc1    $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
-        lwc1    $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
-        lwc1    $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
-        lwc1    $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
-        lwc1    $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
-        lwc1    $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+	l.d	$f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+	l.d	$f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+	l.d	$f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+	l.d	$f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+	l.d	$f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+	l.d	$f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
 #endif
 #endif /* !SOFTFLOAT */
 	bne	a1, zero, 1f
diff --git a/libc/arch-x86/generic/string/swab.S b/libc/arch-x86/generic/string/swab.S
deleted file mode 100644
index b44d134..0000000
--- a/libc/arch-x86/generic/string/swab.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/*	$OpenBSD: swab.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-/*
- * On the i486, this code is negligibly faster than the code generated
- * by gcc at about half the size.  If my i386 databook is correct, it
- * should be considerably faster than the gcc code on a i386.
- */
-
-ENTRY(swab)
-	pushl	%esi
-	pushl	%edi
-	movl	12(%esp),%esi
-	movl	16(%esp),%edi
-	movl	20(%esp),%ecx
-
-	cld				# set direction forward
-
-	shrl	$1,%ecx
-	testl	$7,%ecx			# copy first group of 1 to 7 words
-	jz	L2			# while swaping alternate bytes.
-	.align	2,0x90
-L1:	lodsw
-	rorw	$8,%ax
-	stosw
-	decl	%ecx
-	testl	$7,%ecx
-	jnz	L1
-
-L2:	shrl	$3,%ecx			# copy remainder 8 words at a time
-	jz	L4			# while swapping alternate bytes.
-	.align	2,0x90
-L3:	lodsw
-	rorw	$8,%ax
-	stosw
-	lodsw
-	rorw	$8,%ax
-	stosw
-	lodsw
-	rorw	$8,%ax
-	stosw
-	lodsw
-	rorw	$8,%ax
-	stosw
-	lodsw
-	rorw	$8,%ax
-	stosw
-	lodsw
-	rorw	$8,%ax
-	stosw
-	lodsw
-	rorw	$8,%ax
-	stosw
-	lodsw
-	rorw	$8,%ax
-	stosw
-	decl	%ecx
-	jnz	L3
-
-L4:	popl	%edi
-	popl	%esi
-	ret
-END(swab)
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
new file mode 100644
index 0000000..b8e892e
--- /dev/null
+++ b/libc/bionic/bionic_systrace.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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 <cutils/trace.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "private/bionic_systrace.h"
+#include "private/libc_logging.h"
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#define WRITE_OFFSET   32
+
+static const prop_info* g_pinfo = NULL;
+static uint32_t g_serial = -1;
+static uint64_t g_tags = 0;
+static int g_trace_marker_fd = -1;
+
+static bool should_trace() {
+  // If g_pinfo is null, this means that systrace hasn't been run and it's safe to
+  // assume that no trace writing will need to take place.  However, to avoid running
+  // this costly find check each time, we set it to a non-tracing value so that next
+  // time, it will just check the serial to see if the value has been changed.
+  // this function also deals with the bootup case, during which the call to property
+  // set will fail if the property server hasn't yet started.
+  if (g_pinfo == NULL) {
+    g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
+    if (g_pinfo == NULL) {
+      __system_property_set("debug.atrace.tags.enableflags", "0");
+      g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
+      if (g_pinfo == NULL) {
+        return false;
+      }
+    }
+  }
+
+  // Find out which tags have been enabled on the command line and set
+  // the value of tags accordingly.  If the value of the property changes,
+  // the serial will also change, so the costly system_property_read function
+  // can be avoided by calling the much cheaper system_property_serial
+  // first.  The values within pinfo may change, but its location is guaranteed
+  // not to move.
+  const uint32_t cur_serial = __system_property_serial(g_pinfo);
+  if (cur_serial != g_serial) {
+    g_serial = cur_serial;
+    char value[PROP_VALUE_MAX];
+    __system_property_read(g_pinfo, 0, value);
+    g_tags = strtoull(value, NULL, 0);
+  }
+
+  // Finally, verify that this tag value enables bionic tracing.
+  return ((g_tags & ATRACE_TAG_BIONIC) != 0);
+}
+
+ScopedTrace::ScopedTrace(const char* message) {
+  if (!should_trace()) {
+    return;
+  }
+
+  if (g_trace_marker_fd == -1) {
+    g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY | O_CLOEXEC);
+    if (g_trace_marker_fd == -1) {
+      __libc_fatal("Could not open kernel trace file: %s\n", strerror(errno));
+    }
+  }
+
+  // If bionic tracing has been enabled, then write the message to the
+  // kernel trace_marker.
+  int length = strlen(message);
+  char buf[length + WRITE_OFFSET];
+  size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
+  ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, buf, len));
+
+  // Error while writing
+  if (static_cast<size_t>(wbytes) != len) {
+    __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
+  }
+}
+
+ScopedTrace::~ScopedTrace() {
+  if (!should_trace()) {
+    return;
+  }
+
+  ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, "E", 1));
+
+  // Error while writing
+  if (static_cast<size_t>(wbytes) != 1) {
+    __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
+  }
+}
diff --git a/libc/bionic/debug_mapinfo.cpp b/libc/bionic/debug_mapinfo.cpp
index 17276ce..d83799a 100644
--- a/libc/bionic/debug_mapinfo.cpp
+++ b/libc/bionic/debug_mapinfo.cpp
@@ -26,39 +26,48 @@
  * SUCH DAMAGE.
  */
 
+#include <ctype.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <sys/mman.h>
 
 #include "debug_mapinfo.h"
+#include "malloc_debug_disable.h"
 
-// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so
-// 012345678901234567890123456789012345678901234567890123456789
-// 0         1         2         3         4         5
-
+// Format of /proc/<PID>/maps:
+//   6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so
 static mapinfo_t* parse_maps_line(char* line) {
-  int len = strlen(line);
+  uintptr_t start;
+  uintptr_t end;
+  int name_pos;
+  if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
+             &end, &name_pos) < 2) {
+    return NULL;
+  }
 
-  if (len < 1) return 0;
-  line[--len] = 0;
+  while (isspace(line[name_pos])) {
+    name_pos += 1;
+  }
+  const char* name = line + name_pos;
+  size_t name_len = strlen(name);
+  if (name_len && name[name_len - 1] == '\n') {
+    name_len -= 1;
+  }
 
-  if (len < 50) return 0;
-  if (line[20] != 'x') return 0;
-
-  mapinfo_t* mi = static_cast<mapinfo_t*>(
-      mmap(NULL, sizeof(mapinfo_t) + (len - 47), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0));
-  if (mi == MAP_FAILED) return 0;
-
-  mi->start = strtoul(line, 0, 16);
-  mi->end = strtoul(line + 9, 0, 16);
-  mi->next = 0;
-  strcpy(mi->name, line + 49);
-
+  mapinfo_t* mi = reinterpret_cast<mapinfo_t*>(calloc(1, sizeof(mapinfo_t) + name_len + 1));
+  if (mi) {
+    mi->start = start;
+    mi->end = end;
+    memcpy(mi->name, name, name_len);
+    mi->name[name_len] = '\0';
+  }
   return mi;
 }
 
 __LIBC_HIDDEN__ mapinfo_t* mapinfo_create(pid_t pid) {
+  ScopedDisableDebugCalls disable;
+
   struct mapinfo_t* milist = NULL;
   char data[1024]; // Used to read lines as well as to construct the filename.
   snprintf(data, sizeof(data), "/proc/%d/maps", pid);
@@ -77,10 +86,12 @@
 }
 
 __LIBC_HIDDEN__ void mapinfo_destroy(mapinfo_t* mi) {
+  ScopedDisableDebugCalls disable;
+
   while (mi != NULL) {
     mapinfo_t* del = mi;
     mi = mi->next;
-    munmap(del, sizeof(mapinfo_t) + strlen(del->name) + 2);
+    free(del);
   }
 }
 
diff --git a/libc/bionic/debug_mapinfo.h b/libc/bionic/debug_mapinfo.h
index cccd2e3..926b377 100644
--- a/libc/bionic/debug_mapinfo.h
+++ b/libc/bionic/debug_mapinfo.h
@@ -33,8 +33,8 @@
 
 struct mapinfo_t {
   struct mapinfo_t* next;
-  unsigned start;
-  unsigned end;
+  uintptr_t start;
+  uintptr_t end;
   char name[];
 };
 
diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp
index 713e761..b86e2af 100644
--- a/libc/bionic/debug_stacktrace.cpp
+++ b/libc/bionic/debug_stacktrace.cpp
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 
 #include "debug_mapinfo.h"
+#include "malloc_debug_disable.h"
 #include "private/libc_logging.h"
 
 #if defined(__LP64__)
@@ -56,6 +57,8 @@
 static DemanglerFn g_demangler_fn = NULL;
 
 __LIBC_HIDDEN__ void backtrace_startup() {
+  ScopedDisableDebugCalls disable;
+
   g_map_info = mapinfo_create(getpid());
   g_demangler = dlopen("libgccdemangle.so", RTLD_NOW);
   if (g_demangler != NULL) {
@@ -65,6 +68,8 @@
 }
 
 __LIBC_HIDDEN__ void backtrace_shutdown() {
+  ScopedDisableDebugCalls disable;
+
   mapinfo_destroy(g_map_info);
   dlclose(g_demangler);
 }
@@ -98,7 +103,7 @@
     return _URC_NO_REASON;
   }
 
-#ifdef __arm__
+#if defined(__arm__)
   /*
    * The instruction pointer is pointing at the instruction after the bl(x), and
    * the _Unwind_Backtrace routine already masks the Thumb mode indicator (LSB
@@ -121,12 +126,16 @@
 }
 
 __LIBC_HIDDEN__ int get_backtrace(uintptr_t* frames, size_t max_depth) {
+  ScopedDisableDebugCalls disable;
+
   stack_crawl_state_t state(frames, max_depth);
   _Unwind_Backtrace(trace_function, &state);
   return state.frame_count;
 }
 
 __LIBC_HIDDEN__ void log_backtrace(uintptr_t* frames, size_t frame_count) {
+  ScopedDisableDebugCalls disable;
+
   uintptr_t self_bt[16];
   if (frames == NULL) {
     frame_count = get_backtrace(self_bt, 16);
@@ -146,7 +155,7 @@
       symbol = info.dli_sname;
     }
 
-    uintptr_t rel_pc;
+    uintptr_t rel_pc = offset;
     const mapinfo_t* mi = (g_map_info != NULL) ? mapinfo_find(g_map_info, frames[i], &rel_pc) : NULL;
     const char* soname = (mi != NULL) ? mi->name : info.dli_fname;
     if (soname == NULL) {
diff --git a/libc/bionic/getpt.c b/libc/bionic/getpt.c
deleted file mode 100644
index 8bb5c11..0000000
--- a/libc/bionic/getpt.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <unistd.h>
-#include <fcntl.h>
-
-int getpt(void)
-{
-  return open("/dev/ptmx", O_RDWR|O_NOCTTY);
-}
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index d6fa1db..d0172ed 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -378,9 +378,6 @@
         } else if (c == '%') {
             buffer[0] = '%';
             buffer[1] = '\0';
-        } else if (c == 'm') {
-            // syslog-like %m for strerror(errno).
-            str = strerror(errno);
         } else {
             __assert(__FILE__, __LINE__, "conversion specifier unsupported");
         }
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 5a1da43..363140e 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -79,7 +79,9 @@
 
 static bool __is_supported_locale(const char* locale) {
   return (strcmp(locale, "") == 0 ||
-          strcmp(locale, "C") == 0 || strcmp(locale, "C.UTF-8") == 0 ||
+          strcmp(locale, "C") == 0 ||
+          strcmp(locale, "C.UTF-8") == 0 ||
+          strcmp(locale, "en_US.UTF-8") == 0 ||
           strcmp(locale, "POSIX") == 0);
 }
 
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index 1c63d4d..94ba6f5 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -49,6 +49,7 @@
 #include "debug_mapinfo.h"
 #include "debug_stacktrace.h"
 #include "malloc_debug_common.h"
+#include "malloc_debug_disable.h"
 #include "private/bionic_macros.h"
 #include "private/libc_logging.h"
 #include "private/ScopedPthreadMutexLocker.h"
@@ -331,6 +332,9 @@
 
 extern "C" void* chk_malloc(size_t bytes) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->malloc(bytes);
+    }
 
     size_t size = sizeof(hdr_t) + bytes + sizeof(ftr_t);
     if (size < bytes) { // Overflow
@@ -348,6 +352,10 @@
 }
 
 extern "C" void* chk_memalign(size_t alignment, size_t bytes) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->memalign(alignment, bytes);
+    }
+
     if (alignment <= MALLOC_ALIGNMENT) {
         return chk_malloc(bytes);
     }
@@ -386,6 +394,9 @@
 
 extern "C" void chk_free(void* ptr) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->free(ptr);
+    }
 
     if (!ptr) /* ignore free(NULL) */
         return;
@@ -421,6 +432,9 @@
 
 extern "C" void* chk_realloc(void* ptr, size_t bytes) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->realloc(ptr, bytes);
+    }
 
     if (!ptr) {
         return chk_malloc(bytes);
@@ -496,6 +510,10 @@
 
 extern "C" void* chk_calloc(size_t nmemb, size_t bytes) {
 //  log_message("%s: %s\n", __FILE__, __FUNCTION__);
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->calloc(nmemb, bytes);
+    }
+
     size_t total_bytes = nmemb * bytes;
     size_t size = sizeof(hdr_t) + total_bytes + sizeof(ftr_t);
     if (size < total_bytes || (nmemb && SIZE_MAX / nmemb < bytes)) { // Overflow
@@ -513,6 +531,10 @@
 }
 
 extern "C" size_t chk_malloc_usable_size(const void* ptr) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->malloc_usable_size(ptr);
+    }
+
     // malloc_usable_size returns 0 for NULL and unknown blocks.
     if (ptr == NULL)
         return 0;
@@ -529,6 +551,10 @@
 }
 
 extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->posix_memalign(memptr, alignment, size);
+  }
+
   if (!powerof2(alignment)) {
     return EINVAL;
   }
@@ -538,7 +564,12 @@
   return (*memptr != NULL) ? 0 : ENOMEM;
 }
 
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
 extern "C" void* chk_pvalloc(size_t bytes) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->pvalloc(bytes);
+  }
+
   size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
@@ -548,10 +579,16 @@
 }
 
 extern "C" void* chk_valloc(size_t size) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->valloc(size);
+  }
   return chk_memalign(getpagesize(), size);
 }
+#endif
 
 static void ReportMemoryLeaks() {
+  ScopedDisableDebugCalls disable;
+
   // Use /proc/self/exe link to obtain the program name for logging
   // purposes. If it's not available, we set it to "<unknown>".
   char exe[PATH_MAX];
@@ -585,10 +622,14 @@
   }
 }
 
+pthread_key_t g_debug_calls_disabled;
+
 extern "C" bool malloc_debug_initialize(HashTable* hash_table, const MallocDebug* malloc_dispatch) {
   g_hash_table = hash_table;
   g_malloc_dispatch = malloc_dispatch;
 
+  pthread_key_create(&g_debug_calls_disabled, NULL);
+
   char debug_backlog[PROP_VALUE_MAX];
   if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
     g_malloc_debug_backlog = atoi(debug_backlog);
@@ -605,4 +646,6 @@
     ReportMemoryLeaks();
   }
   backtrace_shutdown();
+
+  pthread_setspecific(g_debug_calls_disabled, NULL);
 }
diff --git a/libc/bionic/malloc_debug_disable.h b/libc/bionic/malloc_debug_disable.h
new file mode 100644
index 0000000..9503128
--- /dev/null
+++ b/libc/bionic/malloc_debug_disable.h
@@ -0,0 +1,64 @@
+/*
+ * 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 MALLOC_DEBUG_DISABLE_H
+#define MALLOC_DEBUG_DISABLE_H
+
+#include <pthread.h>
+
+#include "private/bionic_macros.h"
+
+// =============================================================================
+// Used to disable the debug allocation calls.
+// =============================================================================
+extern pthread_key_t g_debug_calls_disabled;
+
+static inline bool DebugCallsDisabled() {
+  return pthread_getspecific(g_debug_calls_disabled) != NULL;
+}
+
+class ScopedDisableDebugCalls {
+ public:
+  ScopedDisableDebugCalls() : disabled_(DebugCallsDisabled()) {
+    if (!disabled_) {
+      pthread_setspecific(g_debug_calls_disabled, reinterpret_cast<const void*>(1));
+    }
+  }
+  ~ScopedDisableDebugCalls() {
+    if (!disabled_) {
+      pthread_setspecific(g_debug_calls_disabled, NULL);
+    }
+  }
+
+ private:
+  bool disabled_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedDisableDebugCalls);
+};
+
+#endif  // MALLOC_DEBUG_DISABLE_H
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index d9824f0..7926a1f 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -48,6 +48,7 @@
 
 #include "debug_stacktrace.h"
 #include "malloc_debug_common.h"
+#include "malloc_debug_disable.h"
 
 #include "private/bionic_macros.h"
 #include "private/libc_logging.h"
@@ -267,6 +268,7 @@
   return (*memptr != NULL) ? 0 : ENOMEM;
 }
 
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
 extern "C" void* fill_pvalloc(size_t bytes) {
   size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
@@ -279,6 +281,7 @@
 extern "C" void* fill_valloc(size_t size) {
   return fill_memalign(getpagesize(), size);
 }
+#endif
 
 // =============================================================================
 // malloc leak functions
@@ -287,6 +290,10 @@
 static uint32_t MEMALIGN_GUARD      = 0xA1A41520;
 
 extern "C" void* leak_malloc(size_t bytes) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->malloc(bytes);
+    }
+
     // allocate enough space infront of the allocation to store the pointer for
     // the alloc structure. This will making free'ing the structer really fast!
 
@@ -319,6 +326,10 @@
 }
 
 extern "C" void leak_free(void* mem) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->free(mem);
+  }
+
   if (mem == NULL) {
     return;
   }
@@ -355,6 +366,10 @@
 }
 
 extern "C" void* leak_calloc(size_t n_elements, size_t elem_size) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->calloc(n_elements, elem_size);
+    }
+
     // Fail on overflow - just to be safe even though this code runs only
     // within the debugging C library, not the production one.
     if (n_elements && SIZE_MAX / n_elements < elem_size) {
@@ -370,6 +385,10 @@
 }
 
 extern "C" void* leak_realloc(void* oldMem, size_t bytes) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->realloc(oldMem, bytes);
+    }
+
     if (oldMem == NULL) {
         return leak_malloc(bytes);
     }
@@ -398,6 +417,10 @@
 }
 
 extern "C" void* leak_memalign(size_t alignment, size_t bytes) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->memalign(alignment, bytes);
+    }
+
     // we can just use malloc
     if (alignment <= MALLOC_ALIGNMENT) {
         return leak_malloc(bytes);
@@ -439,6 +462,10 @@
 }
 
 extern "C" size_t leak_malloc_usable_size(const void* mem) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->malloc_usable_size(mem);
+    }
+
     if (mem != NULL) {
         // Check the guard to make sure it is valid.
         const AllocationEntry* header = const_to_header((void*)mem);
@@ -467,6 +494,10 @@
 }
 
 extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->posix_memalign(memptr, alignment, size);
+  }
+
   if (!powerof2(alignment)) {
     return EINVAL;
   }
@@ -476,7 +507,12 @@
   return (*memptr != NULL) ? 0 : ENOMEM;
 }
 
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
 extern "C" void* leak_pvalloc(size_t bytes) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->pvalloc(bytes);
+  }
+
   size_t pagesize = getpagesize();
   size_t size = BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) { // Overflow
@@ -486,5 +522,10 @@
 }
 
 extern "C" void* leak_valloc(size_t size) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->valloc(size);
+  }
+
   return leak_memalign(getpagesize(), size);
 }
+#endif
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 174e308..fc8afa2 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -51,9 +51,9 @@
 
 // This code is used both by each new pthread and the code that initializes the main thread.
 void __init_tls(pthread_internal_t* thread) {
-  // Zero-initialize all the slots after TLS_SLOT_SELF and TLS_SLOT_THREAD_ID.
-  for (size_t i = TLS_SLOT_ERRNO; i < BIONIC_TLS_SLOTS; ++i) {
-    thread->tls[i] = NULL;
+  if (thread->user_allocated_stack()) {
+    // We don't know where the user got their stack, so assume the worst and zero the TLS area.
+    memset(&thread->tls[0], 0, BIONIC_TLS_SLOTS * sizeof(void*));
   }
 
   // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
@@ -66,7 +66,7 @@
 void __init_alternate_signal_stack(pthread_internal_t* thread) {
   // Create and set an alternate signal stack.
   stack_t ss;
-  ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+  ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
   if (ss.ss_sp != MAP_FAILED) {
     ss.ss_size = SIGSTKSZ;
     ss.ss_flags = 0;
@@ -227,7 +227,7 @@
     // be unblocked, but we're about to unmap the memory the mutex is stored in, so this serves as a
     // reminder that you can't rewrite this function to use a ScopedPthreadMutexLocker.
     pthread_mutex_unlock(&thread->startup_handshake_mutex);
-    if ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK) == 0) {
+    if (!thread->user_allocated_stack()) {
       munmap(thread->attr.stack_base, thread->attr.stack_size);
     }
     free(thread);
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 2470c9c..a6bb363 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -90,7 +90,7 @@
   // Keep track of what we need to know about the stack before we lose the pthread_internal_t.
   void* stack_base = thread->attr.stack_base;
   size_t stack_size = thread->attr.stack_size;
-  bool user_allocated_stack = ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK) != 0);
+  bool user_allocated_stack = thread->user_allocated_stack();
 
   pthread_mutex_lock(&g_thread_list_lock);
   if ((thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) != 0) {
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index e05d15c..7bcd758 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -30,6 +30,18 @@
 
 #include <pthread.h>
 
+/* Has the thread been detached by a pthread_join or pthread_detach call? */
+#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
+
+/* Was the thread's stack allocated by the user rather than by us? */
+#define PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK 0x00000002
+
+/* Has the thread been joined by another thread? */
+#define PTHREAD_ATTR_FLAG_JOINED 0x00000004
+
+/* Is this the main thread? */
+#define PTHREAD_ATTR_FLAG_MAIN_THREAD 0x80000000
+
 struct pthread_internal_t {
   struct pthread_internal_t* next;
   struct pthread_internal_t* prev;
@@ -56,6 +68,10 @@
     return (*cached_pid != 0);
   }
 
+  bool user_allocated_stack() {
+    return (attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK) != 0;
+  }
+
   void** tls;
 
   pthread_attr_t attr;
@@ -87,20 +103,8 @@
 __LIBC_HIDDEN__ void pthread_key_clean_all(void);
 __LIBC_HIDDEN__ void _pthread_internal_remove_locked(pthread_internal_t* thread);
 
-/* Has the thread been detached by a pthread_join or pthread_detach call? */
-#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
-
-/* Was the thread's stack allocated by the user rather than by us? */
-#define PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK 0x00000002
-
-/* Has the thread been joined by another thread? */
-#define PTHREAD_ATTR_FLAG_JOINED 0x00000004
-
-/* Is this the main thread? */
-#define PTHREAD_ATTR_FLAG_MAIN_THREAD 0x80000000
-
 /*
- * Traditionally we give threads a 1MiB stack. When we started
+ * Traditionally we gave threads a 1MiB stack. When we started
  * allocating per-thread alternate signal stacks to ease debugging of
  * stack overflows, we subtracted the same amount we were using there
  * from the default thread stack size. This should keep memory usage
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 5461661..e00ffb4 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -39,6 +39,8 @@
 #include "private/bionic_futex.h"
 #include "private/bionic_tls.h"
 
+#include "private/bionic_systrace.h"
+
 extern void pthread_debug_mutex_lock_check(pthread_mutex_t *mutex);
 extern void pthread_debug_mutex_unlock_check(pthread_mutex_t *mutex);
 
@@ -333,6 +335,10 @@
          * that the mutex is in state 2 when we go to sleep on it, which
          * guarantees a wake-up call.
          */
+
+         ScopedTrace trace("Contending for pthread mutex");
+
+
         while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
             __futex_wait_ex(&mutex->value, shared, locked_contended, NULL);
         }
@@ -473,6 +479,8 @@
         mvalue = mutex->value;
     }
 
+    ScopedTrace trace("Contending for pthread mutex");
+
     for (;;) {
         int newval;
 
@@ -626,6 +634,8 @@
       return 0;
     }
 
+    ScopedTrace trace("Contending for timed pthread mutex");
+
     // Loop while needed.
     while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
       if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
@@ -658,6 +668,8 @@
     mvalue = mutex->value;
   }
 
+  ScopedTrace trace("Contending for timed pthread mutex");
+
   while (true) {
     // If the value is 'unlocked', try to acquire it directly.
     // NOTE: put state to 2 since we know there is contention.
diff --git a/libc/bionic/ptsname.c b/libc/bionic/ptsname.c
deleted file mode 100644
index 24d5d30..0000000
--- a/libc/bionic/ptsname.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-
-/* not thread-safe */
-char*  ptsname( int fd )
-{
-    unsigned int  pty_num;
-    static char   buff[64];
-
-    if ( ioctl( fd, TIOCGPTN, &pty_num ) != 0 )
-        return NULL;
-
-    snprintf( buff, sizeof(buff), "/dev/pts/%u", pty_num );
-    return buff;
-}
diff --git a/libc/bionic/ptsname_r.c b/libc/bionic/ptsname_r.c
deleted file mode 100644
index 2fa4c3d..0000000
--- a/libc/bionic/ptsname_r.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <string.h>
-
-int    ptsname_r( int  fd, char*  buf, size_t  buflen)
-{
-    unsigned int  pty_num;
-    char          buff[64];
-    int           len;
-
-    if (buf == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    if ( ioctl( fd, TIOCGPTN, &pty_num ) != 0 ) {
-        errno = ENOTTY;
-        return -1;
-    }
-
-    len = snprintf( buff, sizeof(buff), "/dev/pts/%u", pty_num );
-    if (len+1 > (int)buflen) {
-        errno = ERANGE;
-        return -1;
-    }
-    memcpy( buf, buff, len+1 );
-    return 0;
-}
diff --git a/libc/bionic/pty.cpp b/libc/bionic/pty.cpp
new file mode 100644
index 0000000..995e006
--- /dev/null
+++ b/libc/bionic/pty.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+
+int getpt(void) {
+  return posix_openpt(O_RDWR|O_NOCTTY);
+}
+
+int grantpt(int) {
+  return 0;
+}
+
+int posix_openpt(int flags) {
+  return open("/dev/ptmx", flags);
+}
+
+char* ptsname(int fd) {
+  static char buf[64];
+  return ptsname_r(fd, buf, sizeof(buf)) == 0 ? buf : NULL;
+}
+
+int ptsname_r(int fd, char* buf, size_t len) {
+  if (buf == NULL) {
+    errno = EINVAL;
+    return errno;
+  }
+
+  unsigned int pty_num;
+  if (ioctl(fd, TIOCGPTN, &pty_num) != 0) {
+    errno = ENOTTY;
+    return errno;
+  }
+
+  if (snprintf(buf, len, "/dev/pts/%u", pty_num) >= static_cast<int>(len)) {
+    errno = ERANGE;
+    return errno;
+  }
+
+  return 0;
+}
+
+char* ttyname(int fd) {
+  static char buf[64];
+  return ttyname_r(fd, buf, sizeof(buf)) == 0 ? buf : NULL;
+}
+
+int ttyname_r(int fd, char* buf, size_t len) {
+  if (buf == NULL) {
+    errno = EINVAL;
+    return errno;
+  }
+
+  if (!isatty(fd)) {
+    return errno;
+  }
+
+  char path[64];
+  snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+
+  ssize_t count = readlink(path, buf, len);
+  if (count == -1) {
+    return errno;
+  }
+  if (static_cast<size_t>(count) == len) {
+    errno = ERANGE;
+    return errno;
+  }
+  buf[count] = '\0';
+  return 0;
+}
+
+int unlockpt(int fd) {
+  int unlock = 0;
+  return ioctl(fd, TIOCSPTLCK, &unlock);
+}
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 0937e9c..b1e38be 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -444,16 +444,6 @@
   UNIMPLEMENTED;
 }
 
-char* ttyname(int /*fd*/) { // NOLINT: implementing bad function.
-  UNIMPLEMENTED;
-  return NULL;
-}
-
-int ttyname_r(int /*fd*/, char* /*buf*/, size_t /*buflen*/) {
-  UNIMPLEMENTED;
-  return -ERANGE;
-}
-
 char* getusershell() {
   UNIMPLEMENTED;
   return NULL;
diff --git a/libc/bionic/syslog.cpp b/libc/bionic/syslog.cpp
index 7e153eb..d8b8b19 100644
--- a/libc/bionic/syslog.cpp
+++ b/libc/bionic/syslog.cpp
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#include <syslog.h>
-
+#include <errno.h>
 #include <stdlib.h>
+#include <syslog.h>
 
 #include "private/libc_logging.h"
 
@@ -24,6 +24,7 @@
 static int syslog_priority_mask = 0xff;
 
 void closelog() {
+  syslog_log_tag = NULL;
 }
 
 void openlog(const char* log_tag, int /*options*/, int /*facility*/) {
@@ -47,6 +48,8 @@
 }
 
 void vsyslog(int priority, const char* fmt, va_list args) {
+  int caller_errno = errno;
+
   // Check whether we're supposed to be logging messages of this priority.
   if ((syslog_priority_mask & LOG_MASK(LOG_PRI(priority))) == 0) {
     return;
@@ -61,7 +64,7 @@
   // What's our Android log priority?
   priority &= LOG_PRIMASK;
   int android_log_priority;
-  if (priority < LOG_ERR) {
+  if (priority <= LOG_ERR) {
     android_log_priority = ANDROID_LOG_ERROR;
   } else if (priority == LOG_WARNING) {
     android_log_priority = ANDROID_LOG_WARN;
@@ -71,5 +74,48 @@
     android_log_priority = ANDROID_LOG_DEBUG;
   }
 
-  __libc_format_log_va_list(android_log_priority, log_tag, fmt, args);
+  // glibc's printf family support %m directly, but our BSD-based one doesn't.
+  // If the format string seems to contain "%m", rewrite it.
+  const char* log_fmt = fmt;
+  if (strstr(fmt, "%m") != NULL) {
+    size_t dst_len = 1024;
+    char* dst = reinterpret_cast<char*>(malloc(dst_len));
+    log_fmt = dst;
+
+    const char* src = fmt;
+    for (; dst_len > 0 && *src != '\0'; ++src) {
+      if (*src == '%' && *(src + 1) == 'm') {
+        // Expand %m.
+        size_t n = strlcpy(dst, strerror(caller_errno), dst_len);
+        if (n >= dst_len) {
+          n = dst_len;
+        }
+        dst += n;
+        dst_len -= n;
+        ++src;
+      } else if (*src == '%' && *(src + 1) == '%') {
+        // We need to copy pairs of '%'s so the %m test works.
+        if (dst_len <= 2) {
+          break;
+        }
+        *dst++ = '%'; --dst_len;
+        *dst++ = '%'; --dst_len;
+        ++src;
+      } else {
+        *dst++ = *src; --dst_len;
+      }
+    }
+    *dst = '\0';
+  }
+
+  // We can't let __libc_format_log do the formatting because it doesn't support
+  // all the printf functionality.
+  char log_line[1024];
+  vsnprintf(log_line, sizeof(log_line), log_fmt, args);
+
+  if (log_fmt != fmt) {
+    free(const_cast<char*>(log_fmt));
+  }
+
+  __libc_format_log(android_log_priority, log_tag, "%s", log_line);
 }
diff --git a/libc/bionic/tdestroy.cpp b/libc/bionic/tdestroy.cpp
index decde4d..49614b8 100644
--- a/libc/bionic/tdestroy.cpp
+++ b/libc/bionic/tdestroy.cpp
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 
 // Destroy a tree and free all allocated resources.
-// This is a GNU extension, not available from NetBSD.
+// This is a GNU extension, not available from BSD.
 void tdestroy(void* root, void (*destroy_func)(void*)) {
   node_t* root_node = (node_t*) root;
   if (root_node == NULL) {
diff --git a/libc/bionic/unlockpt.c b/libc/bionic/unlockpt.c
deleted file mode 100644
index 998b7a3..0000000
--- a/libc/bionic/unlockpt.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <unistd.h>
-#include <sys/ioctl.h>
-
-int  unlockpt( int  fd )
-{
-    int  unlock = 0;
-
-    return ioctl( fd, TIOCSPTLCK, &unlock );
-}
diff --git a/libc/include/grp.h b/libc/include/grp.h
index 86d99f3..fc4d520 100644
--- a/libc/include/grp.h
+++ b/libc/include/grp.h
@@ -43,10 +43,6 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
-#if __BSD_VISIBLE
-#define	_PATH_GROUP		"/etc/group"
-#endif
-
 struct group {
 	char	*gr_name;		/* group name */
 	char	*gr_passwd;		/* group password */
@@ -57,7 +53,7 @@
 __BEGIN_DECLS
 struct group	*getgrgid(gid_t);
 struct group	*getgrnam(const char *);
-#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE
+#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE
 struct group	*getgrent(void);
 void		 setgrent(void);
 void		 endgrent(void);
@@ -66,11 +62,6 @@
 int		 getgrnam_r(const char *, struct group *, char *,
 		    size_t, struct group **);
 #endif
-#if __BSD_VISIBLE
-void		 setgrfile(const char *);
-int		 setgroupent(int);
-char		*group_from_gid(gid_t, int);
-#endif
 
 int   getgrouplist (const char *user, gid_t group,
                   gid_t *groups, int *ngroups);
diff --git a/libc/include/search.h b/libc/include/search.h
index b2c0e6b..9b01e12 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -29,6 +29,9 @@
 
 __BEGIN_DECLS
 
+void insque(void*, void*);
+void remque(void*);
+
 void* lfind(const void*, const void*, size_t*, size_t, int (*)(const void*, const void*));
 void* lsearch(const void*, void*, size_t*, size_t, int (*)(const void*, const void*));
 
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index e532de4..9c6bd3f 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -223,12 +223,6 @@
 	    FILE * __restrict);
 ssize_t	 getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
 
-#if __BSD_VISIBLE && !defined(__SYS_ERRLIST)
-#define __SYS_ERRLIST
-extern int sys_nerr;			/* perror(3) external variables */
-extern char *sys_errlist[];
-#endif
-
 void	 perror(const char *);
 int	 printf(const char * __restrict, ...)
 		__printflike(1, 2);
@@ -300,9 +294,6 @@
 #define	L_ctermid	1024	/* size for ctermid(); PATH_MAX */
 
 __BEGIN_DECLS
-#if 0 /* MISSING FROM BIONIC */
-char	*ctermid(char *);
-#endif /* MISSING */
 FILE	*fdopen(int, const char *);
 int	 fileno(FILE *);
 
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 0dac650..eb39fc9 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -126,18 +126,12 @@
 char* setstate(char*);
 void srandom(unsigned int);
 
-/* Basic PTY functions.  These only work if devpts is mounted! */
-
-extern int    unlockpt(int);
-extern char*  ptsname(int);
-extern int    ptsname_r(int, char*, size_t);
-extern int    getpt(void);
-
-static __inline__ int grantpt(int __fd __attribute((unused)))
-{
-  (void)__fd;
-  return 0;     /* devpts does this all for us! */
-}
+int getpt(void);
+int grantpt(int);
+int posix_openpt(int);
+char* ptsname(int) __warnattr("ptsname is not thread-safe; use ptsname_r instead");
+int ptsname_r(int, char*, size_t);
+int unlockpt(int);
 
 typedef struct {
     int  quot;
@@ -175,10 +169,6 @@
 
 #define MB_CUR_MAX 4U
 
-#if 0 /* MISSING FROM BIONIC */
-extern int on_exit(void (*)(int, void *), void *);
-#endif /* MISSING */
-
 __END_DECLS
 
 #endif /* _STDLIB_H_ */
diff --git a/libc/include/sys/cdefs_elf.h b/libc/include/sys/cdefs_elf.h
index b5db13e..4dd7dc3 100644
--- a/libc/include/sys/cdefs_elf.h
+++ b/libc/include/sys/cdefs_elf.h
@@ -68,7 +68,7 @@
 #ifdef __LP64__
 #define __LIBC64_HIDDEN__ __LIBC_HIDDEN__
 #else
-#define __LIBC64_HIDDEN__
+#define __LIBC64_HIDDEN__ __LIBC_ABI_PUBLIC__
 #endif
 
 /* Used to tag non-static symbols that are public and exposed by the shared library. */
diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h
index a44b2e5..34a29df 100644
--- a/libc/include/sys/syscall.h
+++ b/libc/include/sys/syscall.h
@@ -37,7 +37,7 @@
 
 __BEGIN_DECLS
 
-int syscall(int number, ...);
+long syscall(long number, ...);
 
 __END_DECLS
 
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index f396fec..cbceab2 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -35,45 +35,48 @@
 
 __BEGIN_DECLS
 
-#define LOG_EMERG	0
-#define LOG_ALERT	1
-#define LOG_CRIT	2
-#define LOG_ERR		3
-#define LOG_WARNING	4
-#define LOG_NOTICE	5
-#define LOG_INFO	6
-#define LOG_DEBUG	7
+/* Priorities are translated to Android log priorities as shown. */
+#define LOG_EMERG   0 /* ERROR */
+#define LOG_ALERT   1 /* ERROR */
+#define LOG_CRIT    2 /* ERROR */
+#define LOG_ERR     3 /* ERROR */
+#define LOG_WARNING 4 /* WARN */
+#define LOG_NOTICE  5 /* INFO */
+#define LOG_INFO    6 /* INFO */
+#define LOG_DEBUG   7 /* DEBUG */
 
-#define LOG_PRIMASK	7
-#define LOG_PRI(x)	((x) & LOG_PRIMASK)
+#define LOG_PRIMASK 7
+#define LOG_PRI(x) ((x) & LOG_PRIMASK)
 
-#define LOG_KERN	0000
-#define LOG_USER	0010
-#define LOG_MAIL	0020
-#define LOG_DAEMON	0030
-#define LOG_AUTH	0040
-#define LOG_SYSLOG	0050
-#define LOG_LPR		0060
-#define LOG_NEWS	0070
-#define LOG_UUCP	0100
-#define LOG_CRON	0110
-#define LOG_AUTHPRIV	0120
-#define LOG_FTP		0130
-#define LOG_LOCAL0	0200
-#define LOG_LOCAL1	0210
-#define LOG_LOCAL2	0220
-#define LOG_LOCAL3	0230
-#define LOG_LOCAL4	0240
-#define LOG_LOCAL5	0250
-#define LOG_LOCAL6	0260
-#define LOG_LOCAL7	0270
+/* Facilities are currently ignored on Android. */
+#define LOG_KERN     0000
+#define LOG_USER     0010
+#define LOG_MAIL     0020
+#define LOG_DAEMON   0030
+#define LOG_AUTH     0040
+#define LOG_SYSLOG   0050
+#define LOG_LPR      0060
+#define LOG_NEWS     0070
+#define LOG_UUCP     0100
+#define LOG_CRON     0110
+#define LOG_AUTHPRIV 0120
+#define LOG_FTP      0130
+#define LOG_LOCAL0   0200
+#define LOG_LOCAL1   0210
+#define LOG_LOCAL2   0220
+#define LOG_LOCAL3   0230
+#define LOG_LOCAL4   0240
+#define LOG_LOCAL5   0250
+#define LOG_LOCAL6   0260
+#define LOG_LOCAL7   0270
 
-#define LOG_FACMASK	01770
-#define LOG_FAC(x)	(((x) >> 3) & (LOG_FACMASK >> 3))
+#define LOG_FACMASK 01770
+#define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3))
 
 #define LOG_MASK(pri) (1 << (pri))
 #define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1)
 
+/* openlog(3) flags are currently ignored on Android. */
 #define LOG_PID    0x01
 #define LOG_CONS   0x02
 #define LOG_ODELAY 0x04
@@ -81,11 +84,11 @@
 #define LOG_NOWAIT 0x10
 #define LOG_PERROR 0x20
 
-extern void closelog(void);
-extern void openlog(const char*, int, int);
-extern int setlogmask(int);
-extern void syslog(int, const char*, ...) __printflike(2, 3);
-extern void vsyslog(int, const char*, va_list) __printflike(2, 0);
+void closelog(void);
+void openlog(const char*, int, int);
+int setlogmask(int);
+void syslog(int, const char*, ...) __printflike(2, 3);
+void vsyslog(int, const char*, va_list) __printflike(2, 0);
 
 __END_DECLS
 
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 12e6257..7fbafdf 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -170,7 +170,7 @@
 extern int optind, opterr, optopt;
 
 extern int isatty(int);
-extern char* ttyname(int);
+extern char* ttyname(int) __warnattr("ttyname is not thread-safe; use ttyname_r instead");
 extern int ttyname_r(int, char*, size_t);
 
 extern int  acct(const char*  filepath);
@@ -189,16 +189,6 @@
 extern pid_t tcgetpgrp(int fd);
 extern int   tcsetpgrp(int fd, pid_t _pid);
 
-#if 0 /* MISSING FROM BIONIC */
-extern int execlpe(const char *, const char *, ...);
-extern int getfsuid(uid_t);
-extern int setfsuid(uid_t);
-extern int getlogin_r(char* name, size_t namesize);
-extern int sethostname(const char *, size_t);
-extern int getdomainname(char *, size_t);
-extern int setdomainname(const char *, size_t);
-#endif /* MISSING */
-
 /* Used to retry syscalls that can return EINTR. */
 #define TEMP_FAILURE_RETRY(exp) ({         \
     __typeof__(exp) _rc;                   \
diff --git a/libc/private/bionic_systrace.h b/libc/private/bionic_systrace.h
new file mode 100644
index 0000000..ad9ff7f
--- /dev/null
+++ b/libc/private/bionic_systrace.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BIONIC_SYSTRACE_H
+#define BIONIC_SYSTRACE_H
+
+#include "bionic_macros.h"
+
+// Tracing class for bionic. To begin a trace at a specified point:
+//   ScopedTrace("Trace message");
+// The trace will end when the contructor goes out of scope.
+
+class ScopedTrace {
+ public:
+  explicit ScopedTrace(const char* message);
+  ~ScopedTrace();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedTrace);
+};
+
+#endif
diff --git a/libc/private/bionic_time.h b/libc/private/bionic_time.h
index ca5c146..030dcfd 100644
--- a/libc/private/bionic_time.h
+++ b/libc/private/bionic_time.h
@@ -33,32 +33,8 @@
 
 __BEGIN_DECLS
 
-#ifndef _BIONIC_STRFTIME_TZ_DECLARED
-#define _BIONIC_STRFTIME_TZ_DECLARED
-
-struct strftime_locale {
-    const char *  mon[12];
-    const char *  month[12];
-    const char *  standalone_month[12];
-    const char *  wday[7];
-    const char *  weekday[7];
-    const char *  X_fmt;
-    const char *  x_fmt;
-    const char *  c_fmt;
-    const char *  am;
-    const char *  pm;
-    const char *  date_fmt;
-};
-
-/*
- * Note: you should consider these extensions deprecated and use managed code or icu4c instead.
- * We'd like to hide them but they're currently still used in frameworks code.
- */
-extern size_t strftime_tz(char*, size_t, const char*, const struct tm*, const struct strftime_locale*);
-extern time_t mktime_tz(struct tm* const, char const*);
-extern void localtime_tz(const time_t* const, struct tm*, const char*);
-
-#endif /* _BIONIC_STRFTIME_TZ_DECLARED */
+// We can't remove this (and this file) until we fix MtpUtils.cpp.
+time_t mktime_tz(struct tm* const, char const*);
 
 __END_DECLS
 
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate-NOTICE.py
index 6d4c761..8cd75a3 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate-NOTICE.py
@@ -77,7 +77,7 @@
     for line in lines[start:end]:
         line = line.replace("\t", "    ")
         line = line.replace("/* ", "")
-        line = line.replace(" * ", "")
+        line = re.sub("^ \* ", "", line)
         line = line.replace("** ", "")
         line = line.replace("# ", "")
         if line.startswith("++Copyright++"):
@@ -144,7 +144,7 @@
 
             i = 0
             while i < len(lines):
-                if "Copyright" in lines[i]:
+                if "Copyright" in lines[i] and not "@(#) Copyright" in lines[i]:
                     i = ExtractCopyrightAt(lines, i)
                 i += 1
 
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 4dd7ab0..5e4e962 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2293,7 +2293,8 @@
 }
 
 // Non-standard API: mktime(3) but with an explicit timezone parameter.
-time_t __attribute__((visibility("default"))) mktime_tz(struct tm* const tmp, const char* tz) {
+// This can't actually be hidden/removed until we fix MtpUtils.cpp
+__attribute__((visibility("default"))) time_t mktime_tz(struct tm* const tmp, const char* tz) {
   struct state* st = malloc(sizeof(*st));
   time_t return_value;
 
@@ -2309,18 +2310,4 @@
   return return_value;
 }
 
-// Non-standard API: localtime(3) but with an explicit timezone parameter.
-void __attribute__((visibility("default"))) localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
-  struct state* st = malloc(sizeof(*st));
-
-  if (st == NULL)
-    return;
-  if (__bionic_tzload_cached(tz, st, TRUE) != 0) {
-    // TODO: not sure what's best here, but for now, we fall back to gmt.
-    gmtload(st);
-  }
-  localsub(timep, 0L, tmp, st);
-  free(st);
-}
-
 // END android-added
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index f996f48..4328b4c 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -29,17 +29,19 @@
 #include "locale.h"
 
 #if __ANDROID__
-/* Android: struct lc_time_T is defined as strftime_locale in "bionic_time.h" */
-#include "private/bionic_time.h"  /* for strftime_tz */
-#define  lc_time_T    strftime_locale
+
+/* LP32 had a 32-bit time_t, so we need to work around that here. */
 #if defined(__LP64__)
 #define time64_t time_t
 #define mktime64 mktime
 #else
 #include <time64.h>
 #endif
+
 #include <ctype.h>
-#else // not __ANDROID__
+
+#endif
+
 struct lc_time_T {
     const char *    mon[MONSPERYEAR];
     const char *    month[MONSPERYEAR];
@@ -52,9 +54,8 @@
     const char *    pm;
     const char *    date_fmt;
 };
-#endif
 
-#if LOCALE_HOME
+#ifdef LOCALE_HOME
 #include "sys/stat.h"
 static struct lc_time_T                localebuf;
 static struct lc_time_T *      _loc(void);
@@ -72,9 +73,6 @@
         "January", "February", "March", "April", "May", "June",
         "July", "August", "September", "October", "November", "December"
     }, {
-        "January", "February", "March", "April", "May", "June",
-        "July", "August", "September", "October", "November", "December"
-    }, {
         "Sun", "Mon", "Tue", "Wed",
         "Thu", "Fri", "Sat"
     }, {
@@ -116,7 +114,7 @@
 static char *   _add(const char *, char *, const char *, int);
 static char *   _conv(int, const char *, char *, const char *);
 static char *   _fmt(const char *, const struct tm *, char *, const char *,
-            int *, const struct strftime_locale*);
+            int *);
 static char *   _yconv(int, int, int, int, char *, const char *, int);
 static char *   getformat(int, char *, char *, char *, char *);
 
@@ -134,29 +132,18 @@
 #define FORCE_LOWER_CASE 0x100
 
 size_t
-strftime(s, maxsize, format, t)
-char * const        s;
-const size_t        maxsize;
-const char * const  format;
-const struct tm * const t;
-{
-    return strftime_tz(s, maxsize, format, t, Locale);
-}
-
-size_t
-__attribute__((visibility("default"))) strftime_tz(s, maxsize, format, t, locale)
-char * const        s;
-const size_t        maxsize;
-const char * const  format;
-const struct tm * const t;
-const struct strftime_locale *locale;
+strftime(char * const s, const size_t maxsize, const char *const format,
+        const struct tm *const t)
 {
     char *  p;
     int warn;
 
     tzset();
+#ifdef LOCALE_HOME
+    localebuf.mon[0] = 0;
+#endif /* defined LOCALE_HOME */
     warn = IN_NONE;
-    p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, locale);
+    p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
 #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
     if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
         (void) fprintf(stderr, "\n");
@@ -196,13 +183,8 @@
 }
 
 static char *
-_fmt(format, t, pt, ptlim, warnp, locale)
-const char *        format;
-const struct tm * const t;
-char *          pt;
-const char * const  ptlim;
-int *           warnp;
-const struct strftime_locale* locale;
+_fmt(const char *format, const struct tm *const t, char * pt,
+        const char *const ptlim, int *warnp)
 {
     for ( ; *format; ++format) {
         if (*format == '%') {
@@ -215,33 +197,26 @@
             case 'A':
                 pt = _add((t->tm_wday < 0 ||
                     t->tm_wday >= DAYSPERWEEK) ?
-                    "?" : locale->weekday[t->tm_wday],
+                    "?" : Locale->weekday[t->tm_wday],
                     pt, ptlim, modifier);
                 continue;
             case 'a':
                 pt = _add((t->tm_wday < 0 ||
                     t->tm_wday >= DAYSPERWEEK) ?
-                    "?" : locale->wday[t->tm_wday],
+                    "?" : Locale->wday[t->tm_wday],
                     pt, ptlim, modifier);
                 continue;
             case 'B':
-                if (modifier == '-') {
-                    pt = _add((t->tm_mon < 0 ||
+                pt = _add((t->tm_mon < 0 ||
                                 t->tm_mon >= MONSPERYEAR) ?
-                                "?" : locale->standalone_month[t->tm_mon],
+                                "?" : Locale->month[t->tm_mon],
                                 pt, ptlim, modifier);
-                } else {
-                    pt = _add((t->tm_mon < 0 ||
-                                t->tm_mon >= MONSPERYEAR) ?
-                                "?" : locale->month[t->tm_mon],
-                                pt, ptlim, modifier);
-                }
                 continue;
             case 'b':
             case 'h':
                 pt = _add((t->tm_mon < 0 ||
                     t->tm_mon >= MONSPERYEAR) ?
-                    "?" : locale->mon[t->tm_mon],
+                    "?" : Locale->mon[t->tm_mon],
                     pt, ptlim, modifier);
                 continue;
             case 'C':
@@ -259,7 +234,7 @@
                 {
                 int warn2 = IN_SOME;
 
-                pt = _fmt(locale->c_fmt, t, pt, ptlim, warnp, locale);
+                pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
                 if (warn2 == IN_ALL)
                     warn2 = IN_THIS;
                 if (warn2 > *warnp)
@@ -267,7 +242,7 @@
                 }
                 continue;
             case 'D':
-                                pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, locale);
+                                pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
                 continue;
             case 'd':
                                 pt = _conv(t->tm_mday,
@@ -301,7 +276,7 @@
                                            pt, ptlim);
                 continue;
             case 'F':
-                pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, locale);
+                pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
                 continue;
             case 'H':
                 pt = _conv(t->tm_hour,
@@ -342,7 +317,7 @@
                 /*
                 ** After all this time, still unclaimed!
                 */
-                pt = _add("kitchen sink", pt, ptlim, modifier);
+                pt = _add("kitchen sink", pt, ptlim);
                 continue;
 #endif /* defined KITCHEN_SINK */
             case 'l':
@@ -378,21 +353,21 @@
                 continue;
             case 'p':
                 pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
-                    locale->pm :
-                    locale->am,
+                    Locale->pm :
+                    Locale->am,
                     pt, ptlim, modifier);
                 continue;
             case 'P':
                 pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
-                    locale->pm :
-                    locale->am,
+                    Locale->pm :
+                    Locale->am,
                     pt, ptlim, FORCE_LOWER_CASE);
                 continue;
             case 'R':
-                pt = _fmt("%H:%M", t, pt, ptlim, warnp, locale);
+                pt = _fmt("%H:%M", t, pt, ptlim, warnp);
                 continue;
             case 'r':
-                pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, locale);
+                pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
                 continue;
             case 'S':
                 pt = _conv(t->tm_sec,
@@ -418,7 +393,7 @@
                 }
                 continue;
             case 'T':
-                pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, locale);
+                pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
                 continue;
             case 't':
                 pt = _add("\t", pt, ptlim, modifier);
@@ -449,7 +424,7 @@
 ** (01-53)."
 ** (ado, 1993-05-24)
 **
-** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** 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
@@ -519,11 +494,7 @@
 #endif /* defined XPG4_1994_04_09 */
                     if (*format == 'V')
                         pt = _conv(w,
-                                                           getformat(modifier,
-                                                                     "%02d",
-                                                                     "%2d",
-                                                                     "%d",
-                                                                     "%02d"),
+                                getformat(modifier, "%02d", "%2d", "%d", "%02d"),
                                pt, ptlim);
                     else if (*format == 'g') {
                         *warnp = IN_ALL;
@@ -539,7 +510,7 @@
                 ** "date as dd-bbb-YYYY"
                 ** (ado, 1993-05-24)
                 */
-                pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, locale);
+                pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
                 continue;
             case 'W':
                 pt = _conv((t->tm_yday + DAYSPERWEEK -
@@ -554,13 +525,13 @@
                 pt = _conv(t->tm_wday, "%d", pt, ptlim);
                 continue;
             case 'X':
-                pt = _fmt(locale->X_fmt, t, pt, ptlim, warnp, locale);
+                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, locale);
+                pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
                 if (warn2 == IN_ALL)
                     warn2 = IN_THIS;
                 if (warn2 > *warnp)
@@ -649,8 +620,8 @@
                 }
                 continue;
             case '+':
-                pt = _fmt(locale->date_fmt, t, pt, ptlim,
-                    warnp, locale);
+                pt = _fmt(Locale->date_fmt, t, pt, ptlim,
+                    warnp);
                 continue;
             case '%':
             /*
@@ -670,11 +641,8 @@
 }
 
 static char *
-_conv(n, format, pt, ptlim)
-const int       n;
-const char * const  format;
-char * const        pt;
-const char * const  ptlim;
+_conv(const int n, const char *const format, char *const pt,
+        const char *const ptlim)
 {
     char    buf[INT_STRLEN_MAXIMUM(int) + 1];
 
@@ -683,11 +651,7 @@
 }
 
 static char *
-_add(str, pt, ptlim, modifier)
-const char *        str;
-char *          pt;
-const char * const  ptlim;
-int                     modifier;
+_add(const char *str, char *pt, const char *const ptlim, int modifier)
 {
         int c;
 
@@ -735,14 +699,8 @@
 */
 
 static char *
-_yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier)
-const int       a;
-const int       b;
-const int       convert_top;
-const int       convert_yy;
-char *          pt;
-const char * const  ptlim;
-int                     modifier;
+_yconv(const int a, const int b, const int convert_top, const int convert_yy,
+        char *pt, const char *const ptlim, int modifier)
 {
     register int    lead;
     register int    trail;
@@ -761,13 +719,9 @@
     if (convert_top) {
         if (lead == 0 && trail < 0)
             pt = _add("-0", pt, ptlim, modifier);
-        else    pt = _conv(lead, getformat(modifier, "%02d",
-                                                   "%2d", "%d", "%02d"),
-                                   pt, ptlim);
+        else    pt = _conv(lead, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
     }
     if (convert_yy)
-        pt = _conv(((trail < 0) ? -trail : trail),
-                           getformat(modifier, "%02d", "%2d", "%d", "%02d"),
-                           pt, ptlim);
+        pt = _conv(((trail < 0) ? -trail : trail), getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
     return pt;
 }
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/insque.c b/libc/upstream-netbsd/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000..09020ae
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/stdlib/insque.c
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (c) 1993 John Brezak
+ *  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 be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: insque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <assert.h>
+#include <search.h>
+
+struct qelem {
+        struct qelem *q_forw;
+        struct qelem *q_back;
+};
+
+void
+insque(void *entry, void *pred)
+{
+	struct qelem *e = (struct qelem *) entry;
+	struct qelem *p = (struct qelem *) pred;
+
+	_DIAGASSERT(e != 0);
+
+	e->q_back = p;
+	if (p) {
+		e->q_forw = p->q_forw;
+		if (p->q_forw)
+			p->q_forw->q_back = e;
+		p->q_forw = e;
+	} else
+		e->q_forw = 0;
+}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/remque.c b/libc/upstream-netbsd/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000..6060ad8
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/stdlib/remque.c
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 1993 John Brezak
+ *  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 be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: remque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <assert.h>
+#include <search.h>
+
+struct qelem {
+        struct qelem *q_forw;
+        struct qelem *q_back;
+};
+
+void
+remque(void *element)
+{
+	struct qelem *e = (struct qelem *) element;
+
+	_DIAGASSERT(e != 0);
+
+	if (e->q_forw)
+		e->q_forw->q_back = e->q_back;
+	if (e->q_back)
+		e->q_back->q_forw = e->q_forw;
+}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/tdelete.c b/libc/upstream-netbsd/lib/libc/stdlib/tdelete.c
deleted file mode 100644
index 84017dc..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/tdelete.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*	$NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $	*/
-
-/*
- * Tree search generalized from Knuth (6.2.2) Algorithm T just like
- * the AT&T man page says.
- *
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
- * Written by reading the System V Interface Definition, not the code.
- *
- * Totally public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#define _SEARCH_PRIVATE
-#include <search.h>
-#include <stdlib.h>
-
-
-/* find a node with key "vkey" in tree "vrootp" */
-void *
-tdelete(const void *vkey, void **vrootp,
-    int (*compar)(const void *, const void *))
-{
-	node_t **rootp = (node_t **)vrootp;
-	node_t *p, *q, *r;
-	int  cmp;
-
-	_DIAGASSERT(vkey != NULL);
-	_DIAGASSERT(compar != NULL);
-
-	if (rootp == NULL || (p = *rootp) == NULL)
-		return NULL;
-
-	while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
-		p = *rootp;
-		rootp = (cmp < 0) ?
-		    &(*rootp)->llink :		/* follow llink branch */
-		    &(*rootp)->rlink;		/* follow rlink branch */
-		if (*rootp == NULL)
-			return NULL;		/* key not found */
-	}
-	r = (*rootp)->rlink;			/* D1: */
-	if ((q = (*rootp)->llink) == NULL)	/* Left NULL? */
-		q = r;
-	else if (r != NULL) {			/* Right link is NULL? */
-		if (r->llink == NULL) {		/* D2: Find successor */
-			r->llink = q;
-			q = r;
-		} else {			/* D3: Find NULL link */
-			for (q = r->llink; q->llink != NULL; q = r->llink)
-				r = q;
-			r->llink = q->rlink;
-			q->llink = (*rootp)->llink;
-			q->rlink = (*rootp)->rlink;
-		}
-	}
-	if (p != *rootp)
-		free(*rootp);			/* D4: Free node */
-	*rootp = q;				/* link parent to new node */
-	return p;
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/tfind.c b/libc/upstream-netbsd/lib/libc/stdlib/tfind.c
deleted file mode 100644
index fd3f362..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/tfind.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*	$NetBSD: tfind.c,v 1.7 2012/06/25 22:32:45 abs Exp $	*/
-
-/*
- * Tree search generalized from Knuth (6.2.2) Algorithm T just like
- * the AT&T man page says.
- *
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
- * Written by reading the System V Interface Definition, not the code.
- *
- * Totally public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: tfind.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#define _SEARCH_PRIVATE
-#include <stdlib.h>
-#include <search.h>
-
-/* find a node by key "vkey" in tree "vrootp", or return 0 */
-void *
-tfind(const void *vkey, void * const *vrootp,
-    int (*compar)(const void *, const void *))
-{
-	node_t * const *rootp = (node_t * const*)vrootp;
-
-	_DIAGASSERT(vkey != NULL);
-	_DIAGASSERT(compar != NULL);
-
-	if (rootp == NULL)
-		return NULL;
-
-	while (*rootp != NULL) {		/* T1: */
-		int r;
-
-		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
-			return *rootp;		/* key found */
-		rootp = (r < 0) ?
-		    &(*rootp)->llink :		/* T3: follow left branch */
-		    &(*rootp)->rlink;		/* T4: follow right branch */
-	}
-	return NULL;
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/tsearch.c b/libc/upstream-netbsd/lib/libc/stdlib/tsearch.c
deleted file mode 100644
index af2fe9c..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/tsearch.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*	$NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $	*/
-
-/*
- * Tree search generalized from Knuth (6.2.2) Algorithm T just like
- * the AT&T man page says.
- *
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
- * Written by reading the System V Interface Definition, not the code.
- *
- * Totally public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#define _SEARCH_PRIVATE
-#include <search.h>
-#include <stdlib.h>
-
-/* find or insert datum into search tree */
-void *
-tsearch(const void *vkey, void **vrootp,
-    int (*compar)(const void *, const void *))
-{
-	node_t *q;
-	node_t **rootp = (node_t **)vrootp;
-
-	_DIAGASSERT(vkey != NULL);
-	_DIAGASSERT(compar != NULL);
-
-	if (rootp == NULL)
-		return NULL;
-
-	while (*rootp != NULL) {	/* Knuth's T1: */
-		int r;
-
-		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
-			return *rootp;		/* we found it! */
-
-		rootp = (r < 0) ?
-		    &(*rootp)->llink :		/* T3: follow left branch */
-		    &(*rootp)->rlink;		/* T4: follow right branch */
-	}
-
-	q = malloc(sizeof(node_t));		/* T5: key not found */
-	if (q != 0) {				/* make new node */
-		*rootp = q;			/* link new node to old */
-		q->key = __UNCONST(vkey);	/* initialize new node */
-		q->llink = q->rlink = NULL;
-	}
-	return q;
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
similarity index 70%
rename from libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
rename to libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
index e17130b..8cad05f 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
@@ -1,3 +1,5 @@
+/*	$OpenBSD: lsearch.c,v 1.5 2014/07/18 04:16:09 matthew Exp $	*/
+
 /*
  * Copyright (c) 1989, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,64 +32,39 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)lsearch.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: lsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
 #include <sys/types.h>
-
-#include <assert.h>
-#include <errno.h>
 #include <string.h>
 #include <search.h>
 
 typedef int (*cmp_fn_t)(const void *, const void *);
-static void *linear_base(const void *, void *, size_t *, size_t,
-			     cmp_fn_t, int);
+static void *linear_base(const void *, const void *, size_t *, size_t,
+    cmp_fn_t, int);
 
 void *
 lsearch(const void *key, void *base, size_t *nelp, size_t width,
-    cmp_fn_t compar)
+    	cmp_fn_t compar)
 {
 
-	_DIAGASSERT(key != NULL);
-	_DIAGASSERT(base != NULL);
-	_DIAGASSERT(compar != NULL);
-
 	return(linear_base(key, base, nelp, width, compar, 1));
 }
 
 void *
 lfind(const void *key, const void *base, size_t *nelp, size_t width,
-    cmp_fn_t compar)
+	cmp_fn_t compar)
 {
-
-	_DIAGASSERT(key != NULL);
-	_DIAGASSERT(base != NULL);
-	_DIAGASSERT(compar != NULL);
-
-	return(linear_base(key, __UNCONST(base), nelp, width, compar, 0));
+	return(linear_base(key, base, nelp, width, compar, 0));
 }
 
 static void *
-linear_base(const void *key, void *base, size_t *nelp, size_t width,
+linear_base(const void *key, const void *base, size_t *nelp, size_t width,
 	cmp_fn_t compar, int add_flag)
 {
-	char *element, *end;
+	const char *element, *end;
 
-	_DIAGASSERT(key != NULL);
-	_DIAGASSERT(base != NULL);
-	_DIAGASSERT(compar != NULL);
-
-	end = (char *)base + *nelp * width;
-	for (element = (char *)base; element < end; element += width)
-		if (!compar(element, key))		/* key found */
-			return element;
+	end = (const char *)base + *nelp * width;
+	for (element = base; element < end; element += width)
+		if (!compar(key, element))		/* key found */
+			return((void *)element);
 
 	if (!add_flag)					/* key not found */
 		return(NULL);
@@ -102,6 +79,6 @@
 	 * manual.
 	 */
 	++*nelp;
-	memcpy(end, key, width);
-	return end;
+	memcpy((void *)end, key, width);
+	return((void *)end);
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/tfind.c b/libc/upstream-openbsd/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000..0d1d519
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
+/*	$OpenBSD: tfind.c,v 1.6 2014/03/16 18:38:30 guenther Exp $	*/
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+/*LINTLIBRARY*/
+#include <search.h>
+
+typedef struct node_t
+{
+    char	  *key;
+    struct node_t *llink, *rlink;
+} node;
+
+/* find a node, or return 0 */
+void *
+tfind(const void *vkey, void * const *vrootp,
+    int (*compar)(const void *, const void *))
+{
+    char *key = (char *)vkey;
+    node **rootp = (node **)vrootp;
+
+    if (rootp == (struct node_t **)0)
+	return ((struct node_t *)0);
+    while (*rootp != (struct node_t *)0) {	/* T1: */
+	int r;
+	if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
+	    return (*rootp);		/* key found */
+	rootp = (r < 0) ?
+	    &(*rootp)->llink :		/* T3: follow left branch */
+	    &(*rootp)->rlink;		/* T4: follow right branch */
+    }
+    return (node *)0;
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c b/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000..a141085
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,119 @@
+/*	$OpenBSD: tsearch.c,v 1.8 2014/03/16 18:38:30 guenther Exp $	*/
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+/*LINTLIBRARY*/
+
+#include <search.h>
+#include <stdlib.h>
+
+typedef struct node_t {
+    char	  *key;
+    struct node_t *left, *right;
+} node;
+
+/* find or insert datum into search tree */
+void *
+tsearch(const void *vkey, void **vrootp,
+    int (*compar)(const void *, const void *))
+{
+    node *q;
+    char *key = (char *)vkey;
+    node **rootp = (node **)vrootp;
+
+    if (rootp == (struct node_t **)0)
+	return ((void *)0);
+    while (*rootp != (struct node_t *)0) {	/* Knuth's T1: */
+	int r;
+
+	if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
+	    return ((void *)*rootp);		/* we found it! */
+	rootp = (r < 0) ?
+	    &(*rootp)->left :		/* T3: follow left branch */
+	    &(*rootp)->right;		/* T4: follow right branch */
+    }
+    q = (node *) malloc(sizeof(node));	/* T5: key not found */
+    if (q != (struct node_t *)0) {	/* make new node */
+	*rootp = q;			/* link new node to old */
+	q->key = key;			/* initialize new node */
+	q->left = q->right = (struct node_t *)0;
+    }
+    return ((void *)q);
+}
+
+/* delete node with given key */
+void *
+tdelete(const void *vkey, void **vrootp,
+    int (*compar)(const void *, const void *))
+{
+    node **rootp = (node **)vrootp;
+    char *key = (char *)vkey;
+    node *p = (node *)1;
+    node *q;
+    node *r;
+    int cmp;
+
+    if (rootp == (struct node_t **)0 || *rootp == (struct node_t *)0)
+	return ((struct node_t *)0);
+    while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
+	p = *rootp;
+	rootp = (cmp < 0) ?
+	    &(*rootp)->left :		/* follow left branch */
+	    &(*rootp)->right;		/* follow right branch */
+	if (*rootp == (struct node_t *)0)
+	    return ((void *)0);		/* key not found */
+    }
+    r = (*rootp)->right;			/* D1: */
+    if ((q = (*rootp)->left) == (struct node_t *)0)	/* Left (struct node_t *)0? */
+	q = r;
+    else if (r != (struct node_t *)0) {		/* Right link is null? */
+	if (r->left == (struct node_t *)0) {	/* D2: Find successor */
+	    r->left = q;
+	    q = r;
+	} else {			/* D3: Find (struct node_t *)0 link */
+	    for (q = r->left; q->left != (struct node_t *)0; q = r->left)
+		r = q;
+	    r->left = q->right;
+	    q->left = (*rootp)->left;
+	    q->right = (*rootp)->right;
+	}
+    }
+    free((struct node_t *) *rootp);	/* D4: Free node */
+    *rootp = q;				/* link parent to new node */
+    return(p);
+}
+
+/* Walk the nodes of a tree */
+static void
+trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
+{
+    if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
+	(*action)(root, leaf, level);
+    else {
+	(*action)(root, preorder, level);
+	if (root->left != (struct node_t *)0)
+	    trecurse(root->left, action, level + 1);
+	(*action)(root, postorder, level);
+	if (root->right != (struct node_t *)0)
+	    trecurse(root->right, action, level + 1);
+	(*action)(root, endorder, level);
+    }
+}
+
+/* Walk the nodes of a tree */
+void
+twalk(const void *vroot, void (*action)(const void *, VISIT, int))
+{
+    node *root = (node *)vroot;
+
+    if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
+	trecurse(root, action, 0);
+}
diff --git a/libstdc++/NOTICE b/libstdc++/NOTICE
index 59d6106..492770d 100644
--- a/libstdc++/NOTICE
+++ b/libstdc++/NOTICE
@@ -4,9 +4,9 @@
 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
+ * 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
+ * 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.
@@ -32,9 +32,9 @@
 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
+ * 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
+ * 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.
diff --git a/libstdc++/include/cstdlib b/libstdc++/include/cstdlib
index bb6f5a5..bd1deae 100644
--- a/libstdc++/include/cstdlib
+++ b/libstdc++/include/cstdlib
@@ -42,9 +42,6 @@
 using ::exit;
 using ::abort;
 using ::atexit;
-#if 0 /* MISSING FROM BIONIC */
-using ::on_exit;
-#endif
 
 using ::getenv;
 using ::putenv;
diff --git a/linker/NOTICE b/linker/NOTICE
index db4ec7b..cb3a1dd 100644
--- a/linker/NOTICE
+++ b/linker/NOTICE
@@ -20,9 +20,9 @@
 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
+ * 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
+ * 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.
@@ -48,9 +48,9 @@
 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
+ * 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
+ * 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.
@@ -76,9 +76,9 @@
 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
+ * 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
+ * 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.
@@ -104,9 +104,9 @@
 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
+ * 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
+ * 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.
@@ -132,9 +132,9 @@
 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
+ * 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
+ * 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.
@@ -176,9 +176,9 @@
 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
+ * 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
+ * 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.
diff --git a/linker/arch/mips/begin.S b/linker/arch/mips/begin.S
index 4a855e6..cbe1e37 100644
--- a/linker/arch/mips/begin.S
+++ b/linker/arch/mips/begin.S
@@ -32,7 +32,9 @@
 
     .ent    __start
     .globl    __start
+    .globl    _start
 __start:
+_start:
     .set    noreorder
     bal    1f
     nop
diff --git a/linker/arch/mips64/begin.S b/linker/arch/mips64/begin.S
index 6827a2c..8f6b94a 100644
--- a/linker/arch/mips64/begin.S
+++ b/linker/arch/mips64/begin.S
@@ -46,7 +46,9 @@
 
     .ent	__start
     .globl	__start
+    .globl	_start
 __start:
+_start:
     .set	noreorder
     bal		1f
      nop
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 9ebb09b..079682c 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -206,6 +206,15 @@
 }
 
 static void send_debuggerd_packet(siginfo_t* info) {
+  if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
+    // process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
+    // Honor that intention by not connecting to debuggerd and asking it
+    // to dump our internal state.
+    __libc_format_log(ANDROID_LOG_INFO, "libc",
+                      "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
+    return;
+  }
+
   int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
   if (s == -1) {
     __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index efb829e..8ebf357 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -111,8 +111,7 @@
       sym = dlsym_linear_lookup(symbol, &found, caller_si->next, caller_si);
     }
   } else {
-    found = reinterpret_cast<soinfo*>(handle);
-    sym = dlsym_handle_lookup(found, symbol, caller_si);
+    sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol, caller_si);
   }
 
   if (sym != NULL && sym->st_shndx != 0) {
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 52af0f1..7f8c901 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -31,13 +31,45 @@
 template<typename T, typename Allocator>
 class LinkedList {
  public:
-  LinkedList() : head_(nullptr) {}
+  LinkedList() : head_(nullptr), tail_(nullptr) {}
 
   void push_front(T* const element) {
     LinkedListEntry<T>* new_entry = Allocator::alloc();
     new_entry->next = head_;
     new_entry->element = element;
     head_ = new_entry;
+    if (tail_ == nullptr) {
+      tail_ = new_entry;
+    }
+  }
+
+  void push_back(T* const element) {
+    LinkedListEntry<T>* new_entry = Allocator::alloc();
+    new_entry->next = nullptr;
+    new_entry->element = element;
+    if (tail_ == nullptr) {
+      tail_ = head_ = new_entry;
+    } else {
+      tail_->next = new_entry;
+      tail_ = new_entry;
+    }
+  }
+
+  T* pop_front() {
+    if (head_ == nullptr) {
+      return nullptr;
+    }
+
+    LinkedListEntry<T>* entry = head_;
+    T* element = entry->element;
+    head_ = entry->next;
+    Allocator::free(entry);
+
+    if (head_ == nullptr) {
+      tail_ = nullptr;
+    }
+
+    return element;
   }
 
   void clear() {
@@ -46,6 +78,8 @@
       head_ = head_->next;
       Allocator::free(p);
     }
+
+    tail_ = nullptr;
   }
 
   template<typename F>
@@ -68,6 +102,7 @@
 
  private:
   LinkedListEntry<T>* head_;
+  LinkedListEntry<T>* tail_;
   DISALLOW_COPY_AND_ASSIGN(LinkedList);
 };
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 04ffe59..f8b35d7 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -469,6 +469,10 @@
     }
   }
 
+  TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
+             name, si->name, reinterpret_cast<void*>(si->base), hash, hash % si->nbucket);
+
+
   return NULL;
 }
 
@@ -585,18 +589,43 @@
     return NULL;
 }
 
-/* This is used by dlsym(3).  It performs symbol lookup only within the
-   specified soinfo object and not in any of its dependencies.
+// Another soinfo list allocator to use in dlsym. We don't reuse
+// SoinfoListAllocator because it is write-protected most of the time.
+static LinkerAllocator<LinkedListEntry<soinfo>> g_soinfo_list_allocator_rw;
+class SoinfoListAllocatorRW {
+ public:
+  static LinkedListEntry<soinfo>* alloc() {
+    return g_soinfo_list_allocator_rw.alloc();
+  }
 
-   TODO: Only looking in the specified soinfo seems wrong. dlsym(3) says
-   that it should do a breadth first search through the dependency
-   tree. This agrees with the ELF spec (aka System V Application
-   Binary Interface) where in Chapter 5 it discuss resolving "Shared
-   Object Dependencies" in breadth first search order.
- */
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller) {
-    return soinfo_elf_lookup(si, elfhash(name), name,
-        caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
+  static void free(LinkedListEntry<soinfo>* ptr) {
+    g_soinfo_list_allocator_rw.free(ptr);
+  }
+};
+
+// This is used by dlsym(3).  It performs symbol lookup only within the
+// specified soinfo object and its dependencies in breadth first order.
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) {
+  LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
+  visit_list.push_back(si);
+  soinfo* current_soinfo;
+  while ((current_soinfo = visit_list.pop_front()) != nullptr) {
+    ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name,
+        caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
+
+    if (result != nullptr) {
+      *found = current_soinfo;
+      visit_list.clear();
+      return result;
+    }
+
+    current_soinfo->get_children().for_each([&](soinfo* child) {
+      visit_list.push_back(child);
+    });
+  }
+
+  visit_list.clear();
+  return nullptr;
 }
 
 /* This is used by dlsym(3) to performs a global symbol lookup. If the
@@ -2077,12 +2106,6 @@
       ldpreload_env = linker_env_get("LD_PRELOAD");
     }
 
-    // Linker does not call constructors for its own
-    // global variables so we need to initialize
-    // the allocators explicitly.
-    g_soinfo_allocator.init();
-    g_soinfo_links_allocator.init();
-
     INFO("[ android linker & debugger ]");
 
     soinfo* si = soinfo_alloc(args.argv[0], NULL);
@@ -2227,6 +2250,8 @@
   return 0;
 }
 
+extern "C" void _start();
+
 /*
  * This is the entry point for the linker, called from begin.S. This
  * method is responsible for fixing the linker's own relocations, and
@@ -2244,12 +2269,23 @@
   KernelArgumentBlock args(raw_args);
 
   ElfW(Addr) linker_addr = args.getauxval(AT_BASE);
+  ElfW(Addr) entry_point = args.getauxval(AT_ENTRY);
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
   ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
 
   soinfo linker_so;
   memset(&linker_so, 0, sizeof(soinfo));
 
+  // If the linker is not acting as PT_INTERP entry_point is equal to
+  // _start. Which means that the linker is running as an executable and
+  // already linked by PT_INTERP.
+  //
+  // This happens when user tries to run 'adb shell /system/bin/linker'
+  // see also https://code.google.com/p/android/issues/detail?id=63174
+  if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) {
+    __libc_fatal("This is %s, the helper program for shared library executables.\n", args.argv[0]);
+  }
+
   strcpy(linker_so.name, "[dynamic linker]");
   linker_so.base = linker_addr;
   linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
@@ -2271,6 +2307,9 @@
     _exit(EXIT_FAILURE);
   }
 
+  // Initialize the linker's own global variables
+  linker_so.CallConstructors();
+
   // We have successfully fixed our own relocations. It's safe to run
   // the main part of the linker now.
   args.abort_message_ptr = &g_abort_message;
diff --git a/linker/linker.h b/linker/linker.h
index e1112e6..03672b2 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -238,7 +238,7 @@
 soinfo* find_containing_library(const void* addr);
 
 ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr);
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller_si);
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller_si);
 
 void debuggerd_init();
 extern "C" abort_msg_t* g_abort_message;
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index c8b97b1..f5d3745 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -28,17 +28,12 @@
   size_t num_free_blocks;
 };
 
-LinkerBlockAllocator::LinkerBlockAllocator()
-  : block_size_(0),
+LinkerBlockAllocator::LinkerBlockAllocator(size_t block_size)
+  : block_size_(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size),
     page_list_(nullptr),
     free_block_list_(nullptr)
 {}
 
-void LinkerBlockAllocator::init(size_t block_size) {
-  block_size_ = block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size;
-}
-
-
 void* LinkerBlockAllocator::alloc() {
   if (free_block_list_ == nullptr) {
     create_new_page();
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index fbf58fe..5d3563f 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -32,9 +32,8 @@
  */
 class LinkerBlockAllocator {
  public:
-  LinkerBlockAllocator();
+  explicit LinkerBlockAllocator(size_t block_size);
 
-  void init(size_t block_size);
   void* alloc();
   void free(void* block);
   void protect_all(int prot);
@@ -60,8 +59,7 @@
 template<typename T>
 class LinkerAllocator {
  public:
-  LinkerAllocator() : block_allocator_() {}
-  void init() { block_allocator_.init(sizeof(T)); }
+  LinkerAllocator() : block_allocator_(sizeof(T)) {}
   T* alloc() { return reinterpret_cast<T*>(block_allocator_.alloc()); }
   void free(T* t) { block_allocator_.free(t); }
   void protect_all(int prot) { block_allocator_.protect_all(prot); }
diff --git a/linker/tests/linked_list_test.cpp b/linker/tests/linked_list_test.cpp
index 31ec7d5..b9816fa 100644
--- a/linker/tests/linked_list_test.cpp
+++ b/linker/tests/linked_list_test.cpp
@@ -95,3 +95,23 @@
   ASSERT_TRUE(free_called);
   ASSERT_EQ("", test_list_to_string(list));
 }
+
+TEST(linked_list, push_pop) {
+  test_list_t list;
+  list.push_front("b");
+  list.push_front("a");
+  ASSERT_EQ("ab", test_list_to_string(list));
+  list.push_back("c");
+  ASSERT_EQ("abc", test_list_to_string(list));
+  ASSERT_EQ("a", list.pop_front());
+  ASSERT_EQ("bc", test_list_to_string(list));
+  ASSERT_EQ("b", list.pop_front());
+  ASSERT_EQ("c", test_list_to_string(list));
+  ASSERT_EQ("c", list.pop_front());
+  ASSERT_EQ("", test_list_to_string(list));
+  ASSERT_TRUE(list.pop_front() == nullptr);
+  list.push_back("r");
+  ASSERT_EQ("r", test_list_to_string(list));
+  ASSERT_EQ("r", list.pop_front());
+  ASSERT_TRUE(list.pop_front() == nullptr);
+}
diff --git a/linker/tests/linker_allocator_test.cpp b/linker/tests/linker_allocator_test.cpp
index 0ed8252..9292a05 100644
--- a/linker/tests/linker_allocator_test.cpp
+++ b/linker/tests/linker_allocator_test.cpp
@@ -50,7 +50,6 @@
 
 TEST(linker_allocator, test_nominal) {
   LinkerAllocator<test_struct_nominal> allocator;
-  allocator.init();
 
   test_struct_nominal* ptr1 = allocator.alloc();
   ASSERT_TRUE(ptr1 != nullptr);
@@ -67,7 +66,6 @@
 
 TEST(linker_allocator, test_small) {
   LinkerAllocator<test_struct_small> allocator;
-  allocator.init();
 
   char* ptr1 = reinterpret_cast<char*>(allocator.alloc());
   char* ptr2 = reinterpret_cast<char*>(allocator.alloc());
@@ -79,7 +77,6 @@
 
 TEST(linker_allocator, test_larger) {
   LinkerAllocator<test_struct_larger> allocator;
-  allocator.init();
 
   test_struct_larger* ptr1 = allocator.alloc();
   test_struct_larger* ptr2 = allocator.alloc();
@@ -103,7 +100,6 @@
 
 static void protect_all() {
   LinkerAllocator<test_struct_larger> allocator;
-  allocator.init();
 
   // number of allocs to reach the end of first page
   size_t n = kPageSize/sizeof(test_struct_larger) - 1;
diff --git a/tests/Android.mk b/tests/Android.mk
index 3e8fbe6..b370b92 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -85,6 +85,7 @@
     pthread_test.cpp \
     regex_test.cpp \
     sched_test.cpp \
+    search_test.cpp \
     signal_test.cpp \
     stack_protector_test.cpp \
     stack_unwinding_test.cpp \
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index f056fb6..9bc2557 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -62,10 +62,9 @@
   ASSERT_EQ(0, dlclose(self));
 }
 
-#if !defined(__LP64__)
-// Current compiler/static linker used for aarch64
-// platform optimizes LOCAL PROTECTED symbol
-// in libtest_local_symbol.so out of existence
+#if defined(__arm__)
+// This seems to be working only for arm.
+// Others platforms optimize LOCAL PROTECTED symbols.
 TEST(dlfcn, dlsym_local_symbol) {
   void* handle = dlopen("libtest_local_symbol.so", RTLD_NOW);
   ASSERT_TRUE(handle != NULL);
@@ -78,9 +77,23 @@
   f = reinterpret_cast<uint32_t (*)(void)>(dlsym(handle, "dlsym_local_symbol_get_taxicab_number_using_dlsym"));
   ASSERT_TRUE(f != NULL);
   ASSERT_EQ(1729U, f());
+  dlclose(handle);
 }
 #endif
 
+TEST(dlfcn, dlsym_with_dependencies) {
+  void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
+  ASSERT_TRUE(handle != NULL);
+  dlerror();
+  // This symbol is in DT_NEEDED library.
+  void* sym = dlsym(handle, "getRandomNumber");
+  ASSERT_TRUE(sym != NULL);
+  int (*fn)(void);
+  fn = reinterpret_cast<int (*)(void)>(sym);
+  EXPECT_EQ(4, fn());
+  dlclose(handle);
+}
+
 TEST(dlfcn, dlopen_noload) {
   void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
   ASSERT_TRUE(handle == NULL);
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 873c71e..352cac6 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -23,6 +23,7 @@
 #include <sys/socket.h>
 #include <malloc.h>
 #include <fcntl.h>
+#include <sys/prctl.h>
 
 // We have to say "DeathTest" here so gtest knows to run this test (which exits)
 // in its own process. Unfortunately, the C preprocessor doesn't give us an
@@ -32,6 +33,21 @@
 #define DEATHTEST_EVALUATOR(name) DEATHTEST_PASTER(name)
 #define DEATHTEST DEATHTEST_EVALUATOR(TEST_NAME)
 
+class DEATHTEST : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    old_dumpable_ = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
+    // Suppress debuggerd stack traces. Too slow.
+    prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
+  }
+
+  virtual void TearDown() {
+    prctl(PR_SET_DUMPABLE, old_dumpable_, 0, 0, 0, 0);
+  }
+ private:
+  int old_dumpable_;
+};
+
 #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE == 2
 struct foo {
   char empty[0];
@@ -43,7 +59,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, stpncpy_fortified2) {
+TEST_F(DEATHTEST, stpncpy_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   int copy_amt = atoi("11");
@@ -55,7 +71,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, stpncpy2_fortified2) {
+TEST_F(DEATHTEST, stpncpy2_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   memset(&myfoo, 0, sizeof(myfoo));
@@ -68,7 +84,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncpy_fortified2) {
+TEST_F(DEATHTEST, strncpy_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   int copy_amt = atoi("11");
@@ -80,7 +96,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncpy2_fortified2) {
+TEST_F(DEATHTEST, strncpy2_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   memset(&myfoo, 0, sizeof(myfoo));
@@ -93,7 +109,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, sprintf_fortified2) {
+TEST_F(DEATHTEST, sprintf_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   char source_buf[15];
@@ -106,7 +122,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, sprintf2_fortified2) {
+TEST_F(DEATHTEST, sprintf2_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   ASSERT_EXIT(sprintf(myfoo.a, "0123456789"),
@@ -128,12 +144,12 @@
   return result;
 }
 
-TEST(DEATHTEST, vsprintf_fortified2) {
+TEST_F(DEATHTEST, vsprintf_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, vsprintf2_fortified2) {
+TEST_F(DEATHTEST, vsprintf2_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
@@ -154,12 +170,12 @@
   return result;
 }
 
-TEST(DEATHTEST, vsnprintf_fortified2) {
+TEST_F(DEATHTEST, vsnprintf_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsnprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, vsnprintf2_fortified2) {
+TEST_F(DEATHTEST, vsnprintf2_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsnprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
@@ -169,7 +185,7 @@
 // zero sized target with "\0" source (should fail)
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, stpcpy_fortified2) {
+TEST_F(DEATHTEST, stpcpy_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -187,7 +203,7 @@
 // zero sized target with "\0" source (should fail)
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcpy_fortified2) {
+TEST_F(DEATHTEST, strcpy_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -205,7 +221,7 @@
 // zero sized target with longer source (should fail)
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcpy2_fortified2) {
+TEST_F(DEATHTEST, strcpy2_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -223,7 +239,7 @@
 // one byte target with longer source (should fail)
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcpy3_fortified2) {
+TEST_F(DEATHTEST, strcpy3_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -240,7 +256,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strchr_fortified2) {
+TEST_F(DEATHTEST, strchr_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -257,7 +273,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strrchr_fortified2) {
+TEST_F(DEATHTEST, strrchr_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -274,7 +290,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strlcpy_fortified2) {
+TEST_F(DEATHTEST, strlcpy_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -291,7 +307,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strlcat_fortified2) {
+TEST_F(DEATHTEST, strlcat_fortified2) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
@@ -309,7 +325,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncat_fortified2) {
+TEST_F(DEATHTEST, strncat_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   size_t n = atoi("10"); // avoid compiler optimizations
@@ -321,7 +337,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncat2_fortified2) {
+TEST_F(DEATHTEST, strncat2_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   myfoo.a[0] = '\0';
@@ -330,7 +346,7 @@
 }
 #endif
 
-TEST(DEATHTEST, strncat3_fortified2) {
+TEST_F(DEATHTEST, strncat3_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
@@ -342,7 +358,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcat_fortified2) {
+TEST_F(DEATHTEST, strcat_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char src[11];
   strcpy(src, "0123456789");
@@ -352,7 +368,7 @@
 }
 #endif
 
-TEST(DEATHTEST, strcat2_fortified2) {
+TEST_F(DEATHTEST, strcat2_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
@@ -360,7 +376,7 @@
   ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, snprintf_fortified2) {
+TEST_F(DEATHTEST, snprintf_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   strcpy(myfoo.a, "012345678");
@@ -368,7 +384,7 @@
   ASSERT_EXIT(snprintf(myfoo.b, n, "a%s", myfoo.a), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, bzero_fortified2) {
+TEST_F(DEATHTEST, bzero_fortified2) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   foo myfoo;
   memcpy(myfoo.b, "0123456789", sizeof(myfoo.b));
@@ -379,7 +395,7 @@
 #endif /* defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE=2 */
 
 // multibyte target where we over fill (should fail)
-TEST(DEATHTEST, strcpy_fortified) {
+TEST_F(DEATHTEST, strcpy_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
@@ -392,7 +408,7 @@
 }
 
 // zero sized target with "\0" source (should fail)
-TEST(DEATHTEST, strcpy2_fortified) {
+TEST_F(DEATHTEST, strcpy2_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[0];
@@ -405,7 +421,7 @@
 }
 
 // zero sized target with longer source (should fail)
-TEST(DEATHTEST, strcpy3_fortified) {
+TEST_F(DEATHTEST, strcpy3_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[0];
@@ -418,7 +434,7 @@
 }
 
 // one byte target with longer source (should fail)
-TEST(DEATHTEST, strcpy4_fortified) {
+TEST_F(DEATHTEST, strcpy4_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[1];
@@ -430,7 +446,7 @@
 #endif // __BIONIC__
 }
 
-TEST(DEATHTEST, strlen_fortified) {
+TEST_F(DEATHTEST, strlen_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
@@ -441,7 +457,7 @@
 #endif // __BIONIC__
 }
 
-TEST(DEATHTEST, strchr_fortified) {
+TEST_F(DEATHTEST, strchr_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
@@ -452,7 +468,7 @@
 #endif // __BIONIC__
 }
 
-TEST(DEATHTEST, strrchr_fortified) {
+TEST_F(DEATHTEST, strrchr_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
@@ -463,7 +479,7 @@
 #endif // __BIONIC__
 }
 
-TEST(DEATHTEST, strlcpy_fortified) {
+TEST_F(DEATHTEST, strlcpy_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char bufa[15];
@@ -476,7 +492,7 @@
 #endif // __BIONIC__
 }
 
-TEST(DEATHTEST, strlcat_fortified) {
+TEST_F(DEATHTEST, strlcat_fortified) {
 #if defined(__BIONIC__)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char bufa[15];
@@ -490,7 +506,7 @@
 #endif // __BIONIC__
 }
 
-TEST(DEATHTEST, sprintf_fortified) {
+TEST_F(DEATHTEST, sprintf_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
   char source_buf[15];
@@ -501,7 +517,7 @@
 #ifndef __clang__
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, sprintf_malloc_fortified) {
+TEST_F(DEATHTEST, sprintf_malloc_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char* buf = (char *) malloc(10);
   char source_buf[11];
@@ -511,7 +527,7 @@
 }
 #endif
 
-TEST(DEATHTEST, sprintf2_fortified) {
+TEST_F(DEATHTEST, sprintf2_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[5];
   ASSERT_EXIT(sprintf(buf, "aaaaa"), testing::KilledBySignal(SIGABRT), "");
@@ -528,12 +544,12 @@
   return result;
 }
 
-TEST(DEATHTEST, vsprintf_fortified) {
+TEST_F(DEATHTEST, vsprintf_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, vsprintf2_fortified) {
+TEST_F(DEATHTEST, vsprintf2_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
@@ -550,17 +566,17 @@
   return result;
 }
 
-TEST(DEATHTEST, vsnprintf_fortified) {
+TEST_F(DEATHTEST, vsnprintf_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsnprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, vsnprintf2_fortified) {
+TEST_F(DEATHTEST, vsnprintf2_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(vsnprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, strncat_fortified) {
+TEST_F(DEATHTEST, strncat_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
   size_t n = atoi("10"); // avoid compiler optimizations
@@ -568,7 +584,7 @@
   ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, strncat2_fortified) {
+TEST_F(DEATHTEST, strncat2_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
   buf[0] = '\0';
@@ -576,7 +592,7 @@
   ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, strcat_fortified) {
+TEST_F(DEATHTEST, strcat_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char src[11];
   strcpy(src, "0123456789");
@@ -585,7 +601,7 @@
   ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, memmove_fortified) {
+TEST_F(DEATHTEST, memmove_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[20];
   strcpy(buf, "0123456789");
@@ -593,7 +609,7 @@
   ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, memcpy_fortified) {
+TEST_F(DEATHTEST, memcpy_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char bufa[10];
   char bufb[10];
@@ -602,7 +618,7 @@
   ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, stpncpy_fortified) {
+TEST_F(DEATHTEST, stpncpy_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char bufa[15];
   char bufb[10];
@@ -611,7 +627,7 @@
   ASSERT_EXIT(stpncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, stpncpy2_fortified) {
+TEST_F(DEATHTEST, stpncpy2_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char dest[11];
   char src[10];
@@ -619,7 +635,7 @@
   ASSERT_EXIT(stpncpy(dest, src, sizeof(dest)), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, strncpy_fortified) {
+TEST_F(DEATHTEST, strncpy_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char bufa[15];
   char bufb[10];
@@ -629,7 +645,7 @@
 }
 
 
-TEST(DEATHTEST, strncpy2_fortified) {
+TEST_F(DEATHTEST, strncpy2_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char dest[11];
   char src[10];
@@ -637,7 +653,7 @@
   ASSERT_EXIT(strncpy(dest, src, sizeof(dest)), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, snprintf_fortified) {
+TEST_F(DEATHTEST, snprintf_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char bufa[15];
   char bufb[10];
@@ -646,7 +662,7 @@
   ASSERT_EXIT(snprintf(bufb, n, "%s", bufa), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, bzero_fortified) {
+TEST_F(DEATHTEST, bzero_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[10];
   memcpy(buf, "0123456789", sizeof(buf));
@@ -654,20 +670,20 @@
   ASSERT_EXIT(bzero(buf, n), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, umask_fortified) {
+TEST_F(DEATHTEST, umask_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   mode_t mask = atoi("1023");  // 01777 in octal
   ASSERT_EXIT(umask(mask), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, recv_fortified) {
+TEST_F(DEATHTEST, recv_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   size_t data_len = atoi("11"); // suppress compiler optimizations
   char buf[10];
   ASSERT_EXIT(recv(0, buf, data_len, 0), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, FD_ISSET_fortified) {
+TEST_F(DEATHTEST, FD_ISSET_fortified) {
 #if defined(__BIONIC__) // glibc catches this at compile-time.
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   fd_set set;
@@ -676,7 +692,7 @@
 #endif
 }
 
-TEST(DEATHTEST, FD_ISSET_2_fortified) {
+TEST_F(DEATHTEST, FD_ISSET_2_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[1];
   fd_set* set = (fd_set*) buf;
@@ -686,14 +702,14 @@
 // gtest's ASSERT_EXIT needs a valid expression, but glibc has a do-while macro.
 static void FD_ZERO_function(fd_set* s) { FD_ZERO(s); }
 
-TEST(DEATHTEST, FD_ZERO_fortified) {
+TEST_F(DEATHTEST, FD_ZERO_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[1];
   fd_set* set = (fd_set*) buf;
   ASSERT_EXIT(FD_ZERO_function(set), testing::KilledBySignal(SIGABRT), "");
 }
 
-TEST(DEATHTEST, read_fortified) {
+TEST_F(DEATHTEST, read_fortified) {
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   char buf[1];
   size_t ct = atoi("2"); // prevent optimizations
diff --git a/tests/libc_logging_test.cpp b/tests/libc_logging_test.cpp
index ef39d1c..950161e 100644
--- a/tests/libc_logging_test.cpp
+++ b/tests/libc_logging_test.cpp
@@ -176,14 +176,3 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-
-TEST(libc_logging, m) {
-#if defined(__BIONIC__)
-  char buf[BUFSIZ];
-  errno = EBADF;
-  __libc_format_buffer(buf, sizeof(buf), "<%m>");
-  EXPECT_STREQ("<Bad file number>", buf);
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index a374e48..7ed3e7b 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -102,6 +102,19 @@
 include $(TEST_PATH)/Android.build.mk
 
 # -----------------------------------------------------------------------------
+# Library with dependency used by dlfcn tests
+# -----------------------------------------------------------------------------
+libtest_with_dependency_src_files := \
+    dlopen_testlib_simple.cpp
+
+libtest_with_dependency_shared_libraries := libdlext_test
+
+module := libtest_with_dependency
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
 # Library used to test local symbol lookup
 # -----------------------------------------------------------------------------
 libtest_local_symbol_src_files := \
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 36da481..4da003f 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -82,6 +82,57 @@
   ASSERT_EQ(EINVAL, pthread_setspecific(key, expected));
 }
 
+TEST(pthread, pthread_key_fork) {
+  void* expected = reinterpret_cast<void*>(1234);
+  pthread_key_t key;
+  ASSERT_EQ(0, pthread_key_create(&key, NULL));
+  ASSERT_EQ(0, pthread_setspecific(key, expected));
+  ASSERT_EQ(expected, pthread_getspecific(key));
+
+  pid_t pid = fork();
+  ASSERT_NE(-1, pid) << strerror(errno);
+
+  if (pid == 0) {
+    // The surviving thread inherits all the forking thread's TLS values...
+    ASSERT_EQ(expected, pthread_getspecific(key));
+    _exit(99);
+  }
+
+  int status;
+  ASSERT_EQ(pid, waitpid(pid, &status, 0));
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(99, WEXITSTATUS(status));
+
+  ASSERT_EQ(expected, pthread_getspecific(key));
+}
+
+static void* DirtyKeyFn(void* key) {
+  return pthread_getspecific(*reinterpret_cast<pthread_key_t*>(key));
+}
+
+TEST(pthread, pthread_key_dirty) {
+  pthread_key_t key;
+  ASSERT_EQ(0, pthread_key_create(&key, NULL));
+
+  size_t stack_size = 128 * 1024;
+  void* stack = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+  ASSERT_NE(MAP_FAILED, stack);
+  memset(stack, 0xff, stack_size);
+
+  pthread_attr_t attr;
+  ASSERT_EQ(0, pthread_attr_init(&attr));
+  ASSERT_EQ(0, pthread_attr_setstack(&attr, stack, stack_size));
+
+  pthread_t t;
+  ASSERT_EQ(0, pthread_create(&t, &attr, DirtyKeyFn, &key));
+
+  void* result;
+  ASSERT_EQ(0, pthread_join(t, &result));
+  ASSERT_EQ(nullptr, result); // Not ~0!
+
+  ASSERT_EQ(0, munmap(stack, stack_size));
+}
+
 static void* IdFn(void* arg) {
   return arg;
 }
diff --git a/tests/search_test.cpp b/tests/search_test.cpp
new file mode 100644
index 0000000..3900c89
--- /dev/null
+++ b/tests/search_test.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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 <search.h>
+
+static int int_cmp(const void* lhs, const void* rhs) {
+  return *reinterpret_cast<const int*>(rhs) - *reinterpret_cast<const int*>(lhs);
+}
+
+TEST(search, lfind_lsearch) {
+  int xs[10];
+  memset(xs, 0, sizeof(xs));
+  size_t x_size = 0;
+
+  int needle;
+
+  // lfind(3) can't find '2' in the empty table.
+  needle = 2;
+  ASSERT_EQ(nullptr, lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+  ASSERT_EQ(0U, x_size);
+
+  // lsearch(3) will add it.
+  ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+  ASSERT_EQ(2, xs[0]);
+  ASSERT_EQ(1U, x_size);
+
+  // And then lfind(3) can find it.
+  ASSERT_EQ(&xs[0], lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+  ASSERT_EQ(1U, x_size);
+
+  // Inserting a duplicate does nothing (but returns the existing element).
+  ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+  ASSERT_EQ(1U, x_size);
+}
+
+struct node {
+  node(const char* s) : s(strdup(s)) {}
+
+  char* s;
+};
+
+static int node_cmp(const void* lhs, const void* rhs) {
+  return strcmp(reinterpret_cast<const node*>(lhs)->s, reinterpret_cast<const node*>(rhs)->s);
+}
+
+static std::vector<std::string> g_nodes;
+
+static void node_walk(const void* p, VISIT order, int) {
+  const node* n = *reinterpret_cast<const node* const*>(p);
+  if (order == postorder || order == leaf)  {
+    g_nodes.push_back(n->s);
+  }
+}
+
+static size_t g_free_calls;
+
+static void node_free(void* p) {
+  node* n = reinterpret_cast<node*>(p);
+  free(n->s);
+  ++g_free_calls;
+}
+
+TEST(search, tfind_tsearch_twalk_tdestroy) {
+  void* root = nullptr;
+
+  node n1("z");
+  node n2("a");
+  node n3("m");
+
+  // tfind(3) can't find anything in the empty tree.
+  ASSERT_EQ(nullptr, tfind(&n1, &root, node_cmp));
+  ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
+  ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
+
+  // tsearch(3) inserts and returns a pointer to a new node.
+  void* i1 = tsearch(&n1, &root, node_cmp);
+  ASSERT_NE(nullptr, i1);
+
+  // ...which tfind(3) will then return.
+  ASSERT_EQ(i1, tfind(&n1, &root, node_cmp));
+  ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
+  ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
+
+  // Add the other nodes.
+  ASSERT_NE(nullptr, tsearch(&n2, &root, node_cmp));
+  ASSERT_NE(nullptr, tsearch(&n3, &root, node_cmp));
+
+  // Use twalk(3) to iterate over the nodes.
+  g_nodes.clear();
+  twalk(root, node_walk);
+  ASSERT_EQ(3U, g_nodes.size());
+  ASSERT_EQ("a", g_nodes[0]);
+  ASSERT_EQ("m", g_nodes[1]);
+  ASSERT_EQ("z", g_nodes[2]);
+
+  // tdestroy(3) removes nodes under a node, calling our callback to destroy each one.
+  g_free_calls = 0;
+  tdestroy(root, node_free);
+  ASSERT_EQ(3U, g_free_calls);
+}
+
+struct pod_node {
+  pod_node(int i) : i(i) {}
+  int i;
+};
+
+static int pod_node_cmp(const void* lhs, const void* rhs) {
+  return reinterpret_cast<const pod_node*>(rhs)->i - reinterpret_cast<const pod_node*>(lhs)->i;
+}
+
+TEST(search, tdelete) {
+  void* root = nullptr;
+
+  pod_node n1(123);
+  ASSERT_NE(nullptr, tsearch(&n1, &root, pod_node_cmp));
+
+  // tdelete(3) leaks n1.
+  pod_node not_there(456);
+  ASSERT_EQ(nullptr, tdelete(&not_there, &root, pod_node_cmp));
+  ASSERT_NE(nullptr, tdelete(&n1, &root, pod_node_cmp));
+}
+
+struct q_node {
+  q_node(int i) : i(i) {}
+
+  q_node* next;
+  q_node* prev;
+
+  int i;
+};
+
+TEST(search, insque_remque) {
+  q_node zero(0);
+  q_node one(1);
+  q_node two(2);
+
+  // Linear (not circular).
+
+  insque(&zero, NULL);
+  insque(&one, &zero);
+  insque(&two, &one);
+
+  int expected = 0;
+  for (q_node* q = &zero; q != NULL; q = q->next) {
+    ASSERT_EQ(expected, q->i);
+    ++expected;
+  }
+  ASSERT_EQ(3, expected);
+
+  for (q_node* q = &two; q != NULL; q = q->prev) {
+    --expected;
+    ASSERT_EQ(expected, q->i);
+  }
+  ASSERT_EQ(0, expected);
+
+  q_node* head = &zero;
+
+  remque(&one);
+  ASSERT_EQ(0, head->i);
+  ASSERT_EQ(2, head->next->i);
+  ASSERT_EQ(nullptr, head->next->next);
+
+  remque(&two);
+  ASSERT_EQ(0, head->i);
+  ASSERT_EQ(nullptr, head->next);
+
+  remque(&zero);
+
+  // Circular.
+
+  zero.next = &zero;
+  zero.prev = &zero;
+
+  insque(&one, &zero);
+  insque(&two, &one);
+
+  ASSERT_EQ(0, head->i);
+  ASSERT_EQ(1, head->next->i);
+  ASSERT_EQ(2, head->next->next->i);
+  ASSERT_EQ(0, head->next->next->next->i);
+  ASSERT_EQ(1, head->next->next->next->next->i);
+  ASSERT_EQ(2, head->next->next->next->next->next->i);
+
+  remque(&one);
+  ASSERT_EQ(0, head->i);
+  ASSERT_EQ(2, head->next->i);
+  ASSERT_EQ(0, head->next->next->i);
+  ASSERT_EQ(2, head->next->next->next->i);
+
+  remque(&two);
+  ASSERT_EQ(0, head->i);
+  ASSERT_EQ(0, head->next->i);
+
+  remque(&zero);
+}
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index d41bfa9..5e88c88 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -66,7 +66,12 @@
   atomic_char small;
   atomic_intmax_t big;
   ASSERT_TRUE(atomic_is_lock_free(&small));
+  // atomic_intmax_t(size = 64) is not lock free on mips32.
+#if defined(__mips__) && !defined(__LP64__)
+  ASSERT_FALSE(atomic_is_lock_free(&big));
+#else
   ASSERT_TRUE(atomic_is_lock_free(&big));
+#endif
 }
 
 TEST(stdatomic, atomic_flag) {
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 6d29421..553f018 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -262,3 +262,102 @@
   ASSERT_TRUE(WIFEXITED(status));
   ASSERT_EQ(99, WEXITSTATUS(status));
 }
+
+TEST(stdlib, pty_smoke) {
+  // getpt returns a pty with O_RDWR|O_NOCTTY.
+  int fd = getpt();
+  ASSERT_NE(-1, fd);
+
+  // grantpt is a no-op.
+  ASSERT_EQ(0, grantpt(fd));
+
+  // ptsname_r should start "/dev/pts/".
+  char name_r[128];
+  ASSERT_EQ(0, ptsname_r(fd, name_r, sizeof(name_r)));
+  name_r[9] = 0;
+  ASSERT_STREQ("/dev/pts/", name_r);
+
+  close(fd);
+}
+
+TEST(stdlib, posix_openpt) {
+  int fd = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC);
+  ASSERT_NE(-1, fd);
+  close(fd);
+}
+
+TEST(stdlib, ptsname_r_ENOTTY) {
+  errno = 0;
+  char buf[128];
+  ASSERT_EQ(ENOTTY, ptsname_r(STDOUT_FILENO, buf, sizeof(buf)));
+  ASSERT_EQ(ENOTTY, errno);
+}
+
+TEST(stdlib, ptsname_r_EINVAL) {
+  int fd = getpt();
+  ASSERT_NE(-1, fd);
+  errno = 0;
+  char* buf = NULL;
+  ASSERT_EQ(EINVAL, ptsname_r(fd, buf, 128));
+  ASSERT_EQ(EINVAL, errno);
+  close(fd);
+}
+
+TEST(stdlib, ptsname_r_ERANGE) {
+  int fd = getpt();
+  ASSERT_NE(-1, fd);
+  errno = 0;
+  char buf[1];
+  ASSERT_EQ(ERANGE, ptsname_r(fd, buf, sizeof(buf)));
+  ASSERT_EQ(ERANGE, errno);
+  close(fd);
+}
+
+TEST(stdlib, ttyname_r) {
+  int fd = getpt();
+  ASSERT_NE(-1, fd);
+
+  // ttyname_r returns "/dev/ptmx" for a pty.
+  char name_r[128];
+  ASSERT_EQ(0, ttyname_r(fd, name_r, sizeof(name_r)));
+  ASSERT_STREQ("/dev/ptmx", name_r);
+
+  close(fd);
+}
+
+TEST(stdlib, ttyname_r_ENOTTY) {
+  int fd = open("/dev/null", O_WRONLY);
+  errno = 0;
+  char buf[128];
+  ASSERT_EQ(ENOTTY, ttyname_r(fd, buf, sizeof(buf)));
+  ASSERT_EQ(ENOTTY, errno);
+  close(fd);
+}
+
+TEST(stdlib, ttyname_r_EINVAL) {
+  int fd = getpt();
+  ASSERT_NE(-1, fd);
+  errno = 0;
+  char* buf = NULL;
+  ASSERT_EQ(EINVAL, ttyname_r(fd, buf, 128));
+  ASSERT_EQ(EINVAL, errno);
+  close(fd);
+}
+
+TEST(stdlib, ttyname_r_ERANGE) {
+  int fd = getpt();
+  ASSERT_NE(-1, fd);
+  errno = 0;
+  char buf[1];
+  ASSERT_EQ(ERANGE, ttyname_r(fd, buf, sizeof(buf)));
+  ASSERT_EQ(ERANGE, errno);
+  close(fd);
+}
+
+TEST(stdlib, unlockpt_ENOTTY) {
+  int fd = open("/dev/null", O_WRONLY);
+  errno = 0;
+  ASSERT_EQ(-1, unlockpt(fd));
+  ASSERT_EQ(ENOTTY, errno);
+  close(fd);
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 12b1ea7..241c4a0 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -27,34 +27,6 @@
 
 #include "ScopedSignalHandler.h"
 
-#if defined(__BIONIC__) // mktime_tz is a bionic extension.
-#include <libc/private/bionic_time.h>
-#endif // __BIONIC__
-
-TEST(time, mktime_tz) {
-#if defined(__BIONIC__)
-  struct tm epoch;
-  memset(&epoch, 0, sizeof(tm));
-  epoch.tm_year = 1970 - 1900;
-  epoch.tm_mon = 1;
-  epoch.tm_mday = 1;
-
-  // Alphabetically first. Coincidentally equivalent to UTC.
-  ASSERT_EQ(2678400, mktime_tz(&epoch, "Africa/Abidjan"));
-
-  // Alphabetically last. Coincidentally equivalent to UTC.
-  ASSERT_EQ(2678400, mktime_tz(&epoch, "Zulu"));
-
-  // Somewhere in the middle, not UTC.
-  ASSERT_EQ(2707200, mktime_tz(&epoch, "America/Los_Angeles"));
-
-  // Missing. Falls back to UTC.
-  ASSERT_EQ(2678400, mktime_tz(&epoch, "PST"));
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
-
 TEST(time, gmtime) {
   time_t t = 0;
   tm* broken_down = gmtime(&t);
@@ -108,9 +80,6 @@
 #if !defined(__LP64__)
   // 32-bit bionic stupidly had a signed 32-bit time_t.
   ASSERT_EQ(-1, mktime(&t));
-#if defined(__BIONIC__)
-  ASSERT_EQ(-1, mktime_tz(&t, "UTC"));
-#endif
 #else
   // Everyone else should be using a signed 64-bit time_t.
   ASSERT_GE(sizeof(time_t) * 8, 64U);
@@ -118,16 +87,10 @@
   setenv("TZ", "America/Los_Angeles", 1);
   tzset();
   ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
-#if defined(__BIONIC__)
-  ASSERT_EQ(static_cast<time_t>(4108320000U), mktime_tz(&t, "UTC"));
-#endif
 
   setenv("TZ", "UTC", 1);
   tzset();
   ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
-#if defined(__BIONIC__)
-  ASSERT_EQ(static_cast<time_t>(4108348800U), mktime_tz(&t, "America/Los_Angeles"));
-#endif
 #endif
 }
 
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 58c9ad9..2a65657 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -20,6 +20,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <stdint.h>
 #include <unistd.h>
 #include <sys/syscall.h>
@@ -212,6 +213,14 @@
   ASSERT_EQ(EBADF, errno);
 }
 
+TEST(unistd, syscall_long) {
+  // Check that syscall(3) correctly returns long results.
+  // https://code.google.com/p/android/issues/detail?id=73952
+  // We assume that the break is > 4GiB, but this is potentially flaky.
+  uintptr_t p = reinterpret_cast<uintptr_t>(sbrk(0));
+  ASSERT_EQ(p, static_cast<uintptr_t>(syscall(__NR_brk, 0)));
+}
+
 TEST(unistd, alarm) {
   ASSERT_EQ(0U, alarm(0));
 }