Merge "Switch to OpenBSD res_random."
diff --git a/HACKING.txt b/HACKING.txt
index fb93b5a..27e1368 100644
--- a/HACKING.txt
+++ b/HACKING.txt
@@ -81,13 +81,6 @@
   private/
     # These are private header files meant for use within bionic itself.
 
-  stdio/
-  stdlib/
-  unistd/
-    # These are legacy files of unknown provenance. In the past, bionic was a
-    # mess of random versions of random files from all three of FreeBSD, NetBSD,
-    # and OpenBSD! We've been working to clean that up, but these directories
-    # are basically where all the stuff we haven't got to yet lives.
   dns/
     # Contains the DNS resolver (originates from NetBSD code).
 
@@ -114,6 +107,10 @@
     # current upstream source in one of the upstream directories or by
     # switching the file to C++ and cleaning it up.
 
+  stdio/
+    # These are legacy files of dubious provenance. We're working to clean
+    # this mess up, and this directory should disappear.
+
   tools/
     # Various tools used to maintain bionic.
 
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 2d87ebb..977469a 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -37,7 +37,6 @@
 # Define the common source files for all the libc instances
 # =========================================================
 libc_common_src_files := \
-    bionic/arc4random.c \
     bionic/bindresvport.c \
     bionic/daemon.c \
     bionic/err.c \
@@ -46,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 \
@@ -54,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 \
@@ -64,10 +60,9 @@
     bionic/siginterrupt.c \
     bionic/sigsetmask.c \
     bionic/system_properties_compat.c \
-    bionic/unlockpt.c \
     stdio/snprintf.c\
     stdio/sprintf.c \
-    unistd/syslog.c \
+    stdio/stdio_ext.cpp \
 
 # Fortify implementations of libc functions.
 libc_common_src_files += \
@@ -96,6 +91,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 \
@@ -108,8 +104,6 @@
     bionic/__cmsg_nxthdr.cpp \
     bionic/connect.cpp \
     bionic/ctype.cpp \
-    bionic/__cxa_guard.cpp \
-    bionic/__cxa_pure_virtual.cpp \
     bionic/dirent.cpp \
     bionic/dup2.cpp \
     bionic/epoll_create.cpp \
@@ -125,9 +119,11 @@
     bionic/futimens.cpp \
     bionic/getauxval.cpp \
     bionic/getcwd.cpp \
+    bionic/getentropy_linux.c \
     bionic/getpgrp.cpp \
     bionic/getpid.cpp \
     bionic/gettid.cpp \
+    bionic/__gnu_basename.cpp \
     bionic/inotify_init.cpp \
     bionic/lchown.cpp \
     bionic/lfs64_support.cpp \
@@ -139,6 +135,7 @@
     bionic/link.cpp \
     bionic/locale.cpp \
     bionic/lstat.cpp \
+    bionic/malloc_info.cpp \
     bionic/mbrtoc16.cpp \
     bionic/mbrtoc32.cpp \
     bionic/mbstate.cpp \
@@ -147,7 +144,6 @@
     bionic/mknod.cpp \
     bionic/mntent.cpp \
     bionic/NetdClientDispatch.cpp \
-    bionic/new.cpp \
     bionic/open.cpp \
     bionic/pause.cpp \
     bionic/pipe.cpp \
@@ -175,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 \
@@ -218,6 +215,7 @@
     bionic/stubs.cpp \
     bionic/symlink.cpp \
     bionic/sysconf.cpp \
+    bionic/syslog.cpp \
     bionic/sys_siglist.c \
     bionic/sys_signame.c \
     bionic/system_properties.cpp \
@@ -229,11 +227,15 @@
     bionic/unlink.cpp \
     bionic/utimes.cpp \
     bionic/vdso.cpp \
-    bionic/vfork.cpp \
     bionic/wait.cpp \
     bionic/wchar.cpp \
     bionic/wctype.cpp \
 
+libc_cxa_src_files := \
+    bionic/__cxa_guard.cpp \
+    bionic/__cxa_pure_virtual.cpp \
+    bionic/new.cpp \
+
 libc_upstream_freebsd_src_files := \
     upstream-freebsd/lib/libc/gen/ldexp.c \
     upstream-freebsd/lib/libc/gen/sleep.c \
@@ -282,25 +284,22 @@
     upstream-netbsd/lib/libc/regex/regerror.c \
     upstream-netbsd/lib/libc/regex/regexec.c \
     upstream-netbsd/lib/libc/regex/regfree.c \
-    upstream-netbsd/lib/libc/resolv/mtctxres.c \
     upstream-netbsd/lib/libc/stdlib/bsearch.c \
     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 \
@@ -335,6 +334,8 @@
     upstream-openbsd/lib/libc/gdtoa/strtorQ.c \
 
 libc_upstream_openbsd_src_files := \
+    upstream-openbsd/lib/libc/crypt/arc4random.c \
+    upstream-openbsd/lib/libc/crypt/arc4random_uniform.c \
     upstream-openbsd/lib/libc/gen/alarm.c \
     upstream-openbsd/lib/libc/gen/ctype_.c \
     upstream-openbsd/lib/libc/gen/exec.c \
@@ -391,6 +392,7 @@
     upstream-openbsd/lib/libc/stdio/fgetws.c \
     upstream-openbsd/lib/libc/stdio/fileno.c \
     upstream-openbsd/lib/libc/stdio/findfp.c \
+    upstream-openbsd/lib/libc/stdio/fmemopen.c \
     upstream-openbsd/lib/libc/stdio/fprintf.c \
     upstream-openbsd/lib/libc/stdio/fpurge.c \
     upstream-openbsd/lib/libc/stdio/fputc.c \
@@ -419,6 +421,8 @@
     upstream-openbsd/lib/libc/stdio/getwchar.c \
     upstream-openbsd/lib/libc/stdio/makebuf.c \
     upstream-openbsd/lib/libc/stdio/mktemp.c \
+    upstream-openbsd/lib/libc/stdio/open_memstream.c \
+    upstream-openbsd/lib/libc/stdio/open_wmemstream.c \
     upstream-openbsd/lib/libc/stdio/perror.c \
     upstream-openbsd/lib/libc/stdio/printf.c \
     upstream-openbsd/lib/libc/stdio/putc.c \
@@ -467,6 +471,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 \
@@ -475,6 +480,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 \
@@ -635,6 +642,7 @@
     $(call all-c-files-under,dns) \
     upstream-netbsd/lib/libc/isc/ev_streams.c \
     upstream-netbsd/lib/libc/isc/ev_timers.c \
+    upstream-netbsd/lib/libc/resolv/mtctxres.c \
 
 # We use the OpenBSD res_random.
 LOCAL_CFLAGS += \
@@ -813,6 +821,27 @@
 
 
 # ========================================================
+# libc_cxa.a - Things traditionally in libstdc++
+# ========================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(libc_cxa_src_files)
+LOCAL_CFLAGS := $(libc_common_cflags) \
+    -fvisibility=hidden \
+
+LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
+LOCAL_CPPFLAGS := $(libc_common_cppflags)
+LOCAL_C_INCLUDES := $(libc_common_c_includes)
+LOCAL_MODULE := libc_cxa
+LOCAL_CLANG := true # GCC refuses to hide new/delete
+LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
+LOCAL_SYSTEM_SHARED_LIBRARIES :=
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+# ========================================================
 # libc_syscalls.a
 # ========================================================
 
@@ -864,6 +893,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_WHOLE_STATIC_LIBRARIES := \
     libc_bionic \
+    libc_cxa \
     libc_dns \
     libc_freebsd \
     libc_gdtoa \
@@ -985,8 +1015,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 \
 
@@ -1052,7 +1080,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 \
@@ -1067,6 +1098,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
@@ -1109,6 +1141,36 @@
 
 endif  #!user
 
+# ========================================================
+# libstdc++.so
+# ========================================================
+libstdcxx_common_src_files := \
+    bionic/__cxa_guard.cpp \
+    bionic/__cxa_pure_virtual.cpp \
+    bionic/new.cpp \
+    bionic/libc_logging.cpp \
+
+include $(CLEAR_VARS)
+LOCAL_C_INCLUDES := $(libc_common_c_includes)
+LOCAL_CFLAGS := $(libc_common_cflags)
+LOCAL_SRC_FILES := $(libstdcxx_common_src_files)
+LOCAL_MODULE:= libstdc++
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+include $(BUILD_SHARED_LIBRARY)
+
+# ========================================================
+# libstdc++.a
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_C_INCLUDES := $(libc_common_c_includes)
+LOCAL_CFLAGS := $(libc_common_cflags)
+LOCAL_SRC_FILES := $(libstdcxx_common_src_files)
+LOCAL_MODULE:= libstdc++
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+include $(BUILD_STATIC_LIBRARY)
+
 
 # ========================================================
 include $(call all-makefiles-under,$(LOCAL_PATH))
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/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 014d554..bfa13b7 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -77,6 +77,7 @@
 int     setgroups:setgroups32(int, const gid_t*)   arm,x86
 int     setgroups:setgroups(int, const gid_t*)     arm64,mips,mips64,x86_64
 int     setpgid(pid_t, pid_t)  all
+pid_t   vfork(void)  arm
 int     setregid:setregid32(gid_t, gid_t)  arm,x86
 int     setregid:setregid(gid_t, gid_t)    arm64,mips,mips64,x86_64
 int     chroot(const char*)  all
@@ -303,6 +304,9 @@
 
 int __set_tid_address:set_tid_address(int*)  all
 
+int setfsgid(gid_t)  all
+int setfsuid(uid_t)  all
+
 pid_t wait4(pid_t, int*, int, struct rusage*)  all
 int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*)  all
 
@@ -311,7 +315,7 @@
 int     cacheflush:__ARM_NR_cacheflush(long start, long end, long flags)  arm
 
 # MIPS-specific
-int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips,mips64
+int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips
 int     __set_tls:set_thread_area(void*) mips,mips64
 
 # x86-specific
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 00be4ae..70cc8eb 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -53,7 +53,6 @@
     arch-arm/bionic/atomics_arm.c \
     arch-arm/bionic/__bionic_clone.S \
     arch-arm/bionic/_exit_with_stack_teardown.S \
-    arch-arm/bionic/__get_sp.S \
     arch-arm/bionic/libgcc_compat.c \
     arch-arm/bionic/memcmp.S \
     arch-arm/bionic/_setjmp.S \
diff --git a/libc/arch-arm/bionic/__get_sp.S b/libc/arch-arm/bionic/__get_sp.S
deleted file mode 100644
index 9ae6f24..0000000
--- a/libc/arch-arm/bionic/__get_sp.S
+++ /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 <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
-  mov r0, sp
-  bx lr
-END(__get_sp)
diff --git a/libc/arch-arm/bionic/_setjmp.S b/libc/arch-arm/bionic/_setjmp.S
index 64a0a31..7d637fd 100644
--- a/libc/arch-arm/bionic/_setjmp.S
+++ b/libc/arch-arm/bionic/_setjmp.S
@@ -107,7 +107,7 @@
 
 	/* validation failed, die die die. */
 botch:
-	bl	PIC_SYM(longjmperror, PLT)
-	bl	PIC_SYM(abort, PLT)
+	bl	longjmperror
+	bl	abort
 	b	. - 8		/* Cannot get here */
 END(_longjmp)
diff --git a/libc/arch-arm/bionic/abort_arm.S b/libc/arch-arm/bionic/abort_arm.S
index 6b181ef..1039502 100644
--- a/libc/arch-arm/bionic/abort_arm.S
+++ b/libc/arch-arm/bionic/abort_arm.S
@@ -40,5 +40,5 @@
     .cfi_def_cfa_offset 8
     .cfi_rel_offset r3, 0
     .cfi_rel_offset r14, 4
-    bl      PIC_SYM(__libc_android_abort, PLT)
+    bl      __libc_android_abort
 END(abort)
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
index ed59d07..0c9082c 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -56,7 +56,7 @@
 	.cfi_rel_offset r14, 4
 	mov	r0, #0x00000000
 
-	bl	PIC_SYM(sigblock, PLT)
+	bl	sigblock
 	mov	r1, r0
 
 	ldmfd	sp!, {r0, r14}
@@ -108,7 +108,7 @@
 	.cfi_adjust_cfa_offset 4
 
 	mov	r0, r2
-	bl	PIC_SYM(sigsetmask, PLT)
+	bl	sigsetmask
 
 	add	sp, sp, #4	/* unalign the stack */
 	.cfi_adjust_cfa_offset -4
@@ -147,7 +147,7 @@
 
 	/* validation failed, die die die. */
 botch:
-	bl	PIC_SYM(longjmperror, PLT)
-	bl	PIC_SYM(abort, PLT)
+	bl	longjmperror
+	bl	abort
 	b	. - 8		/* Cannot get here */
 END(longjmp)
diff --git a/libc/arch-arm/bionic/sigsetjmp.S b/libc/arch-arm/bionic/sigsetjmp.S
index 7016f50..6a25a12 100644
--- a/libc/arch-arm/bionic/sigsetjmp.S
+++ b/libc/arch-arm/bionic/sigsetjmp.S
@@ -33,8 +33,6 @@
  * SUCH DAMAGE.
  */
 
-#define _ALIGN_TEXT .align 0
-
 #include <private/bionic_asm.h>
 #include <machine/setjmp.h>
 
@@ -50,8 +48,8 @@
 
 ENTRY(sigsetjmp)
 	teq	r1, #0
-	beq	PIC_SYM(_setjmp, PLT)
-	b	PIC_SYM(setjmp, PLT)
+	beq	_setjmp
+	b	setjmp
 END(sigsetjmp)
 
 .L_setjmp_magic:
@@ -61,6 +59,6 @@
 	ldr	r2, .L_setjmp_magic
 	ldr	r3, [r0]
 	teq	r2, r3
-	beq	PIC_SYM(_longjmp, PLT)
-	b	PIC_SYM(longjmp, PLT)
+	beq	_longjmp
+	b	longjmp
 END(siglongjmp)
diff --git a/libc/arch-arm/include/machine/asm.h b/libc/arch-arm/include/machine/asm.h
index 7954f05..70dbe67 100644
--- a/libc/arch-arm/include/machine/asm.h
+++ b/libc/arch-arm/include/machine/asm.h
@@ -38,9 +38,7 @@
 #ifndef _ARM32_ASM_H_
 #define _ARM32_ASM_H_
 
-#ifndef _ALIGN_TEXT
-# define _ALIGN_TEXT .align 0
-#endif
+#define __bionic_asm_align 0
 
 #undef __bionic_asm_custom_entry
 #undef __bionic_asm_custom_end
@@ -50,10 +48,4 @@
 #undef __bionic_asm_function_type
 #define __bionic_asm_function_type #function
 
-#if defined(__ELF__) && defined(PIC)
-#define PIC_SYM(x,y) x ## ( ## y ## )
-#else
-#define PIC_SYM(x,y) x
-#endif
-
 #endif /* !_ARM_ASM_H_ */
diff --git a/libc/arch-arm/syscalls/__accept4.S b/libc/arch-arm/syscalls/__accept4.S
index 9a6874b..2b1eb28 100644
--- a/libc/arch-arm/syscalls/__accept4.S
+++ b/libc/arch-arm/syscalls/__accept4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__accept4)
     mov     ip, r7
     ldr     r7, =__NR_accept4
diff --git a/libc/arch-arm/syscalls/__brk.S b/libc/arch-arm/syscalls/__brk.S
index 31de0d2..0987f0e 100644
--- a/libc/arch-arm/syscalls/__brk.S
+++ b/libc/arch-arm/syscalls/__brk.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__brk)
     mov     ip, r7
     ldr     r7, =__NR_brk
diff --git a/libc/arch-arm/syscalls/__connect.S b/libc/arch-arm/syscalls/__connect.S
index 8cb026c..510af95 100644
--- a/libc/arch-arm/syscalls/__connect.S
+++ b/libc/arch-arm/syscalls/__connect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__connect)
     mov     ip, r7
     ldr     r7, =__NR_connect
diff --git a/libc/arch-arm/syscalls/__epoll_pwait.S b/libc/arch-arm/syscalls/__epoll_pwait.S
index b2d8d48..bbba2e1 100644
--- a/libc/arch-arm/syscalls/__epoll_pwait.S
+++ b/libc/arch-arm/syscalls/__epoll_pwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__epoll_pwait)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/__exit.S b/libc/arch-arm/syscalls/__exit.S
index c534bb0..ceef94e 100644
--- a/libc/arch-arm/syscalls/__exit.S
+++ b/libc/arch-arm/syscalls/__exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__exit)
     mov     ip, r7
     ldr     r7, =__NR_exit
diff --git a/libc/arch-arm/syscalls/__fcntl64.S b/libc/arch-arm/syscalls/__fcntl64.S
index 2132cb7..bb2068d 100644
--- a/libc/arch-arm/syscalls/__fcntl64.S
+++ b/libc/arch-arm/syscalls/__fcntl64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__fcntl64)
     mov     ip, r7
     ldr     r7, =__NR_fcntl64
diff --git a/libc/arch-arm/syscalls/__fstatfs64.S b/libc/arch-arm/syscalls/__fstatfs64.S
index 18942bc..b493aa0 100644
--- a/libc/arch-arm/syscalls/__fstatfs64.S
+++ b/libc/arch-arm/syscalls/__fstatfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__fstatfs64)
     mov     ip, r7
     ldr     r7, =__NR_fstatfs64
diff --git a/libc/arch-arm/syscalls/__getcpu.S b/libc/arch-arm/syscalls/__getcpu.S
index 1aea50a..1b3fc46 100644
--- a/libc/arch-arm/syscalls/__getcpu.S
+++ b/libc/arch-arm/syscalls/__getcpu.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcpu)
     mov     ip, r7
     ldr     r7, =__NR_getcpu
diff --git a/libc/arch-arm/syscalls/__getcwd.S b/libc/arch-arm/syscalls/__getcwd.S
index 1c2ac6c..d91b3ca 100644
--- a/libc/arch-arm/syscalls/__getcwd.S
+++ b/libc/arch-arm/syscalls/__getcwd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcwd)
     mov     ip, r7
     ldr     r7, =__NR_getcwd
diff --git a/libc/arch-arm/syscalls/__getdents64.S b/libc/arch-arm/syscalls/__getdents64.S
index c3d5e5b..7d3d81c 100644
--- a/libc/arch-arm/syscalls/__getdents64.S
+++ b/libc/arch-arm/syscalls/__getdents64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getdents64)
     mov     ip, r7
     ldr     r7, =__NR_getdents64
diff --git a/libc/arch-arm/syscalls/__getpid.S b/libc/arch-arm/syscalls/__getpid.S
index eedc33a..ede0865 100644
--- a/libc/arch-arm/syscalls/__getpid.S
+++ b/libc/arch-arm/syscalls/__getpid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpid)
     mov     ip, r7
     ldr     r7, =__NR_getpid
diff --git a/libc/arch-arm/syscalls/__getpriority.S b/libc/arch-arm/syscalls/__getpriority.S
index 90ccaea..d3a6468 100644
--- a/libc/arch-arm/syscalls/__getpriority.S
+++ b/libc/arch-arm/syscalls/__getpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpriority)
     mov     ip, r7
     ldr     r7, =__NR_getpriority
diff --git a/libc/arch-arm/syscalls/__ioctl.S b/libc/arch-arm/syscalls/__ioctl.S
index 3f816db..b3ac82f 100644
--- a/libc/arch-arm/syscalls/__ioctl.S
+++ b/libc/arch-arm/syscalls/__ioctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ioctl)
     mov     ip, r7
     ldr     r7, =__NR_ioctl
diff --git a/libc/arch-arm/syscalls/__llseek.S b/libc/arch-arm/syscalls/__llseek.S
index ec307d2..b36164c 100644
--- a/libc/arch-arm/syscalls/__llseek.S
+++ b/libc/arch-arm/syscalls/__llseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__llseek)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/__mmap2.S b/libc/arch-arm/syscalls/__mmap2.S
index 8a17997..ba74716 100644
--- a/libc/arch-arm/syscalls/__mmap2.S
+++ b/libc/arch-arm/syscalls/__mmap2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__mmap2)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/__openat.S b/libc/arch-arm/syscalls/__openat.S
index 7a38dc3..6b119e1 100644
--- a/libc/arch-arm/syscalls/__openat.S
+++ b/libc/arch-arm/syscalls/__openat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__openat)
     mov     ip, r7
     ldr     r7, =__NR_openat
diff --git a/libc/arch-arm/syscalls/__ppoll.S b/libc/arch-arm/syscalls/__ppoll.S
index d9fb3d9..3a0e80c 100644
--- a/libc/arch-arm/syscalls/__ppoll.S
+++ b/libc/arch-arm/syscalls/__ppoll.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ppoll)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/__pselect6.S b/libc/arch-arm/syscalls/__pselect6.S
index 05fea54..1417be8 100644
--- a/libc/arch-arm/syscalls/__pselect6.S
+++ b/libc/arch-arm/syscalls/__pselect6.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__pselect6)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/__ptrace.S b/libc/arch-arm/syscalls/__ptrace.S
index 4e41d9d..bc03232 100644
--- a/libc/arch-arm/syscalls/__ptrace.S
+++ b/libc/arch-arm/syscalls/__ptrace.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ptrace)
     mov     ip, r7
     ldr     r7, =__NR_ptrace
diff --git a/libc/arch-arm/syscalls/__reboot.S b/libc/arch-arm/syscalls/__reboot.S
index 18e29a7..91bbf7c 100644
--- a/libc/arch-arm/syscalls/__reboot.S
+++ b/libc/arch-arm/syscalls/__reboot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__reboot)
     mov     ip, r7
     ldr     r7, =__NR_reboot
diff --git a/libc/arch-arm/syscalls/__rt_sigaction.S b/libc/arch-arm/syscalls/__rt_sigaction.S
index 974c0e2..6a5e058 100644
--- a/libc/arch-arm/syscalls/__rt_sigaction.S
+++ b/libc/arch-arm/syscalls/__rt_sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigaction)
     mov     ip, r7
     ldr     r7, =__NR_rt_sigaction
diff --git a/libc/arch-arm/syscalls/__rt_sigpending.S b/libc/arch-arm/syscalls/__rt_sigpending.S
index 4a0f5d7..44da9b2 100644
--- a/libc/arch-arm/syscalls/__rt_sigpending.S
+++ b/libc/arch-arm/syscalls/__rt_sigpending.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigpending)
     mov     ip, r7
     ldr     r7, =__NR_rt_sigpending
diff --git a/libc/arch-arm/syscalls/__rt_sigprocmask.S b/libc/arch-arm/syscalls/__rt_sigprocmask.S
index 19abdc1..81cdb85 100644
--- a/libc/arch-arm/syscalls/__rt_sigprocmask.S
+++ b/libc/arch-arm/syscalls/__rt_sigprocmask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigprocmask)
     mov     ip, r7
     ldr     r7, =__NR_rt_sigprocmask
diff --git a/libc/arch-arm/syscalls/__rt_sigsuspend.S b/libc/arch-arm/syscalls/__rt_sigsuspend.S
index a0af905..a9a3903 100644
--- a/libc/arch-arm/syscalls/__rt_sigsuspend.S
+++ b/libc/arch-arm/syscalls/__rt_sigsuspend.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigsuspend)
     mov     ip, r7
     ldr     r7, =__NR_rt_sigsuspend
diff --git a/libc/arch-arm/syscalls/__rt_sigtimedwait.S b/libc/arch-arm/syscalls/__rt_sigtimedwait.S
index 0ba7ce2..7b78a43 100644
--- a/libc/arch-arm/syscalls/__rt_sigtimedwait.S
+++ b/libc/arch-arm/syscalls/__rt_sigtimedwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigtimedwait)
     mov     ip, r7
     ldr     r7, =__NR_rt_sigtimedwait
diff --git a/libc/arch-arm/syscalls/__sched_getaffinity.S b/libc/arch-arm/syscalls/__sched_getaffinity.S
index e977cfb..a22c55e 100644
--- a/libc/arch-arm/syscalls/__sched_getaffinity.S
+++ b/libc/arch-arm/syscalls/__sched_getaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sched_getaffinity)
     mov     ip, r7
     ldr     r7, =__NR_sched_getaffinity
diff --git a/libc/arch-arm/syscalls/__set_tid_address.S b/libc/arch-arm/syscalls/__set_tid_address.S
index b4b42e7..0838c8b 100644
--- a/libc/arch-arm/syscalls/__set_tid_address.S
+++ b/libc/arch-arm/syscalls/__set_tid_address.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tid_address)
     mov     ip, r7
     ldr     r7, =__NR_set_tid_address
diff --git a/libc/arch-arm/syscalls/__set_tls.S b/libc/arch-arm/syscalls/__set_tls.S
index 94c7cf4..c4c2eb7 100644
--- a/libc/arch-arm/syscalls/__set_tls.S
+++ b/libc/arch-arm/syscalls/__set_tls.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tls)
     mov     ip, r7
     ldr     r7, =__ARM_NR_set_tls
diff --git a/libc/arch-arm/syscalls/__sigaction.S b/libc/arch-arm/syscalls/__sigaction.S
index 7e2e07e..869b4c8 100644
--- a/libc/arch-arm/syscalls/__sigaction.S
+++ b/libc/arch-arm/syscalls/__sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sigaction)
     mov     ip, r7
     ldr     r7, =__NR_sigaction
diff --git a/libc/arch-arm/syscalls/__signalfd4.S b/libc/arch-arm/syscalls/__signalfd4.S
index 712f975..3bcf031 100644
--- a/libc/arch-arm/syscalls/__signalfd4.S
+++ b/libc/arch-arm/syscalls/__signalfd4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__signalfd4)
     mov     ip, r7
     ldr     r7, =__NR_signalfd4
diff --git a/libc/arch-arm/syscalls/__socket.S b/libc/arch-arm/syscalls/__socket.S
index d63028b..a655b5b 100644
--- a/libc/arch-arm/syscalls/__socket.S
+++ b/libc/arch-arm/syscalls/__socket.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__socket)
     mov     ip, r7
     ldr     r7, =__NR_socket
diff --git a/libc/arch-arm/syscalls/__statfs64.S b/libc/arch-arm/syscalls/__statfs64.S
index 2563562..80ea6ce 100644
--- a/libc/arch-arm/syscalls/__statfs64.S
+++ b/libc/arch-arm/syscalls/__statfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__statfs64)
     mov     ip, r7
     ldr     r7, =__NR_statfs64
diff --git a/libc/arch-arm/syscalls/__timer_create.S b/libc/arch-arm/syscalls/__timer_create.S
index 9b75749..75fc347 100644
--- a/libc/arch-arm/syscalls/__timer_create.S
+++ b/libc/arch-arm/syscalls/__timer_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_create)
     mov     ip, r7
     ldr     r7, =__NR_timer_create
diff --git a/libc/arch-arm/syscalls/__timer_delete.S b/libc/arch-arm/syscalls/__timer_delete.S
index db32b3b..ad5ec36 100644
--- a/libc/arch-arm/syscalls/__timer_delete.S
+++ b/libc/arch-arm/syscalls/__timer_delete.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_delete)
     mov     ip, r7
     ldr     r7, =__NR_timer_delete
diff --git a/libc/arch-arm/syscalls/__timer_getoverrun.S b/libc/arch-arm/syscalls/__timer_getoverrun.S
index 5701b12..529712c 100644
--- a/libc/arch-arm/syscalls/__timer_getoverrun.S
+++ b/libc/arch-arm/syscalls/__timer_getoverrun.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_getoverrun)
     mov     ip, r7
     ldr     r7, =__NR_timer_getoverrun
diff --git a/libc/arch-arm/syscalls/__timer_gettime.S b/libc/arch-arm/syscalls/__timer_gettime.S
index e9a4ff9..180da39 100644
--- a/libc/arch-arm/syscalls/__timer_gettime.S
+++ b/libc/arch-arm/syscalls/__timer_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_gettime)
     mov     ip, r7
     ldr     r7, =__NR_timer_gettime
diff --git a/libc/arch-arm/syscalls/__timer_settime.S b/libc/arch-arm/syscalls/__timer_settime.S
index 2f1ab19..e2950dd 100644
--- a/libc/arch-arm/syscalls/__timer_settime.S
+++ b/libc/arch-arm/syscalls/__timer_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_settime)
     mov     ip, r7
     ldr     r7, =__NR_timer_settime
diff --git a/libc/arch-arm/syscalls/__waitid.S b/libc/arch-arm/syscalls/__waitid.S
index e5e1f54..8c6ba66 100644
--- a/libc/arch-arm/syscalls/__waitid.S
+++ b/libc/arch-arm/syscalls/__waitid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__waitid)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/_exit.S b/libc/arch-arm/syscalls/_exit.S
index 581b340..fd072c3 100644
--- a/libc/arch-arm/syscalls/_exit.S
+++ b/libc/arch-arm/syscalls/_exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(_exit)
     mov     ip, r7
     ldr     r7, =__NR_exit_group
diff --git a/libc/arch-arm/syscalls/acct.S b/libc/arch-arm/syscalls/acct.S
index e360c5a..156db48 100644
--- a/libc/arch-arm/syscalls/acct.S
+++ b/libc/arch-arm/syscalls/acct.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(acct)
     mov     ip, r7
     ldr     r7, =__NR_acct
diff --git a/libc/arch-arm/syscalls/bind.S b/libc/arch-arm/syscalls/bind.S
index e07dd77..892c77f 100644
--- a/libc/arch-arm/syscalls/bind.S
+++ b/libc/arch-arm/syscalls/bind.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(bind)
     mov     ip, r7
     ldr     r7, =__NR_bind
diff --git a/libc/arch-arm/syscalls/cacheflush.S b/libc/arch-arm/syscalls/cacheflush.S
index ac2a218..0739c32 100644
--- a/libc/arch-arm/syscalls/cacheflush.S
+++ b/libc/arch-arm/syscalls/cacheflush.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(cacheflush)
     mov     ip, r7
     ldr     r7, =__ARM_NR_cacheflush
diff --git a/libc/arch-arm/syscalls/capget.S b/libc/arch-arm/syscalls/capget.S
index b912830..6fd0f7c 100644
--- a/libc/arch-arm/syscalls/capget.S
+++ b/libc/arch-arm/syscalls/capget.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capget)
     mov     ip, r7
     ldr     r7, =__NR_capget
diff --git a/libc/arch-arm/syscalls/capset.S b/libc/arch-arm/syscalls/capset.S
index cef68c5..2708ff6 100644
--- a/libc/arch-arm/syscalls/capset.S
+++ b/libc/arch-arm/syscalls/capset.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capset)
     mov     ip, r7
     ldr     r7, =__NR_capset
diff --git a/libc/arch-arm/syscalls/chdir.S b/libc/arch-arm/syscalls/chdir.S
index ea93fd6..0b86a0f 100644
--- a/libc/arch-arm/syscalls/chdir.S
+++ b/libc/arch-arm/syscalls/chdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chdir)
     mov     ip, r7
     ldr     r7, =__NR_chdir
diff --git a/libc/arch-arm/syscalls/chroot.S b/libc/arch-arm/syscalls/chroot.S
index b1199e6..15aa392 100644
--- a/libc/arch-arm/syscalls/chroot.S
+++ b/libc/arch-arm/syscalls/chroot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chroot)
     mov     ip, r7
     ldr     r7, =__NR_chroot
diff --git a/libc/arch-arm/syscalls/clock_getres.S b/libc/arch-arm/syscalls/clock_getres.S
index f1e7fa2..b92289a 100644
--- a/libc/arch-arm/syscalls/clock_getres.S
+++ b/libc/arch-arm/syscalls/clock_getres.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_getres)
     mov     ip, r7
     ldr     r7, =__NR_clock_getres
diff --git a/libc/arch-arm/syscalls/clock_gettime.S b/libc/arch-arm/syscalls/clock_gettime.S
index 9b3e132..203db8f 100644
--- a/libc/arch-arm/syscalls/clock_gettime.S
+++ b/libc/arch-arm/syscalls/clock_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_gettime)
     mov     ip, r7
     ldr     r7, =__NR_clock_gettime
diff --git a/libc/arch-arm/syscalls/clock_nanosleep.S b/libc/arch-arm/syscalls/clock_nanosleep.S
index fda7394..5de2267 100644
--- a/libc/arch-arm/syscalls/clock_nanosleep.S
+++ b/libc/arch-arm/syscalls/clock_nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_nanosleep)
     mov     ip, r7
     ldr     r7, =__NR_clock_nanosleep
diff --git a/libc/arch-arm/syscalls/clock_settime.S b/libc/arch-arm/syscalls/clock_settime.S
index 5a0059e..71e61f8 100644
--- a/libc/arch-arm/syscalls/clock_settime.S
+++ b/libc/arch-arm/syscalls/clock_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_settime)
     mov     ip, r7
     ldr     r7, =__NR_clock_settime
diff --git a/libc/arch-arm/syscalls/close.S b/libc/arch-arm/syscalls/close.S
index 00c8f85..3e0fd32 100644
--- a/libc/arch-arm/syscalls/close.S
+++ b/libc/arch-arm/syscalls/close.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(close)
     mov     ip, r7
     ldr     r7, =__NR_close
diff --git a/libc/arch-arm/syscalls/delete_module.S b/libc/arch-arm/syscalls/delete_module.S
index a26b478..0af2520 100644
--- a/libc/arch-arm/syscalls/delete_module.S
+++ b/libc/arch-arm/syscalls/delete_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(delete_module)
     mov     ip, r7
     ldr     r7, =__NR_delete_module
diff --git a/libc/arch-arm/syscalls/dup.S b/libc/arch-arm/syscalls/dup.S
index b1859d9..4105438 100644
--- a/libc/arch-arm/syscalls/dup.S
+++ b/libc/arch-arm/syscalls/dup.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup)
     mov     ip, r7
     ldr     r7, =__NR_dup
diff --git a/libc/arch-arm/syscalls/dup3.S b/libc/arch-arm/syscalls/dup3.S
index 3e47c10..409e8f9 100644
--- a/libc/arch-arm/syscalls/dup3.S
+++ b/libc/arch-arm/syscalls/dup3.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup3)
     mov     ip, r7
     ldr     r7, =__NR_dup3
diff --git a/libc/arch-arm/syscalls/epoll_create1.S b/libc/arch-arm/syscalls/epoll_create1.S
index 2eebc0c..631afab 100644
--- a/libc/arch-arm/syscalls/epoll_create1.S
+++ b/libc/arch-arm/syscalls/epoll_create1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_create1)
     mov     ip, r7
     ldr     r7, =__NR_epoll_create1
diff --git a/libc/arch-arm/syscalls/epoll_ctl.S b/libc/arch-arm/syscalls/epoll_ctl.S
index 7a1cc41..187fe0a 100644
--- a/libc/arch-arm/syscalls/epoll_ctl.S
+++ b/libc/arch-arm/syscalls/epoll_ctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_ctl)
     mov     ip, r7
     ldr     r7, =__NR_epoll_ctl
diff --git a/libc/arch-arm/syscalls/eventfd.S b/libc/arch-arm/syscalls/eventfd.S
index 08272d3..c35f537 100644
--- a/libc/arch-arm/syscalls/eventfd.S
+++ b/libc/arch-arm/syscalls/eventfd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(eventfd)
     mov     ip, r7
     ldr     r7, =__NR_eventfd2
diff --git a/libc/arch-arm/syscalls/execve.S b/libc/arch-arm/syscalls/execve.S
index 361ec63..1b24f76 100644
--- a/libc/arch-arm/syscalls/execve.S
+++ b/libc/arch-arm/syscalls/execve.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(execve)
     mov     ip, r7
     ldr     r7, =__NR_execve
diff --git a/libc/arch-arm/syscalls/faccessat.S b/libc/arch-arm/syscalls/faccessat.S
index c82b2ce..3f663e3 100644
--- a/libc/arch-arm/syscalls/faccessat.S
+++ b/libc/arch-arm/syscalls/faccessat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(faccessat)
     mov     ip, r7
     ldr     r7, =__NR_faccessat
diff --git a/libc/arch-arm/syscalls/fallocate64.S b/libc/arch-arm/syscalls/fallocate64.S
index c6992b0..fd90637 100644
--- a/libc/arch-arm/syscalls/fallocate64.S
+++ b/libc/arch-arm/syscalls/fallocate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fallocate64)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/fchdir.S b/libc/arch-arm/syscalls/fchdir.S
index 1a7eb51..c109718 100644
--- a/libc/arch-arm/syscalls/fchdir.S
+++ b/libc/arch-arm/syscalls/fchdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchdir)
     mov     ip, r7
     ldr     r7, =__NR_fchdir
diff --git a/libc/arch-arm/syscalls/fchmod.S b/libc/arch-arm/syscalls/fchmod.S
index 42dc5b8..4b598a2 100644
--- a/libc/arch-arm/syscalls/fchmod.S
+++ b/libc/arch-arm/syscalls/fchmod.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmod)
     mov     ip, r7
     ldr     r7, =__NR_fchmod
diff --git a/libc/arch-arm/syscalls/fchmodat.S b/libc/arch-arm/syscalls/fchmodat.S
index e03da8c..8e43118 100644
--- a/libc/arch-arm/syscalls/fchmodat.S
+++ b/libc/arch-arm/syscalls/fchmodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmodat)
     mov     ip, r7
     ldr     r7, =__NR_fchmodat
diff --git a/libc/arch-arm/syscalls/fchown.S b/libc/arch-arm/syscalls/fchown.S
index c2c3982..24a38f6 100644
--- a/libc/arch-arm/syscalls/fchown.S
+++ b/libc/arch-arm/syscalls/fchown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchown)
     mov     ip, r7
     ldr     r7, =__NR_fchown32
diff --git a/libc/arch-arm/syscalls/fchownat.S b/libc/arch-arm/syscalls/fchownat.S
index ea8193f..8fd76a3 100644
--- a/libc/arch-arm/syscalls/fchownat.S
+++ b/libc/arch-arm/syscalls/fchownat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchownat)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/fdatasync.S b/libc/arch-arm/syscalls/fdatasync.S
index 9c8317d..9556665 100644
--- a/libc/arch-arm/syscalls/fdatasync.S
+++ b/libc/arch-arm/syscalls/fdatasync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fdatasync)
     mov     ip, r7
     ldr     r7, =__NR_fdatasync
diff --git a/libc/arch-arm/syscalls/fgetxattr.S b/libc/arch-arm/syscalls/fgetxattr.S
index bef536b..95e2809 100644
--- a/libc/arch-arm/syscalls/fgetxattr.S
+++ b/libc/arch-arm/syscalls/fgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fgetxattr)
     mov     ip, r7
     ldr     r7, =__NR_fgetxattr
diff --git a/libc/arch-arm/syscalls/flistxattr.S b/libc/arch-arm/syscalls/flistxattr.S
index d9a30bb..0d411b1 100644
--- a/libc/arch-arm/syscalls/flistxattr.S
+++ b/libc/arch-arm/syscalls/flistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flistxattr)
     mov     ip, r7
     ldr     r7, =__NR_flistxattr
diff --git a/libc/arch-arm/syscalls/flock.S b/libc/arch-arm/syscalls/flock.S
index 016e824..e59d4f6 100644
--- a/libc/arch-arm/syscalls/flock.S
+++ b/libc/arch-arm/syscalls/flock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flock)
     mov     ip, r7
     ldr     r7, =__NR_flock
diff --git a/libc/arch-arm/syscalls/fremovexattr.S b/libc/arch-arm/syscalls/fremovexattr.S
index c7ff034..3ec647f 100644
--- a/libc/arch-arm/syscalls/fremovexattr.S
+++ b/libc/arch-arm/syscalls/fremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fremovexattr)
     mov     ip, r7
     ldr     r7, =__NR_fremovexattr
diff --git a/libc/arch-arm/syscalls/fsetxattr.S b/libc/arch-arm/syscalls/fsetxattr.S
index 64b8d03..225e64b 100644
--- a/libc/arch-arm/syscalls/fsetxattr.S
+++ b/libc/arch-arm/syscalls/fsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsetxattr)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/fstat64.S b/libc/arch-arm/syscalls/fstat64.S
index 7517a65..560bb94 100644
--- a/libc/arch-arm/syscalls/fstat64.S
+++ b/libc/arch-arm/syscalls/fstat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstat64)
     mov     ip, r7
     ldr     r7, =__NR_fstat64
diff --git a/libc/arch-arm/syscalls/fstatat64.S b/libc/arch-arm/syscalls/fstatat64.S
index 752ee2f..cda5845 100644
--- a/libc/arch-arm/syscalls/fstatat64.S
+++ b/libc/arch-arm/syscalls/fstatat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatat64)
     mov     ip, r7
     ldr     r7, =__NR_fstatat64
diff --git a/libc/arch-arm/syscalls/fsync.S b/libc/arch-arm/syscalls/fsync.S
index 6b7c4a8..c6ba47b 100644
--- a/libc/arch-arm/syscalls/fsync.S
+++ b/libc/arch-arm/syscalls/fsync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsync)
     mov     ip, r7
     ldr     r7, =__NR_fsync
diff --git a/libc/arch-arm/syscalls/ftruncate.S b/libc/arch-arm/syscalls/ftruncate.S
index 4a3d56c..168d722 100644
--- a/libc/arch-arm/syscalls/ftruncate.S
+++ b/libc/arch-arm/syscalls/ftruncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate)
     mov     ip, r7
     ldr     r7, =__NR_ftruncate
diff --git a/libc/arch-arm/syscalls/ftruncate64.S b/libc/arch-arm/syscalls/ftruncate64.S
index 910ca68..a2b73b8 100644
--- a/libc/arch-arm/syscalls/ftruncate64.S
+++ b/libc/arch-arm/syscalls/ftruncate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate64)
     mov     ip, r7
     ldr     r7, =__NR_ftruncate64
diff --git a/libc/arch-arm/syscalls/getegid.S b/libc/arch-arm/syscalls/getegid.S
index 6afca90..e2f9fe9 100644
--- a/libc/arch-arm/syscalls/getegid.S
+++ b/libc/arch-arm/syscalls/getegid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getegid)
     mov     ip, r7
     ldr     r7, =__NR_getegid32
diff --git a/libc/arch-arm/syscalls/geteuid.S b/libc/arch-arm/syscalls/geteuid.S
index 78e5cf4..1d55320 100644
--- a/libc/arch-arm/syscalls/geteuid.S
+++ b/libc/arch-arm/syscalls/geteuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(geteuid)
     mov     ip, r7
     ldr     r7, =__NR_geteuid32
diff --git a/libc/arch-arm/syscalls/getgid.S b/libc/arch-arm/syscalls/getgid.S
index c2d3538..9d81d73 100644
--- a/libc/arch-arm/syscalls/getgid.S
+++ b/libc/arch-arm/syscalls/getgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgid)
     mov     ip, r7
     ldr     r7, =__NR_getgid32
diff --git a/libc/arch-arm/syscalls/getgroups.S b/libc/arch-arm/syscalls/getgroups.S
index e6b8e10..23aafaf 100644
--- a/libc/arch-arm/syscalls/getgroups.S
+++ b/libc/arch-arm/syscalls/getgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgroups)
     mov     ip, r7
     ldr     r7, =__NR_getgroups32
diff --git a/libc/arch-arm/syscalls/getitimer.S b/libc/arch-arm/syscalls/getitimer.S
index 3dce707..095cf8f 100644
--- a/libc/arch-arm/syscalls/getitimer.S
+++ b/libc/arch-arm/syscalls/getitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getitimer)
     mov     ip, r7
     ldr     r7, =__NR_getitimer
diff --git a/libc/arch-arm/syscalls/getpeername.S b/libc/arch-arm/syscalls/getpeername.S
index 0613231..760f6fb 100644
--- a/libc/arch-arm/syscalls/getpeername.S
+++ b/libc/arch-arm/syscalls/getpeername.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpeername)
     mov     ip, r7
     ldr     r7, =__NR_getpeername
diff --git a/libc/arch-arm/syscalls/getpgid.S b/libc/arch-arm/syscalls/getpgid.S
index 1992afc..d07b058 100644
--- a/libc/arch-arm/syscalls/getpgid.S
+++ b/libc/arch-arm/syscalls/getpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpgid)
     mov     ip, r7
     ldr     r7, =__NR_getpgid
diff --git a/libc/arch-arm/syscalls/getppid.S b/libc/arch-arm/syscalls/getppid.S
index 594fca5..bcc13a8 100644
--- a/libc/arch-arm/syscalls/getppid.S
+++ b/libc/arch-arm/syscalls/getppid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getppid)
     mov     ip, r7
     ldr     r7, =__NR_getppid
diff --git a/libc/arch-arm/syscalls/getresgid.S b/libc/arch-arm/syscalls/getresgid.S
index 9dcdb33..9a87eaa 100644
--- a/libc/arch-arm/syscalls/getresgid.S
+++ b/libc/arch-arm/syscalls/getresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresgid)
     mov     ip, r7
     ldr     r7, =__NR_getresgid32
diff --git a/libc/arch-arm/syscalls/getresuid.S b/libc/arch-arm/syscalls/getresuid.S
index 387bd7c..a332928 100644
--- a/libc/arch-arm/syscalls/getresuid.S
+++ b/libc/arch-arm/syscalls/getresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresuid)
     mov     ip, r7
     ldr     r7, =__NR_getresuid32
diff --git a/libc/arch-arm/syscalls/getrlimit.S b/libc/arch-arm/syscalls/getrlimit.S
index 879b666..4a9c62a 100644
--- a/libc/arch-arm/syscalls/getrlimit.S
+++ b/libc/arch-arm/syscalls/getrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrlimit)
     mov     ip, r7
     ldr     r7, =__NR_ugetrlimit
diff --git a/libc/arch-arm/syscalls/getrusage.S b/libc/arch-arm/syscalls/getrusage.S
index ee84f49..4799b69 100644
--- a/libc/arch-arm/syscalls/getrusage.S
+++ b/libc/arch-arm/syscalls/getrusage.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrusage)
     mov     ip, r7
     ldr     r7, =__NR_getrusage
diff --git a/libc/arch-arm/syscalls/getsid.S b/libc/arch-arm/syscalls/getsid.S
index 715f217..5a26e94 100644
--- a/libc/arch-arm/syscalls/getsid.S
+++ b/libc/arch-arm/syscalls/getsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsid)
     mov     ip, r7
     ldr     r7, =__NR_getsid
diff --git a/libc/arch-arm/syscalls/getsockname.S b/libc/arch-arm/syscalls/getsockname.S
index 2ee68f3..78e0752 100644
--- a/libc/arch-arm/syscalls/getsockname.S
+++ b/libc/arch-arm/syscalls/getsockname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockname)
     mov     ip, r7
     ldr     r7, =__NR_getsockname
diff --git a/libc/arch-arm/syscalls/getsockopt.S b/libc/arch-arm/syscalls/getsockopt.S
index 2ded34f..e1badfb 100644
--- a/libc/arch-arm/syscalls/getsockopt.S
+++ b/libc/arch-arm/syscalls/getsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockopt)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/gettimeofday.S b/libc/arch-arm/syscalls/gettimeofday.S
index 4d33b5d..611c0d4 100644
--- a/libc/arch-arm/syscalls/gettimeofday.S
+++ b/libc/arch-arm/syscalls/gettimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(gettimeofday)
     mov     ip, r7
     ldr     r7, =__NR_gettimeofday
diff --git a/libc/arch-arm/syscalls/getuid.S b/libc/arch-arm/syscalls/getuid.S
index 66f570f..2e97c55 100644
--- a/libc/arch-arm/syscalls/getuid.S
+++ b/libc/arch-arm/syscalls/getuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getuid)
     mov     ip, r7
     ldr     r7, =__NR_getuid32
diff --git a/libc/arch-arm/syscalls/getxattr.S b/libc/arch-arm/syscalls/getxattr.S
index 71d0035..da0e86d 100644
--- a/libc/arch-arm/syscalls/getxattr.S
+++ b/libc/arch-arm/syscalls/getxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getxattr)
     mov     ip, r7
     ldr     r7, =__NR_getxattr
diff --git a/libc/arch-arm/syscalls/init_module.S b/libc/arch-arm/syscalls/init_module.S
index 6850ddf..bf30b03 100644
--- a/libc/arch-arm/syscalls/init_module.S
+++ b/libc/arch-arm/syscalls/init_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(init_module)
     mov     ip, r7
     ldr     r7, =__NR_init_module
diff --git a/libc/arch-arm/syscalls/inotify_add_watch.S b/libc/arch-arm/syscalls/inotify_add_watch.S
index 367a49f..982d338 100644
--- a/libc/arch-arm/syscalls/inotify_add_watch.S
+++ b/libc/arch-arm/syscalls/inotify_add_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_add_watch)
     mov     ip, r7
     ldr     r7, =__NR_inotify_add_watch
diff --git a/libc/arch-arm/syscalls/inotify_init1.S b/libc/arch-arm/syscalls/inotify_init1.S
index 13e175f..2253ec8 100644
--- a/libc/arch-arm/syscalls/inotify_init1.S
+++ b/libc/arch-arm/syscalls/inotify_init1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_init1)
     mov     ip, r7
     ldr     r7, =__NR_inotify_init1
diff --git a/libc/arch-arm/syscalls/inotify_rm_watch.S b/libc/arch-arm/syscalls/inotify_rm_watch.S
index b80e0f8..9d7e6ae 100644
--- a/libc/arch-arm/syscalls/inotify_rm_watch.S
+++ b/libc/arch-arm/syscalls/inotify_rm_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_rm_watch)
     mov     ip, r7
     ldr     r7, =__NR_inotify_rm_watch
diff --git a/libc/arch-arm/syscalls/kill.S b/libc/arch-arm/syscalls/kill.S
index 9a44208..7e4d6c4 100644
--- a/libc/arch-arm/syscalls/kill.S
+++ b/libc/arch-arm/syscalls/kill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(kill)
     mov     ip, r7
     ldr     r7, =__NR_kill
diff --git a/libc/arch-arm/syscalls/klogctl.S b/libc/arch-arm/syscalls/klogctl.S
index 84ce7f6..f5fe27f 100644
--- a/libc/arch-arm/syscalls/klogctl.S
+++ b/libc/arch-arm/syscalls/klogctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(klogctl)
     mov     ip, r7
     ldr     r7, =__NR_syslog
diff --git a/libc/arch-arm/syscalls/lgetxattr.S b/libc/arch-arm/syscalls/lgetxattr.S
index 9eed67f..70b7235 100644
--- a/libc/arch-arm/syscalls/lgetxattr.S
+++ b/libc/arch-arm/syscalls/lgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lgetxattr)
     mov     ip, r7
     ldr     r7, =__NR_lgetxattr
diff --git a/libc/arch-arm/syscalls/linkat.S b/libc/arch-arm/syscalls/linkat.S
index 27f1e00..7a578f8 100644
--- a/libc/arch-arm/syscalls/linkat.S
+++ b/libc/arch-arm/syscalls/linkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(linkat)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/listen.S b/libc/arch-arm/syscalls/listen.S
index 330ea56..5c33912 100644
--- a/libc/arch-arm/syscalls/listen.S
+++ b/libc/arch-arm/syscalls/listen.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listen)
     mov     ip, r7
     ldr     r7, =__NR_listen
diff --git a/libc/arch-arm/syscalls/listxattr.S b/libc/arch-arm/syscalls/listxattr.S
index c64e484..ea8f5d8 100644
--- a/libc/arch-arm/syscalls/listxattr.S
+++ b/libc/arch-arm/syscalls/listxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listxattr)
     mov     ip, r7
     ldr     r7, =__NR_listxattr
diff --git a/libc/arch-arm/syscalls/llistxattr.S b/libc/arch-arm/syscalls/llistxattr.S
index cea926b..b7f3375 100644
--- a/libc/arch-arm/syscalls/llistxattr.S
+++ b/libc/arch-arm/syscalls/llistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(llistxattr)
     mov     ip, r7
     ldr     r7, =__NR_llistxattr
diff --git a/libc/arch-arm/syscalls/lremovexattr.S b/libc/arch-arm/syscalls/lremovexattr.S
index c7a6458..a8d0d2d 100644
--- a/libc/arch-arm/syscalls/lremovexattr.S
+++ b/libc/arch-arm/syscalls/lremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lremovexattr)
     mov     ip, r7
     ldr     r7, =__NR_lremovexattr
diff --git a/libc/arch-arm/syscalls/lseek.S b/libc/arch-arm/syscalls/lseek.S
index 9edae37..17697d4 100644
--- a/libc/arch-arm/syscalls/lseek.S
+++ b/libc/arch-arm/syscalls/lseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lseek)
     mov     ip, r7
     ldr     r7, =__NR_lseek
diff --git a/libc/arch-arm/syscalls/lsetxattr.S b/libc/arch-arm/syscalls/lsetxattr.S
index fb3f75f..166ef7f 100644
--- a/libc/arch-arm/syscalls/lsetxattr.S
+++ b/libc/arch-arm/syscalls/lsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lsetxattr)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/madvise.S b/libc/arch-arm/syscalls/madvise.S
index ee2c2a5..ffa71c4 100644
--- a/libc/arch-arm/syscalls/madvise.S
+++ b/libc/arch-arm/syscalls/madvise.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(madvise)
     mov     ip, r7
     ldr     r7, =__NR_madvise
diff --git a/libc/arch-arm/syscalls/mincore.S b/libc/arch-arm/syscalls/mincore.S
index 9ef9237..5eb5f10 100644
--- a/libc/arch-arm/syscalls/mincore.S
+++ b/libc/arch-arm/syscalls/mincore.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mincore)
     mov     ip, r7
     ldr     r7, =__NR_mincore
diff --git a/libc/arch-arm/syscalls/mkdirat.S b/libc/arch-arm/syscalls/mkdirat.S
index 9e77ef0..d9c58ad 100644
--- a/libc/arch-arm/syscalls/mkdirat.S
+++ b/libc/arch-arm/syscalls/mkdirat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mkdirat)
     mov     ip, r7
     ldr     r7, =__NR_mkdirat
diff --git a/libc/arch-arm/syscalls/mknodat.S b/libc/arch-arm/syscalls/mknodat.S
index de492da..d6296f1 100644
--- a/libc/arch-arm/syscalls/mknodat.S
+++ b/libc/arch-arm/syscalls/mknodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mknodat)
     mov     ip, r7
     ldr     r7, =__NR_mknodat
diff --git a/libc/arch-arm/syscalls/mlock.S b/libc/arch-arm/syscalls/mlock.S
index 043b21b..21fd5f9 100644
--- a/libc/arch-arm/syscalls/mlock.S
+++ b/libc/arch-arm/syscalls/mlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlock)
     mov     ip, r7
     ldr     r7, =__NR_mlock
diff --git a/libc/arch-arm/syscalls/mlockall.S b/libc/arch-arm/syscalls/mlockall.S
index 9c6c4e4..750b7ec 100644
--- a/libc/arch-arm/syscalls/mlockall.S
+++ b/libc/arch-arm/syscalls/mlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlockall)
     mov     ip, r7
     ldr     r7, =__NR_mlockall
diff --git a/libc/arch-arm/syscalls/mount.S b/libc/arch-arm/syscalls/mount.S
index d56682c..d2fa20e 100644
--- a/libc/arch-arm/syscalls/mount.S
+++ b/libc/arch-arm/syscalls/mount.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mount)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/mprotect.S b/libc/arch-arm/syscalls/mprotect.S
index 9461d9b..dfc6f08 100644
--- a/libc/arch-arm/syscalls/mprotect.S
+++ b/libc/arch-arm/syscalls/mprotect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mprotect)
     mov     ip, r7
     ldr     r7, =__NR_mprotect
diff --git a/libc/arch-arm/syscalls/mremap.S b/libc/arch-arm/syscalls/mremap.S
index 2486fc9..a674571 100644
--- a/libc/arch-arm/syscalls/mremap.S
+++ b/libc/arch-arm/syscalls/mremap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mremap)
     mov     ip, r7
     ldr     r7, =__NR_mremap
diff --git a/libc/arch-arm/syscalls/msync.S b/libc/arch-arm/syscalls/msync.S
index 3fc4118..e062a5e 100644
--- a/libc/arch-arm/syscalls/msync.S
+++ b/libc/arch-arm/syscalls/msync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(msync)
     mov     ip, r7
     ldr     r7, =__NR_msync
diff --git a/libc/arch-arm/syscalls/munlock.S b/libc/arch-arm/syscalls/munlock.S
index c89fd3c..c44d147 100644
--- a/libc/arch-arm/syscalls/munlock.S
+++ b/libc/arch-arm/syscalls/munlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlock)
     mov     ip, r7
     ldr     r7, =__NR_munlock
diff --git a/libc/arch-arm/syscalls/munlockall.S b/libc/arch-arm/syscalls/munlockall.S
index 3ac9f32..3a36b7e 100644
--- a/libc/arch-arm/syscalls/munlockall.S
+++ b/libc/arch-arm/syscalls/munlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlockall)
     mov     ip, r7
     ldr     r7, =__NR_munlockall
diff --git a/libc/arch-arm/syscalls/munmap.S b/libc/arch-arm/syscalls/munmap.S
index ed3bb1e..a94e4e5 100644
--- a/libc/arch-arm/syscalls/munmap.S
+++ b/libc/arch-arm/syscalls/munmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munmap)
     mov     ip, r7
     ldr     r7, =__NR_munmap
diff --git a/libc/arch-arm/syscalls/nanosleep.S b/libc/arch-arm/syscalls/nanosleep.S
index 695c126..743adc2 100644
--- a/libc/arch-arm/syscalls/nanosleep.S
+++ b/libc/arch-arm/syscalls/nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(nanosleep)
     mov     ip, r7
     ldr     r7, =__NR_nanosleep
diff --git a/libc/arch-arm/syscalls/personality.S b/libc/arch-arm/syscalls/personality.S
index e3f7371..90dfe22 100644
--- a/libc/arch-arm/syscalls/personality.S
+++ b/libc/arch-arm/syscalls/personality.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(personality)
     mov     ip, r7
     ldr     r7, =__NR_personality
diff --git a/libc/arch-arm/syscalls/pipe2.S b/libc/arch-arm/syscalls/pipe2.S
index 420dee9..b295df5 100644
--- a/libc/arch-arm/syscalls/pipe2.S
+++ b/libc/arch-arm/syscalls/pipe2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pipe2)
     mov     ip, r7
     ldr     r7, =__NR_pipe2
diff --git a/libc/arch-arm/syscalls/prctl.S b/libc/arch-arm/syscalls/prctl.S
index 615a2fa..c8f68d3 100644
--- a/libc/arch-arm/syscalls/prctl.S
+++ b/libc/arch-arm/syscalls/prctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prctl)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/pread64.S b/libc/arch-arm/syscalls/pread64.S
index 0bfb6d0..3eeae3d 100644
--- a/libc/arch-arm/syscalls/pread64.S
+++ b/libc/arch-arm/syscalls/pread64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pread64)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/prlimit64.S b/libc/arch-arm/syscalls/prlimit64.S
index 8d9c4ff..87c53d5 100644
--- a/libc/arch-arm/syscalls/prlimit64.S
+++ b/libc/arch-arm/syscalls/prlimit64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prlimit64)
     mov     ip, r7
     ldr     r7, =__NR_prlimit64
diff --git a/libc/arch-arm/syscalls/pwrite64.S b/libc/arch-arm/syscalls/pwrite64.S
index 03247b1..c63b835 100644
--- a/libc/arch-arm/syscalls/pwrite64.S
+++ b/libc/arch-arm/syscalls/pwrite64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pwrite64)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/read.S b/libc/arch-arm/syscalls/read.S
index b01daf5..9de525c 100644
--- a/libc/arch-arm/syscalls/read.S
+++ b/libc/arch-arm/syscalls/read.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(read)
     mov     ip, r7
     ldr     r7, =__NR_read
diff --git a/libc/arch-arm/syscalls/readahead.S b/libc/arch-arm/syscalls/readahead.S
index 83d8442..995f00e 100644
--- a/libc/arch-arm/syscalls/readahead.S
+++ b/libc/arch-arm/syscalls/readahead.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readahead)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/readlinkat.S b/libc/arch-arm/syscalls/readlinkat.S
index 28926ab..f865de5 100644
--- a/libc/arch-arm/syscalls/readlinkat.S
+++ b/libc/arch-arm/syscalls/readlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readlinkat)
     mov     ip, r7
     ldr     r7, =__NR_readlinkat
diff --git a/libc/arch-arm/syscalls/readv.S b/libc/arch-arm/syscalls/readv.S
index 433d33d..9401687 100644
--- a/libc/arch-arm/syscalls/readv.S
+++ b/libc/arch-arm/syscalls/readv.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readv)
     mov     ip, r7
     ldr     r7, =__NR_readv
diff --git a/libc/arch-arm/syscalls/recvfrom.S b/libc/arch-arm/syscalls/recvfrom.S
index cb89f72..6390a82 100644
--- a/libc/arch-arm/syscalls/recvfrom.S
+++ b/libc/arch-arm/syscalls/recvfrom.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvfrom)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/recvmmsg.S b/libc/arch-arm/syscalls/recvmmsg.S
index dd8cd8c..067ed1e 100644
--- a/libc/arch-arm/syscalls/recvmmsg.S
+++ b/libc/arch-arm/syscalls/recvmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmmsg)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/recvmsg.S b/libc/arch-arm/syscalls/recvmsg.S
index 47e82a7..f688481 100644
--- a/libc/arch-arm/syscalls/recvmsg.S
+++ b/libc/arch-arm/syscalls/recvmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmsg)
     mov     ip, r7
     ldr     r7, =__NR_recvmsg
diff --git a/libc/arch-arm/syscalls/removexattr.S b/libc/arch-arm/syscalls/removexattr.S
index a3fcdfa..59d0e2f 100644
--- a/libc/arch-arm/syscalls/removexattr.S
+++ b/libc/arch-arm/syscalls/removexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(removexattr)
     mov     ip, r7
     ldr     r7, =__NR_removexattr
diff --git a/libc/arch-arm/syscalls/renameat.S b/libc/arch-arm/syscalls/renameat.S
index cea6286..7a4d268 100644
--- a/libc/arch-arm/syscalls/renameat.S
+++ b/libc/arch-arm/syscalls/renameat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(renameat)
     mov     ip, r7
     ldr     r7, =__NR_renameat
diff --git a/libc/arch-arm/syscalls/sched_get_priority_max.S b/libc/arch-arm/syscalls/sched_get_priority_max.S
index c940adc..2aafafc 100644
--- a/libc/arch-arm/syscalls/sched_get_priority_max.S
+++ b/libc/arch-arm/syscalls/sched_get_priority_max.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_max)
     mov     ip, r7
     ldr     r7, =__NR_sched_get_priority_max
diff --git a/libc/arch-arm/syscalls/sched_get_priority_min.S b/libc/arch-arm/syscalls/sched_get_priority_min.S
index 39faede..40e14ef 100644
--- a/libc/arch-arm/syscalls/sched_get_priority_min.S
+++ b/libc/arch-arm/syscalls/sched_get_priority_min.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_min)
     mov     ip, r7
     ldr     r7, =__NR_sched_get_priority_min
diff --git a/libc/arch-arm/syscalls/sched_getparam.S b/libc/arch-arm/syscalls/sched_getparam.S
index 59df104..3d58651 100644
--- a/libc/arch-arm/syscalls/sched_getparam.S
+++ b/libc/arch-arm/syscalls/sched_getparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getparam)
     mov     ip, r7
     ldr     r7, =__NR_sched_getparam
diff --git a/libc/arch-arm/syscalls/sched_getscheduler.S b/libc/arch-arm/syscalls/sched_getscheduler.S
index 953368d..e9478ca 100644
--- a/libc/arch-arm/syscalls/sched_getscheduler.S
+++ b/libc/arch-arm/syscalls/sched_getscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getscheduler)
     mov     ip, r7
     ldr     r7, =__NR_sched_getscheduler
diff --git a/libc/arch-arm/syscalls/sched_rr_get_interval.S b/libc/arch-arm/syscalls/sched_rr_get_interval.S
index 1fa7d15..ed90b73 100644
--- a/libc/arch-arm/syscalls/sched_rr_get_interval.S
+++ b/libc/arch-arm/syscalls/sched_rr_get_interval.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_rr_get_interval)
     mov     ip, r7
     ldr     r7, =__NR_sched_rr_get_interval
diff --git a/libc/arch-arm/syscalls/sched_setaffinity.S b/libc/arch-arm/syscalls/sched_setaffinity.S
index 63bfe4d..d5f72a9 100644
--- a/libc/arch-arm/syscalls/sched_setaffinity.S
+++ b/libc/arch-arm/syscalls/sched_setaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setaffinity)
     mov     ip, r7
     ldr     r7, =__NR_sched_setaffinity
diff --git a/libc/arch-arm/syscalls/sched_setparam.S b/libc/arch-arm/syscalls/sched_setparam.S
index 324f0bb..3ec06c0 100644
--- a/libc/arch-arm/syscalls/sched_setparam.S
+++ b/libc/arch-arm/syscalls/sched_setparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setparam)
     mov     ip, r7
     ldr     r7, =__NR_sched_setparam
diff --git a/libc/arch-arm/syscalls/sched_setscheduler.S b/libc/arch-arm/syscalls/sched_setscheduler.S
index 0ce6b15..0e61ffb 100644
--- a/libc/arch-arm/syscalls/sched_setscheduler.S
+++ b/libc/arch-arm/syscalls/sched_setscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setscheduler)
     mov     ip, r7
     ldr     r7, =__NR_sched_setscheduler
diff --git a/libc/arch-arm/syscalls/sched_yield.S b/libc/arch-arm/syscalls/sched_yield.S
index 8e6d65a..f26297e 100644
--- a/libc/arch-arm/syscalls/sched_yield.S
+++ b/libc/arch-arm/syscalls/sched_yield.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_yield)
     mov     ip, r7
     ldr     r7, =__NR_sched_yield
diff --git a/libc/arch-arm/syscalls/sendfile.S b/libc/arch-arm/syscalls/sendfile.S
index 28b25a3..e4df8ff 100644
--- a/libc/arch-arm/syscalls/sendfile.S
+++ b/libc/arch-arm/syscalls/sendfile.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile)
     mov     ip, r7
     ldr     r7, =__NR_sendfile
diff --git a/libc/arch-arm/syscalls/sendfile64.S b/libc/arch-arm/syscalls/sendfile64.S
index 4a9f245..ab48963 100644
--- a/libc/arch-arm/syscalls/sendfile64.S
+++ b/libc/arch-arm/syscalls/sendfile64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile64)
     mov     ip, r7
     ldr     r7, =__NR_sendfile64
diff --git a/libc/arch-arm/syscalls/sendmmsg.S b/libc/arch-arm/syscalls/sendmmsg.S
index 04c3fe3..998e6c7 100644
--- a/libc/arch-arm/syscalls/sendmmsg.S
+++ b/libc/arch-arm/syscalls/sendmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmmsg)
     mov     ip, r7
     ldr     r7, =__NR_sendmmsg
diff --git a/libc/arch-arm/syscalls/sendmsg.S b/libc/arch-arm/syscalls/sendmsg.S
index 554f307..d25d6b4 100644
--- a/libc/arch-arm/syscalls/sendmsg.S
+++ b/libc/arch-arm/syscalls/sendmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmsg)
     mov     ip, r7
     ldr     r7, =__NR_sendmsg
diff --git a/libc/arch-arm/syscalls/sendto.S b/libc/arch-arm/syscalls/sendto.S
index bd0ec1d..b5e8de9 100644
--- a/libc/arch-arm/syscalls/sendto.S
+++ b/libc/arch-arm/syscalls/sendto.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendto)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/setfsgid.S b/libc/arch-arm/syscalls/setfsgid.S
new file mode 100644
index 0000000..7cdb610
--- /dev/null
+++ b/libc/arch-arm/syscalls/setfsgid.S
@@ -0,0 +1,16 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsgid)
+    mov     ip, r7
+    ldr     r7, =__NR_setfsgid
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(setfsgid)
diff --git a/libc/arch-arm/syscalls/setfsuid.S b/libc/arch-arm/syscalls/setfsuid.S
new file mode 100644
index 0000000..ae65298
--- /dev/null
+++ b/libc/arch-arm/syscalls/setfsuid.S
@@ -0,0 +1,16 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsuid)
+    mov     ip, r7
+    ldr     r7, =__NR_setfsuid
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(setfsuid)
diff --git a/libc/arch-arm/syscalls/setgid.S b/libc/arch-arm/syscalls/setgid.S
index fb38148..15583ac 100644
--- a/libc/arch-arm/syscalls/setgid.S
+++ b/libc/arch-arm/syscalls/setgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgid)
     mov     ip, r7
     ldr     r7, =__NR_setgid32
diff --git a/libc/arch-arm/syscalls/setgroups.S b/libc/arch-arm/syscalls/setgroups.S
index 5420a53..eb610b1 100644
--- a/libc/arch-arm/syscalls/setgroups.S
+++ b/libc/arch-arm/syscalls/setgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgroups)
     mov     ip, r7
     ldr     r7, =__NR_setgroups32
diff --git a/libc/arch-arm/syscalls/setitimer.S b/libc/arch-arm/syscalls/setitimer.S
index 2345e5b..4da2b40 100644
--- a/libc/arch-arm/syscalls/setitimer.S
+++ b/libc/arch-arm/syscalls/setitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setitimer)
     mov     ip, r7
     ldr     r7, =__NR_setitimer
diff --git a/libc/arch-arm/syscalls/setns.S b/libc/arch-arm/syscalls/setns.S
index 7afbff0..891a0ac 100644
--- a/libc/arch-arm/syscalls/setns.S
+++ b/libc/arch-arm/syscalls/setns.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setns)
     mov     ip, r7
     ldr     r7, =__NR_setns
diff --git a/libc/arch-arm/syscalls/setpgid.S b/libc/arch-arm/syscalls/setpgid.S
index 1470a9d..e4edcdf 100644
--- a/libc/arch-arm/syscalls/setpgid.S
+++ b/libc/arch-arm/syscalls/setpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpgid)
     mov     ip, r7
     ldr     r7, =__NR_setpgid
diff --git a/libc/arch-arm/syscalls/setpriority.S b/libc/arch-arm/syscalls/setpriority.S
index b7f47be..80d0d82 100644
--- a/libc/arch-arm/syscalls/setpriority.S
+++ b/libc/arch-arm/syscalls/setpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpriority)
     mov     ip, r7
     ldr     r7, =__NR_setpriority
diff --git a/libc/arch-arm/syscalls/setregid.S b/libc/arch-arm/syscalls/setregid.S
index a4323d4..b2cd345 100644
--- a/libc/arch-arm/syscalls/setregid.S
+++ b/libc/arch-arm/syscalls/setregid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setregid)
     mov     ip, r7
     ldr     r7, =__NR_setregid32
diff --git a/libc/arch-arm/syscalls/setresgid.S b/libc/arch-arm/syscalls/setresgid.S
index a578440..75a9f75 100644
--- a/libc/arch-arm/syscalls/setresgid.S
+++ b/libc/arch-arm/syscalls/setresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresgid)
     mov     ip, r7
     ldr     r7, =__NR_setresgid32
diff --git a/libc/arch-arm/syscalls/setresuid.S b/libc/arch-arm/syscalls/setresuid.S
index 9798bc5..f3382f2 100644
--- a/libc/arch-arm/syscalls/setresuid.S
+++ b/libc/arch-arm/syscalls/setresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresuid)
     mov     ip, r7
     ldr     r7, =__NR_setresuid32
diff --git a/libc/arch-arm/syscalls/setreuid.S b/libc/arch-arm/syscalls/setreuid.S
index fa83dc6..1d866e9 100644
--- a/libc/arch-arm/syscalls/setreuid.S
+++ b/libc/arch-arm/syscalls/setreuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setreuid)
     mov     ip, r7
     ldr     r7, =__NR_setreuid32
diff --git a/libc/arch-arm/syscalls/setrlimit.S b/libc/arch-arm/syscalls/setrlimit.S
index 0711aca..0ddd711 100644
--- a/libc/arch-arm/syscalls/setrlimit.S
+++ b/libc/arch-arm/syscalls/setrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setrlimit)
     mov     ip, r7
     ldr     r7, =__NR_setrlimit
diff --git a/libc/arch-arm/syscalls/setsid.S b/libc/arch-arm/syscalls/setsid.S
index df6196b..69b351f 100644
--- a/libc/arch-arm/syscalls/setsid.S
+++ b/libc/arch-arm/syscalls/setsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsid)
     mov     ip, r7
     ldr     r7, =__NR_setsid
diff --git a/libc/arch-arm/syscalls/setsockopt.S b/libc/arch-arm/syscalls/setsockopt.S
index b2d7597..87df622 100644
--- a/libc/arch-arm/syscalls/setsockopt.S
+++ b/libc/arch-arm/syscalls/setsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsockopt)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/settimeofday.S b/libc/arch-arm/syscalls/settimeofday.S
index af39761..76697fc 100644
--- a/libc/arch-arm/syscalls/settimeofday.S
+++ b/libc/arch-arm/syscalls/settimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(settimeofday)
     mov     ip, r7
     ldr     r7, =__NR_settimeofday
diff --git a/libc/arch-arm/syscalls/setuid.S b/libc/arch-arm/syscalls/setuid.S
index 1999c2b..26d3ed1 100644
--- a/libc/arch-arm/syscalls/setuid.S
+++ b/libc/arch-arm/syscalls/setuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setuid)
     mov     ip, r7
     ldr     r7, =__NR_setuid32
diff --git a/libc/arch-arm/syscalls/setxattr.S b/libc/arch-arm/syscalls/setxattr.S
index 022195d..ec948ce 100644
--- a/libc/arch-arm/syscalls/setxattr.S
+++ b/libc/arch-arm/syscalls/setxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setxattr)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/shutdown.S b/libc/arch-arm/syscalls/shutdown.S
index 744f384..e9a27d4 100644
--- a/libc/arch-arm/syscalls/shutdown.S
+++ b/libc/arch-arm/syscalls/shutdown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(shutdown)
     mov     ip, r7
     ldr     r7, =__NR_shutdown
diff --git a/libc/arch-arm/syscalls/sigaltstack.S b/libc/arch-arm/syscalls/sigaltstack.S
index d8777b4..18a1ffe 100644
--- a/libc/arch-arm/syscalls/sigaltstack.S
+++ b/libc/arch-arm/syscalls/sigaltstack.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sigaltstack)
     mov     ip, r7
     ldr     r7, =__NR_sigaltstack
diff --git a/libc/arch-arm/syscalls/socketpair.S b/libc/arch-arm/syscalls/socketpair.S
index f896313..66f0c32 100644
--- a/libc/arch-arm/syscalls/socketpair.S
+++ b/libc/arch-arm/syscalls/socketpair.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(socketpair)
     mov     ip, r7
     ldr     r7, =__NR_socketpair
diff --git a/libc/arch-arm/syscalls/splice.S b/libc/arch-arm/syscalls/splice.S
index 782ba6c..6273138 100644
--- a/libc/arch-arm/syscalls/splice.S
+++ b/libc/arch-arm/syscalls/splice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(splice)
     mov     ip, sp
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/swapoff.S b/libc/arch-arm/syscalls/swapoff.S
index f78bc7f..a497aad 100644
--- a/libc/arch-arm/syscalls/swapoff.S
+++ b/libc/arch-arm/syscalls/swapoff.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapoff)
     mov     ip, r7
     ldr     r7, =__NR_swapoff
diff --git a/libc/arch-arm/syscalls/swapon.S b/libc/arch-arm/syscalls/swapon.S
index d28216a..ded2abc 100644
--- a/libc/arch-arm/syscalls/swapon.S
+++ b/libc/arch-arm/syscalls/swapon.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapon)
     mov     ip, r7
     ldr     r7, =__NR_swapon
diff --git a/libc/arch-arm/syscalls/symlinkat.S b/libc/arch-arm/syscalls/symlinkat.S
index d81e43b..cc91b88 100644
--- a/libc/arch-arm/syscalls/symlinkat.S
+++ b/libc/arch-arm/syscalls/symlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(symlinkat)
     mov     ip, r7
     ldr     r7, =__NR_symlinkat
diff --git a/libc/arch-arm/syscalls/sync.S b/libc/arch-arm/syscalls/sync.S
index 279a192..ab22855 100644
--- a/libc/arch-arm/syscalls/sync.S
+++ b/libc/arch-arm/syscalls/sync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sync)
     mov     ip, r7
     ldr     r7, =__NR_sync
diff --git a/libc/arch-arm/syscalls/sysinfo.S b/libc/arch-arm/syscalls/sysinfo.S
index 6bee583..f5fb4e6 100644
--- a/libc/arch-arm/syscalls/sysinfo.S
+++ b/libc/arch-arm/syscalls/sysinfo.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sysinfo)
     mov     ip, r7
     ldr     r7, =__NR_sysinfo
diff --git a/libc/arch-arm/syscalls/tee.S b/libc/arch-arm/syscalls/tee.S
index 9174617..7e155df 100644
--- a/libc/arch-arm/syscalls/tee.S
+++ b/libc/arch-arm/syscalls/tee.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tee)
     mov     ip, r7
     ldr     r7, =__NR_tee
diff --git a/libc/arch-arm/syscalls/tgkill.S b/libc/arch-arm/syscalls/tgkill.S
index 4ea04f5..98440b1 100644
--- a/libc/arch-arm/syscalls/tgkill.S
+++ b/libc/arch-arm/syscalls/tgkill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tgkill)
     mov     ip, r7
     ldr     r7, =__NR_tgkill
diff --git a/libc/arch-arm/syscalls/timerfd_create.S b/libc/arch-arm/syscalls/timerfd_create.S
index f5842e9..9211b54 100644
--- a/libc/arch-arm/syscalls/timerfd_create.S
+++ b/libc/arch-arm/syscalls/timerfd_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_create)
     mov     ip, r7
     ldr     r7, =__NR_timerfd_create
diff --git a/libc/arch-arm/syscalls/timerfd_gettime.S b/libc/arch-arm/syscalls/timerfd_gettime.S
index 6f254e5..c27e008 100644
--- a/libc/arch-arm/syscalls/timerfd_gettime.S
+++ b/libc/arch-arm/syscalls/timerfd_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_gettime)
     mov     ip, r7
     ldr     r7, =__NR_timerfd_gettime
diff --git a/libc/arch-arm/syscalls/timerfd_settime.S b/libc/arch-arm/syscalls/timerfd_settime.S
index 75d175c..7acd408 100644
--- a/libc/arch-arm/syscalls/timerfd_settime.S
+++ b/libc/arch-arm/syscalls/timerfd_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_settime)
     mov     ip, r7
     ldr     r7, =__NR_timerfd_settime
diff --git a/libc/arch-arm/syscalls/times.S b/libc/arch-arm/syscalls/times.S
index 4792ad1..b5695c4 100644
--- a/libc/arch-arm/syscalls/times.S
+++ b/libc/arch-arm/syscalls/times.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(times)
     mov     ip, r7
     ldr     r7, =__NR_times
diff --git a/libc/arch-arm/syscalls/truncate.S b/libc/arch-arm/syscalls/truncate.S
index ff8fd19..7915722 100644
--- a/libc/arch-arm/syscalls/truncate.S
+++ b/libc/arch-arm/syscalls/truncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate)
     mov     ip, r7
     ldr     r7, =__NR_truncate
diff --git a/libc/arch-arm/syscalls/truncate64.S b/libc/arch-arm/syscalls/truncate64.S
index 8fd0855..d59374a 100644
--- a/libc/arch-arm/syscalls/truncate64.S
+++ b/libc/arch-arm/syscalls/truncate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate64)
     mov     ip, r7
     ldr     r7, =__NR_truncate64
diff --git a/libc/arch-arm/syscalls/umask.S b/libc/arch-arm/syscalls/umask.S
index 830af21..5b03fb3 100644
--- a/libc/arch-arm/syscalls/umask.S
+++ b/libc/arch-arm/syscalls/umask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umask)
     mov     ip, r7
     ldr     r7, =__NR_umask
diff --git a/libc/arch-arm/syscalls/umount2.S b/libc/arch-arm/syscalls/umount2.S
index 4c0ce4d..841eb97 100644
--- a/libc/arch-arm/syscalls/umount2.S
+++ b/libc/arch-arm/syscalls/umount2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umount2)
     mov     ip, r7
     ldr     r7, =__NR_umount2
diff --git a/libc/arch-arm/syscalls/uname.S b/libc/arch-arm/syscalls/uname.S
index 20a6d7d..76480b4 100644
--- a/libc/arch-arm/syscalls/uname.S
+++ b/libc/arch-arm/syscalls/uname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(uname)
     mov     ip, r7
     ldr     r7, =__NR_uname
diff --git a/libc/arch-arm/syscalls/unlinkat.S b/libc/arch-arm/syscalls/unlinkat.S
index 1c27416..6759768 100644
--- a/libc/arch-arm/syscalls/unlinkat.S
+++ b/libc/arch-arm/syscalls/unlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unlinkat)
     mov     ip, r7
     ldr     r7, =__NR_unlinkat
diff --git a/libc/arch-arm/syscalls/unshare.S b/libc/arch-arm/syscalls/unshare.S
index 5ec1049..19a5b6a 100644
--- a/libc/arch-arm/syscalls/unshare.S
+++ b/libc/arch-arm/syscalls/unshare.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unshare)
     mov     ip, r7
     ldr     r7, =__NR_unshare
diff --git a/libc/arch-arm/syscalls/utimensat.S b/libc/arch-arm/syscalls/utimensat.S
index f0f834f..6d50688 100644
--- a/libc/arch-arm/syscalls/utimensat.S
+++ b/libc/arch-arm/syscalls/utimensat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(utimensat)
     mov     ip, r7
     ldr     r7, =__NR_utimensat
diff --git a/libc/arch-arm/syscalls/vfork.S b/libc/arch-arm/syscalls/vfork.S
new file mode 100644
index 0000000..8543986
--- /dev/null
+++ b/libc/arch-arm/syscalls/vfork.S
@@ -0,0 +1,16 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(vfork)
+    mov     ip, r7
+    ldr     r7, =__NR_vfork
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(vfork)
diff --git a/libc/arch-arm/syscalls/vmsplice.S b/libc/arch-arm/syscalls/vmsplice.S
index 3b89623..8239158 100644
--- a/libc/arch-arm/syscalls/vmsplice.S
+++ b/libc/arch-arm/syscalls/vmsplice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(vmsplice)
     mov     ip, r7
     ldr     r7, =__NR_vmsplice
diff --git a/libc/arch-arm/syscalls/wait4.S b/libc/arch-arm/syscalls/wait4.S
index a197c2e..ffb2587 100644
--- a/libc/arch-arm/syscalls/wait4.S
+++ b/libc/arch-arm/syscalls/wait4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(wait4)
     mov     ip, r7
     ldr     r7, =__NR_wait4
diff --git a/libc/arch-arm/syscalls/write.S b/libc/arch-arm/syscalls/write.S
index ed7cfa2..8da1176 100644
--- a/libc/arch-arm/syscalls/write.S
+++ b/libc/arch-arm/syscalls/write.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(write)
     mov     ip, r7
     ldr     r7, =__NR_write
diff --git a/libc/arch-arm/syscalls/writev.S b/libc/arch-arm/syscalls/writev.S
index 8cc506f..f17ad94 100644
--- a/libc/arch-arm/syscalls/writev.S
+++ b/libc/arch-arm/syscalls/writev.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(writev)
     mov     ip, r7
     ldr     r7, =__NR_writev
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 314358e..6c4f6a6 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -29,13 +29,13 @@
 libc_bionic_src_files_arm64 := \
     arch-arm64/bionic/__bionic_clone.S \
     arch-arm64/bionic/_exit_with_stack_teardown.S \
-    arch-arm64/bionic/__get_sp.S \
     arch-arm64/bionic/__rt_sigreturn.S \
     arch-arm64/bionic/_setjmp.S \
     arch-arm64/bionic/setjmp.S \
     arch-arm64/bionic/__set_tls.c \
     arch-arm64/bionic/sigsetjmp.S \
     arch-arm64/bionic/syscall.S \
+    arch-arm64/bionic/vfork.S \
 
 
 libc_crt_target_cflags_arm64 := \
diff --git a/libc/arch-arm64/bionic/_setjmp.S b/libc/arch-arm64/bionic/_setjmp.S
index 3836899..e11ef68 100644
--- a/libc/arch-arm64/bionic/_setjmp.S
+++ b/libc/arch-arm64/bionic/_setjmp.S
@@ -105,7 +105,7 @@
 
     /* validation failed, die die die */
 .L_fail:
-    bl      PIC_SYM(longjmperror, PLT)
-    bl      PIC_SYM(abort, PLT)
+    bl      longjmperror
+    bl      abort
     b        . - 8       /* Cannot get here */
 END(_longjmp)
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index f9d2266..35815a6 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -45,7 +45,7 @@
     stp     x0, x30, [sp, #-16]!
 
     mov     x0, xzr
-    bl      PIC_SYM(sigblock, PLT)
+    bl      sigblock
     mov     w1, w0
 
     ldp     x0, x30, [sp], #16
@@ -117,7 +117,7 @@
 
     /* validation failed, die die die */
 .L_fail:
-    bl      PIC_SYM(longjmperror, PLT)
-    bl      PIC_SYM(abort, PLT)
+    bl      longjmperror
+    bl      abort
     b       . - 8       /* Cannot get here */
 END(longjmp)
diff --git a/libc/arch-arm64/bionic/sigsetjmp.S b/libc/arch-arm64/bionic/sigsetjmp.S
index 4fdb367..be7cecb 100644
--- a/libc/arch-arm64/bionic/sigsetjmp.S
+++ b/libc/arch-arm64/bionic/sigsetjmp.S
@@ -35,8 +35,8 @@
  */
 
 ENTRY(sigsetjmp)
-    cbz     w1, PIC_SYM(_setjmp, PLT)
-    b       PIC_SYM(setjmp, PLT)
+    cbz     w1, _setjmp
+    b       setjmp
 END(sigsetjmp)
 
 .L_setjmp_magic:
@@ -46,6 +46,6 @@
     ldr     w2, .L_setjmp_magic
     ldr     w3, [x0]
     cmp     w2, w3
-    b.eq    PIC_SYM(_longjmp, PLT)
-    b       PIC_SYM(longjmp, PLT)
+    b.eq    _longjmp
+    b       longjmp
 END(siglongjmp)
diff --git a/libc/arch-arm64/bionic/__get_sp.S b/libc/arch-arm64/bionic/vfork.S
similarity index 81%
rename from libc/arch-arm64/bionic/__get_sp.S
rename to libc/arch-arm64/bionic/vfork.S
index d5e88e9..c700623 100644
--- a/libc/arch-arm64/bionic/__get_sp.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -27,8 +27,22 @@
  */
 
 #include <private/bionic_asm.h>
+#include <asm/signal.h>
+#include <linux/sched.h>
 
-ENTRY_PRIVATE(__get_sp)
-    mov x0, sp
+ENTRY(vfork)
+    mov     x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
+    mov     x1, xzr
+    mov     x2, xzr
+    mov     x3, xzr
+    mov     x4, xzr
+
+    mov     x8, __NR_clone
+    svc     #0
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno
+
     ret
-END(__get_sp)
+END(vfork)
diff --git a/libc/arch-arm64/generic/bionic/memchr.S b/libc/arch-arm64/generic/bionic/memchr.S
index fbb00ca..e5ea57d 100644
--- a/libc/arch-arm64/generic/bionic/memchr.S
+++ b/libc/arch-arm64/generic/bionic/memchr.S
@@ -75,6 +75,7 @@
 	 * Magic constant 0x40100401 allows us to identify which lane matches
 	 * the requested byte.
 	 */
+	cbz	cntin, .Lzero_length
 	mov	wtmp2, #0x0401
 	movk	wtmp2, #0x4010, lsl #16
 	dup	vrepchr.16b, chrin
@@ -157,4 +158,8 @@
 	/* Select result or NULL */
 	csel	result, xzr, result, eq
 	ret
+
+.Lzero_length:
+	mov	result, xzr
+	ret
 END(memchr)
diff --git a/libc/arch-arm64/include/machine/asm.h b/libc/arch-arm64/include/machine/asm.h
index 4bfabaf..2bea043 100644
--- a/libc/arch-arm64/include/machine/asm.h
+++ b/libc/arch-arm64/include/machine/asm.h
@@ -38,17 +38,9 @@
 #ifndef _AARCH64_ASM_H_
 #define _AARCH64_ASM_H_
 
-#ifndef _ALIGN_TEXT
-# define _ALIGN_TEXT .align 0
-#endif
+#define __bionic_asm_align 0
 
 #undef __bionic_asm_function_type
 #define __bionic_asm_function_type %function
 
-#if defined(__ELF__) && defined(PIC)
-#define PIC_SYM(x,y) x ## ( ## y ## )
-#else
-#define PIC_SYM(x,y) x
-#endif
-
 #endif /* _AARCH64_ASM_H_ */
diff --git a/libc/arch-arm64/syscalls/__accept4.S b/libc/arch-arm64/syscalls/__accept4.S
index 1c2a674..bee9fda 100644
--- a/libc/arch-arm64/syscalls/__accept4.S
+++ b/libc/arch-arm64/syscalls/__accept4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__accept4)
     mov     x8, __NR_accept4
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__brk.S b/libc/arch-arm64/syscalls/__brk.S
index 85ed767..e91e762 100644
--- a/libc/arch-arm64/syscalls/__brk.S
+++ b/libc/arch-arm64/syscalls/__brk.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__brk)
     mov     x8, __NR_brk
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__clock_gettime.S b/libc/arch-arm64/syscalls/__clock_gettime.S
index f346648..d4a65e8 100644
--- a/libc/arch-arm64/syscalls/__clock_gettime.S
+++ b/libc/arch-arm64/syscalls/__clock_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__clock_gettime)
     mov     x8, __NR_clock_gettime
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__connect.S b/libc/arch-arm64/syscalls/__connect.S
index 0d664f0..4f19dc7 100644
--- a/libc/arch-arm64/syscalls/__connect.S
+++ b/libc/arch-arm64/syscalls/__connect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__connect)
     mov     x8, __NR_connect
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__epoll_pwait.S b/libc/arch-arm64/syscalls/__epoll_pwait.S
index 45275c0..7f40fbc 100644
--- a/libc/arch-arm64/syscalls/__epoll_pwait.S
+++ b/libc/arch-arm64/syscalls/__epoll_pwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__epoll_pwait)
     mov     x8, __NR_epoll_pwait
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__exit.S b/libc/arch-arm64/syscalls/__exit.S
index e358513..30849ce 100644
--- a/libc/arch-arm64/syscalls/__exit.S
+++ b/libc/arch-arm64/syscalls/__exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__exit)
     mov     x8, __NR_exit
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__getcpu.S b/libc/arch-arm64/syscalls/__getcpu.S
index 5e4368f..4821917 100644
--- a/libc/arch-arm64/syscalls/__getcpu.S
+++ b/libc/arch-arm64/syscalls/__getcpu.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcpu)
     mov     x8, __NR_getcpu
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__getcwd.S b/libc/arch-arm64/syscalls/__getcwd.S
index bd4fbaa..f0212a2 100644
--- a/libc/arch-arm64/syscalls/__getcwd.S
+++ b/libc/arch-arm64/syscalls/__getcwd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcwd)
     mov     x8, __NR_getcwd
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__getdents64.S b/libc/arch-arm64/syscalls/__getdents64.S
index bf0f9a4..0061cd6 100644
--- a/libc/arch-arm64/syscalls/__getdents64.S
+++ b/libc/arch-arm64/syscalls/__getdents64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getdents64)
     mov     x8, __NR_getdents64
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__getpid.S b/libc/arch-arm64/syscalls/__getpid.S
index c3003c3..011d82d 100644
--- a/libc/arch-arm64/syscalls/__getpid.S
+++ b/libc/arch-arm64/syscalls/__getpid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpid)
     mov     x8, __NR_getpid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__getpriority.S b/libc/arch-arm64/syscalls/__getpriority.S
index 57ceabf..80188b3 100644
--- a/libc/arch-arm64/syscalls/__getpriority.S
+++ b/libc/arch-arm64/syscalls/__getpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpriority)
     mov     x8, __NR_getpriority
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__gettimeofday.S b/libc/arch-arm64/syscalls/__gettimeofday.S
index 6582c49..7d1b5d3 100644
--- a/libc/arch-arm64/syscalls/__gettimeofday.S
+++ b/libc/arch-arm64/syscalls/__gettimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__gettimeofday)
     mov     x8, __NR_gettimeofday
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__ioctl.S b/libc/arch-arm64/syscalls/__ioctl.S
index f632555..3d42f1a 100644
--- a/libc/arch-arm64/syscalls/__ioctl.S
+++ b/libc/arch-arm64/syscalls/__ioctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ioctl)
     mov     x8, __NR_ioctl
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__openat.S b/libc/arch-arm64/syscalls/__openat.S
index e1b0da3..1ff0b48 100644
--- a/libc/arch-arm64/syscalls/__openat.S
+++ b/libc/arch-arm64/syscalls/__openat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__openat)
     mov     x8, __NR_openat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__ppoll.S b/libc/arch-arm64/syscalls/__ppoll.S
index 31e5578..9517ce3 100644
--- a/libc/arch-arm64/syscalls/__ppoll.S
+++ b/libc/arch-arm64/syscalls/__ppoll.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ppoll)
     mov     x8, __NR_ppoll
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__pselect6.S b/libc/arch-arm64/syscalls/__pselect6.S
index b0e4770..7e14e02 100644
--- a/libc/arch-arm64/syscalls/__pselect6.S
+++ b/libc/arch-arm64/syscalls/__pselect6.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__pselect6)
     mov     x8, __NR_pselect6
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__ptrace.S b/libc/arch-arm64/syscalls/__ptrace.S
index 054bb6f..b325e29 100644
--- a/libc/arch-arm64/syscalls/__ptrace.S
+++ b/libc/arch-arm64/syscalls/__ptrace.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ptrace)
     mov     x8, __NR_ptrace
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__reboot.S b/libc/arch-arm64/syscalls/__reboot.S
index e24553c..04b18c9 100644
--- a/libc/arch-arm64/syscalls/__reboot.S
+++ b/libc/arch-arm64/syscalls/__reboot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__reboot)
     mov     x8, __NR_reboot
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__rt_sigaction.S b/libc/arch-arm64/syscalls/__rt_sigaction.S
index 3d84544..3def558 100644
--- a/libc/arch-arm64/syscalls/__rt_sigaction.S
+++ b/libc/arch-arm64/syscalls/__rt_sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigaction)
     mov     x8, __NR_rt_sigaction
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__rt_sigpending.S b/libc/arch-arm64/syscalls/__rt_sigpending.S
index 60f0a10..3ac0cb8 100644
--- a/libc/arch-arm64/syscalls/__rt_sigpending.S
+++ b/libc/arch-arm64/syscalls/__rt_sigpending.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigpending)
     mov     x8, __NR_rt_sigpending
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__rt_sigprocmask.S b/libc/arch-arm64/syscalls/__rt_sigprocmask.S
index 7f5b3ac..72c7ea6 100644
--- a/libc/arch-arm64/syscalls/__rt_sigprocmask.S
+++ b/libc/arch-arm64/syscalls/__rt_sigprocmask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigprocmask)
     mov     x8, __NR_rt_sigprocmask
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__rt_sigsuspend.S b/libc/arch-arm64/syscalls/__rt_sigsuspend.S
index 08b1197..a289713 100644
--- a/libc/arch-arm64/syscalls/__rt_sigsuspend.S
+++ b/libc/arch-arm64/syscalls/__rt_sigsuspend.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigsuspend)
     mov     x8, __NR_rt_sigsuspend
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__rt_sigtimedwait.S b/libc/arch-arm64/syscalls/__rt_sigtimedwait.S
index 8bc9a7a..c61e4ac 100644
--- a/libc/arch-arm64/syscalls/__rt_sigtimedwait.S
+++ b/libc/arch-arm64/syscalls/__rt_sigtimedwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigtimedwait)
     mov     x8, __NR_rt_sigtimedwait
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__sched_getaffinity.S b/libc/arch-arm64/syscalls/__sched_getaffinity.S
index c0d392c..5bee77e 100644
--- a/libc/arch-arm64/syscalls/__sched_getaffinity.S
+++ b/libc/arch-arm64/syscalls/__sched_getaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sched_getaffinity)
     mov     x8, __NR_sched_getaffinity
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__set_tid_address.S b/libc/arch-arm64/syscalls/__set_tid_address.S
index 296c907..e4790bf 100644
--- a/libc/arch-arm64/syscalls/__set_tid_address.S
+++ b/libc/arch-arm64/syscalls/__set_tid_address.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tid_address)
     mov     x8, __NR_set_tid_address
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__signalfd4.S b/libc/arch-arm64/syscalls/__signalfd4.S
index 3932003..a977a6c 100644
--- a/libc/arch-arm64/syscalls/__signalfd4.S
+++ b/libc/arch-arm64/syscalls/__signalfd4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__signalfd4)
     mov     x8, __NR_signalfd4
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__socket.S b/libc/arch-arm64/syscalls/__socket.S
index db7f2aa..f8bb2ac 100644
--- a/libc/arch-arm64/syscalls/__socket.S
+++ b/libc/arch-arm64/syscalls/__socket.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__socket)
     mov     x8, __NR_socket
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__timer_create.S b/libc/arch-arm64/syscalls/__timer_create.S
index a5e69e3..bb54952 100644
--- a/libc/arch-arm64/syscalls/__timer_create.S
+++ b/libc/arch-arm64/syscalls/__timer_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_create)
     mov     x8, __NR_timer_create
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__timer_delete.S b/libc/arch-arm64/syscalls/__timer_delete.S
index 44a7481..47d82f2 100644
--- a/libc/arch-arm64/syscalls/__timer_delete.S
+++ b/libc/arch-arm64/syscalls/__timer_delete.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_delete)
     mov     x8, __NR_timer_delete
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__timer_getoverrun.S b/libc/arch-arm64/syscalls/__timer_getoverrun.S
index e1d959a..9c06112 100644
--- a/libc/arch-arm64/syscalls/__timer_getoverrun.S
+++ b/libc/arch-arm64/syscalls/__timer_getoverrun.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_getoverrun)
     mov     x8, __NR_timer_getoverrun
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__timer_gettime.S b/libc/arch-arm64/syscalls/__timer_gettime.S
index 7632290..e7c7cfe 100644
--- a/libc/arch-arm64/syscalls/__timer_gettime.S
+++ b/libc/arch-arm64/syscalls/__timer_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_gettime)
     mov     x8, __NR_timer_gettime
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__timer_settime.S b/libc/arch-arm64/syscalls/__timer_settime.S
index 92e4a76..d4a4996 100644
--- a/libc/arch-arm64/syscalls/__timer_settime.S
+++ b/libc/arch-arm64/syscalls/__timer_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_settime)
     mov     x8, __NR_timer_settime
     svc     #0
diff --git a/libc/arch-arm64/syscalls/__waitid.S b/libc/arch-arm64/syscalls/__waitid.S
index 9267239..5bff488 100644
--- a/libc/arch-arm64/syscalls/__waitid.S
+++ b/libc/arch-arm64/syscalls/__waitid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__waitid)
     mov     x8, __NR_waitid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/_exit.S b/libc/arch-arm64/syscalls/_exit.S
index 38b073b..e88e77a 100644
--- a/libc/arch-arm64/syscalls/_exit.S
+++ b/libc/arch-arm64/syscalls/_exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(_exit)
     mov     x8, __NR_exit_group
     svc     #0
diff --git a/libc/arch-arm64/syscalls/acct.S b/libc/arch-arm64/syscalls/acct.S
index 15e3086..97a8a0c 100644
--- a/libc/arch-arm64/syscalls/acct.S
+++ b/libc/arch-arm64/syscalls/acct.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(acct)
     mov     x8, __NR_acct
     svc     #0
diff --git a/libc/arch-arm64/syscalls/bind.S b/libc/arch-arm64/syscalls/bind.S
index b3925db..1d6d901 100644
--- a/libc/arch-arm64/syscalls/bind.S
+++ b/libc/arch-arm64/syscalls/bind.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(bind)
     mov     x8, __NR_bind
     svc     #0
diff --git a/libc/arch-arm64/syscalls/capget.S b/libc/arch-arm64/syscalls/capget.S
index b897e5d..de84929 100644
--- a/libc/arch-arm64/syscalls/capget.S
+++ b/libc/arch-arm64/syscalls/capget.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capget)
     mov     x8, __NR_capget
     svc     #0
diff --git a/libc/arch-arm64/syscalls/capset.S b/libc/arch-arm64/syscalls/capset.S
index 1d94aa3..1616f8f 100644
--- a/libc/arch-arm64/syscalls/capset.S
+++ b/libc/arch-arm64/syscalls/capset.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capset)
     mov     x8, __NR_capset
     svc     #0
diff --git a/libc/arch-arm64/syscalls/chdir.S b/libc/arch-arm64/syscalls/chdir.S
index a7bf6c2..ccaa2e2 100644
--- a/libc/arch-arm64/syscalls/chdir.S
+++ b/libc/arch-arm64/syscalls/chdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chdir)
     mov     x8, __NR_chdir
     svc     #0
diff --git a/libc/arch-arm64/syscalls/chroot.S b/libc/arch-arm64/syscalls/chroot.S
index 98bd5d1..bede172 100644
--- a/libc/arch-arm64/syscalls/chroot.S
+++ b/libc/arch-arm64/syscalls/chroot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chroot)
     mov     x8, __NR_chroot
     svc     #0
diff --git a/libc/arch-arm64/syscalls/clock_getres.S b/libc/arch-arm64/syscalls/clock_getres.S
index b6e7e56..3944a15 100644
--- a/libc/arch-arm64/syscalls/clock_getres.S
+++ b/libc/arch-arm64/syscalls/clock_getres.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_getres)
     mov     x8, __NR_clock_getres
     svc     #0
diff --git a/libc/arch-arm64/syscalls/clock_nanosleep.S b/libc/arch-arm64/syscalls/clock_nanosleep.S
index b64ff68..2182f67 100644
--- a/libc/arch-arm64/syscalls/clock_nanosleep.S
+++ b/libc/arch-arm64/syscalls/clock_nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_nanosleep)
     mov     x8, __NR_clock_nanosleep
     svc     #0
diff --git a/libc/arch-arm64/syscalls/clock_settime.S b/libc/arch-arm64/syscalls/clock_settime.S
index adc1680..14a662b 100644
--- a/libc/arch-arm64/syscalls/clock_settime.S
+++ b/libc/arch-arm64/syscalls/clock_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_settime)
     mov     x8, __NR_clock_settime
     svc     #0
diff --git a/libc/arch-arm64/syscalls/close.S b/libc/arch-arm64/syscalls/close.S
index b4b72d9..da9a151 100644
--- a/libc/arch-arm64/syscalls/close.S
+++ b/libc/arch-arm64/syscalls/close.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(close)
     mov     x8, __NR_close
     svc     #0
diff --git a/libc/arch-arm64/syscalls/delete_module.S b/libc/arch-arm64/syscalls/delete_module.S
index ed51847..5dcd07f 100644
--- a/libc/arch-arm64/syscalls/delete_module.S
+++ b/libc/arch-arm64/syscalls/delete_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(delete_module)
     mov     x8, __NR_delete_module
     svc     #0
diff --git a/libc/arch-arm64/syscalls/dup.S b/libc/arch-arm64/syscalls/dup.S
index 9584c51..33a1b65 100644
--- a/libc/arch-arm64/syscalls/dup.S
+++ b/libc/arch-arm64/syscalls/dup.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup)
     mov     x8, __NR_dup
     svc     #0
diff --git a/libc/arch-arm64/syscalls/dup3.S b/libc/arch-arm64/syscalls/dup3.S
index e303fba..441fec9 100644
--- a/libc/arch-arm64/syscalls/dup3.S
+++ b/libc/arch-arm64/syscalls/dup3.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup3)
     mov     x8, __NR_dup3
     svc     #0
diff --git a/libc/arch-arm64/syscalls/epoll_create1.S b/libc/arch-arm64/syscalls/epoll_create1.S
index 4ca8bfa..d314f55 100644
--- a/libc/arch-arm64/syscalls/epoll_create1.S
+++ b/libc/arch-arm64/syscalls/epoll_create1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_create1)
     mov     x8, __NR_epoll_create1
     svc     #0
diff --git a/libc/arch-arm64/syscalls/epoll_ctl.S b/libc/arch-arm64/syscalls/epoll_ctl.S
index c1c0dba..004c066 100644
--- a/libc/arch-arm64/syscalls/epoll_ctl.S
+++ b/libc/arch-arm64/syscalls/epoll_ctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_ctl)
     mov     x8, __NR_epoll_ctl
     svc     #0
diff --git a/libc/arch-arm64/syscalls/eventfd.S b/libc/arch-arm64/syscalls/eventfd.S
index ace608e..11e97d0 100644
--- a/libc/arch-arm64/syscalls/eventfd.S
+++ b/libc/arch-arm64/syscalls/eventfd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(eventfd)
     mov     x8, __NR_eventfd2
     svc     #0
diff --git a/libc/arch-arm64/syscalls/execve.S b/libc/arch-arm64/syscalls/execve.S
index ab0cb57..7b6d943 100644
--- a/libc/arch-arm64/syscalls/execve.S
+++ b/libc/arch-arm64/syscalls/execve.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(execve)
     mov     x8, __NR_execve
     svc     #0
diff --git a/libc/arch-arm64/syscalls/faccessat.S b/libc/arch-arm64/syscalls/faccessat.S
index 30a3852..7bd8665 100644
--- a/libc/arch-arm64/syscalls/faccessat.S
+++ b/libc/arch-arm64/syscalls/faccessat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(faccessat)
     mov     x8, __NR_faccessat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fallocate.S b/libc/arch-arm64/syscalls/fallocate.S
index 3092b34..d8795ae 100644
--- a/libc/arch-arm64/syscalls/fallocate.S
+++ b/libc/arch-arm64/syscalls/fallocate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fallocate)
     mov     x8, __NR_fallocate
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fchdir.S b/libc/arch-arm64/syscalls/fchdir.S
index f7687f8..7739fed 100644
--- a/libc/arch-arm64/syscalls/fchdir.S
+++ b/libc/arch-arm64/syscalls/fchdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchdir)
     mov     x8, __NR_fchdir
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fchmod.S b/libc/arch-arm64/syscalls/fchmod.S
index acc6718..3eec6cb 100644
--- a/libc/arch-arm64/syscalls/fchmod.S
+++ b/libc/arch-arm64/syscalls/fchmod.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmod)
     mov     x8, __NR_fchmod
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fchmodat.S b/libc/arch-arm64/syscalls/fchmodat.S
index 23c2fd5..f2f285e 100644
--- a/libc/arch-arm64/syscalls/fchmodat.S
+++ b/libc/arch-arm64/syscalls/fchmodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmodat)
     mov     x8, __NR_fchmodat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fchown.S b/libc/arch-arm64/syscalls/fchown.S
index 8e9db62..a689ba0 100644
--- a/libc/arch-arm64/syscalls/fchown.S
+++ b/libc/arch-arm64/syscalls/fchown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchown)
     mov     x8, __NR_fchown
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fchownat.S b/libc/arch-arm64/syscalls/fchownat.S
index 3cf2c3d..7ede083 100644
--- a/libc/arch-arm64/syscalls/fchownat.S
+++ b/libc/arch-arm64/syscalls/fchownat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchownat)
     mov     x8, __NR_fchownat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fcntl.S b/libc/arch-arm64/syscalls/fcntl.S
index 45eff74..257c765 100644
--- a/libc/arch-arm64/syscalls/fcntl.S
+++ b/libc/arch-arm64/syscalls/fcntl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fcntl)
     mov     x8, __NR_fcntl
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fdatasync.S b/libc/arch-arm64/syscalls/fdatasync.S
index 77b76c4..233abda 100644
--- a/libc/arch-arm64/syscalls/fdatasync.S
+++ b/libc/arch-arm64/syscalls/fdatasync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fdatasync)
     mov     x8, __NR_fdatasync
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fgetxattr.S b/libc/arch-arm64/syscalls/fgetxattr.S
index 1f8edb6..bd579ff 100644
--- a/libc/arch-arm64/syscalls/fgetxattr.S
+++ b/libc/arch-arm64/syscalls/fgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fgetxattr)
     mov     x8, __NR_fgetxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/flistxattr.S b/libc/arch-arm64/syscalls/flistxattr.S
index 997529e..95ccbe2 100644
--- a/libc/arch-arm64/syscalls/flistxattr.S
+++ b/libc/arch-arm64/syscalls/flistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flistxattr)
     mov     x8, __NR_flistxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/flock.S b/libc/arch-arm64/syscalls/flock.S
index 0e1c3f5..2151d6c 100644
--- a/libc/arch-arm64/syscalls/flock.S
+++ b/libc/arch-arm64/syscalls/flock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flock)
     mov     x8, __NR_flock
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fremovexattr.S b/libc/arch-arm64/syscalls/fremovexattr.S
index d43430f..8dd107d 100644
--- a/libc/arch-arm64/syscalls/fremovexattr.S
+++ b/libc/arch-arm64/syscalls/fremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fremovexattr)
     mov     x8, __NR_fremovexattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fsetxattr.S b/libc/arch-arm64/syscalls/fsetxattr.S
index f40f875..9e54686 100644
--- a/libc/arch-arm64/syscalls/fsetxattr.S
+++ b/libc/arch-arm64/syscalls/fsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsetxattr)
     mov     x8, __NR_fsetxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fstat64.S b/libc/arch-arm64/syscalls/fstat64.S
index 9afe95b..f354e13 100644
--- a/libc/arch-arm64/syscalls/fstat64.S
+++ b/libc/arch-arm64/syscalls/fstat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstat64)
     mov     x8, __NR_fstat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fstatat64.S b/libc/arch-arm64/syscalls/fstatat64.S
index 30efd3b..2fe056e 100644
--- a/libc/arch-arm64/syscalls/fstatat64.S
+++ b/libc/arch-arm64/syscalls/fstatat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatat64)
     mov     x8, __NR_newfstatat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fstatfs64.S b/libc/arch-arm64/syscalls/fstatfs64.S
index 67ae67e..c67ffd6 100644
--- a/libc/arch-arm64/syscalls/fstatfs64.S
+++ b/libc/arch-arm64/syscalls/fstatfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatfs64)
     mov     x8, __NR_fstatfs
     svc     #0
diff --git a/libc/arch-arm64/syscalls/fsync.S b/libc/arch-arm64/syscalls/fsync.S
index e22589e..ae2fc61 100644
--- a/libc/arch-arm64/syscalls/fsync.S
+++ b/libc/arch-arm64/syscalls/fsync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsync)
     mov     x8, __NR_fsync
     svc     #0
diff --git a/libc/arch-arm64/syscalls/ftruncate.S b/libc/arch-arm64/syscalls/ftruncate.S
index b45a170..adf87fe 100644
--- a/libc/arch-arm64/syscalls/ftruncate.S
+++ b/libc/arch-arm64/syscalls/ftruncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate)
     mov     x8, __NR_ftruncate
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getegid.S b/libc/arch-arm64/syscalls/getegid.S
index 675731c..5066cae 100644
--- a/libc/arch-arm64/syscalls/getegid.S
+++ b/libc/arch-arm64/syscalls/getegid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getegid)
     mov     x8, __NR_getegid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/geteuid.S b/libc/arch-arm64/syscalls/geteuid.S
index 8d9461e..25b1ea9 100644
--- a/libc/arch-arm64/syscalls/geteuid.S
+++ b/libc/arch-arm64/syscalls/geteuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(geteuid)
     mov     x8, __NR_geteuid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getgid.S b/libc/arch-arm64/syscalls/getgid.S
index 4653fd8..3f49cb4 100644
--- a/libc/arch-arm64/syscalls/getgid.S
+++ b/libc/arch-arm64/syscalls/getgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgid)
     mov     x8, __NR_getgid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getgroups.S b/libc/arch-arm64/syscalls/getgroups.S
index f22f1e9..3df4974 100644
--- a/libc/arch-arm64/syscalls/getgroups.S
+++ b/libc/arch-arm64/syscalls/getgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgroups)
     mov     x8, __NR_getgroups
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getitimer.S b/libc/arch-arm64/syscalls/getitimer.S
index 25d0b38..70cb731 100644
--- a/libc/arch-arm64/syscalls/getitimer.S
+++ b/libc/arch-arm64/syscalls/getitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getitimer)
     mov     x8, __NR_getitimer
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getpeername.S b/libc/arch-arm64/syscalls/getpeername.S
index aefd0c5..eefb24a 100644
--- a/libc/arch-arm64/syscalls/getpeername.S
+++ b/libc/arch-arm64/syscalls/getpeername.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpeername)
     mov     x8, __NR_getpeername
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getpgid.S b/libc/arch-arm64/syscalls/getpgid.S
index 4c750fb..d12ac52 100644
--- a/libc/arch-arm64/syscalls/getpgid.S
+++ b/libc/arch-arm64/syscalls/getpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpgid)
     mov     x8, __NR_getpgid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getppid.S b/libc/arch-arm64/syscalls/getppid.S
index 540ecc4..af8965b 100644
--- a/libc/arch-arm64/syscalls/getppid.S
+++ b/libc/arch-arm64/syscalls/getppid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getppid)
     mov     x8, __NR_getppid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getresgid.S b/libc/arch-arm64/syscalls/getresgid.S
index 3ce5799..3c1c0c0 100644
--- a/libc/arch-arm64/syscalls/getresgid.S
+++ b/libc/arch-arm64/syscalls/getresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresgid)
     mov     x8, __NR_getresgid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getresuid.S b/libc/arch-arm64/syscalls/getresuid.S
index 56851cc..f50e060 100644
--- a/libc/arch-arm64/syscalls/getresuid.S
+++ b/libc/arch-arm64/syscalls/getresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresuid)
     mov     x8, __NR_getresuid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getrlimit.S b/libc/arch-arm64/syscalls/getrlimit.S
index 1f74773..b759912 100644
--- a/libc/arch-arm64/syscalls/getrlimit.S
+++ b/libc/arch-arm64/syscalls/getrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrlimit)
     mov     x8, __NR_getrlimit
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getrusage.S b/libc/arch-arm64/syscalls/getrusage.S
index 8154e4a..1a0d30f 100644
--- a/libc/arch-arm64/syscalls/getrusage.S
+++ b/libc/arch-arm64/syscalls/getrusage.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrusage)
     mov     x8, __NR_getrusage
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getsid.S b/libc/arch-arm64/syscalls/getsid.S
index f99623f..3c3d753 100644
--- a/libc/arch-arm64/syscalls/getsid.S
+++ b/libc/arch-arm64/syscalls/getsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsid)
     mov     x8, __NR_getsid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getsockname.S b/libc/arch-arm64/syscalls/getsockname.S
index e8bc006..a337986 100644
--- a/libc/arch-arm64/syscalls/getsockname.S
+++ b/libc/arch-arm64/syscalls/getsockname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockname)
     mov     x8, __NR_getsockname
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getsockopt.S b/libc/arch-arm64/syscalls/getsockopt.S
index 4559d1d..4b3abd5 100644
--- a/libc/arch-arm64/syscalls/getsockopt.S
+++ b/libc/arch-arm64/syscalls/getsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockopt)
     mov     x8, __NR_getsockopt
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getuid.S b/libc/arch-arm64/syscalls/getuid.S
index 4e37d47..a9193c5 100644
--- a/libc/arch-arm64/syscalls/getuid.S
+++ b/libc/arch-arm64/syscalls/getuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getuid)
     mov     x8, __NR_getuid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/getxattr.S b/libc/arch-arm64/syscalls/getxattr.S
index 3f69956..afa81ef 100644
--- a/libc/arch-arm64/syscalls/getxattr.S
+++ b/libc/arch-arm64/syscalls/getxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getxattr)
     mov     x8, __NR_getxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/init_module.S b/libc/arch-arm64/syscalls/init_module.S
index cc1a0da..bf0f7d3 100644
--- a/libc/arch-arm64/syscalls/init_module.S
+++ b/libc/arch-arm64/syscalls/init_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(init_module)
     mov     x8, __NR_init_module
     svc     #0
diff --git a/libc/arch-arm64/syscalls/inotify_add_watch.S b/libc/arch-arm64/syscalls/inotify_add_watch.S
index fbc8dd4..dc30ae5 100644
--- a/libc/arch-arm64/syscalls/inotify_add_watch.S
+++ b/libc/arch-arm64/syscalls/inotify_add_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_add_watch)
     mov     x8, __NR_inotify_add_watch
     svc     #0
diff --git a/libc/arch-arm64/syscalls/inotify_init1.S b/libc/arch-arm64/syscalls/inotify_init1.S
index 5726d0c..1b40ef2 100644
--- a/libc/arch-arm64/syscalls/inotify_init1.S
+++ b/libc/arch-arm64/syscalls/inotify_init1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_init1)
     mov     x8, __NR_inotify_init1
     svc     #0
diff --git a/libc/arch-arm64/syscalls/inotify_rm_watch.S b/libc/arch-arm64/syscalls/inotify_rm_watch.S
index 37eabcf..7c99e86 100644
--- a/libc/arch-arm64/syscalls/inotify_rm_watch.S
+++ b/libc/arch-arm64/syscalls/inotify_rm_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_rm_watch)
     mov     x8, __NR_inotify_rm_watch
     svc     #0
diff --git a/libc/arch-arm64/syscalls/kill.S b/libc/arch-arm64/syscalls/kill.S
index 7fc2c5a..e86e3a4 100644
--- a/libc/arch-arm64/syscalls/kill.S
+++ b/libc/arch-arm64/syscalls/kill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(kill)
     mov     x8, __NR_kill
     svc     #0
diff --git a/libc/arch-arm64/syscalls/klogctl.S b/libc/arch-arm64/syscalls/klogctl.S
index abbee55..567db27 100644
--- a/libc/arch-arm64/syscalls/klogctl.S
+++ b/libc/arch-arm64/syscalls/klogctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(klogctl)
     mov     x8, __NR_syslog
     svc     #0
diff --git a/libc/arch-arm64/syscalls/lgetxattr.S b/libc/arch-arm64/syscalls/lgetxattr.S
index e1a760c..187462a 100644
--- a/libc/arch-arm64/syscalls/lgetxattr.S
+++ b/libc/arch-arm64/syscalls/lgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lgetxattr)
     mov     x8, __NR_lgetxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/linkat.S b/libc/arch-arm64/syscalls/linkat.S
index c3e2cd8..7cfc2e0 100644
--- a/libc/arch-arm64/syscalls/linkat.S
+++ b/libc/arch-arm64/syscalls/linkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(linkat)
     mov     x8, __NR_linkat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/listen.S b/libc/arch-arm64/syscalls/listen.S
index 9b7be28..028b9bd 100644
--- a/libc/arch-arm64/syscalls/listen.S
+++ b/libc/arch-arm64/syscalls/listen.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listen)
     mov     x8, __NR_listen
     svc     #0
diff --git a/libc/arch-arm64/syscalls/listxattr.S b/libc/arch-arm64/syscalls/listxattr.S
index a5e55c7..335fafe 100644
--- a/libc/arch-arm64/syscalls/listxattr.S
+++ b/libc/arch-arm64/syscalls/listxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listxattr)
     mov     x8, __NR_listxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/llistxattr.S b/libc/arch-arm64/syscalls/llistxattr.S
index 447e208..e796741 100644
--- a/libc/arch-arm64/syscalls/llistxattr.S
+++ b/libc/arch-arm64/syscalls/llistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(llistxattr)
     mov     x8, __NR_llistxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/lremovexattr.S b/libc/arch-arm64/syscalls/lremovexattr.S
index 1f620db..9f4c027 100644
--- a/libc/arch-arm64/syscalls/lremovexattr.S
+++ b/libc/arch-arm64/syscalls/lremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lremovexattr)
     mov     x8, __NR_lremovexattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/lseek.S b/libc/arch-arm64/syscalls/lseek.S
index 1b858b2..aa71768 100644
--- a/libc/arch-arm64/syscalls/lseek.S
+++ b/libc/arch-arm64/syscalls/lseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lseek)
     mov     x8, __NR_lseek
     svc     #0
diff --git a/libc/arch-arm64/syscalls/lsetxattr.S b/libc/arch-arm64/syscalls/lsetxattr.S
index 8315bba..babf02d 100644
--- a/libc/arch-arm64/syscalls/lsetxattr.S
+++ b/libc/arch-arm64/syscalls/lsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lsetxattr)
     mov     x8, __NR_lsetxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/madvise.S b/libc/arch-arm64/syscalls/madvise.S
index 17282c0..3d393f1 100644
--- a/libc/arch-arm64/syscalls/madvise.S
+++ b/libc/arch-arm64/syscalls/madvise.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(madvise)
     mov     x8, __NR_madvise
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mincore.S b/libc/arch-arm64/syscalls/mincore.S
index abdcf6c..4432574 100644
--- a/libc/arch-arm64/syscalls/mincore.S
+++ b/libc/arch-arm64/syscalls/mincore.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mincore)
     mov     x8, __NR_mincore
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mkdirat.S b/libc/arch-arm64/syscalls/mkdirat.S
index d6bafca..36c876d 100644
--- a/libc/arch-arm64/syscalls/mkdirat.S
+++ b/libc/arch-arm64/syscalls/mkdirat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mkdirat)
     mov     x8, __NR_mkdirat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mknodat.S b/libc/arch-arm64/syscalls/mknodat.S
index 598e789..e0584db 100644
--- a/libc/arch-arm64/syscalls/mknodat.S
+++ b/libc/arch-arm64/syscalls/mknodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mknodat)
     mov     x8, __NR_mknodat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mlock.S b/libc/arch-arm64/syscalls/mlock.S
index 631ce02..10ddb07 100644
--- a/libc/arch-arm64/syscalls/mlock.S
+++ b/libc/arch-arm64/syscalls/mlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlock)
     mov     x8, __NR_mlock
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mlockall.S b/libc/arch-arm64/syscalls/mlockall.S
index 42dac9e..3602d71 100644
--- a/libc/arch-arm64/syscalls/mlockall.S
+++ b/libc/arch-arm64/syscalls/mlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlockall)
     mov     x8, __NR_mlockall
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mmap.S b/libc/arch-arm64/syscalls/mmap.S
index da18e10..e4e39ca 100644
--- a/libc/arch-arm64/syscalls/mmap.S
+++ b/libc/arch-arm64/syscalls/mmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mmap)
     mov     x8, __NR_mmap
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mount.S b/libc/arch-arm64/syscalls/mount.S
index c43a71f..9b53754 100644
--- a/libc/arch-arm64/syscalls/mount.S
+++ b/libc/arch-arm64/syscalls/mount.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mount)
     mov     x8, __NR_mount
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mprotect.S b/libc/arch-arm64/syscalls/mprotect.S
index a7d26dd..788d46e 100644
--- a/libc/arch-arm64/syscalls/mprotect.S
+++ b/libc/arch-arm64/syscalls/mprotect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mprotect)
     mov     x8, __NR_mprotect
     svc     #0
diff --git a/libc/arch-arm64/syscalls/mremap.S b/libc/arch-arm64/syscalls/mremap.S
index 337bbae..861d52a 100644
--- a/libc/arch-arm64/syscalls/mremap.S
+++ b/libc/arch-arm64/syscalls/mremap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mremap)
     mov     x8, __NR_mremap
     svc     #0
diff --git a/libc/arch-arm64/syscalls/msync.S b/libc/arch-arm64/syscalls/msync.S
index c54797e..009ce18 100644
--- a/libc/arch-arm64/syscalls/msync.S
+++ b/libc/arch-arm64/syscalls/msync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(msync)
     mov     x8, __NR_msync
     svc     #0
diff --git a/libc/arch-arm64/syscalls/munlock.S b/libc/arch-arm64/syscalls/munlock.S
index b1ec016..45d6d17 100644
--- a/libc/arch-arm64/syscalls/munlock.S
+++ b/libc/arch-arm64/syscalls/munlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlock)
     mov     x8, __NR_munlock
     svc     #0
diff --git a/libc/arch-arm64/syscalls/munlockall.S b/libc/arch-arm64/syscalls/munlockall.S
index f9162a8..6240622 100644
--- a/libc/arch-arm64/syscalls/munlockall.S
+++ b/libc/arch-arm64/syscalls/munlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlockall)
     mov     x8, __NR_munlockall
     svc     #0
diff --git a/libc/arch-arm64/syscalls/munmap.S b/libc/arch-arm64/syscalls/munmap.S
index 6bd5afe..0291268 100644
--- a/libc/arch-arm64/syscalls/munmap.S
+++ b/libc/arch-arm64/syscalls/munmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munmap)
     mov     x8, __NR_munmap
     svc     #0
diff --git a/libc/arch-arm64/syscalls/nanosleep.S b/libc/arch-arm64/syscalls/nanosleep.S
index c84accc..7496530 100644
--- a/libc/arch-arm64/syscalls/nanosleep.S
+++ b/libc/arch-arm64/syscalls/nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(nanosleep)
     mov     x8, __NR_nanosleep
     svc     #0
diff --git a/libc/arch-arm64/syscalls/personality.S b/libc/arch-arm64/syscalls/personality.S
index 02bcf9b..1c6530c 100644
--- a/libc/arch-arm64/syscalls/personality.S
+++ b/libc/arch-arm64/syscalls/personality.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(personality)
     mov     x8, __NR_personality
     svc     #0
diff --git a/libc/arch-arm64/syscalls/pipe2.S b/libc/arch-arm64/syscalls/pipe2.S
index f4da37d..45538d3 100644
--- a/libc/arch-arm64/syscalls/pipe2.S
+++ b/libc/arch-arm64/syscalls/pipe2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pipe2)
     mov     x8, __NR_pipe2
     svc     #0
diff --git a/libc/arch-arm64/syscalls/prctl.S b/libc/arch-arm64/syscalls/prctl.S
index 2e6dca7..ddfe5a6 100644
--- a/libc/arch-arm64/syscalls/prctl.S
+++ b/libc/arch-arm64/syscalls/prctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prctl)
     mov     x8, __NR_prctl
     svc     #0
diff --git a/libc/arch-arm64/syscalls/pread64.S b/libc/arch-arm64/syscalls/pread64.S
index 2aba596..9c2fb34 100644
--- a/libc/arch-arm64/syscalls/pread64.S
+++ b/libc/arch-arm64/syscalls/pread64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pread64)
     mov     x8, __NR_pread64
     svc     #0
diff --git a/libc/arch-arm64/syscalls/prlimit64.S b/libc/arch-arm64/syscalls/prlimit64.S
index a2173d9..d3e07b9 100644
--- a/libc/arch-arm64/syscalls/prlimit64.S
+++ b/libc/arch-arm64/syscalls/prlimit64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prlimit64)
     mov     x8, __NR_prlimit64
     svc     #0
diff --git a/libc/arch-arm64/syscalls/pwrite64.S b/libc/arch-arm64/syscalls/pwrite64.S
index 5674a7c..33ae24b 100644
--- a/libc/arch-arm64/syscalls/pwrite64.S
+++ b/libc/arch-arm64/syscalls/pwrite64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pwrite64)
     mov     x8, __NR_pwrite64
     svc     #0
diff --git a/libc/arch-arm64/syscalls/read.S b/libc/arch-arm64/syscalls/read.S
index 906fb98..3440391 100644
--- a/libc/arch-arm64/syscalls/read.S
+++ b/libc/arch-arm64/syscalls/read.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(read)
     mov     x8, __NR_read
     svc     #0
diff --git a/libc/arch-arm64/syscalls/readahead.S b/libc/arch-arm64/syscalls/readahead.S
index 2994b83..73683f2 100644
--- a/libc/arch-arm64/syscalls/readahead.S
+++ b/libc/arch-arm64/syscalls/readahead.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readahead)
     mov     x8, __NR_readahead
     svc     #0
diff --git a/libc/arch-arm64/syscalls/readlinkat.S b/libc/arch-arm64/syscalls/readlinkat.S
index 1782c94..1a89d21 100644
--- a/libc/arch-arm64/syscalls/readlinkat.S
+++ b/libc/arch-arm64/syscalls/readlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readlinkat)
     mov     x8, __NR_readlinkat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/readv.S b/libc/arch-arm64/syscalls/readv.S
index bc988d4..b5d154a 100644
--- a/libc/arch-arm64/syscalls/readv.S
+++ b/libc/arch-arm64/syscalls/readv.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readv)
     mov     x8, __NR_readv
     svc     #0
diff --git a/libc/arch-arm64/syscalls/recvfrom.S b/libc/arch-arm64/syscalls/recvfrom.S
index 16f97d5..80bc1aa 100644
--- a/libc/arch-arm64/syscalls/recvfrom.S
+++ b/libc/arch-arm64/syscalls/recvfrom.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvfrom)
     mov     x8, __NR_recvfrom
     svc     #0
diff --git a/libc/arch-arm64/syscalls/recvmmsg.S b/libc/arch-arm64/syscalls/recvmmsg.S
index bd1495a..aa69442 100644
--- a/libc/arch-arm64/syscalls/recvmmsg.S
+++ b/libc/arch-arm64/syscalls/recvmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmmsg)
     mov     x8, __NR_recvmmsg
     svc     #0
diff --git a/libc/arch-arm64/syscalls/recvmsg.S b/libc/arch-arm64/syscalls/recvmsg.S
index c9b78c4..095e2aa 100644
--- a/libc/arch-arm64/syscalls/recvmsg.S
+++ b/libc/arch-arm64/syscalls/recvmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmsg)
     mov     x8, __NR_recvmsg
     svc     #0
diff --git a/libc/arch-arm64/syscalls/removexattr.S b/libc/arch-arm64/syscalls/removexattr.S
index c12cc84..f279f01 100644
--- a/libc/arch-arm64/syscalls/removexattr.S
+++ b/libc/arch-arm64/syscalls/removexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(removexattr)
     mov     x8, __NR_removexattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/renameat.S b/libc/arch-arm64/syscalls/renameat.S
index cf79472..7c308cd 100644
--- a/libc/arch-arm64/syscalls/renameat.S
+++ b/libc/arch-arm64/syscalls/renameat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(renameat)
     mov     x8, __NR_renameat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_get_priority_max.S b/libc/arch-arm64/syscalls/sched_get_priority_max.S
index 672d0ea..e80ce35 100644
--- a/libc/arch-arm64/syscalls/sched_get_priority_max.S
+++ b/libc/arch-arm64/syscalls/sched_get_priority_max.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_max)
     mov     x8, __NR_sched_get_priority_max
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_get_priority_min.S b/libc/arch-arm64/syscalls/sched_get_priority_min.S
index f5cf1f3..3f5f487 100644
--- a/libc/arch-arm64/syscalls/sched_get_priority_min.S
+++ b/libc/arch-arm64/syscalls/sched_get_priority_min.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_min)
     mov     x8, __NR_sched_get_priority_min
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_getparam.S b/libc/arch-arm64/syscalls/sched_getparam.S
index 7ffe8fb..1756867 100644
--- a/libc/arch-arm64/syscalls/sched_getparam.S
+++ b/libc/arch-arm64/syscalls/sched_getparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getparam)
     mov     x8, __NR_sched_getparam
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_getscheduler.S b/libc/arch-arm64/syscalls/sched_getscheduler.S
index b69b8c0..8fa145f 100644
--- a/libc/arch-arm64/syscalls/sched_getscheduler.S
+++ b/libc/arch-arm64/syscalls/sched_getscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getscheduler)
     mov     x8, __NR_sched_getscheduler
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_rr_get_interval.S b/libc/arch-arm64/syscalls/sched_rr_get_interval.S
index 0be14ba..7ff393c 100644
--- a/libc/arch-arm64/syscalls/sched_rr_get_interval.S
+++ b/libc/arch-arm64/syscalls/sched_rr_get_interval.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_rr_get_interval)
     mov     x8, __NR_sched_rr_get_interval
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_setaffinity.S b/libc/arch-arm64/syscalls/sched_setaffinity.S
index f5cbc77..2878459 100644
--- a/libc/arch-arm64/syscalls/sched_setaffinity.S
+++ b/libc/arch-arm64/syscalls/sched_setaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setaffinity)
     mov     x8, __NR_sched_setaffinity
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_setparam.S b/libc/arch-arm64/syscalls/sched_setparam.S
index cff64f5..4135606 100644
--- a/libc/arch-arm64/syscalls/sched_setparam.S
+++ b/libc/arch-arm64/syscalls/sched_setparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setparam)
     mov     x8, __NR_sched_setparam
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_setscheduler.S b/libc/arch-arm64/syscalls/sched_setscheduler.S
index 31600a0..e8f991c 100644
--- a/libc/arch-arm64/syscalls/sched_setscheduler.S
+++ b/libc/arch-arm64/syscalls/sched_setscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setscheduler)
     mov     x8, __NR_sched_setscheduler
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sched_yield.S b/libc/arch-arm64/syscalls/sched_yield.S
index 21ad601..cd6a978 100644
--- a/libc/arch-arm64/syscalls/sched_yield.S
+++ b/libc/arch-arm64/syscalls/sched_yield.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_yield)
     mov     x8, __NR_sched_yield
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sendfile.S b/libc/arch-arm64/syscalls/sendfile.S
index db90caa..c579224 100644
--- a/libc/arch-arm64/syscalls/sendfile.S
+++ b/libc/arch-arm64/syscalls/sendfile.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile)
     mov     x8, __NR_sendfile
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sendmmsg.S b/libc/arch-arm64/syscalls/sendmmsg.S
index e85798a..e9ce811 100644
--- a/libc/arch-arm64/syscalls/sendmmsg.S
+++ b/libc/arch-arm64/syscalls/sendmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmmsg)
     mov     x8, __NR_sendmmsg
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sendmsg.S b/libc/arch-arm64/syscalls/sendmsg.S
index 25eff84..78c5e68 100644
--- a/libc/arch-arm64/syscalls/sendmsg.S
+++ b/libc/arch-arm64/syscalls/sendmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmsg)
     mov     x8, __NR_sendmsg
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sendto.S b/libc/arch-arm64/syscalls/sendto.S
index 39e4e4e..a3ef95d 100644
--- a/libc/arch-arm64/syscalls/sendto.S
+++ b/libc/arch-arm64/syscalls/sendto.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendto)
     mov     x8, __NR_sendto
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setfsgid.S b/libc/arch-arm64/syscalls/setfsgid.S
new file mode 100644
index 0000000..4d28536
--- /dev/null
+++ b/libc/arch-arm64/syscalls/setfsgid.S
@@ -0,0 +1,16 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsgid)
+    mov     x8, __NR_setfsgid
+    svc     #0
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno
+
+    ret
+END(setfsgid)
diff --git a/libc/arch-arm64/syscalls/setfsuid.S b/libc/arch-arm64/syscalls/setfsuid.S
new file mode 100644
index 0000000..238bbf8
--- /dev/null
+++ b/libc/arch-arm64/syscalls/setfsuid.S
@@ -0,0 +1,16 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsuid)
+    mov     x8, __NR_setfsuid
+    svc     #0
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno
+
+    ret
+END(setfsuid)
diff --git a/libc/arch-arm64/syscalls/setgid.S b/libc/arch-arm64/syscalls/setgid.S
index a9789f7..182ce1f 100644
--- a/libc/arch-arm64/syscalls/setgid.S
+++ b/libc/arch-arm64/syscalls/setgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgid)
     mov     x8, __NR_setgid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setgroups.S b/libc/arch-arm64/syscalls/setgroups.S
index ce9bf01..2bc5c7f 100644
--- a/libc/arch-arm64/syscalls/setgroups.S
+++ b/libc/arch-arm64/syscalls/setgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgroups)
     mov     x8, __NR_setgroups
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setitimer.S b/libc/arch-arm64/syscalls/setitimer.S
index d8e3d7e..1a5bbb3 100644
--- a/libc/arch-arm64/syscalls/setitimer.S
+++ b/libc/arch-arm64/syscalls/setitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setitimer)
     mov     x8, __NR_setitimer
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setns.S b/libc/arch-arm64/syscalls/setns.S
index 615f888..68c32da 100644
--- a/libc/arch-arm64/syscalls/setns.S
+++ b/libc/arch-arm64/syscalls/setns.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setns)
     mov     x8, __NR_setns
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setpgid.S b/libc/arch-arm64/syscalls/setpgid.S
index 6015264..890d354 100644
--- a/libc/arch-arm64/syscalls/setpgid.S
+++ b/libc/arch-arm64/syscalls/setpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpgid)
     mov     x8, __NR_setpgid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setpriority.S b/libc/arch-arm64/syscalls/setpriority.S
index d2f517e..17550ea 100644
--- a/libc/arch-arm64/syscalls/setpriority.S
+++ b/libc/arch-arm64/syscalls/setpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpriority)
     mov     x8, __NR_setpriority
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setregid.S b/libc/arch-arm64/syscalls/setregid.S
index 7b333bf..aa351a8 100644
--- a/libc/arch-arm64/syscalls/setregid.S
+++ b/libc/arch-arm64/syscalls/setregid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setregid)
     mov     x8, __NR_setregid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setresgid.S b/libc/arch-arm64/syscalls/setresgid.S
index 39504bd..517e59e 100644
--- a/libc/arch-arm64/syscalls/setresgid.S
+++ b/libc/arch-arm64/syscalls/setresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresgid)
     mov     x8, __NR_setresgid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setresuid.S b/libc/arch-arm64/syscalls/setresuid.S
index 5acbffd..6829cef 100644
--- a/libc/arch-arm64/syscalls/setresuid.S
+++ b/libc/arch-arm64/syscalls/setresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresuid)
     mov     x8, __NR_setresuid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setreuid.S b/libc/arch-arm64/syscalls/setreuid.S
index 63630d6..af342ef 100644
--- a/libc/arch-arm64/syscalls/setreuid.S
+++ b/libc/arch-arm64/syscalls/setreuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setreuid)
     mov     x8, __NR_setreuid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setrlimit.S b/libc/arch-arm64/syscalls/setrlimit.S
index f9f56a6..4401984 100644
--- a/libc/arch-arm64/syscalls/setrlimit.S
+++ b/libc/arch-arm64/syscalls/setrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setrlimit)
     mov     x8, __NR_setrlimit
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setsid.S b/libc/arch-arm64/syscalls/setsid.S
index 04c28e3..64c76f2 100644
--- a/libc/arch-arm64/syscalls/setsid.S
+++ b/libc/arch-arm64/syscalls/setsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsid)
     mov     x8, __NR_setsid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setsockopt.S b/libc/arch-arm64/syscalls/setsockopt.S
index 0ebc6d0..51af847 100644
--- a/libc/arch-arm64/syscalls/setsockopt.S
+++ b/libc/arch-arm64/syscalls/setsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsockopt)
     mov     x8, __NR_setsockopt
     svc     #0
diff --git a/libc/arch-arm64/syscalls/settimeofday.S b/libc/arch-arm64/syscalls/settimeofday.S
index 474e40d..357998c 100644
--- a/libc/arch-arm64/syscalls/settimeofday.S
+++ b/libc/arch-arm64/syscalls/settimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(settimeofday)
     mov     x8, __NR_settimeofday
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setuid.S b/libc/arch-arm64/syscalls/setuid.S
index fe52921..ad42434 100644
--- a/libc/arch-arm64/syscalls/setuid.S
+++ b/libc/arch-arm64/syscalls/setuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setuid)
     mov     x8, __NR_setuid
     svc     #0
diff --git a/libc/arch-arm64/syscalls/setxattr.S b/libc/arch-arm64/syscalls/setxattr.S
index 8d0b415..cde2d5f 100644
--- a/libc/arch-arm64/syscalls/setxattr.S
+++ b/libc/arch-arm64/syscalls/setxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setxattr)
     mov     x8, __NR_setxattr
     svc     #0
diff --git a/libc/arch-arm64/syscalls/shutdown.S b/libc/arch-arm64/syscalls/shutdown.S
index e35cdea..4813647 100644
--- a/libc/arch-arm64/syscalls/shutdown.S
+++ b/libc/arch-arm64/syscalls/shutdown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(shutdown)
     mov     x8, __NR_shutdown
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sigaltstack.S b/libc/arch-arm64/syscalls/sigaltstack.S
index 6a38203..74f7e50 100644
--- a/libc/arch-arm64/syscalls/sigaltstack.S
+++ b/libc/arch-arm64/syscalls/sigaltstack.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sigaltstack)
     mov     x8, __NR_sigaltstack
     svc     #0
diff --git a/libc/arch-arm64/syscalls/socketpair.S b/libc/arch-arm64/syscalls/socketpair.S
index dcd7223..ec2a3d2 100644
--- a/libc/arch-arm64/syscalls/socketpair.S
+++ b/libc/arch-arm64/syscalls/socketpair.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(socketpair)
     mov     x8, __NR_socketpair
     svc     #0
diff --git a/libc/arch-arm64/syscalls/splice.S b/libc/arch-arm64/syscalls/splice.S
index 103805a..30443a8 100644
--- a/libc/arch-arm64/syscalls/splice.S
+++ b/libc/arch-arm64/syscalls/splice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(splice)
     mov     x8, __NR_splice
     svc     #0
diff --git a/libc/arch-arm64/syscalls/statfs64.S b/libc/arch-arm64/syscalls/statfs64.S
index 55633c1..00b32e7 100644
--- a/libc/arch-arm64/syscalls/statfs64.S
+++ b/libc/arch-arm64/syscalls/statfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(statfs64)
     mov     x8, __NR_statfs
     svc     #0
diff --git a/libc/arch-arm64/syscalls/swapoff.S b/libc/arch-arm64/syscalls/swapoff.S
index dcef4af..54dabb5 100644
--- a/libc/arch-arm64/syscalls/swapoff.S
+++ b/libc/arch-arm64/syscalls/swapoff.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapoff)
     mov     x8, __NR_swapoff
     svc     #0
diff --git a/libc/arch-arm64/syscalls/swapon.S b/libc/arch-arm64/syscalls/swapon.S
index aef7627..952252f 100644
--- a/libc/arch-arm64/syscalls/swapon.S
+++ b/libc/arch-arm64/syscalls/swapon.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapon)
     mov     x8, __NR_swapon
     svc     #0
diff --git a/libc/arch-arm64/syscalls/symlinkat.S b/libc/arch-arm64/syscalls/symlinkat.S
index 9830865..27f9334 100644
--- a/libc/arch-arm64/syscalls/symlinkat.S
+++ b/libc/arch-arm64/syscalls/symlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(symlinkat)
     mov     x8, __NR_symlinkat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sync.S b/libc/arch-arm64/syscalls/sync.S
index 3ef0460..622b028 100644
--- a/libc/arch-arm64/syscalls/sync.S
+++ b/libc/arch-arm64/syscalls/sync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sync)
     mov     x8, __NR_sync
     svc     #0
diff --git a/libc/arch-arm64/syscalls/sysinfo.S b/libc/arch-arm64/syscalls/sysinfo.S
index 7dbe152..81d8a94 100644
--- a/libc/arch-arm64/syscalls/sysinfo.S
+++ b/libc/arch-arm64/syscalls/sysinfo.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sysinfo)
     mov     x8, __NR_sysinfo
     svc     #0
diff --git a/libc/arch-arm64/syscalls/tee.S b/libc/arch-arm64/syscalls/tee.S
index d730076..cb317aa 100644
--- a/libc/arch-arm64/syscalls/tee.S
+++ b/libc/arch-arm64/syscalls/tee.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tee)
     mov     x8, __NR_tee
     svc     #0
diff --git a/libc/arch-arm64/syscalls/tgkill.S b/libc/arch-arm64/syscalls/tgkill.S
index 477c477..908811d 100644
--- a/libc/arch-arm64/syscalls/tgkill.S
+++ b/libc/arch-arm64/syscalls/tgkill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tgkill)
     mov     x8, __NR_tgkill
     svc     #0
diff --git a/libc/arch-arm64/syscalls/timerfd_create.S b/libc/arch-arm64/syscalls/timerfd_create.S
index 83b5910..5487492 100644
--- a/libc/arch-arm64/syscalls/timerfd_create.S
+++ b/libc/arch-arm64/syscalls/timerfd_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_create)
     mov     x8, __NR_timerfd_create
     svc     #0
diff --git a/libc/arch-arm64/syscalls/timerfd_gettime.S b/libc/arch-arm64/syscalls/timerfd_gettime.S
index 253cb79..1c5151f 100644
--- a/libc/arch-arm64/syscalls/timerfd_gettime.S
+++ b/libc/arch-arm64/syscalls/timerfd_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_gettime)
     mov     x8, __NR_timerfd_gettime
     svc     #0
diff --git a/libc/arch-arm64/syscalls/timerfd_settime.S b/libc/arch-arm64/syscalls/timerfd_settime.S
index 8872481..edd81fac 100644
--- a/libc/arch-arm64/syscalls/timerfd_settime.S
+++ b/libc/arch-arm64/syscalls/timerfd_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_settime)
     mov     x8, __NR_timerfd_settime
     svc     #0
diff --git a/libc/arch-arm64/syscalls/times.S b/libc/arch-arm64/syscalls/times.S
index 33c7d55..5541732 100644
--- a/libc/arch-arm64/syscalls/times.S
+++ b/libc/arch-arm64/syscalls/times.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(times)
     mov     x8, __NR_times
     svc     #0
diff --git a/libc/arch-arm64/syscalls/truncate.S b/libc/arch-arm64/syscalls/truncate.S
index f15253b..be5765c 100644
--- a/libc/arch-arm64/syscalls/truncate.S
+++ b/libc/arch-arm64/syscalls/truncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate)
     mov     x8, __NR_truncate
     svc     #0
diff --git a/libc/arch-arm64/syscalls/umask.S b/libc/arch-arm64/syscalls/umask.S
index 8b907b4..c605b8f 100644
--- a/libc/arch-arm64/syscalls/umask.S
+++ b/libc/arch-arm64/syscalls/umask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umask)
     mov     x8, __NR_umask
     svc     #0
diff --git a/libc/arch-arm64/syscalls/umount2.S b/libc/arch-arm64/syscalls/umount2.S
index 5646dba..73ed330 100644
--- a/libc/arch-arm64/syscalls/umount2.S
+++ b/libc/arch-arm64/syscalls/umount2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umount2)
     mov     x8, __NR_umount2
     svc     #0
diff --git a/libc/arch-arm64/syscalls/uname.S b/libc/arch-arm64/syscalls/uname.S
index 09ec096..4d52190 100644
--- a/libc/arch-arm64/syscalls/uname.S
+++ b/libc/arch-arm64/syscalls/uname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(uname)
     mov     x8, __NR_uname
     svc     #0
diff --git a/libc/arch-arm64/syscalls/unlinkat.S b/libc/arch-arm64/syscalls/unlinkat.S
index 992f675..8fde96e 100644
--- a/libc/arch-arm64/syscalls/unlinkat.S
+++ b/libc/arch-arm64/syscalls/unlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unlinkat)
     mov     x8, __NR_unlinkat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/unshare.S b/libc/arch-arm64/syscalls/unshare.S
index 1062dcd..ba960e2 100644
--- a/libc/arch-arm64/syscalls/unshare.S
+++ b/libc/arch-arm64/syscalls/unshare.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unshare)
     mov     x8, __NR_unshare
     svc     #0
diff --git a/libc/arch-arm64/syscalls/utimensat.S b/libc/arch-arm64/syscalls/utimensat.S
index 8a25ed6..9e4b1ca 100644
--- a/libc/arch-arm64/syscalls/utimensat.S
+++ b/libc/arch-arm64/syscalls/utimensat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(utimensat)
     mov     x8, __NR_utimensat
     svc     #0
diff --git a/libc/arch-arm64/syscalls/vmsplice.S b/libc/arch-arm64/syscalls/vmsplice.S
index b4bec3f..6a13c5b 100644
--- a/libc/arch-arm64/syscalls/vmsplice.S
+++ b/libc/arch-arm64/syscalls/vmsplice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(vmsplice)
     mov     x8, __NR_vmsplice
     svc     #0
diff --git a/libc/arch-arm64/syscalls/wait4.S b/libc/arch-arm64/syscalls/wait4.S
index a0d5d62..f2bcd34 100644
--- a/libc/arch-arm64/syscalls/wait4.S
+++ b/libc/arch-arm64/syscalls/wait4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(wait4)
     mov     x8, __NR_wait4
     svc     #0
diff --git a/libc/arch-arm64/syscalls/write.S b/libc/arch-arm64/syscalls/write.S
index d64552e..1fedabe 100644
--- a/libc/arch-arm64/syscalls/write.S
+++ b/libc/arch-arm64/syscalls/write.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(write)
     mov     x8, __NR_write
     svc     #0
diff --git a/libc/arch-arm64/syscalls/writev.S b/libc/arch-arm64/syscalls/writev.S
index 45d5c8d..9942ddb 100644
--- a/libc/arch-arm64/syscalls/writev.S
+++ b/libc/arch-arm64/syscalls/writev.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(writev)
     mov     x8, __NR_writev
     svc     #0
diff --git a/libc/arch-mips/bionic/__get_sp.S b/libc/arch-mips/bionic/__get_sp.S
deleted file mode 100644
index 5f5d32e..0000000
--- a/libc/arch-mips/bionic/__get_sp.S
+++ /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 <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
-  move v0, sp
-  j ra
-END(__get_sp)
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-x86/bionic/__get_sp.S b/libc/arch-mips/bionic/vfork.S
similarity index 77%
copy from libc/arch-x86/bionic/__get_sp.S
copy to libc/arch-mips/bionic/vfork.S
index aea6ac6..96de69e 100644
--- a/libc/arch-x86/bionic/__get_sp.S
+++ b/libc/arch-mips/bionic/vfork.S
@@ -27,8 +27,32 @@
  */
 
 #include <private/bionic_asm.h>
+#include <linux/sched.h>
 
-ENTRY_PRIVATE(__get_sp)
-  mov  %esp, %eax
-  ret
-END(__get_sp)
+// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__.
+// #include <asm/signal.h>
+#define SIGCHLD 18
+
+ENTRY(vfork)
+	.set	noreorder
+	.cpload	t9
+
+	li	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
+	li	a1, 0
+	li	a2, 0
+	li	a3, 0
+	subu	sp, 8
+	sw	$0, 16(sp)
+	li	v0, __NR_clone
+	syscall
+	addu	sp, 8
+	bnez	a3, 1f
+	 move	a0, v0
+
+	j	ra
+	 nop
+1:
+	la	t9, __set_errno
+	j	t9
+	 nop
+END(vfork)
diff --git a/libc/arch-mips/include/machine/asm.h b/libc/arch-mips/include/machine/asm.h
index 5eacde3..cdc7914 100644
--- a/libc/arch-mips/include/machine/asm.h
+++ b/libc/arch-mips/include/machine/asm.h
@@ -28,9 +28,7 @@
 #ifndef _MIPS64_ASM_H
 #define _MIPS64_ASM_H
 
-#ifndef _ALIGN_TEXT
-# define _ALIGN_TEXT .align 4
-#endif
+#define __bionic_asm_align 4
 
 #undef __bionic_asm_custom_entry
 #undef __bionic_asm_custom_end
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index 0a3718b..31a1f32 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 += \
@@ -59,15 +54,26 @@
     arch-mips/bionic/bzero.S \
     arch-mips/bionic/cacheflush.cpp \
     arch-mips/bionic/_exit_with_stack_teardown.S \
-    arch-mips/bionic/__get_sp.S \
     arch-mips/bionic/_setjmp.S \
     arch-mips/bionic/setjmp.S \
     arch-mips/bionic/sigsetjmp.S \
     arch-mips/bionic/syscall.S \
+    arch-mips/bionic/vfork.S \
+
+ifndef ARCH_MIPS_REV6
+libc_bionic_src_files_mips += \
     arch-mips/string/memcpy.S \
     arch-mips/string/memset.S \
     arch-mips/string/mips_strlen.c \
 
+else
+libc_bionic_src_files_mips += \
+    bionic/memcpy.cpp \
+    bionic/memset.c
+libc_common_src_files_mips += \
+    upstream-openbsd/lib/libc/string/strlen.c
+endif
+
 libc_netbsd_src_files_mips := \
     upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
 
@@ -83,3 +89,6 @@
 
 libc_crt_target_so_cflags_mips := \
     -fPIC
+
+libc_crt_target_ldflags_mips := \
+    -melf32ltsmip
diff --git a/libc/arch-mips/syscalls/__accept4.S b/libc/arch-mips/syscalls/__accept4.S
index 8634a35..2fc8b2a 100644
--- a/libc/arch-mips/syscalls/__accept4.S
+++ b/libc/arch-mips/syscalls/__accept4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__accept4)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__brk.S b/libc/arch-mips/syscalls/__brk.S
index 9325c26..0593b4f 100644
--- a/libc/arch-mips/syscalls/__brk.S
+++ b/libc/arch-mips/syscalls/__brk.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__brk)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__connect.S b/libc/arch-mips/syscalls/__connect.S
index f7ac916..20f60e4 100644
--- a/libc/arch-mips/syscalls/__connect.S
+++ b/libc/arch-mips/syscalls/__connect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__connect)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__epoll_pwait.S b/libc/arch-mips/syscalls/__epoll_pwait.S
index a417cdd..3e735f1 100644
--- a/libc/arch-mips/syscalls/__epoll_pwait.S
+++ b/libc/arch-mips/syscalls/__epoll_pwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__epoll_pwait)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__exit.S b/libc/arch-mips/syscalls/__exit.S
index 1515b41..40c2f87 100644
--- a/libc/arch-mips/syscalls/__exit.S
+++ b/libc/arch-mips/syscalls/__exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__exit)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__fcntl64.S b/libc/arch-mips/syscalls/__fcntl64.S
index b9815a1..b541edd 100644
--- a/libc/arch-mips/syscalls/__fcntl64.S
+++ b/libc/arch-mips/syscalls/__fcntl64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__fcntl64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__fstatfs64.S b/libc/arch-mips/syscalls/__fstatfs64.S
index 8774a53..d1d68ab 100644
--- a/libc/arch-mips/syscalls/__fstatfs64.S
+++ b/libc/arch-mips/syscalls/__fstatfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__fstatfs64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__getcpu.S b/libc/arch-mips/syscalls/__getcpu.S
index 2352e01..ab3acca 100644
--- a/libc/arch-mips/syscalls/__getcpu.S
+++ b/libc/arch-mips/syscalls/__getcpu.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcpu)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__getcwd.S b/libc/arch-mips/syscalls/__getcwd.S
index e844f9a..af1c494 100644
--- a/libc/arch-mips/syscalls/__getcwd.S
+++ b/libc/arch-mips/syscalls/__getcwd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcwd)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__getdents64.S b/libc/arch-mips/syscalls/__getdents64.S
index 136b408..e88c6df 100644
--- a/libc/arch-mips/syscalls/__getdents64.S
+++ b/libc/arch-mips/syscalls/__getdents64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getdents64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__getpid.S b/libc/arch-mips/syscalls/__getpid.S
index 52cf6f4..d20188b 100644
--- a/libc/arch-mips/syscalls/__getpid.S
+++ b/libc/arch-mips/syscalls/__getpid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__getpriority.S b/libc/arch-mips/syscalls/__getpriority.S
index 882386b..bc1efb3 100644
--- a/libc/arch-mips/syscalls/__getpriority.S
+++ b/libc/arch-mips/syscalls/__getpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpriority)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__ioctl.S b/libc/arch-mips/syscalls/__ioctl.S
index ddf5323..28af834 100644
--- a/libc/arch-mips/syscalls/__ioctl.S
+++ b/libc/arch-mips/syscalls/__ioctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ioctl)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__llseek.S b/libc/arch-mips/syscalls/__llseek.S
index 10819f7..81cf459 100644
--- a/libc/arch-mips/syscalls/__llseek.S
+++ b/libc/arch-mips/syscalls/__llseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__llseek)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__mmap2.S b/libc/arch-mips/syscalls/__mmap2.S
index 5372817..e6022c3 100644
--- a/libc/arch-mips/syscalls/__mmap2.S
+++ b/libc/arch-mips/syscalls/__mmap2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__mmap2)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__openat.S b/libc/arch-mips/syscalls/__openat.S
index f833dd8..0482b5a 100644
--- a/libc/arch-mips/syscalls/__openat.S
+++ b/libc/arch-mips/syscalls/__openat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__openat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__ppoll.S b/libc/arch-mips/syscalls/__ppoll.S
index a5711d9..7cd29f6 100644
--- a/libc/arch-mips/syscalls/__ppoll.S
+++ b/libc/arch-mips/syscalls/__ppoll.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ppoll)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__pselect6.S b/libc/arch-mips/syscalls/__pselect6.S
index 4c0a0a5..b4279b8 100644
--- a/libc/arch-mips/syscalls/__pselect6.S
+++ b/libc/arch-mips/syscalls/__pselect6.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__pselect6)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__ptrace.S b/libc/arch-mips/syscalls/__ptrace.S
index fcbe529..07dcd8f 100644
--- a/libc/arch-mips/syscalls/__ptrace.S
+++ b/libc/arch-mips/syscalls/__ptrace.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ptrace)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__reboot.S b/libc/arch-mips/syscalls/__reboot.S
index 4aa0e7a..3a0a70b 100644
--- a/libc/arch-mips/syscalls/__reboot.S
+++ b/libc/arch-mips/syscalls/__reboot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__reboot)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__rt_sigaction.S b/libc/arch-mips/syscalls/__rt_sigaction.S
index 6c5bc37..858a241 100644
--- a/libc/arch-mips/syscalls/__rt_sigaction.S
+++ b/libc/arch-mips/syscalls/__rt_sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigaction)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__rt_sigpending.S b/libc/arch-mips/syscalls/__rt_sigpending.S
index e62f079..484da4f 100644
--- a/libc/arch-mips/syscalls/__rt_sigpending.S
+++ b/libc/arch-mips/syscalls/__rt_sigpending.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigpending)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__rt_sigprocmask.S b/libc/arch-mips/syscalls/__rt_sigprocmask.S
index 94ef493..5e61f52 100644
--- a/libc/arch-mips/syscalls/__rt_sigprocmask.S
+++ b/libc/arch-mips/syscalls/__rt_sigprocmask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigprocmask)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__rt_sigsuspend.S b/libc/arch-mips/syscalls/__rt_sigsuspend.S
index 077746f..d128caa 100644
--- a/libc/arch-mips/syscalls/__rt_sigsuspend.S
+++ b/libc/arch-mips/syscalls/__rt_sigsuspend.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigsuspend)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__rt_sigtimedwait.S b/libc/arch-mips/syscalls/__rt_sigtimedwait.S
index 404eab7..7e70660 100644
--- a/libc/arch-mips/syscalls/__rt_sigtimedwait.S
+++ b/libc/arch-mips/syscalls/__rt_sigtimedwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigtimedwait)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__sched_getaffinity.S b/libc/arch-mips/syscalls/__sched_getaffinity.S
index da71709..f83b7ba 100644
--- a/libc/arch-mips/syscalls/__sched_getaffinity.S
+++ b/libc/arch-mips/syscalls/__sched_getaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sched_getaffinity)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__set_tid_address.S b/libc/arch-mips/syscalls/__set_tid_address.S
index 146cd0d..7ec0f63 100644
--- a/libc/arch-mips/syscalls/__set_tid_address.S
+++ b/libc/arch-mips/syscalls/__set_tid_address.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tid_address)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__set_tls.S b/libc/arch-mips/syscalls/__set_tls.S
index e5b0ca2..bb2fa6d 100644
--- a/libc/arch-mips/syscalls/__set_tls.S
+++ b/libc/arch-mips/syscalls/__set_tls.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tls)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__sigaction.S b/libc/arch-mips/syscalls/__sigaction.S
index 03dd9da..03eb582 100644
--- a/libc/arch-mips/syscalls/__sigaction.S
+++ b/libc/arch-mips/syscalls/__sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sigaction)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__signalfd4.S b/libc/arch-mips/syscalls/__signalfd4.S
index cc9b212..9b191c2 100644
--- a/libc/arch-mips/syscalls/__signalfd4.S
+++ b/libc/arch-mips/syscalls/__signalfd4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__signalfd4)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__socket.S b/libc/arch-mips/syscalls/__socket.S
index 6508911..9e9a926 100644
--- a/libc/arch-mips/syscalls/__socket.S
+++ b/libc/arch-mips/syscalls/__socket.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__socket)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__statfs64.S b/libc/arch-mips/syscalls/__statfs64.S
index 9f94e6a..5017e96 100644
--- a/libc/arch-mips/syscalls/__statfs64.S
+++ b/libc/arch-mips/syscalls/__statfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__statfs64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__timer_create.S b/libc/arch-mips/syscalls/__timer_create.S
index 449bd28..81cc8c4 100644
--- a/libc/arch-mips/syscalls/__timer_create.S
+++ b/libc/arch-mips/syscalls/__timer_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_create)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__timer_delete.S b/libc/arch-mips/syscalls/__timer_delete.S
index 7bc5e05..fddb703 100644
--- a/libc/arch-mips/syscalls/__timer_delete.S
+++ b/libc/arch-mips/syscalls/__timer_delete.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_delete)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__timer_getoverrun.S b/libc/arch-mips/syscalls/__timer_getoverrun.S
index 7382c91..3a7313d 100644
--- a/libc/arch-mips/syscalls/__timer_getoverrun.S
+++ b/libc/arch-mips/syscalls/__timer_getoverrun.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_getoverrun)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__timer_gettime.S b/libc/arch-mips/syscalls/__timer_gettime.S
index d6195b9..7b9bed7 100644
--- a/libc/arch-mips/syscalls/__timer_gettime.S
+++ b/libc/arch-mips/syscalls/__timer_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_gettime)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__timer_settime.S b/libc/arch-mips/syscalls/__timer_settime.S
index 9fbab86..b1198de 100644
--- a/libc/arch-mips/syscalls/__timer_settime.S
+++ b/libc/arch-mips/syscalls/__timer_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_settime)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/__waitid.S b/libc/arch-mips/syscalls/__waitid.S
index 4c9142e..e60da7f 100644
--- a/libc/arch-mips/syscalls/__waitid.S
+++ b/libc/arch-mips/syscalls/__waitid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__waitid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/_exit.S b/libc/arch-mips/syscalls/_exit.S
index f546b66..ae1d61f 100644
--- a/libc/arch-mips/syscalls/_exit.S
+++ b/libc/arch-mips/syscalls/_exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(_exit)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/_flush_cache.S b/libc/arch-mips/syscalls/_flush_cache.S
index 64967fe..0074578 100644
--- a/libc/arch-mips/syscalls/_flush_cache.S
+++ b/libc/arch-mips/syscalls/_flush_cache.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(_flush_cache)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/acct.S b/libc/arch-mips/syscalls/acct.S
index 6e4a4f2..29a7119 100644
--- a/libc/arch-mips/syscalls/acct.S
+++ b/libc/arch-mips/syscalls/acct.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(acct)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/bind.S b/libc/arch-mips/syscalls/bind.S
index 9119aa8..6d92fd0 100644
--- a/libc/arch-mips/syscalls/bind.S
+++ b/libc/arch-mips/syscalls/bind.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(bind)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/capget.S b/libc/arch-mips/syscalls/capget.S
index 549dc76..de76fa3 100644
--- a/libc/arch-mips/syscalls/capget.S
+++ b/libc/arch-mips/syscalls/capget.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capget)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/capset.S b/libc/arch-mips/syscalls/capset.S
index 637ac37..77fb3a7 100644
--- a/libc/arch-mips/syscalls/capset.S
+++ b/libc/arch-mips/syscalls/capset.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capset)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/chdir.S b/libc/arch-mips/syscalls/chdir.S
index 752e4e7..2668d69 100644
--- a/libc/arch-mips/syscalls/chdir.S
+++ b/libc/arch-mips/syscalls/chdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chdir)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/chroot.S b/libc/arch-mips/syscalls/chroot.S
index d1ffc97..d804c4f 100644
--- a/libc/arch-mips/syscalls/chroot.S
+++ b/libc/arch-mips/syscalls/chroot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chroot)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/clock_getres.S b/libc/arch-mips/syscalls/clock_getres.S
index 49d9bba..5219b32 100644
--- a/libc/arch-mips/syscalls/clock_getres.S
+++ b/libc/arch-mips/syscalls/clock_getres.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_getres)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/clock_gettime.S b/libc/arch-mips/syscalls/clock_gettime.S
index 42929e8..32120b1 100644
--- a/libc/arch-mips/syscalls/clock_gettime.S
+++ b/libc/arch-mips/syscalls/clock_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_gettime)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/clock_nanosleep.S b/libc/arch-mips/syscalls/clock_nanosleep.S
index e7c25ce..01bab5a 100644
--- a/libc/arch-mips/syscalls/clock_nanosleep.S
+++ b/libc/arch-mips/syscalls/clock_nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_nanosleep)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/clock_settime.S b/libc/arch-mips/syscalls/clock_settime.S
index e7dda91..6b642a1 100644
--- a/libc/arch-mips/syscalls/clock_settime.S
+++ b/libc/arch-mips/syscalls/clock_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_settime)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/close.S b/libc/arch-mips/syscalls/close.S
index bc2c325..4e3ab67 100644
--- a/libc/arch-mips/syscalls/close.S
+++ b/libc/arch-mips/syscalls/close.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(close)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/delete_module.S b/libc/arch-mips/syscalls/delete_module.S
index 9247f5a..5c84930 100644
--- a/libc/arch-mips/syscalls/delete_module.S
+++ b/libc/arch-mips/syscalls/delete_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(delete_module)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/dup.S b/libc/arch-mips/syscalls/dup.S
index 61b1c03..6969553 100644
--- a/libc/arch-mips/syscalls/dup.S
+++ b/libc/arch-mips/syscalls/dup.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/dup3.S b/libc/arch-mips/syscalls/dup3.S
index d0694e8..39e403d 100644
--- a/libc/arch-mips/syscalls/dup3.S
+++ b/libc/arch-mips/syscalls/dup3.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup3)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/epoll_create1.S b/libc/arch-mips/syscalls/epoll_create1.S
index 2043f39..6feb715 100644
--- a/libc/arch-mips/syscalls/epoll_create1.S
+++ b/libc/arch-mips/syscalls/epoll_create1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_create1)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/epoll_ctl.S b/libc/arch-mips/syscalls/epoll_ctl.S
index 9474d3a..4517ea1 100644
--- a/libc/arch-mips/syscalls/epoll_ctl.S
+++ b/libc/arch-mips/syscalls/epoll_ctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_ctl)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/eventfd.S b/libc/arch-mips/syscalls/eventfd.S
index 5282a91..167a851 100644
--- a/libc/arch-mips/syscalls/eventfd.S
+++ b/libc/arch-mips/syscalls/eventfd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(eventfd)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/execve.S b/libc/arch-mips/syscalls/execve.S
index fcaec0a..e6f3af6 100644
--- a/libc/arch-mips/syscalls/execve.S
+++ b/libc/arch-mips/syscalls/execve.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(execve)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/faccessat.S b/libc/arch-mips/syscalls/faccessat.S
index e7afe2a..3bf7717 100644
--- a/libc/arch-mips/syscalls/faccessat.S
+++ b/libc/arch-mips/syscalls/faccessat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(faccessat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fallocate64.S b/libc/arch-mips/syscalls/fallocate64.S
index d814606..5395c6f 100644
--- a/libc/arch-mips/syscalls/fallocate64.S
+++ b/libc/arch-mips/syscalls/fallocate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fallocate64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fchdir.S b/libc/arch-mips/syscalls/fchdir.S
index daac0f5..4a5c1e3 100644
--- a/libc/arch-mips/syscalls/fchdir.S
+++ b/libc/arch-mips/syscalls/fchdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchdir)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fchmod.S b/libc/arch-mips/syscalls/fchmod.S
index e947e41..78dc3f7 100644
--- a/libc/arch-mips/syscalls/fchmod.S
+++ b/libc/arch-mips/syscalls/fchmod.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmod)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fchmodat.S b/libc/arch-mips/syscalls/fchmodat.S
index 4d2a7d3..ebc3a74 100644
--- a/libc/arch-mips/syscalls/fchmodat.S
+++ b/libc/arch-mips/syscalls/fchmodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmodat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fchown.S b/libc/arch-mips/syscalls/fchown.S
index f59c0f4..74956e0 100644
--- a/libc/arch-mips/syscalls/fchown.S
+++ b/libc/arch-mips/syscalls/fchown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchown)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fchownat.S b/libc/arch-mips/syscalls/fchownat.S
index af44cbc..54d1fde 100644
--- a/libc/arch-mips/syscalls/fchownat.S
+++ b/libc/arch-mips/syscalls/fchownat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchownat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fdatasync.S b/libc/arch-mips/syscalls/fdatasync.S
index 07e3592..f2d1b1f 100644
--- a/libc/arch-mips/syscalls/fdatasync.S
+++ b/libc/arch-mips/syscalls/fdatasync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fdatasync)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fgetxattr.S b/libc/arch-mips/syscalls/fgetxattr.S
index 035e71c..096cd97 100644
--- a/libc/arch-mips/syscalls/fgetxattr.S
+++ b/libc/arch-mips/syscalls/fgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fgetxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/flistxattr.S b/libc/arch-mips/syscalls/flistxattr.S
index 500cd97..b577e57 100644
--- a/libc/arch-mips/syscalls/flistxattr.S
+++ b/libc/arch-mips/syscalls/flistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flistxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/flock.S b/libc/arch-mips/syscalls/flock.S
index 7d843ab..87e9e04 100644
--- a/libc/arch-mips/syscalls/flock.S
+++ b/libc/arch-mips/syscalls/flock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flock)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fremovexattr.S b/libc/arch-mips/syscalls/fremovexattr.S
index 9f16186..8f7e74e 100644
--- a/libc/arch-mips/syscalls/fremovexattr.S
+++ b/libc/arch-mips/syscalls/fremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fremovexattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fsetxattr.S b/libc/arch-mips/syscalls/fsetxattr.S
index 0347128..e9a3490 100644
--- a/libc/arch-mips/syscalls/fsetxattr.S
+++ b/libc/arch-mips/syscalls/fsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsetxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fstat64.S b/libc/arch-mips/syscalls/fstat64.S
index 7228541..c6d2a32 100644
--- a/libc/arch-mips/syscalls/fstat64.S
+++ b/libc/arch-mips/syscalls/fstat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstat64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fstatat64.S b/libc/arch-mips/syscalls/fstatat64.S
index b2903f2..2418b02 100644
--- a/libc/arch-mips/syscalls/fstatat64.S
+++ b/libc/arch-mips/syscalls/fstatat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatat64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/fsync.S b/libc/arch-mips/syscalls/fsync.S
index 96b417d..c5528dc 100644
--- a/libc/arch-mips/syscalls/fsync.S
+++ b/libc/arch-mips/syscalls/fsync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsync)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/ftruncate.S b/libc/arch-mips/syscalls/ftruncate.S
index bd428fb..dfd57a9 100644
--- a/libc/arch-mips/syscalls/ftruncate.S
+++ b/libc/arch-mips/syscalls/ftruncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/ftruncate64.S b/libc/arch-mips/syscalls/ftruncate64.S
index 357e9a5..a1df9e8 100644
--- a/libc/arch-mips/syscalls/ftruncate64.S
+++ b/libc/arch-mips/syscalls/ftruncate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getegid.S b/libc/arch-mips/syscalls/getegid.S
index c3a3ac0..10f102c 100644
--- a/libc/arch-mips/syscalls/getegid.S
+++ b/libc/arch-mips/syscalls/getegid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getegid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/geteuid.S b/libc/arch-mips/syscalls/geteuid.S
index 66e6d4f..bac3b74 100644
--- a/libc/arch-mips/syscalls/geteuid.S
+++ b/libc/arch-mips/syscalls/geteuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(geteuid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getgid.S b/libc/arch-mips/syscalls/getgid.S
index 674d527..a1814bb 100644
--- a/libc/arch-mips/syscalls/getgid.S
+++ b/libc/arch-mips/syscalls/getgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getgroups.S b/libc/arch-mips/syscalls/getgroups.S
index caa031b..51ed523 100644
--- a/libc/arch-mips/syscalls/getgroups.S
+++ b/libc/arch-mips/syscalls/getgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgroups)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getitimer.S b/libc/arch-mips/syscalls/getitimer.S
index e7a655a..1afeee4 100644
--- a/libc/arch-mips/syscalls/getitimer.S
+++ b/libc/arch-mips/syscalls/getitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getitimer)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getpeername.S b/libc/arch-mips/syscalls/getpeername.S
index 31df8ad..b6e5f07 100644
--- a/libc/arch-mips/syscalls/getpeername.S
+++ b/libc/arch-mips/syscalls/getpeername.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpeername)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getpgid.S b/libc/arch-mips/syscalls/getpgid.S
index 7e3e439..01c6ec5 100644
--- a/libc/arch-mips/syscalls/getpgid.S
+++ b/libc/arch-mips/syscalls/getpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpgid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getppid.S b/libc/arch-mips/syscalls/getppid.S
index 3d76fc2..9ed04c0 100644
--- a/libc/arch-mips/syscalls/getppid.S
+++ b/libc/arch-mips/syscalls/getppid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getppid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getresgid.S b/libc/arch-mips/syscalls/getresgid.S
index 235902a..a2e16d4 100644
--- a/libc/arch-mips/syscalls/getresgid.S
+++ b/libc/arch-mips/syscalls/getresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresgid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getresuid.S b/libc/arch-mips/syscalls/getresuid.S
index c6c4c13..ff162e0 100644
--- a/libc/arch-mips/syscalls/getresuid.S
+++ b/libc/arch-mips/syscalls/getresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresuid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getrlimit.S b/libc/arch-mips/syscalls/getrlimit.S
index ef4ae89..1632f4d 100644
--- a/libc/arch-mips/syscalls/getrlimit.S
+++ b/libc/arch-mips/syscalls/getrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrlimit)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getrusage.S b/libc/arch-mips/syscalls/getrusage.S
index 21cabfa..b9c4207 100644
--- a/libc/arch-mips/syscalls/getrusage.S
+++ b/libc/arch-mips/syscalls/getrusage.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrusage)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getsid.S b/libc/arch-mips/syscalls/getsid.S
index b0b21a0..cb56f54 100644
--- a/libc/arch-mips/syscalls/getsid.S
+++ b/libc/arch-mips/syscalls/getsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getsockname.S b/libc/arch-mips/syscalls/getsockname.S
index 82d0b83..f7bff60 100644
--- a/libc/arch-mips/syscalls/getsockname.S
+++ b/libc/arch-mips/syscalls/getsockname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockname)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getsockopt.S b/libc/arch-mips/syscalls/getsockopt.S
index ad360e3..1490aa3 100644
--- a/libc/arch-mips/syscalls/getsockopt.S
+++ b/libc/arch-mips/syscalls/getsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockopt)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/gettimeofday.S b/libc/arch-mips/syscalls/gettimeofday.S
index e66fd77..a72ced6 100644
--- a/libc/arch-mips/syscalls/gettimeofday.S
+++ b/libc/arch-mips/syscalls/gettimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(gettimeofday)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getuid.S b/libc/arch-mips/syscalls/getuid.S
index 345af71..290a701 100644
--- a/libc/arch-mips/syscalls/getuid.S
+++ b/libc/arch-mips/syscalls/getuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getuid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/getxattr.S b/libc/arch-mips/syscalls/getxattr.S
index c7e215e..6ed4316 100644
--- a/libc/arch-mips/syscalls/getxattr.S
+++ b/libc/arch-mips/syscalls/getxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/init_module.S b/libc/arch-mips/syscalls/init_module.S
index 21ba5b1..6caf450 100644
--- a/libc/arch-mips/syscalls/init_module.S
+++ b/libc/arch-mips/syscalls/init_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(init_module)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/inotify_add_watch.S b/libc/arch-mips/syscalls/inotify_add_watch.S
index beb70ec..8464f8f 100644
--- a/libc/arch-mips/syscalls/inotify_add_watch.S
+++ b/libc/arch-mips/syscalls/inotify_add_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_add_watch)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/inotify_init1.S b/libc/arch-mips/syscalls/inotify_init1.S
index 6c825c6..b6cb6bc 100644
--- a/libc/arch-mips/syscalls/inotify_init1.S
+++ b/libc/arch-mips/syscalls/inotify_init1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_init1)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/inotify_rm_watch.S b/libc/arch-mips/syscalls/inotify_rm_watch.S
index 280f2b4..87a396a 100644
--- a/libc/arch-mips/syscalls/inotify_rm_watch.S
+++ b/libc/arch-mips/syscalls/inotify_rm_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_rm_watch)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/kill.S b/libc/arch-mips/syscalls/kill.S
index 0941717..3dda006 100644
--- a/libc/arch-mips/syscalls/kill.S
+++ b/libc/arch-mips/syscalls/kill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(kill)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/klogctl.S b/libc/arch-mips/syscalls/klogctl.S
index ebc8837..ae9a445 100644
--- a/libc/arch-mips/syscalls/klogctl.S
+++ b/libc/arch-mips/syscalls/klogctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(klogctl)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/lgetxattr.S b/libc/arch-mips/syscalls/lgetxattr.S
index 8c4a252..63c5add 100644
--- a/libc/arch-mips/syscalls/lgetxattr.S
+++ b/libc/arch-mips/syscalls/lgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lgetxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/linkat.S b/libc/arch-mips/syscalls/linkat.S
index cc7278d..5bea417 100644
--- a/libc/arch-mips/syscalls/linkat.S
+++ b/libc/arch-mips/syscalls/linkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(linkat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/listen.S b/libc/arch-mips/syscalls/listen.S
index 68eba52..8d945f5 100644
--- a/libc/arch-mips/syscalls/listen.S
+++ b/libc/arch-mips/syscalls/listen.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listen)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/listxattr.S b/libc/arch-mips/syscalls/listxattr.S
index 006bfce..260d089 100644
--- a/libc/arch-mips/syscalls/listxattr.S
+++ b/libc/arch-mips/syscalls/listxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/llistxattr.S b/libc/arch-mips/syscalls/llistxattr.S
index 7f833ad..69474d8 100644
--- a/libc/arch-mips/syscalls/llistxattr.S
+++ b/libc/arch-mips/syscalls/llistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(llistxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/lremovexattr.S b/libc/arch-mips/syscalls/lremovexattr.S
index 21d00ea..e33f31f 100644
--- a/libc/arch-mips/syscalls/lremovexattr.S
+++ b/libc/arch-mips/syscalls/lremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lremovexattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/lseek.S b/libc/arch-mips/syscalls/lseek.S
index 82c2776..21abe1c 100644
--- a/libc/arch-mips/syscalls/lseek.S
+++ b/libc/arch-mips/syscalls/lseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lseek)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/lsetxattr.S b/libc/arch-mips/syscalls/lsetxattr.S
index d54ec69..dcd510a 100644
--- a/libc/arch-mips/syscalls/lsetxattr.S
+++ b/libc/arch-mips/syscalls/lsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lsetxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/madvise.S b/libc/arch-mips/syscalls/madvise.S
index 9aa2815..49c007a 100644
--- a/libc/arch-mips/syscalls/madvise.S
+++ b/libc/arch-mips/syscalls/madvise.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(madvise)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mincore.S b/libc/arch-mips/syscalls/mincore.S
index 0db4313..07102a6 100644
--- a/libc/arch-mips/syscalls/mincore.S
+++ b/libc/arch-mips/syscalls/mincore.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mincore)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mkdirat.S b/libc/arch-mips/syscalls/mkdirat.S
index 0ac98d4..96a2d08 100644
--- a/libc/arch-mips/syscalls/mkdirat.S
+++ b/libc/arch-mips/syscalls/mkdirat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mkdirat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mknodat.S b/libc/arch-mips/syscalls/mknodat.S
index b85d8bf..a88b906 100644
--- a/libc/arch-mips/syscalls/mknodat.S
+++ b/libc/arch-mips/syscalls/mknodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mknodat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mlock.S b/libc/arch-mips/syscalls/mlock.S
index 0ba2bca..eff66b8 100644
--- a/libc/arch-mips/syscalls/mlock.S
+++ b/libc/arch-mips/syscalls/mlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlock)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mlockall.S b/libc/arch-mips/syscalls/mlockall.S
index 642c6e2..c31eeaf 100644
--- a/libc/arch-mips/syscalls/mlockall.S
+++ b/libc/arch-mips/syscalls/mlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlockall)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mount.S b/libc/arch-mips/syscalls/mount.S
index f0c5f6b..cb1f1d1 100644
--- a/libc/arch-mips/syscalls/mount.S
+++ b/libc/arch-mips/syscalls/mount.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mount)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mprotect.S b/libc/arch-mips/syscalls/mprotect.S
index c0ce988..4e390eb 100644
--- a/libc/arch-mips/syscalls/mprotect.S
+++ b/libc/arch-mips/syscalls/mprotect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mprotect)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/mremap.S b/libc/arch-mips/syscalls/mremap.S
index bd4c385..7b9a68a 100644
--- a/libc/arch-mips/syscalls/mremap.S
+++ b/libc/arch-mips/syscalls/mremap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mremap)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/msync.S b/libc/arch-mips/syscalls/msync.S
index e8ecb2a..7b19a83 100644
--- a/libc/arch-mips/syscalls/msync.S
+++ b/libc/arch-mips/syscalls/msync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(msync)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/munlock.S b/libc/arch-mips/syscalls/munlock.S
index f8ddc3a..17dc719 100644
--- a/libc/arch-mips/syscalls/munlock.S
+++ b/libc/arch-mips/syscalls/munlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlock)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/munlockall.S b/libc/arch-mips/syscalls/munlockall.S
index 5ced5c6..f0dc2d4 100644
--- a/libc/arch-mips/syscalls/munlockall.S
+++ b/libc/arch-mips/syscalls/munlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlockall)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/munmap.S b/libc/arch-mips/syscalls/munmap.S
index 527825c..dc3a524 100644
--- a/libc/arch-mips/syscalls/munmap.S
+++ b/libc/arch-mips/syscalls/munmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munmap)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/nanosleep.S b/libc/arch-mips/syscalls/nanosleep.S
index 8dc816a..fa74288 100644
--- a/libc/arch-mips/syscalls/nanosleep.S
+++ b/libc/arch-mips/syscalls/nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(nanosleep)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/personality.S b/libc/arch-mips/syscalls/personality.S
index e8449a7..467f2ec 100644
--- a/libc/arch-mips/syscalls/personality.S
+++ b/libc/arch-mips/syscalls/personality.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(personality)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/pipe2.S b/libc/arch-mips/syscalls/pipe2.S
index 478d364..c505956 100644
--- a/libc/arch-mips/syscalls/pipe2.S
+++ b/libc/arch-mips/syscalls/pipe2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pipe2)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/prctl.S b/libc/arch-mips/syscalls/prctl.S
index e9aff3c..60c18be 100644
--- a/libc/arch-mips/syscalls/prctl.S
+++ b/libc/arch-mips/syscalls/prctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prctl)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/pread64.S b/libc/arch-mips/syscalls/pread64.S
index 55a54c6..debc558 100644
--- a/libc/arch-mips/syscalls/pread64.S
+++ b/libc/arch-mips/syscalls/pread64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pread64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/prlimit64.S b/libc/arch-mips/syscalls/prlimit64.S
index c695d18..ce1686f 100644
--- a/libc/arch-mips/syscalls/prlimit64.S
+++ b/libc/arch-mips/syscalls/prlimit64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prlimit64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/pwrite64.S b/libc/arch-mips/syscalls/pwrite64.S
index 64d3ee1..b1ff89b 100644
--- a/libc/arch-mips/syscalls/pwrite64.S
+++ b/libc/arch-mips/syscalls/pwrite64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pwrite64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/read.S b/libc/arch-mips/syscalls/read.S
index ff548ab..d98c9a6 100644
--- a/libc/arch-mips/syscalls/read.S
+++ b/libc/arch-mips/syscalls/read.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(read)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/readahead.S b/libc/arch-mips/syscalls/readahead.S
index 674286a..7dd4473 100644
--- a/libc/arch-mips/syscalls/readahead.S
+++ b/libc/arch-mips/syscalls/readahead.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readahead)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/readlinkat.S b/libc/arch-mips/syscalls/readlinkat.S
index a1c7d6b..99f07a4 100644
--- a/libc/arch-mips/syscalls/readlinkat.S
+++ b/libc/arch-mips/syscalls/readlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readlinkat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/readv.S b/libc/arch-mips/syscalls/readv.S
index af5a4cb..3985c9c 100644
--- a/libc/arch-mips/syscalls/readv.S
+++ b/libc/arch-mips/syscalls/readv.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readv)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/recvfrom.S b/libc/arch-mips/syscalls/recvfrom.S
index 04b04f6..afda11e 100644
--- a/libc/arch-mips/syscalls/recvfrom.S
+++ b/libc/arch-mips/syscalls/recvfrom.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvfrom)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/recvmmsg.S b/libc/arch-mips/syscalls/recvmmsg.S
index 23e511b..1122c01 100644
--- a/libc/arch-mips/syscalls/recvmmsg.S
+++ b/libc/arch-mips/syscalls/recvmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmmsg)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/recvmsg.S b/libc/arch-mips/syscalls/recvmsg.S
index a0a3a3f..a64606b 100644
--- a/libc/arch-mips/syscalls/recvmsg.S
+++ b/libc/arch-mips/syscalls/recvmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmsg)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/removexattr.S b/libc/arch-mips/syscalls/removexattr.S
index 0f72ebf..a356160 100644
--- a/libc/arch-mips/syscalls/removexattr.S
+++ b/libc/arch-mips/syscalls/removexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(removexattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/renameat.S b/libc/arch-mips/syscalls/renameat.S
index 210b439..63de839 100644
--- a/libc/arch-mips/syscalls/renameat.S
+++ b/libc/arch-mips/syscalls/renameat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(renameat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_get_priority_max.S b/libc/arch-mips/syscalls/sched_get_priority_max.S
index d15a868..ea88c0f 100644
--- a/libc/arch-mips/syscalls/sched_get_priority_max.S
+++ b/libc/arch-mips/syscalls/sched_get_priority_max.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_max)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_get_priority_min.S b/libc/arch-mips/syscalls/sched_get_priority_min.S
index 5ff21c6..0320847 100644
--- a/libc/arch-mips/syscalls/sched_get_priority_min.S
+++ b/libc/arch-mips/syscalls/sched_get_priority_min.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_min)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_getparam.S b/libc/arch-mips/syscalls/sched_getparam.S
index 1cbe720..4be69b3 100644
--- a/libc/arch-mips/syscalls/sched_getparam.S
+++ b/libc/arch-mips/syscalls/sched_getparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getparam)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_getscheduler.S b/libc/arch-mips/syscalls/sched_getscheduler.S
index 88b16e0..aaf0e91 100644
--- a/libc/arch-mips/syscalls/sched_getscheduler.S
+++ b/libc/arch-mips/syscalls/sched_getscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getscheduler)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_rr_get_interval.S b/libc/arch-mips/syscalls/sched_rr_get_interval.S
index 647ee3c..fcf2bcb 100644
--- a/libc/arch-mips/syscalls/sched_rr_get_interval.S
+++ b/libc/arch-mips/syscalls/sched_rr_get_interval.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_rr_get_interval)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_setaffinity.S b/libc/arch-mips/syscalls/sched_setaffinity.S
index 1184766..b9394c5 100644
--- a/libc/arch-mips/syscalls/sched_setaffinity.S
+++ b/libc/arch-mips/syscalls/sched_setaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setaffinity)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_setparam.S b/libc/arch-mips/syscalls/sched_setparam.S
index 1811c74..90c82fe 100644
--- a/libc/arch-mips/syscalls/sched_setparam.S
+++ b/libc/arch-mips/syscalls/sched_setparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setparam)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_setscheduler.S b/libc/arch-mips/syscalls/sched_setscheduler.S
index 8921d30..05e4e8b 100644
--- a/libc/arch-mips/syscalls/sched_setscheduler.S
+++ b/libc/arch-mips/syscalls/sched_setscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setscheduler)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sched_yield.S b/libc/arch-mips/syscalls/sched_yield.S
index 37f09be..1556580 100644
--- a/libc/arch-mips/syscalls/sched_yield.S
+++ b/libc/arch-mips/syscalls/sched_yield.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_yield)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sendfile.S b/libc/arch-mips/syscalls/sendfile.S
index 84466b9..eb99d09 100644
--- a/libc/arch-mips/syscalls/sendfile.S
+++ b/libc/arch-mips/syscalls/sendfile.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sendfile64.S b/libc/arch-mips/syscalls/sendfile64.S
index d9733f6..1d5c5f0 100644
--- a/libc/arch-mips/syscalls/sendfile64.S
+++ b/libc/arch-mips/syscalls/sendfile64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sendmmsg.S b/libc/arch-mips/syscalls/sendmmsg.S
index d99ba93..16f37a1 100644
--- a/libc/arch-mips/syscalls/sendmmsg.S
+++ b/libc/arch-mips/syscalls/sendmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmmsg)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sendmsg.S b/libc/arch-mips/syscalls/sendmsg.S
index 5c37c62..31bb563 100644
--- a/libc/arch-mips/syscalls/sendmsg.S
+++ b/libc/arch-mips/syscalls/sendmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmsg)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sendto.S b/libc/arch-mips/syscalls/sendto.S
index 580d142..2ba696d 100644
--- a/libc/arch-mips/syscalls/sendto.S
+++ b/libc/arch-mips/syscalls/sendto.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendto)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setfsgid.S b/libc/arch-mips/syscalls/setfsgid.S
new file mode 100644
index 0000000..81d33d0
--- /dev/null
+++ b/libc/arch-mips/syscalls/setfsgid.S
@@ -0,0 +1,21 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsgid)
+    .set noreorder
+    .cpload t9
+    li v0, __NR_setfsgid
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    la t9,__set_errno
+    j t9
+    nop
+    .set reorder
+END(setfsgid)
diff --git a/libc/arch-mips/syscalls/setfsuid.S b/libc/arch-mips/syscalls/setfsuid.S
new file mode 100644
index 0000000..6889077
--- /dev/null
+++ b/libc/arch-mips/syscalls/setfsuid.S
@@ -0,0 +1,21 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsuid)
+    .set noreorder
+    .cpload t9
+    li v0, __NR_setfsuid
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    la t9,__set_errno
+    j t9
+    nop
+    .set reorder
+END(setfsuid)
diff --git a/libc/arch-mips/syscalls/setgid.S b/libc/arch-mips/syscalls/setgid.S
index 8fa188e..83649da 100644
--- a/libc/arch-mips/syscalls/setgid.S
+++ b/libc/arch-mips/syscalls/setgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setgroups.S b/libc/arch-mips/syscalls/setgroups.S
index f2d271c..b98608c 100644
--- a/libc/arch-mips/syscalls/setgroups.S
+++ b/libc/arch-mips/syscalls/setgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgroups)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setitimer.S b/libc/arch-mips/syscalls/setitimer.S
index a2eea84..dc9a8f3 100644
--- a/libc/arch-mips/syscalls/setitimer.S
+++ b/libc/arch-mips/syscalls/setitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setitimer)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setns.S b/libc/arch-mips/syscalls/setns.S
index 8a4f674..9a4939d 100644
--- a/libc/arch-mips/syscalls/setns.S
+++ b/libc/arch-mips/syscalls/setns.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setns)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setpgid.S b/libc/arch-mips/syscalls/setpgid.S
index c68f9a6..cbc1ff3 100644
--- a/libc/arch-mips/syscalls/setpgid.S
+++ b/libc/arch-mips/syscalls/setpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpgid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setpriority.S b/libc/arch-mips/syscalls/setpriority.S
index 2bf9f47..6b8a504 100644
--- a/libc/arch-mips/syscalls/setpriority.S
+++ b/libc/arch-mips/syscalls/setpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpriority)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setregid.S b/libc/arch-mips/syscalls/setregid.S
index de77e39..6388784 100644
--- a/libc/arch-mips/syscalls/setregid.S
+++ b/libc/arch-mips/syscalls/setregid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setregid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setresgid.S b/libc/arch-mips/syscalls/setresgid.S
index b2fd85f..76968a8 100644
--- a/libc/arch-mips/syscalls/setresgid.S
+++ b/libc/arch-mips/syscalls/setresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresgid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setresuid.S b/libc/arch-mips/syscalls/setresuid.S
index ad9ea9b..fae15f8 100644
--- a/libc/arch-mips/syscalls/setresuid.S
+++ b/libc/arch-mips/syscalls/setresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresuid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setreuid.S b/libc/arch-mips/syscalls/setreuid.S
index 888d219..8350cb7 100644
--- a/libc/arch-mips/syscalls/setreuid.S
+++ b/libc/arch-mips/syscalls/setreuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setreuid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setrlimit.S b/libc/arch-mips/syscalls/setrlimit.S
index 71b49ac..d708c2d 100644
--- a/libc/arch-mips/syscalls/setrlimit.S
+++ b/libc/arch-mips/syscalls/setrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setrlimit)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setsid.S b/libc/arch-mips/syscalls/setsid.S
index 9467a08..cb5838d 100644
--- a/libc/arch-mips/syscalls/setsid.S
+++ b/libc/arch-mips/syscalls/setsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setsockopt.S b/libc/arch-mips/syscalls/setsockopt.S
index e8dd3f6..da348f1 100644
--- a/libc/arch-mips/syscalls/setsockopt.S
+++ b/libc/arch-mips/syscalls/setsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsockopt)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/settimeofday.S b/libc/arch-mips/syscalls/settimeofday.S
index b9b588f..cd52b40 100644
--- a/libc/arch-mips/syscalls/settimeofday.S
+++ b/libc/arch-mips/syscalls/settimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(settimeofday)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setuid.S b/libc/arch-mips/syscalls/setuid.S
index 55c75c1..a80ec5c 100644
--- a/libc/arch-mips/syscalls/setuid.S
+++ b/libc/arch-mips/syscalls/setuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setuid)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/setxattr.S b/libc/arch-mips/syscalls/setxattr.S
index 0cca64c..df7bcdb 100644
--- a/libc/arch-mips/syscalls/setxattr.S
+++ b/libc/arch-mips/syscalls/setxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setxattr)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/shutdown.S b/libc/arch-mips/syscalls/shutdown.S
index f6e9979..71e6366 100644
--- a/libc/arch-mips/syscalls/shutdown.S
+++ b/libc/arch-mips/syscalls/shutdown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(shutdown)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sigaltstack.S b/libc/arch-mips/syscalls/sigaltstack.S
index 6632164..b52c60a 100644
--- a/libc/arch-mips/syscalls/sigaltstack.S
+++ b/libc/arch-mips/syscalls/sigaltstack.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sigaltstack)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/socketpair.S b/libc/arch-mips/syscalls/socketpair.S
index 6257327..47223e1 100644
--- a/libc/arch-mips/syscalls/socketpair.S
+++ b/libc/arch-mips/syscalls/socketpair.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(socketpair)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/splice.S b/libc/arch-mips/syscalls/splice.S
index d344a6c..611a062 100644
--- a/libc/arch-mips/syscalls/splice.S
+++ b/libc/arch-mips/syscalls/splice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(splice)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/swapoff.S b/libc/arch-mips/syscalls/swapoff.S
index 04b5b70..8b57068 100644
--- a/libc/arch-mips/syscalls/swapoff.S
+++ b/libc/arch-mips/syscalls/swapoff.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapoff)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/swapon.S b/libc/arch-mips/syscalls/swapon.S
index 1fe3698..ef3a537 100644
--- a/libc/arch-mips/syscalls/swapon.S
+++ b/libc/arch-mips/syscalls/swapon.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapon)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/symlinkat.S b/libc/arch-mips/syscalls/symlinkat.S
index 5bd6e6c..65971a9 100644
--- a/libc/arch-mips/syscalls/symlinkat.S
+++ b/libc/arch-mips/syscalls/symlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(symlinkat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sync.S b/libc/arch-mips/syscalls/sync.S
index eb788f0..d62ae76 100644
--- a/libc/arch-mips/syscalls/sync.S
+++ b/libc/arch-mips/syscalls/sync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sync)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/sysinfo.S b/libc/arch-mips/syscalls/sysinfo.S
index 7cdccb9..600e086 100644
--- a/libc/arch-mips/syscalls/sysinfo.S
+++ b/libc/arch-mips/syscalls/sysinfo.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sysinfo)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/tee.S b/libc/arch-mips/syscalls/tee.S
index e51732d..90ec911 100644
--- a/libc/arch-mips/syscalls/tee.S
+++ b/libc/arch-mips/syscalls/tee.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tee)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/tgkill.S b/libc/arch-mips/syscalls/tgkill.S
index 9938843..39a148b 100644
--- a/libc/arch-mips/syscalls/tgkill.S
+++ b/libc/arch-mips/syscalls/tgkill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tgkill)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/timerfd_create.S b/libc/arch-mips/syscalls/timerfd_create.S
index c42f4e1..b50903a 100644
--- a/libc/arch-mips/syscalls/timerfd_create.S
+++ b/libc/arch-mips/syscalls/timerfd_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_create)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/timerfd_gettime.S b/libc/arch-mips/syscalls/timerfd_gettime.S
index 469d174..97d3045 100644
--- a/libc/arch-mips/syscalls/timerfd_gettime.S
+++ b/libc/arch-mips/syscalls/timerfd_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_gettime)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/timerfd_settime.S b/libc/arch-mips/syscalls/timerfd_settime.S
index c7c6f47..1e56f86 100644
--- a/libc/arch-mips/syscalls/timerfd_settime.S
+++ b/libc/arch-mips/syscalls/timerfd_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_settime)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/times.S b/libc/arch-mips/syscalls/times.S
index 157b34c..60904d1 100644
--- a/libc/arch-mips/syscalls/times.S
+++ b/libc/arch-mips/syscalls/times.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(times)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/truncate.S b/libc/arch-mips/syscalls/truncate.S
index 7fe4a0f..ec7bc49 100644
--- a/libc/arch-mips/syscalls/truncate.S
+++ b/libc/arch-mips/syscalls/truncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/truncate64.S b/libc/arch-mips/syscalls/truncate64.S
index 0911f5f..b6a0234 100644
--- a/libc/arch-mips/syscalls/truncate64.S
+++ b/libc/arch-mips/syscalls/truncate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate64)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/umask.S b/libc/arch-mips/syscalls/umask.S
index 57a6aed..8f66e77 100644
--- a/libc/arch-mips/syscalls/umask.S
+++ b/libc/arch-mips/syscalls/umask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umask)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/umount2.S b/libc/arch-mips/syscalls/umount2.S
index bf8267d..58e31f3 100644
--- a/libc/arch-mips/syscalls/umount2.S
+++ b/libc/arch-mips/syscalls/umount2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umount2)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/uname.S b/libc/arch-mips/syscalls/uname.S
index ce77bd5..401d139 100644
--- a/libc/arch-mips/syscalls/uname.S
+++ b/libc/arch-mips/syscalls/uname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(uname)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/unlinkat.S b/libc/arch-mips/syscalls/unlinkat.S
index 82e584b..b6e849d 100644
--- a/libc/arch-mips/syscalls/unlinkat.S
+++ b/libc/arch-mips/syscalls/unlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unlinkat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/unshare.S b/libc/arch-mips/syscalls/unshare.S
index 0521f30..5262832 100644
--- a/libc/arch-mips/syscalls/unshare.S
+++ b/libc/arch-mips/syscalls/unshare.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unshare)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/utimensat.S b/libc/arch-mips/syscalls/utimensat.S
index 208ef58..9ecb5c0 100644
--- a/libc/arch-mips/syscalls/utimensat.S
+++ b/libc/arch-mips/syscalls/utimensat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(utimensat)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/vmsplice.S b/libc/arch-mips/syscalls/vmsplice.S
index 24da515..5ad23a6 100644
--- a/libc/arch-mips/syscalls/vmsplice.S
+++ b/libc/arch-mips/syscalls/vmsplice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(vmsplice)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/wait4.S b/libc/arch-mips/syscalls/wait4.S
index ec6bd84..8f8d879 100644
--- a/libc/arch-mips/syscalls/wait4.S
+++ b/libc/arch-mips/syscalls/wait4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(wait4)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/write.S b/libc/arch-mips/syscalls/write.S
index d10e55a..3e37919 100644
--- a/libc/arch-mips/syscalls/write.S
+++ b/libc/arch-mips/syscalls/write.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(write)
     .set noreorder
     .cpload t9
diff --git a/libc/arch-mips/syscalls/writev.S b/libc/arch-mips/syscalls/writev.S
index 0a2c033..72ea2f2 100644
--- a/libc/arch-mips/syscalls/writev.S
+++ b/libc/arch-mips/syscalls/writev.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(writev)
     .set noreorder
     .cpload t9
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-mips64/bionic/__get_sp.S b/libc/arch-mips64/bionic/vfork.S
similarity index 67%
rename from libc/arch-mips64/bionic/__get_sp.S
rename to libc/arch-mips64/bionic/vfork.S
index 5f5d32e..911a264 100644
--- a/libc/arch-mips64/bionic/__get_sp.S
+++ b/libc/arch-mips64/bionic/vfork.S
@@ -27,8 +27,45 @@
  */
 
 #include <private/bionic_asm.h>
+#include <linux/sched.h>
 
-ENTRY_PRIVATE(__get_sp)
-  move v0, sp
-  j ra
-END(__get_sp)
+// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__.
+// #include <asm/signal.h>
+#define SIGCHLD 18
+
+	.text
+
+#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32)
+FRAMESZ		=	MKFSIZ(5,0)
+#else
+FRAMESZ		=	MKFSIZ(0,0)
+#endif
+
+LEAF(vfork,FRAMESZ)
+#if FRAMESZ!=0
+	PTR_SUBU sp, FRAMESZ
+#endif
+	SETUP_GP64(a5, vfork)
+	LI	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
+	move	a1, $0
+	move	a2, $0
+	move	a3, $0
+#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32)
+	REG_S	$0, 4*REGSZ(sp)
+#else
+	move	a4, $0
+#endif
+	LI	v0, __NR_clone
+	syscall
+#if FRAMESZ!=0
+	PTR_ADDU sp,FRAMESZ
+#endif
+	move	a0, v0
+	bnez	a3, 1f
+	RESTORE_GP64
+	j	ra
+1:
+	LA	t9,__set_errno
+	RESTORE_GP64
+	j	t9
+	END(vfork)
diff --git a/libc/arch-mips64/include/machine/asm.h b/libc/arch-mips64/include/machine/asm.h
index 5eacde3..cdc7914 100644
--- a/libc/arch-mips64/include/machine/asm.h
+++ b/libc/arch-mips64/include/machine/asm.h
@@ -28,9 +28,7 @@
 #ifndef _MIPS64_ASM_H
 #define _MIPS64_ASM_H
 
-#ifndef _ALIGN_TEXT
-# define _ALIGN_TEXT .align 4
-#endif
+#define __bionic_asm_align 4
 
 #undef __bionic_asm_custom_entry
 #undef __bionic_asm_custom_end
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk
index 6f7a928..230cb26 100644
--- a/libc/arch-mips64/mips64.mk
+++ b/libc/arch-mips64/mips64.mk
@@ -46,6 +46,7 @@
     arch-mips64/bionic/setjmp.S \
     arch-mips64/bionic/sigsetjmp.S \
     arch-mips64/bionic/syscall.S \
+    arch-mips64/bionic/vfork.S \
 
 # FIXME TODO
 ## libc_bionic_src_files_mips64 += arch-mips64/string/memcpy.S
diff --git a/libc/arch-mips64/syscalls/__accept4.S b/libc/arch-mips64/syscalls/__accept4.S
index e68bdb6..0891d7f 100644
--- a/libc/arch-mips64/syscalls/__accept4.S
+++ b/libc/arch-mips64/syscalls/__accept4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__accept4)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__brk.S b/libc/arch-mips64/syscalls/__brk.S
index 99a108a..86f390c 100644
--- a/libc/arch-mips64/syscalls/__brk.S
+++ b/libc/arch-mips64/syscalls/__brk.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__brk)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__connect.S b/libc/arch-mips64/syscalls/__connect.S
index b1475fb..2efbb2a 100644
--- a/libc/arch-mips64/syscalls/__connect.S
+++ b/libc/arch-mips64/syscalls/__connect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__connect)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__epoll_pwait.S b/libc/arch-mips64/syscalls/__epoll_pwait.S
index fc3867a..430d9bb 100644
--- a/libc/arch-mips64/syscalls/__epoll_pwait.S
+++ b/libc/arch-mips64/syscalls/__epoll_pwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__epoll_pwait)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__exit.S b/libc/arch-mips64/syscalls/__exit.S
index dac53b9..ebee0d1 100644
--- a/libc/arch-mips64/syscalls/__exit.S
+++ b/libc/arch-mips64/syscalls/__exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__exit)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__getcpu.S b/libc/arch-mips64/syscalls/__getcpu.S
index 9c08710..34a8acb 100644
--- a/libc/arch-mips64/syscalls/__getcpu.S
+++ b/libc/arch-mips64/syscalls/__getcpu.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcpu)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__getcwd.S b/libc/arch-mips64/syscalls/__getcwd.S
index 79fbca3..e7a09a6 100644
--- a/libc/arch-mips64/syscalls/__getcwd.S
+++ b/libc/arch-mips64/syscalls/__getcwd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcwd)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__getdents64.S b/libc/arch-mips64/syscalls/__getdents64.S
index 6df556a..dc51e72 100644
--- a/libc/arch-mips64/syscalls/__getdents64.S
+++ b/libc/arch-mips64/syscalls/__getdents64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getdents64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__getpid.S b/libc/arch-mips64/syscalls/__getpid.S
index 0977ff0..86b4071 100644
--- a/libc/arch-mips64/syscalls/__getpid.S
+++ b/libc/arch-mips64/syscalls/__getpid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__getpriority.S b/libc/arch-mips64/syscalls/__getpriority.S
index 6ca2e1f..f0c7267 100644
--- a/libc/arch-mips64/syscalls/__getpriority.S
+++ b/libc/arch-mips64/syscalls/__getpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpriority)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__ioctl.S b/libc/arch-mips64/syscalls/__ioctl.S
index 013ce18..1f94075 100644
--- a/libc/arch-mips64/syscalls/__ioctl.S
+++ b/libc/arch-mips64/syscalls/__ioctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ioctl)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__openat.S b/libc/arch-mips64/syscalls/__openat.S
index 1d46ef6..6cc56da 100644
--- a/libc/arch-mips64/syscalls/__openat.S
+++ b/libc/arch-mips64/syscalls/__openat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__openat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__ppoll.S b/libc/arch-mips64/syscalls/__ppoll.S
index fb0e19a..ce3a551 100644
--- a/libc/arch-mips64/syscalls/__ppoll.S
+++ b/libc/arch-mips64/syscalls/__ppoll.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ppoll)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__pselect6.S b/libc/arch-mips64/syscalls/__pselect6.S
index 3055b31..dbfe79f 100644
--- a/libc/arch-mips64/syscalls/__pselect6.S
+++ b/libc/arch-mips64/syscalls/__pselect6.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__pselect6)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__ptrace.S b/libc/arch-mips64/syscalls/__ptrace.S
index bae7733..e26217f 100644
--- a/libc/arch-mips64/syscalls/__ptrace.S
+++ b/libc/arch-mips64/syscalls/__ptrace.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ptrace)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__reboot.S b/libc/arch-mips64/syscalls/__reboot.S
index 31a97e3..a4f4e71 100644
--- a/libc/arch-mips64/syscalls/__reboot.S
+++ b/libc/arch-mips64/syscalls/__reboot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__reboot)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__rt_sigaction.S b/libc/arch-mips64/syscalls/__rt_sigaction.S
index 3728c58..10f3598 100644
--- a/libc/arch-mips64/syscalls/__rt_sigaction.S
+++ b/libc/arch-mips64/syscalls/__rt_sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigaction)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__rt_sigpending.S b/libc/arch-mips64/syscalls/__rt_sigpending.S
index e0d40cc..7855cca 100644
--- a/libc/arch-mips64/syscalls/__rt_sigpending.S
+++ b/libc/arch-mips64/syscalls/__rt_sigpending.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigpending)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__rt_sigprocmask.S b/libc/arch-mips64/syscalls/__rt_sigprocmask.S
index d34a34b..f1ba2e9 100644
--- a/libc/arch-mips64/syscalls/__rt_sigprocmask.S
+++ b/libc/arch-mips64/syscalls/__rt_sigprocmask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigprocmask)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__rt_sigsuspend.S b/libc/arch-mips64/syscalls/__rt_sigsuspend.S
index f36e1c3..50ebf5e 100644
--- a/libc/arch-mips64/syscalls/__rt_sigsuspend.S
+++ b/libc/arch-mips64/syscalls/__rt_sigsuspend.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigsuspend)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__rt_sigtimedwait.S b/libc/arch-mips64/syscalls/__rt_sigtimedwait.S
index 798d6f8..304d049 100644
--- a/libc/arch-mips64/syscalls/__rt_sigtimedwait.S
+++ b/libc/arch-mips64/syscalls/__rt_sigtimedwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigtimedwait)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__sched_getaffinity.S b/libc/arch-mips64/syscalls/__sched_getaffinity.S
index a287815..cf590c3 100644
--- a/libc/arch-mips64/syscalls/__sched_getaffinity.S
+++ b/libc/arch-mips64/syscalls/__sched_getaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sched_getaffinity)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__set_tid_address.S b/libc/arch-mips64/syscalls/__set_tid_address.S
index 8757001..d08aa7b 100644
--- a/libc/arch-mips64/syscalls/__set_tid_address.S
+++ b/libc/arch-mips64/syscalls/__set_tid_address.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tid_address)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__set_tls.S b/libc/arch-mips64/syscalls/__set_tls.S
index f1c31b4..430c5fb 100644
--- a/libc/arch-mips64/syscalls/__set_tls.S
+++ b/libc/arch-mips64/syscalls/__set_tls.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tls)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__signalfd4.S b/libc/arch-mips64/syscalls/__signalfd4.S
index c4fe77b..0200138 100644
--- a/libc/arch-mips64/syscalls/__signalfd4.S
+++ b/libc/arch-mips64/syscalls/__signalfd4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__signalfd4)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__socket.S b/libc/arch-mips64/syscalls/__socket.S
index d1e0058..ac7586a 100644
--- a/libc/arch-mips64/syscalls/__socket.S
+++ b/libc/arch-mips64/syscalls/__socket.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__socket)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__timer_create.S b/libc/arch-mips64/syscalls/__timer_create.S
index 5a4daac..518207d 100644
--- a/libc/arch-mips64/syscalls/__timer_create.S
+++ b/libc/arch-mips64/syscalls/__timer_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_create)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__timer_delete.S b/libc/arch-mips64/syscalls/__timer_delete.S
index 8bbbdb7..4db1c85 100644
--- a/libc/arch-mips64/syscalls/__timer_delete.S
+++ b/libc/arch-mips64/syscalls/__timer_delete.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_delete)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__timer_getoverrun.S b/libc/arch-mips64/syscalls/__timer_getoverrun.S
index 3bf06cc..c5aa40f 100644
--- a/libc/arch-mips64/syscalls/__timer_getoverrun.S
+++ b/libc/arch-mips64/syscalls/__timer_getoverrun.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_getoverrun)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__timer_gettime.S b/libc/arch-mips64/syscalls/__timer_gettime.S
index a15ec17..8bebdd8 100644
--- a/libc/arch-mips64/syscalls/__timer_gettime.S
+++ b/libc/arch-mips64/syscalls/__timer_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_gettime)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__timer_settime.S b/libc/arch-mips64/syscalls/__timer_settime.S
index 10e2ca8..536c816 100644
--- a/libc/arch-mips64/syscalls/__timer_settime.S
+++ b/libc/arch-mips64/syscalls/__timer_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_settime)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/__waitid.S b/libc/arch-mips64/syscalls/__waitid.S
index 4d971e6..28b99bc 100644
--- a/libc/arch-mips64/syscalls/__waitid.S
+++ b/libc/arch-mips64/syscalls/__waitid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__waitid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/_exit.S b/libc/arch-mips64/syscalls/_exit.S
index eb84def..370960e 100644
--- a/libc/arch-mips64/syscalls/_exit.S
+++ b/libc/arch-mips64/syscalls/_exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(_exit)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/acct.S b/libc/arch-mips64/syscalls/acct.S
index 7185877..70bdd3e 100644
--- a/libc/arch-mips64/syscalls/acct.S
+++ b/libc/arch-mips64/syscalls/acct.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(acct)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/bind.S b/libc/arch-mips64/syscalls/bind.S
index cb28bb4..fab9b42 100644
--- a/libc/arch-mips64/syscalls/bind.S
+++ b/libc/arch-mips64/syscalls/bind.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(bind)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/capget.S b/libc/arch-mips64/syscalls/capget.S
index 068e076..6c1a13c 100644
--- a/libc/arch-mips64/syscalls/capget.S
+++ b/libc/arch-mips64/syscalls/capget.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capget)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/capset.S b/libc/arch-mips64/syscalls/capset.S
index f29501b..da8e9e6 100644
--- a/libc/arch-mips64/syscalls/capset.S
+++ b/libc/arch-mips64/syscalls/capset.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capset)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/chdir.S b/libc/arch-mips64/syscalls/chdir.S
index c2753bd..37f8f69 100644
--- a/libc/arch-mips64/syscalls/chdir.S
+++ b/libc/arch-mips64/syscalls/chdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chdir)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/chroot.S b/libc/arch-mips64/syscalls/chroot.S
index ca1d4a8..7dced37 100644
--- a/libc/arch-mips64/syscalls/chroot.S
+++ b/libc/arch-mips64/syscalls/chroot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chroot)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/clock_getres.S b/libc/arch-mips64/syscalls/clock_getres.S
index e7a8dd3..72ad146 100644
--- a/libc/arch-mips64/syscalls/clock_getres.S
+++ b/libc/arch-mips64/syscalls/clock_getres.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_getres)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/clock_gettime.S b/libc/arch-mips64/syscalls/clock_gettime.S
index 4c92a38..431e667 100644
--- a/libc/arch-mips64/syscalls/clock_gettime.S
+++ b/libc/arch-mips64/syscalls/clock_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_gettime)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/clock_nanosleep.S b/libc/arch-mips64/syscalls/clock_nanosleep.S
index 2934591..c0db781 100644
--- a/libc/arch-mips64/syscalls/clock_nanosleep.S
+++ b/libc/arch-mips64/syscalls/clock_nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_nanosleep)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/clock_settime.S b/libc/arch-mips64/syscalls/clock_settime.S
index 1969cb6..c9a4a79 100644
--- a/libc/arch-mips64/syscalls/clock_settime.S
+++ b/libc/arch-mips64/syscalls/clock_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_settime)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/close.S b/libc/arch-mips64/syscalls/close.S
index f446000..ff093e4 100644
--- a/libc/arch-mips64/syscalls/close.S
+++ b/libc/arch-mips64/syscalls/close.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(close)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/delete_module.S b/libc/arch-mips64/syscalls/delete_module.S
index d24adf8..86c64d6 100644
--- a/libc/arch-mips64/syscalls/delete_module.S
+++ b/libc/arch-mips64/syscalls/delete_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(delete_module)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/dup.S b/libc/arch-mips64/syscalls/dup.S
index 5d2d7de..23aa5c0 100644
--- a/libc/arch-mips64/syscalls/dup.S
+++ b/libc/arch-mips64/syscalls/dup.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/dup3.S b/libc/arch-mips64/syscalls/dup3.S
index 90f0f89..a5392dc 100644
--- a/libc/arch-mips64/syscalls/dup3.S
+++ b/libc/arch-mips64/syscalls/dup3.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup3)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/epoll_create1.S b/libc/arch-mips64/syscalls/epoll_create1.S
index 312887f..c3219d4 100644
--- a/libc/arch-mips64/syscalls/epoll_create1.S
+++ b/libc/arch-mips64/syscalls/epoll_create1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_create1)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/epoll_ctl.S b/libc/arch-mips64/syscalls/epoll_ctl.S
index 461ad7b..9b740d0 100644
--- a/libc/arch-mips64/syscalls/epoll_ctl.S
+++ b/libc/arch-mips64/syscalls/epoll_ctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_ctl)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/eventfd.S b/libc/arch-mips64/syscalls/eventfd.S
index da8866e..ea3a2c6 100644
--- a/libc/arch-mips64/syscalls/eventfd.S
+++ b/libc/arch-mips64/syscalls/eventfd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(eventfd)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/execve.S b/libc/arch-mips64/syscalls/execve.S
index 3cb49b6..af2c6d0 100644
--- a/libc/arch-mips64/syscalls/execve.S
+++ b/libc/arch-mips64/syscalls/execve.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(execve)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/faccessat.S b/libc/arch-mips64/syscalls/faccessat.S
index d06f420..c8ee9e5 100644
--- a/libc/arch-mips64/syscalls/faccessat.S
+++ b/libc/arch-mips64/syscalls/faccessat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(faccessat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fallocate.S b/libc/arch-mips64/syscalls/fallocate.S
index d1e64b5..9e7c89e 100644
--- a/libc/arch-mips64/syscalls/fallocate.S
+++ b/libc/arch-mips64/syscalls/fallocate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fallocate)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fchdir.S b/libc/arch-mips64/syscalls/fchdir.S
index 0c8ab73..780a8a2 100644
--- a/libc/arch-mips64/syscalls/fchdir.S
+++ b/libc/arch-mips64/syscalls/fchdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchdir)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fchmod.S b/libc/arch-mips64/syscalls/fchmod.S
index 4ebb796..b9e7cab 100644
--- a/libc/arch-mips64/syscalls/fchmod.S
+++ b/libc/arch-mips64/syscalls/fchmod.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmod)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fchmodat.S b/libc/arch-mips64/syscalls/fchmodat.S
index 4887324..ff04c8c 100644
--- a/libc/arch-mips64/syscalls/fchmodat.S
+++ b/libc/arch-mips64/syscalls/fchmodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmodat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fchown.S b/libc/arch-mips64/syscalls/fchown.S
index c21c831..97bd208 100644
--- a/libc/arch-mips64/syscalls/fchown.S
+++ b/libc/arch-mips64/syscalls/fchown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchown)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fchownat.S b/libc/arch-mips64/syscalls/fchownat.S
index eba230c..0e5635a 100644
--- a/libc/arch-mips64/syscalls/fchownat.S
+++ b/libc/arch-mips64/syscalls/fchownat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchownat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fcntl.S b/libc/arch-mips64/syscalls/fcntl.S
index 1f54b0e..325d9fd 100644
--- a/libc/arch-mips64/syscalls/fcntl.S
+++ b/libc/arch-mips64/syscalls/fcntl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fcntl)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fdatasync.S b/libc/arch-mips64/syscalls/fdatasync.S
index ba1eccc..8a714c3 100644
--- a/libc/arch-mips64/syscalls/fdatasync.S
+++ b/libc/arch-mips64/syscalls/fdatasync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fdatasync)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fgetxattr.S b/libc/arch-mips64/syscalls/fgetxattr.S
index 5b9c8ed..87a21ce 100644
--- a/libc/arch-mips64/syscalls/fgetxattr.S
+++ b/libc/arch-mips64/syscalls/fgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fgetxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/flistxattr.S b/libc/arch-mips64/syscalls/flistxattr.S
index c0bf93c..b430931 100644
--- a/libc/arch-mips64/syscalls/flistxattr.S
+++ b/libc/arch-mips64/syscalls/flistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flistxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/flock.S b/libc/arch-mips64/syscalls/flock.S
index b63f6fc..bc4c835 100644
--- a/libc/arch-mips64/syscalls/flock.S
+++ b/libc/arch-mips64/syscalls/flock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flock)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fremovexattr.S b/libc/arch-mips64/syscalls/fremovexattr.S
index be20d00..4121223 100644
--- a/libc/arch-mips64/syscalls/fremovexattr.S
+++ b/libc/arch-mips64/syscalls/fremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fremovexattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fsetxattr.S b/libc/arch-mips64/syscalls/fsetxattr.S
index 92198ce..4180bd0 100644
--- a/libc/arch-mips64/syscalls/fsetxattr.S
+++ b/libc/arch-mips64/syscalls/fsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsetxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fstat64.S b/libc/arch-mips64/syscalls/fstat64.S
index 078e3dd..03cbf69 100644
--- a/libc/arch-mips64/syscalls/fstat64.S
+++ b/libc/arch-mips64/syscalls/fstat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstat64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fstatat64.S b/libc/arch-mips64/syscalls/fstatat64.S
index cc38de1..55ae243 100644
--- a/libc/arch-mips64/syscalls/fstatat64.S
+++ b/libc/arch-mips64/syscalls/fstatat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatat64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fstatfs64.S b/libc/arch-mips64/syscalls/fstatfs64.S
index 3474bc2..5fb5d95 100644
--- a/libc/arch-mips64/syscalls/fstatfs64.S
+++ b/libc/arch-mips64/syscalls/fstatfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatfs64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/fsync.S b/libc/arch-mips64/syscalls/fsync.S
index 3543fef..fa5de87 100644
--- a/libc/arch-mips64/syscalls/fsync.S
+++ b/libc/arch-mips64/syscalls/fsync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsync)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/ftruncate.S b/libc/arch-mips64/syscalls/ftruncate.S
index cd97b87..b605a37 100644
--- a/libc/arch-mips64/syscalls/ftruncate.S
+++ b/libc/arch-mips64/syscalls/ftruncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getegid.S b/libc/arch-mips64/syscalls/getegid.S
index d6b3d7f..7ef8fe3 100644
--- a/libc/arch-mips64/syscalls/getegid.S
+++ b/libc/arch-mips64/syscalls/getegid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getegid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/geteuid.S b/libc/arch-mips64/syscalls/geteuid.S
index a1d9713..c21f0ef 100644
--- a/libc/arch-mips64/syscalls/geteuid.S
+++ b/libc/arch-mips64/syscalls/geteuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(geteuid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getgid.S b/libc/arch-mips64/syscalls/getgid.S
index c89d709..bd690dc 100644
--- a/libc/arch-mips64/syscalls/getgid.S
+++ b/libc/arch-mips64/syscalls/getgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getgroups.S b/libc/arch-mips64/syscalls/getgroups.S
index 8d9cddb..d7aded7 100644
--- a/libc/arch-mips64/syscalls/getgroups.S
+++ b/libc/arch-mips64/syscalls/getgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgroups)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getitimer.S b/libc/arch-mips64/syscalls/getitimer.S
index 12dad03..a438faa 100644
--- a/libc/arch-mips64/syscalls/getitimer.S
+++ b/libc/arch-mips64/syscalls/getitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getitimer)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getpeername.S b/libc/arch-mips64/syscalls/getpeername.S
index 278428a..bf40141 100644
--- a/libc/arch-mips64/syscalls/getpeername.S
+++ b/libc/arch-mips64/syscalls/getpeername.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpeername)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getpgid.S b/libc/arch-mips64/syscalls/getpgid.S
index 56551ef..739a6e2 100644
--- a/libc/arch-mips64/syscalls/getpgid.S
+++ b/libc/arch-mips64/syscalls/getpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpgid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getppid.S b/libc/arch-mips64/syscalls/getppid.S
index 97066f8..e642a79 100644
--- a/libc/arch-mips64/syscalls/getppid.S
+++ b/libc/arch-mips64/syscalls/getppid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getppid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getresgid.S b/libc/arch-mips64/syscalls/getresgid.S
index f07fc11..d88516f 100644
--- a/libc/arch-mips64/syscalls/getresgid.S
+++ b/libc/arch-mips64/syscalls/getresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresgid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getresuid.S b/libc/arch-mips64/syscalls/getresuid.S
index 4f1ba86..b439211 100644
--- a/libc/arch-mips64/syscalls/getresuid.S
+++ b/libc/arch-mips64/syscalls/getresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresuid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getrlimit.S b/libc/arch-mips64/syscalls/getrlimit.S
index f825db9..423bc0f 100644
--- a/libc/arch-mips64/syscalls/getrlimit.S
+++ b/libc/arch-mips64/syscalls/getrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrlimit)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getrusage.S b/libc/arch-mips64/syscalls/getrusage.S
index 49f3c42..9f57b84 100644
--- a/libc/arch-mips64/syscalls/getrusage.S
+++ b/libc/arch-mips64/syscalls/getrusage.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrusage)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getsid.S b/libc/arch-mips64/syscalls/getsid.S
index 6fa362c..125da4e 100644
--- a/libc/arch-mips64/syscalls/getsid.S
+++ b/libc/arch-mips64/syscalls/getsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getsockname.S b/libc/arch-mips64/syscalls/getsockname.S
index 5e16aff..3481d65 100644
--- a/libc/arch-mips64/syscalls/getsockname.S
+++ b/libc/arch-mips64/syscalls/getsockname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockname)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getsockopt.S b/libc/arch-mips64/syscalls/getsockopt.S
index fab05b1..2e9b6d7 100644
--- a/libc/arch-mips64/syscalls/getsockopt.S
+++ b/libc/arch-mips64/syscalls/getsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockopt)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/gettimeofday.S b/libc/arch-mips64/syscalls/gettimeofday.S
index 07407a4..9bbbd28 100644
--- a/libc/arch-mips64/syscalls/gettimeofday.S
+++ b/libc/arch-mips64/syscalls/gettimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(gettimeofday)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getuid.S b/libc/arch-mips64/syscalls/getuid.S
index 87c16e1..4809a5a 100644
--- a/libc/arch-mips64/syscalls/getuid.S
+++ b/libc/arch-mips64/syscalls/getuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getuid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/getxattr.S b/libc/arch-mips64/syscalls/getxattr.S
index b42ca1e..7a7a4d4 100644
--- a/libc/arch-mips64/syscalls/getxattr.S
+++ b/libc/arch-mips64/syscalls/getxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/init_module.S b/libc/arch-mips64/syscalls/init_module.S
index 90fb6b1..e46dedc 100644
--- a/libc/arch-mips64/syscalls/init_module.S
+++ b/libc/arch-mips64/syscalls/init_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(init_module)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/inotify_add_watch.S b/libc/arch-mips64/syscalls/inotify_add_watch.S
index 17db414..4a4fe5f 100644
--- a/libc/arch-mips64/syscalls/inotify_add_watch.S
+++ b/libc/arch-mips64/syscalls/inotify_add_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_add_watch)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/inotify_init1.S b/libc/arch-mips64/syscalls/inotify_init1.S
index 356dd2d..6ef6021 100644
--- a/libc/arch-mips64/syscalls/inotify_init1.S
+++ b/libc/arch-mips64/syscalls/inotify_init1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_init1)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/inotify_rm_watch.S b/libc/arch-mips64/syscalls/inotify_rm_watch.S
index 4096ca3..10e239a 100644
--- a/libc/arch-mips64/syscalls/inotify_rm_watch.S
+++ b/libc/arch-mips64/syscalls/inotify_rm_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_rm_watch)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/kill.S b/libc/arch-mips64/syscalls/kill.S
index 2d8b452..f85a3ef 100644
--- a/libc/arch-mips64/syscalls/kill.S
+++ b/libc/arch-mips64/syscalls/kill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(kill)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/klogctl.S b/libc/arch-mips64/syscalls/klogctl.S
index 2f9ca6a..8e94b62 100644
--- a/libc/arch-mips64/syscalls/klogctl.S
+++ b/libc/arch-mips64/syscalls/klogctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(klogctl)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/lgetxattr.S b/libc/arch-mips64/syscalls/lgetxattr.S
index f8e57b3..c5990ab 100644
--- a/libc/arch-mips64/syscalls/lgetxattr.S
+++ b/libc/arch-mips64/syscalls/lgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lgetxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/linkat.S b/libc/arch-mips64/syscalls/linkat.S
index a866fa6..88db867 100644
--- a/libc/arch-mips64/syscalls/linkat.S
+++ b/libc/arch-mips64/syscalls/linkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(linkat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/listen.S b/libc/arch-mips64/syscalls/listen.S
index 0768c72..4db8789 100644
--- a/libc/arch-mips64/syscalls/listen.S
+++ b/libc/arch-mips64/syscalls/listen.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listen)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/listxattr.S b/libc/arch-mips64/syscalls/listxattr.S
index f2c00f6..56b13f6 100644
--- a/libc/arch-mips64/syscalls/listxattr.S
+++ b/libc/arch-mips64/syscalls/listxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/llistxattr.S b/libc/arch-mips64/syscalls/llistxattr.S
index f324e2c..d800f7f 100644
--- a/libc/arch-mips64/syscalls/llistxattr.S
+++ b/libc/arch-mips64/syscalls/llistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(llistxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/lremovexattr.S b/libc/arch-mips64/syscalls/lremovexattr.S
index e44c9d0..e05733f 100644
--- a/libc/arch-mips64/syscalls/lremovexattr.S
+++ b/libc/arch-mips64/syscalls/lremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lremovexattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/lseek.S b/libc/arch-mips64/syscalls/lseek.S
index 2858aa8..34533cf 100644
--- a/libc/arch-mips64/syscalls/lseek.S
+++ b/libc/arch-mips64/syscalls/lseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lseek)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/lsetxattr.S b/libc/arch-mips64/syscalls/lsetxattr.S
index ed1b4df..dea6add 100644
--- a/libc/arch-mips64/syscalls/lsetxattr.S
+++ b/libc/arch-mips64/syscalls/lsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lsetxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/madvise.S b/libc/arch-mips64/syscalls/madvise.S
index fe6a828..ab174e9 100644
--- a/libc/arch-mips64/syscalls/madvise.S
+++ b/libc/arch-mips64/syscalls/madvise.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(madvise)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mincore.S b/libc/arch-mips64/syscalls/mincore.S
index 1e0b544..349d2f6 100644
--- a/libc/arch-mips64/syscalls/mincore.S
+++ b/libc/arch-mips64/syscalls/mincore.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mincore)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mkdirat.S b/libc/arch-mips64/syscalls/mkdirat.S
index b1c94e1..b395ba4 100644
--- a/libc/arch-mips64/syscalls/mkdirat.S
+++ b/libc/arch-mips64/syscalls/mkdirat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mkdirat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mknodat.S b/libc/arch-mips64/syscalls/mknodat.S
index edbd3b6..c13d979 100644
--- a/libc/arch-mips64/syscalls/mknodat.S
+++ b/libc/arch-mips64/syscalls/mknodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mknodat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mlock.S b/libc/arch-mips64/syscalls/mlock.S
index ae599cd..82338f3 100644
--- a/libc/arch-mips64/syscalls/mlock.S
+++ b/libc/arch-mips64/syscalls/mlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlock)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mlockall.S b/libc/arch-mips64/syscalls/mlockall.S
index b214758..b34cf81 100644
--- a/libc/arch-mips64/syscalls/mlockall.S
+++ b/libc/arch-mips64/syscalls/mlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlockall)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mmap.S b/libc/arch-mips64/syscalls/mmap.S
index ba6d4fa..814b745 100644
--- a/libc/arch-mips64/syscalls/mmap.S
+++ b/libc/arch-mips64/syscalls/mmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mmap)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mount.S b/libc/arch-mips64/syscalls/mount.S
index 71e08a7..3f42df5 100644
--- a/libc/arch-mips64/syscalls/mount.S
+++ b/libc/arch-mips64/syscalls/mount.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mount)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mprotect.S b/libc/arch-mips64/syscalls/mprotect.S
index 66ffa1a..adf9a67 100644
--- a/libc/arch-mips64/syscalls/mprotect.S
+++ b/libc/arch-mips64/syscalls/mprotect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mprotect)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/mremap.S b/libc/arch-mips64/syscalls/mremap.S
index c73320f..70c8a8c 100644
--- a/libc/arch-mips64/syscalls/mremap.S
+++ b/libc/arch-mips64/syscalls/mremap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mremap)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/msync.S b/libc/arch-mips64/syscalls/msync.S
index a97cba8..dced6e7 100644
--- a/libc/arch-mips64/syscalls/msync.S
+++ b/libc/arch-mips64/syscalls/msync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(msync)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/munlock.S b/libc/arch-mips64/syscalls/munlock.S
index f5919ae..075c061 100644
--- a/libc/arch-mips64/syscalls/munlock.S
+++ b/libc/arch-mips64/syscalls/munlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlock)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/munlockall.S b/libc/arch-mips64/syscalls/munlockall.S
index 39e717c..10ff274 100644
--- a/libc/arch-mips64/syscalls/munlockall.S
+++ b/libc/arch-mips64/syscalls/munlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlockall)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/munmap.S b/libc/arch-mips64/syscalls/munmap.S
index c1c9b01..5d0b0b0 100644
--- a/libc/arch-mips64/syscalls/munmap.S
+++ b/libc/arch-mips64/syscalls/munmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munmap)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/nanosleep.S b/libc/arch-mips64/syscalls/nanosleep.S
index 6bfd73e..a0c7d36 100644
--- a/libc/arch-mips64/syscalls/nanosleep.S
+++ b/libc/arch-mips64/syscalls/nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(nanosleep)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/personality.S b/libc/arch-mips64/syscalls/personality.S
index e234636..326cf24 100644
--- a/libc/arch-mips64/syscalls/personality.S
+++ b/libc/arch-mips64/syscalls/personality.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(personality)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/pipe2.S b/libc/arch-mips64/syscalls/pipe2.S
index 52d5baa..8e207ac 100644
--- a/libc/arch-mips64/syscalls/pipe2.S
+++ b/libc/arch-mips64/syscalls/pipe2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pipe2)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/prctl.S b/libc/arch-mips64/syscalls/prctl.S
index 01d422e..9e805f4 100644
--- a/libc/arch-mips64/syscalls/prctl.S
+++ b/libc/arch-mips64/syscalls/prctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prctl)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/pread64.S b/libc/arch-mips64/syscalls/pread64.S
index 5ab8389..3aa0620 100644
--- a/libc/arch-mips64/syscalls/pread64.S
+++ b/libc/arch-mips64/syscalls/pread64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pread64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/prlimit64.S b/libc/arch-mips64/syscalls/prlimit64.S
index e52ca92..f767ac1 100644
--- a/libc/arch-mips64/syscalls/prlimit64.S
+++ b/libc/arch-mips64/syscalls/prlimit64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prlimit64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/pwrite64.S b/libc/arch-mips64/syscalls/pwrite64.S
index 8d7a8b5..8b3bcc0 100644
--- a/libc/arch-mips64/syscalls/pwrite64.S
+++ b/libc/arch-mips64/syscalls/pwrite64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pwrite64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/read.S b/libc/arch-mips64/syscalls/read.S
index 3f805ca..ab687d1 100644
--- a/libc/arch-mips64/syscalls/read.S
+++ b/libc/arch-mips64/syscalls/read.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(read)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/readahead.S b/libc/arch-mips64/syscalls/readahead.S
index 8f5c8c6..1d9b15b 100644
--- a/libc/arch-mips64/syscalls/readahead.S
+++ b/libc/arch-mips64/syscalls/readahead.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readahead)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/readlinkat.S b/libc/arch-mips64/syscalls/readlinkat.S
index 1381c22..24da46b 100644
--- a/libc/arch-mips64/syscalls/readlinkat.S
+++ b/libc/arch-mips64/syscalls/readlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readlinkat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/readv.S b/libc/arch-mips64/syscalls/readv.S
index 9c7afd5..6aca131 100644
--- a/libc/arch-mips64/syscalls/readv.S
+++ b/libc/arch-mips64/syscalls/readv.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readv)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/recvfrom.S b/libc/arch-mips64/syscalls/recvfrom.S
index d3911c6..b9fb037 100644
--- a/libc/arch-mips64/syscalls/recvfrom.S
+++ b/libc/arch-mips64/syscalls/recvfrom.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvfrom)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/recvmmsg.S b/libc/arch-mips64/syscalls/recvmmsg.S
index fa9fbb2..b187cf0 100644
--- a/libc/arch-mips64/syscalls/recvmmsg.S
+++ b/libc/arch-mips64/syscalls/recvmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmmsg)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/recvmsg.S b/libc/arch-mips64/syscalls/recvmsg.S
index 21ec51d..49dbb48 100644
--- a/libc/arch-mips64/syscalls/recvmsg.S
+++ b/libc/arch-mips64/syscalls/recvmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmsg)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/removexattr.S b/libc/arch-mips64/syscalls/removexattr.S
index ea31771..61d6da1 100644
--- a/libc/arch-mips64/syscalls/removexattr.S
+++ b/libc/arch-mips64/syscalls/removexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(removexattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/renameat.S b/libc/arch-mips64/syscalls/renameat.S
index 074a6a4..f012fad 100644
--- a/libc/arch-mips64/syscalls/renameat.S
+++ b/libc/arch-mips64/syscalls/renameat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(renameat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_get_priority_max.S b/libc/arch-mips64/syscalls/sched_get_priority_max.S
index 1b67bbf..264545b 100644
--- a/libc/arch-mips64/syscalls/sched_get_priority_max.S
+++ b/libc/arch-mips64/syscalls/sched_get_priority_max.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_max)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_get_priority_min.S b/libc/arch-mips64/syscalls/sched_get_priority_min.S
index 2d68752..4984abf 100644
--- a/libc/arch-mips64/syscalls/sched_get_priority_min.S
+++ b/libc/arch-mips64/syscalls/sched_get_priority_min.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_min)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_getparam.S b/libc/arch-mips64/syscalls/sched_getparam.S
index d0b2069..2837fc8 100644
--- a/libc/arch-mips64/syscalls/sched_getparam.S
+++ b/libc/arch-mips64/syscalls/sched_getparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getparam)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_getscheduler.S b/libc/arch-mips64/syscalls/sched_getscheduler.S
index f25bde5..3f8dbe3 100644
--- a/libc/arch-mips64/syscalls/sched_getscheduler.S
+++ b/libc/arch-mips64/syscalls/sched_getscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getscheduler)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_rr_get_interval.S b/libc/arch-mips64/syscalls/sched_rr_get_interval.S
index 48233f8..80ea18e 100644
--- a/libc/arch-mips64/syscalls/sched_rr_get_interval.S
+++ b/libc/arch-mips64/syscalls/sched_rr_get_interval.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_rr_get_interval)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_setaffinity.S b/libc/arch-mips64/syscalls/sched_setaffinity.S
index e604863..843e06f 100644
--- a/libc/arch-mips64/syscalls/sched_setaffinity.S
+++ b/libc/arch-mips64/syscalls/sched_setaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setaffinity)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_setparam.S b/libc/arch-mips64/syscalls/sched_setparam.S
index b02439f..78435b1 100644
--- a/libc/arch-mips64/syscalls/sched_setparam.S
+++ b/libc/arch-mips64/syscalls/sched_setparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setparam)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_setscheduler.S b/libc/arch-mips64/syscalls/sched_setscheduler.S
index dda1ce5..7f78cc7 100644
--- a/libc/arch-mips64/syscalls/sched_setscheduler.S
+++ b/libc/arch-mips64/syscalls/sched_setscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setscheduler)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sched_yield.S b/libc/arch-mips64/syscalls/sched_yield.S
index 509b029..f81b7ef 100644
--- a/libc/arch-mips64/syscalls/sched_yield.S
+++ b/libc/arch-mips64/syscalls/sched_yield.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_yield)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sendfile.S b/libc/arch-mips64/syscalls/sendfile.S
index 684a83a..c3e80de 100644
--- a/libc/arch-mips64/syscalls/sendfile.S
+++ b/libc/arch-mips64/syscalls/sendfile.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sendmmsg.S b/libc/arch-mips64/syscalls/sendmmsg.S
index e4d8019..40efcb6 100644
--- a/libc/arch-mips64/syscalls/sendmmsg.S
+++ b/libc/arch-mips64/syscalls/sendmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmmsg)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sendmsg.S b/libc/arch-mips64/syscalls/sendmsg.S
index 6983f9a..9f90717 100644
--- a/libc/arch-mips64/syscalls/sendmsg.S
+++ b/libc/arch-mips64/syscalls/sendmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmsg)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sendto.S b/libc/arch-mips64/syscalls/sendto.S
index cfe774d..3ebfbae 100644
--- a/libc/arch-mips64/syscalls/sendto.S
+++ b/libc/arch-mips64/syscalls/sendto.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendto)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/_flush_cache.S b/libc/arch-mips64/syscalls/setfsgid.S
similarity index 79%
copy from libc/arch-mips64/syscalls/_flush_cache.S
copy to libc/arch-mips64/syscalls/setfsgid.S
index 132fd4e..9b36038 100644
--- a/libc/arch-mips64/syscalls/_flush_cache.S
+++ b/libc/arch-mips64/syscalls/setfsgid.S
@@ -2,10 +2,12 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(_flush_cache)
+    .hidden __set_errno
+
+ENTRY(setfsgid)
     .set push
     .set noreorder
-    li v0, __NR_cacheflush
+    li v0, __NR_setfsgid
     syscall
     bnez a3, 1f
     move a0, v0
@@ -22,4 +24,4 @@
     j t9
     move ra, t0
     .set pop
-END(_flush_cache)
+END(setfsgid)
diff --git a/libc/arch-mips64/syscalls/_flush_cache.S b/libc/arch-mips64/syscalls/setfsuid.S
similarity index 79%
rename from libc/arch-mips64/syscalls/_flush_cache.S
rename to libc/arch-mips64/syscalls/setfsuid.S
index 132fd4e..e42601f 100644
--- a/libc/arch-mips64/syscalls/_flush_cache.S
+++ b/libc/arch-mips64/syscalls/setfsuid.S
@@ -2,10 +2,12 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(_flush_cache)
+    .hidden __set_errno
+
+ENTRY(setfsuid)
     .set push
     .set noreorder
-    li v0, __NR_cacheflush
+    li v0, __NR_setfsuid
     syscall
     bnez a3, 1f
     move a0, v0
@@ -22,4 +24,4 @@
     j t9
     move ra, t0
     .set pop
-END(_flush_cache)
+END(setfsuid)
diff --git a/libc/arch-mips64/syscalls/setgid.S b/libc/arch-mips64/syscalls/setgid.S
index cc8d3ab..7ce8599 100644
--- a/libc/arch-mips64/syscalls/setgid.S
+++ b/libc/arch-mips64/syscalls/setgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setgroups.S b/libc/arch-mips64/syscalls/setgroups.S
index 63f2329..2724068 100644
--- a/libc/arch-mips64/syscalls/setgroups.S
+++ b/libc/arch-mips64/syscalls/setgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgroups)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setitimer.S b/libc/arch-mips64/syscalls/setitimer.S
index 9ee02dc..f5dcff0 100644
--- a/libc/arch-mips64/syscalls/setitimer.S
+++ b/libc/arch-mips64/syscalls/setitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setitimer)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setns.S b/libc/arch-mips64/syscalls/setns.S
index 191a1a0..cbe2e06 100644
--- a/libc/arch-mips64/syscalls/setns.S
+++ b/libc/arch-mips64/syscalls/setns.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setns)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setpgid.S b/libc/arch-mips64/syscalls/setpgid.S
index 8972160..da44532 100644
--- a/libc/arch-mips64/syscalls/setpgid.S
+++ b/libc/arch-mips64/syscalls/setpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpgid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setpriority.S b/libc/arch-mips64/syscalls/setpriority.S
index dce3a76..150a5d4 100644
--- a/libc/arch-mips64/syscalls/setpriority.S
+++ b/libc/arch-mips64/syscalls/setpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpriority)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setregid.S b/libc/arch-mips64/syscalls/setregid.S
index d677b32..b80115c 100644
--- a/libc/arch-mips64/syscalls/setregid.S
+++ b/libc/arch-mips64/syscalls/setregid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setregid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setresgid.S b/libc/arch-mips64/syscalls/setresgid.S
index 312eb3a..0fbf302 100644
--- a/libc/arch-mips64/syscalls/setresgid.S
+++ b/libc/arch-mips64/syscalls/setresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresgid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setresuid.S b/libc/arch-mips64/syscalls/setresuid.S
index 4da79d0..89af745 100644
--- a/libc/arch-mips64/syscalls/setresuid.S
+++ b/libc/arch-mips64/syscalls/setresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresuid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setreuid.S b/libc/arch-mips64/syscalls/setreuid.S
index 33f6fce..797091f 100644
--- a/libc/arch-mips64/syscalls/setreuid.S
+++ b/libc/arch-mips64/syscalls/setreuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setreuid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setrlimit.S b/libc/arch-mips64/syscalls/setrlimit.S
index 3060298..034f3db 100644
--- a/libc/arch-mips64/syscalls/setrlimit.S
+++ b/libc/arch-mips64/syscalls/setrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setrlimit)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setsid.S b/libc/arch-mips64/syscalls/setsid.S
index c8d1ad5..ef14eba 100644
--- a/libc/arch-mips64/syscalls/setsid.S
+++ b/libc/arch-mips64/syscalls/setsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setsockopt.S b/libc/arch-mips64/syscalls/setsockopt.S
index b40aad1..5c263bd 100644
--- a/libc/arch-mips64/syscalls/setsockopt.S
+++ b/libc/arch-mips64/syscalls/setsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsockopt)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/settimeofday.S b/libc/arch-mips64/syscalls/settimeofday.S
index 2e333f8..a73638f 100644
--- a/libc/arch-mips64/syscalls/settimeofday.S
+++ b/libc/arch-mips64/syscalls/settimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(settimeofday)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setuid.S b/libc/arch-mips64/syscalls/setuid.S
index fb8125e..4321fae 100644
--- a/libc/arch-mips64/syscalls/setuid.S
+++ b/libc/arch-mips64/syscalls/setuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setuid)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/setxattr.S b/libc/arch-mips64/syscalls/setxattr.S
index 04e746d..58ccb5f 100644
--- a/libc/arch-mips64/syscalls/setxattr.S
+++ b/libc/arch-mips64/syscalls/setxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setxattr)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/shutdown.S b/libc/arch-mips64/syscalls/shutdown.S
index 59f437a..cdd6c78 100644
--- a/libc/arch-mips64/syscalls/shutdown.S
+++ b/libc/arch-mips64/syscalls/shutdown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(shutdown)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sigaltstack.S b/libc/arch-mips64/syscalls/sigaltstack.S
index 0fbd3a1..a2e663c 100644
--- a/libc/arch-mips64/syscalls/sigaltstack.S
+++ b/libc/arch-mips64/syscalls/sigaltstack.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sigaltstack)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/socketpair.S b/libc/arch-mips64/syscalls/socketpair.S
index fa684d1..7be7814 100644
--- a/libc/arch-mips64/syscalls/socketpair.S
+++ b/libc/arch-mips64/syscalls/socketpair.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(socketpair)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/splice.S b/libc/arch-mips64/syscalls/splice.S
index d626904..efee6cd 100644
--- a/libc/arch-mips64/syscalls/splice.S
+++ b/libc/arch-mips64/syscalls/splice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(splice)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/statfs64.S b/libc/arch-mips64/syscalls/statfs64.S
index e835e41..d377522 100644
--- a/libc/arch-mips64/syscalls/statfs64.S
+++ b/libc/arch-mips64/syscalls/statfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(statfs64)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/swapoff.S b/libc/arch-mips64/syscalls/swapoff.S
index dfaf185..b257b1e 100644
--- a/libc/arch-mips64/syscalls/swapoff.S
+++ b/libc/arch-mips64/syscalls/swapoff.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapoff)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/swapon.S b/libc/arch-mips64/syscalls/swapon.S
index 8e844c4..e18ff4c 100644
--- a/libc/arch-mips64/syscalls/swapon.S
+++ b/libc/arch-mips64/syscalls/swapon.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapon)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/symlinkat.S b/libc/arch-mips64/syscalls/symlinkat.S
index e43d597..560bf0d 100644
--- a/libc/arch-mips64/syscalls/symlinkat.S
+++ b/libc/arch-mips64/syscalls/symlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(symlinkat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sync.S b/libc/arch-mips64/syscalls/sync.S
index ec342a3..240a6d4 100644
--- a/libc/arch-mips64/syscalls/sync.S
+++ b/libc/arch-mips64/syscalls/sync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sync)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/sysinfo.S b/libc/arch-mips64/syscalls/sysinfo.S
index 16486fd..6b07be3 100644
--- a/libc/arch-mips64/syscalls/sysinfo.S
+++ b/libc/arch-mips64/syscalls/sysinfo.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sysinfo)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/tee.S b/libc/arch-mips64/syscalls/tee.S
index 429700c..0115f71 100644
--- a/libc/arch-mips64/syscalls/tee.S
+++ b/libc/arch-mips64/syscalls/tee.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tee)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/tgkill.S b/libc/arch-mips64/syscalls/tgkill.S
index d98d9ae..bf30a8d 100644
--- a/libc/arch-mips64/syscalls/tgkill.S
+++ b/libc/arch-mips64/syscalls/tgkill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tgkill)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/timerfd_create.S b/libc/arch-mips64/syscalls/timerfd_create.S
index ab8e9e0..e65874f 100644
--- a/libc/arch-mips64/syscalls/timerfd_create.S
+++ b/libc/arch-mips64/syscalls/timerfd_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_create)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/timerfd_gettime.S b/libc/arch-mips64/syscalls/timerfd_gettime.S
index 2ec7b9c..a843598 100644
--- a/libc/arch-mips64/syscalls/timerfd_gettime.S
+++ b/libc/arch-mips64/syscalls/timerfd_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_gettime)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/timerfd_settime.S b/libc/arch-mips64/syscalls/timerfd_settime.S
index 0aec09f..8c5994f 100644
--- a/libc/arch-mips64/syscalls/timerfd_settime.S
+++ b/libc/arch-mips64/syscalls/timerfd_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_settime)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/times.S b/libc/arch-mips64/syscalls/times.S
index 2457e0c..ff504e7 100644
--- a/libc/arch-mips64/syscalls/times.S
+++ b/libc/arch-mips64/syscalls/times.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(times)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/truncate.S b/libc/arch-mips64/syscalls/truncate.S
index a0cbe51..3fc06a2 100644
--- a/libc/arch-mips64/syscalls/truncate.S
+++ b/libc/arch-mips64/syscalls/truncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/umask.S b/libc/arch-mips64/syscalls/umask.S
index 33624d2..9e6c910 100644
--- a/libc/arch-mips64/syscalls/umask.S
+++ b/libc/arch-mips64/syscalls/umask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umask)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/umount2.S b/libc/arch-mips64/syscalls/umount2.S
index 6193459..f8d1996 100644
--- a/libc/arch-mips64/syscalls/umount2.S
+++ b/libc/arch-mips64/syscalls/umount2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umount2)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/uname.S b/libc/arch-mips64/syscalls/uname.S
index df50f45..ce93f08 100644
--- a/libc/arch-mips64/syscalls/uname.S
+++ b/libc/arch-mips64/syscalls/uname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(uname)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/unlinkat.S b/libc/arch-mips64/syscalls/unlinkat.S
index 29d4442..870e8d7 100644
--- a/libc/arch-mips64/syscalls/unlinkat.S
+++ b/libc/arch-mips64/syscalls/unlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unlinkat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/unshare.S b/libc/arch-mips64/syscalls/unshare.S
index 6d8fbf3..231c29a 100644
--- a/libc/arch-mips64/syscalls/unshare.S
+++ b/libc/arch-mips64/syscalls/unshare.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unshare)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/utimensat.S b/libc/arch-mips64/syscalls/utimensat.S
index 654b8a4..4b4243e 100644
--- a/libc/arch-mips64/syscalls/utimensat.S
+++ b/libc/arch-mips64/syscalls/utimensat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(utimensat)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/vmsplice.S b/libc/arch-mips64/syscalls/vmsplice.S
index aa03585..f854004 100644
--- a/libc/arch-mips64/syscalls/vmsplice.S
+++ b/libc/arch-mips64/syscalls/vmsplice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(vmsplice)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/wait4.S b/libc/arch-mips64/syscalls/wait4.S
index e3755b5..2d2b487 100644
--- a/libc/arch-mips64/syscalls/wait4.S
+++ b/libc/arch-mips64/syscalls/wait4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(wait4)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/write.S b/libc/arch-mips64/syscalls/write.S
index ce7f702..f603fb5 100644
--- a/libc/arch-mips64/syscalls/write.S
+++ b/libc/arch-mips64/syscalls/write.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(write)
     .set push
     .set noreorder
diff --git a/libc/arch-mips64/syscalls/writev.S b/libc/arch-mips64/syscalls/writev.S
index e2c7875..032e749 100644
--- a/libc/arch-mips64/syscalls/writev.S
+++ b/libc/arch-mips64/syscalls/writev.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(writev)
     .set push
     .set noreorder
diff --git a/libc/arch-x86/bionic/__stack_chk_fail_local.h b/libc/arch-x86/bionic/__stack_chk_fail_local.h
index 4f3699a..0b0fd7f 100644
--- a/libc/arch-x86/bionic/__stack_chk_fail_local.h
+++ b/libc/arch-x86/bionic/__stack_chk_fail_local.h
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
 
 /*
    __stack_chk_fail routine is runtime part of stack protector compiler
@@ -48,13 +49,9 @@
 */
 
 #ifdef __i386__
-#ifdef __PIC__
 extern void __stack_chk_fail();
 
-__attribute__ ((visibility ("hidden")))
-void __stack_chk_fail_local()
-{
+__LIBC_HIDDEN__ void __stack_chk_fail_local() {
   __stack_chk_fail();
 }
 #endif
-#endif
diff --git a/libc/arch-x86/bionic/setjmp.S b/libc/arch-x86/bionic/setjmp.S
index 5b94311..8f9d67c 100644
--- a/libc/arch-x86/bionic/setjmp.S
+++ b/libc/arch-x86/bionic/setjmp.S
@@ -46,11 +46,7 @@
 ENTRY(setjmp)
 	PIC_PROLOGUE
 	pushl	$0
-#ifdef PIC
 	call	PIC_PLT(sigblock)
-#else
-	call	sigblock
-#endif
 	addl	$4,%esp
 	PIC_EPILOGUE
 
@@ -71,11 +67,7 @@
 	movl	4(%esp),%edx
 	PIC_PROLOGUE
 	pushl	24(%edx)
-#ifdef PIC
 	call	PIC_PLT(sigsetmask)
-#else
-	call	sigsetmask
-#endif
 	addl	$4,%esp
 	PIC_EPILOGUE
 
diff --git a/libc/arch-x86/bionic/sigsetjmp.S b/libc/arch-x86/bionic/sigsetjmp.S
index 7ef732e..250c606 100644
--- a/libc/arch-x86/bionic/sigsetjmp.S
+++ b/libc/arch-x86/bionic/sigsetjmp.S
@@ -42,11 +42,7 @@
 
 	PIC_PROLOGUE
 	pushl	$0
-#ifdef PIC
 	call	PIC_PLT(sigblock)
-#else
-	call	sigblock
-#endif
 	addl	$4,%esp
 	PIC_EPILOGUE
 
@@ -70,11 +66,7 @@
 
 	PIC_PROLOGUE
 	pushl	24(%edx)
-#ifdef PIC
 	call	PIC_PLT(sigsetmask)
-#else
-	call	sigsetmask
-#endif
 	addl	$4,%esp
 	PIC_EPILOGUE
 
diff --git a/libc/arch-x86/bionic/__get_sp.S b/libc/arch-x86/bionic/vfork.S
similarity index 80%
rename from libc/arch-x86/bionic/__get_sp.S
rename to libc/arch-x86/bionic/vfork.S
index aea6ac6..ffa6b16 100644
--- a/libc/arch-x86/bionic/__get_sp.S
+++ b/libc/arch-x86/bionic/vfork.S
@@ -28,7 +28,17 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY_PRIVATE(__get_sp)
-  mov  %esp, %eax
-  ret
-END(__get_sp)
+// This custom code preserves the return address across the system call.
+
+ENTRY(vfork)
+  popl    %ecx  // Grab the return address.
+  movl    $__NR_vfork, %eax
+  int     $0x80
+  cmpl    $-MAX_ERRNO, %eax
+  jb      1f
+  negl    %eax
+  pushl   %eax
+  call    __set_errno
+1:
+  jmp     *%ecx  // Jump to the stored return address.
+END(vfork)
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/arch-x86/include/machine/asm.h b/libc/arch-x86/include/machine/asm.h
index 913e6c8..943f9dd 100644
--- a/libc/arch-x86/include/machine/asm.h
+++ b/libc/arch-x86/include/machine/asm.h
@@ -37,35 +37,18 @@
 #ifndef _I386_ASM_H_
 #define _I386_ASM_H_
 
-#ifdef PIC
 #define PIC_PROLOGUE	\
 	pushl	%ebx;	\
-	call	1f;	\
-1:			\
+	call	666f;	\
+666:			\
 	popl	%ebx;	\
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-666b], %ebx
 #define PIC_EPILOGUE	\
 	popl	%ebx
 #define PIC_PLT(x)	x@PLT
 #define PIC_GOT(x)	x@GOT(%ebx)
 #define PIC_GOTOFF(x)	x@GOTOFF(%ebx)
-#else
-#define PIC_PROLOGUE
-#define PIC_EPILOGUE
-#define PIC_PLT(x)	x
-#define PIC_GOT(x)	x
-#define PIC_GOTOFF(x)	x
-#endif
 
-/* let kernels and others override entrypoint alignment */
-#if !defined(_ALIGN_TEXT) && !defined(_KERNEL)
-# ifdef _STANDALONE
-#  define _ALIGN_TEXT .align 1
-# elif defined __ELF__
-#  define _ALIGN_TEXT .align 16
-# else
-#  define _ALIGN_TEXT .align 4
-# endif
-#endif
+#define __bionic_asm_align 16
 
 #endif /* !_I386_ASM_H_ */
diff --git a/libc/arch-x86/syscalls/__accept4.S b/libc/arch-x86/syscalls/__accept4.S
index 2d9cc42..c28f211 100644
--- a/libc/arch-x86/syscalls/__accept4.S
+++ b/libc/arch-x86/syscalls/__accept4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__accept4)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__brk.S b/libc/arch-x86/syscalls/__brk.S
index 632dfcf..c5702cf 100644
--- a/libc/arch-x86/syscalls/__brk.S
+++ b/libc/arch-x86/syscalls/__brk.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__brk)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__connect.S b/libc/arch-x86/syscalls/__connect.S
index 5ee4fbf..4f845b7 100644
--- a/libc/arch-x86/syscalls/__connect.S
+++ b/libc/arch-x86/syscalls/__connect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__connect)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__epoll_pwait.S b/libc/arch-x86/syscalls/__epoll_pwait.S
index 641ca6d..c7acb2b 100644
--- a/libc/arch-x86/syscalls/__epoll_pwait.S
+++ b/libc/arch-x86/syscalls/__epoll_pwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__epoll_pwait)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__exit.S b/libc/arch-x86/syscalls/__exit.S
index 8578f56..bf76e04 100644
--- a/libc/arch-x86/syscalls/__exit.S
+++ b/libc/arch-x86/syscalls/__exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__exit)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__fcntl64.S b/libc/arch-x86/syscalls/__fcntl64.S
index ef58d15..7c41c88 100644
--- a/libc/arch-x86/syscalls/__fcntl64.S
+++ b/libc/arch-x86/syscalls/__fcntl64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__fcntl64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__fstatfs64.S b/libc/arch-x86/syscalls/__fstatfs64.S
index 0ca3360..b182ae3 100644
--- a/libc/arch-x86/syscalls/__fstatfs64.S
+++ b/libc/arch-x86/syscalls/__fstatfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__fstatfs64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__getcpu.S b/libc/arch-x86/syscalls/__getcpu.S
index b181877..4cdbafa 100644
--- a/libc/arch-x86/syscalls/__getcpu.S
+++ b/libc/arch-x86/syscalls/__getcpu.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcpu)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__getcwd.S b/libc/arch-x86/syscalls/__getcwd.S
index b71ba0d..f5b9b9c 100644
--- a/libc/arch-x86/syscalls/__getcwd.S
+++ b/libc/arch-x86/syscalls/__getcwd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcwd)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__getdents64.S b/libc/arch-x86/syscalls/__getdents64.S
index 3fc8719..0ff217d 100644
--- a/libc/arch-x86/syscalls/__getdents64.S
+++ b/libc/arch-x86/syscalls/__getdents64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getdents64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__getpid.S b/libc/arch-x86/syscalls/__getpid.S
index f138d2f..6a3602e 100644
--- a/libc/arch-x86/syscalls/__getpid.S
+++ b/libc/arch-x86/syscalls/__getpid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpid)
     movl    $__NR_getpid, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/__getpriority.S b/libc/arch-x86/syscalls/__getpriority.S
index 103431d..6a94f43 100644
--- a/libc/arch-x86/syscalls/__getpriority.S
+++ b/libc/arch-x86/syscalls/__getpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpriority)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__ioctl.S b/libc/arch-x86/syscalls/__ioctl.S
index 99d2d2c..edb990a 100644
--- a/libc/arch-x86/syscalls/__ioctl.S
+++ b/libc/arch-x86/syscalls/__ioctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ioctl)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__llseek.S b/libc/arch-x86/syscalls/__llseek.S
index 0cdb98a..db39106 100644
--- a/libc/arch-x86/syscalls/__llseek.S
+++ b/libc/arch-x86/syscalls/__llseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__llseek)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__mmap2.S b/libc/arch-x86/syscalls/__mmap2.S
index 47131ef..5c8f2a3 100644
--- a/libc/arch-x86/syscalls/__mmap2.S
+++ b/libc/arch-x86/syscalls/__mmap2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__mmap2)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__openat.S b/libc/arch-x86/syscalls/__openat.S
index aec10e5..87687e5 100644
--- a/libc/arch-x86/syscalls/__openat.S
+++ b/libc/arch-x86/syscalls/__openat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__openat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__ppoll.S b/libc/arch-x86/syscalls/__ppoll.S
index 92197b7..e48f841 100644
--- a/libc/arch-x86/syscalls/__ppoll.S
+++ b/libc/arch-x86/syscalls/__ppoll.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ppoll)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__pselect6.S b/libc/arch-x86/syscalls/__pselect6.S
index 38402f0..53edb8c 100644
--- a/libc/arch-x86/syscalls/__pselect6.S
+++ b/libc/arch-x86/syscalls/__pselect6.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__pselect6)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__ptrace.S b/libc/arch-x86/syscalls/__ptrace.S
index cea5847..9d1e460 100644
--- a/libc/arch-x86/syscalls/__ptrace.S
+++ b/libc/arch-x86/syscalls/__ptrace.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ptrace)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__reboot.S b/libc/arch-x86/syscalls/__reboot.S
index 4546994..3ef78bb 100644
--- a/libc/arch-x86/syscalls/__reboot.S
+++ b/libc/arch-x86/syscalls/__reboot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__reboot)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__rt_sigaction.S b/libc/arch-x86/syscalls/__rt_sigaction.S
index bfbe5ba..1ce7ef9 100644
--- a/libc/arch-x86/syscalls/__rt_sigaction.S
+++ b/libc/arch-x86/syscalls/__rt_sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigaction)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__rt_sigpending.S b/libc/arch-x86/syscalls/__rt_sigpending.S
index dac478a..a4cb3c1 100644
--- a/libc/arch-x86/syscalls/__rt_sigpending.S
+++ b/libc/arch-x86/syscalls/__rt_sigpending.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigpending)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__rt_sigprocmask.S b/libc/arch-x86/syscalls/__rt_sigprocmask.S
index f112360..9d8e90d 100644
--- a/libc/arch-x86/syscalls/__rt_sigprocmask.S
+++ b/libc/arch-x86/syscalls/__rt_sigprocmask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigprocmask)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__rt_sigsuspend.S b/libc/arch-x86/syscalls/__rt_sigsuspend.S
index ef505c0..e0d0c3d 100644
--- a/libc/arch-x86/syscalls/__rt_sigsuspend.S
+++ b/libc/arch-x86/syscalls/__rt_sigsuspend.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigsuspend)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__rt_sigtimedwait.S b/libc/arch-x86/syscalls/__rt_sigtimedwait.S
index d19c7db..091c1a7 100644
--- a/libc/arch-x86/syscalls/__rt_sigtimedwait.S
+++ b/libc/arch-x86/syscalls/__rt_sigtimedwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigtimedwait)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__sched_getaffinity.S b/libc/arch-x86/syscalls/__sched_getaffinity.S
index e7cb8f1..2c278db 100644
--- a/libc/arch-x86/syscalls/__sched_getaffinity.S
+++ b/libc/arch-x86/syscalls/__sched_getaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sched_getaffinity)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__set_thread_area.S b/libc/arch-x86/syscalls/__set_thread_area.S
index dda23a0..29e1238 100644
--- a/libc/arch-x86/syscalls/__set_thread_area.S
+++ b/libc/arch-x86/syscalls/__set_thread_area.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_thread_area)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__set_tid_address.S b/libc/arch-x86/syscalls/__set_tid_address.S
index 1566d9a..3517442 100644
--- a/libc/arch-x86/syscalls/__set_tid_address.S
+++ b/libc/arch-x86/syscalls/__set_tid_address.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tid_address)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__sigaction.S b/libc/arch-x86/syscalls/__sigaction.S
index f1a51d2..0a3e77e 100644
--- a/libc/arch-x86/syscalls/__sigaction.S
+++ b/libc/arch-x86/syscalls/__sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sigaction)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__signalfd4.S b/libc/arch-x86/syscalls/__signalfd4.S
index 335e206..acfced5 100644
--- a/libc/arch-x86/syscalls/__signalfd4.S
+++ b/libc/arch-x86/syscalls/__signalfd4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__signalfd4)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__socket.S b/libc/arch-x86/syscalls/__socket.S
index 368680f..59988f3 100644
--- a/libc/arch-x86/syscalls/__socket.S
+++ b/libc/arch-x86/syscalls/__socket.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__socket)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__statfs64.S b/libc/arch-x86/syscalls/__statfs64.S
index 6bb9d99..63d866e 100644
--- a/libc/arch-x86/syscalls/__statfs64.S
+++ b/libc/arch-x86/syscalls/__statfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__statfs64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__timer_create.S b/libc/arch-x86/syscalls/__timer_create.S
index 3d28ae9..1265aa6 100644
--- a/libc/arch-x86/syscalls/__timer_create.S
+++ b/libc/arch-x86/syscalls/__timer_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_create)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__timer_delete.S b/libc/arch-x86/syscalls/__timer_delete.S
index 7d64d6d..bc1fbc5 100644
--- a/libc/arch-x86/syscalls/__timer_delete.S
+++ b/libc/arch-x86/syscalls/__timer_delete.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_delete)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__timer_getoverrun.S b/libc/arch-x86/syscalls/__timer_getoverrun.S
index cb37765..2a8de1e 100644
--- a/libc/arch-x86/syscalls/__timer_getoverrun.S
+++ b/libc/arch-x86/syscalls/__timer_getoverrun.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_getoverrun)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__timer_gettime.S b/libc/arch-x86/syscalls/__timer_gettime.S
index 5c43f4a..9edd15a 100644
--- a/libc/arch-x86/syscalls/__timer_gettime.S
+++ b/libc/arch-x86/syscalls/__timer_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_gettime)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__timer_settime.S b/libc/arch-x86/syscalls/__timer_settime.S
index da7c587..4bb0790 100644
--- a/libc/arch-x86/syscalls/__timer_settime.S
+++ b/libc/arch-x86/syscalls/__timer_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_settime)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/__waitid.S b/libc/arch-x86/syscalls/__waitid.S
index 7e3ecdd..331baf5 100644
--- a/libc/arch-x86/syscalls/__waitid.S
+++ b/libc/arch-x86/syscalls/__waitid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__waitid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/_exit.S b/libc/arch-x86/syscalls/_exit.S
index 36e884a..0da6e79 100644
--- a/libc/arch-x86/syscalls/_exit.S
+++ b/libc/arch-x86/syscalls/_exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(_exit)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/acct.S b/libc/arch-x86/syscalls/acct.S
index a036114..34a23a4 100644
--- a/libc/arch-x86/syscalls/acct.S
+++ b/libc/arch-x86/syscalls/acct.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(acct)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/bind.S b/libc/arch-x86/syscalls/bind.S
index ab5a29e..1d45319 100644
--- a/libc/arch-x86/syscalls/bind.S
+++ b/libc/arch-x86/syscalls/bind.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(bind)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/capget.S b/libc/arch-x86/syscalls/capget.S
index 5441e49..82b5b73 100644
--- a/libc/arch-x86/syscalls/capget.S
+++ b/libc/arch-x86/syscalls/capget.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capget)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/capset.S b/libc/arch-x86/syscalls/capset.S
index d04e411..79e8747 100644
--- a/libc/arch-x86/syscalls/capset.S
+++ b/libc/arch-x86/syscalls/capset.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capset)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/chdir.S b/libc/arch-x86/syscalls/chdir.S
index d32a0bd..98bdf37 100644
--- a/libc/arch-x86/syscalls/chdir.S
+++ b/libc/arch-x86/syscalls/chdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chdir)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/chroot.S b/libc/arch-x86/syscalls/chroot.S
index 63d7e00..978eec7 100644
--- a/libc/arch-x86/syscalls/chroot.S
+++ b/libc/arch-x86/syscalls/chroot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chroot)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/clock_getres.S b/libc/arch-x86/syscalls/clock_getres.S
index 321299c..c93a279 100644
--- a/libc/arch-x86/syscalls/clock_getres.S
+++ b/libc/arch-x86/syscalls/clock_getres.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_getres)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/clock_gettime.S b/libc/arch-x86/syscalls/clock_gettime.S
index 54f769a..9c5c240 100644
--- a/libc/arch-x86/syscalls/clock_gettime.S
+++ b/libc/arch-x86/syscalls/clock_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_gettime)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/clock_nanosleep.S b/libc/arch-x86/syscalls/clock_nanosleep.S
index ca961c0..edadec2 100644
--- a/libc/arch-x86/syscalls/clock_nanosleep.S
+++ b/libc/arch-x86/syscalls/clock_nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_nanosleep)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/clock_settime.S b/libc/arch-x86/syscalls/clock_settime.S
index ab8c43e..41012d0 100644
--- a/libc/arch-x86/syscalls/clock_settime.S
+++ b/libc/arch-x86/syscalls/clock_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_settime)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/close.S b/libc/arch-x86/syscalls/close.S
index 0b3e73a..b73c4b4 100644
--- a/libc/arch-x86/syscalls/close.S
+++ b/libc/arch-x86/syscalls/close.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(close)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/delete_module.S b/libc/arch-x86/syscalls/delete_module.S
index 757c8c1..73a5128 100644
--- a/libc/arch-x86/syscalls/delete_module.S
+++ b/libc/arch-x86/syscalls/delete_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(delete_module)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/dup.S b/libc/arch-x86/syscalls/dup.S
index 64e1538..f8e8772 100644
--- a/libc/arch-x86/syscalls/dup.S
+++ b/libc/arch-x86/syscalls/dup.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/dup3.S b/libc/arch-x86/syscalls/dup3.S
index a0ecd19..1203e64 100644
--- a/libc/arch-x86/syscalls/dup3.S
+++ b/libc/arch-x86/syscalls/dup3.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup3)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/epoll_create1.S b/libc/arch-x86/syscalls/epoll_create1.S
index 5b6a1ba..6384b92 100644
--- a/libc/arch-x86/syscalls/epoll_create1.S
+++ b/libc/arch-x86/syscalls/epoll_create1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_create1)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/epoll_ctl.S b/libc/arch-x86/syscalls/epoll_ctl.S
index 3fd8acd..cdc880e 100644
--- a/libc/arch-x86/syscalls/epoll_ctl.S
+++ b/libc/arch-x86/syscalls/epoll_ctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_ctl)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/eventfd.S b/libc/arch-x86/syscalls/eventfd.S
index 55c5e6a..fe85967 100644
--- a/libc/arch-x86/syscalls/eventfd.S
+++ b/libc/arch-x86/syscalls/eventfd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(eventfd)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/execve.S b/libc/arch-x86/syscalls/execve.S
index 7ad54f7..a897c42 100644
--- a/libc/arch-x86/syscalls/execve.S
+++ b/libc/arch-x86/syscalls/execve.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(execve)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/faccessat.S b/libc/arch-x86/syscalls/faccessat.S
index 115d645..4ac3e2a 100644
--- a/libc/arch-x86/syscalls/faccessat.S
+++ b/libc/arch-x86/syscalls/faccessat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(faccessat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fallocate64.S b/libc/arch-x86/syscalls/fallocate64.S
index f8bde62..e1dfa08 100644
--- a/libc/arch-x86/syscalls/fallocate64.S
+++ b/libc/arch-x86/syscalls/fallocate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fallocate64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fchdir.S b/libc/arch-x86/syscalls/fchdir.S
index 56e496c..af43acb 100644
--- a/libc/arch-x86/syscalls/fchdir.S
+++ b/libc/arch-x86/syscalls/fchdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchdir)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fchmod.S b/libc/arch-x86/syscalls/fchmod.S
index 4badcea..5c58359 100644
--- a/libc/arch-x86/syscalls/fchmod.S
+++ b/libc/arch-x86/syscalls/fchmod.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmod)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fchmodat.S b/libc/arch-x86/syscalls/fchmodat.S
index 552e85c..aed8d29 100644
--- a/libc/arch-x86/syscalls/fchmodat.S
+++ b/libc/arch-x86/syscalls/fchmodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmodat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fchown.S b/libc/arch-x86/syscalls/fchown.S
index 7e82637..da80251 100644
--- a/libc/arch-x86/syscalls/fchown.S
+++ b/libc/arch-x86/syscalls/fchown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchown)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fchownat.S b/libc/arch-x86/syscalls/fchownat.S
index de039d0..8514243 100644
--- a/libc/arch-x86/syscalls/fchownat.S
+++ b/libc/arch-x86/syscalls/fchownat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchownat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fdatasync.S b/libc/arch-x86/syscalls/fdatasync.S
index fdb5578..fc2c163 100644
--- a/libc/arch-x86/syscalls/fdatasync.S
+++ b/libc/arch-x86/syscalls/fdatasync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fdatasync)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fgetxattr.S b/libc/arch-x86/syscalls/fgetxattr.S
index 3ed63d3..767a675 100644
--- a/libc/arch-x86/syscalls/fgetxattr.S
+++ b/libc/arch-x86/syscalls/fgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fgetxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/flistxattr.S b/libc/arch-x86/syscalls/flistxattr.S
index 2840114..dbb4977 100644
--- a/libc/arch-x86/syscalls/flistxattr.S
+++ b/libc/arch-x86/syscalls/flistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flistxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/flock.S b/libc/arch-x86/syscalls/flock.S
index dc9ef02..b4b748e 100644
--- a/libc/arch-x86/syscalls/flock.S
+++ b/libc/arch-x86/syscalls/flock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flock)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fremovexattr.S b/libc/arch-x86/syscalls/fremovexattr.S
index 1e77f82..c34cbc4 100644
--- a/libc/arch-x86/syscalls/fremovexattr.S
+++ b/libc/arch-x86/syscalls/fremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fremovexattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fsetxattr.S b/libc/arch-x86/syscalls/fsetxattr.S
index 703a8d7..5593dca 100644
--- a/libc/arch-x86/syscalls/fsetxattr.S
+++ b/libc/arch-x86/syscalls/fsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsetxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fstat64.S b/libc/arch-x86/syscalls/fstat64.S
index 970eeb1..2e29ae5 100644
--- a/libc/arch-x86/syscalls/fstat64.S
+++ b/libc/arch-x86/syscalls/fstat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstat64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fstatat64.S b/libc/arch-x86/syscalls/fstatat64.S
index 476578d..72922cb 100644
--- a/libc/arch-x86/syscalls/fstatat64.S
+++ b/libc/arch-x86/syscalls/fstatat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatat64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/fsync.S b/libc/arch-x86/syscalls/fsync.S
index 9fc84b7..af10e9a 100644
--- a/libc/arch-x86/syscalls/fsync.S
+++ b/libc/arch-x86/syscalls/fsync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsync)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/ftruncate.S b/libc/arch-x86/syscalls/ftruncate.S
index 6765d98..7343985 100644
--- a/libc/arch-x86/syscalls/ftruncate.S
+++ b/libc/arch-x86/syscalls/ftruncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/ftruncate64.S b/libc/arch-x86/syscalls/ftruncate64.S
index 21e26ce..47b925b 100644
--- a/libc/arch-x86/syscalls/ftruncate64.S
+++ b/libc/arch-x86/syscalls/ftruncate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getegid.S b/libc/arch-x86/syscalls/getegid.S
index 445cd97..bc21b5a 100644
--- a/libc/arch-x86/syscalls/getegid.S
+++ b/libc/arch-x86/syscalls/getegid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getegid)
     movl    $__NR_getegid32, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/geteuid.S b/libc/arch-x86/syscalls/geteuid.S
index 8290a93..469f9c9 100644
--- a/libc/arch-x86/syscalls/geteuid.S
+++ b/libc/arch-x86/syscalls/geteuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(geteuid)
     movl    $__NR_geteuid32, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/getgid.S b/libc/arch-x86/syscalls/getgid.S
index d90767f..6b15674 100644
--- a/libc/arch-x86/syscalls/getgid.S
+++ b/libc/arch-x86/syscalls/getgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgid)
     movl    $__NR_getgid32, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/getgroups.S b/libc/arch-x86/syscalls/getgroups.S
index d36c09c..a7aa1b2 100644
--- a/libc/arch-x86/syscalls/getgroups.S
+++ b/libc/arch-x86/syscalls/getgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgroups)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getitimer.S b/libc/arch-x86/syscalls/getitimer.S
index ebf1260..1b424a3 100644
--- a/libc/arch-x86/syscalls/getitimer.S
+++ b/libc/arch-x86/syscalls/getitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getitimer)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getpeername.S b/libc/arch-x86/syscalls/getpeername.S
index abecd4e..94b43fb 100644
--- a/libc/arch-x86/syscalls/getpeername.S
+++ b/libc/arch-x86/syscalls/getpeername.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpeername)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getpgid.S b/libc/arch-x86/syscalls/getpgid.S
index e74ed3b..7d7149e 100644
--- a/libc/arch-x86/syscalls/getpgid.S
+++ b/libc/arch-x86/syscalls/getpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpgid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getppid.S b/libc/arch-x86/syscalls/getppid.S
index 025fa42..3103ed2 100644
--- a/libc/arch-x86/syscalls/getppid.S
+++ b/libc/arch-x86/syscalls/getppid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getppid)
     movl    $__NR_getppid, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/getresgid.S b/libc/arch-x86/syscalls/getresgid.S
index fe08cdf..2f03a03 100644
--- a/libc/arch-x86/syscalls/getresgid.S
+++ b/libc/arch-x86/syscalls/getresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresgid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getresuid.S b/libc/arch-x86/syscalls/getresuid.S
index 8e292fc..d6fe915 100644
--- a/libc/arch-x86/syscalls/getresuid.S
+++ b/libc/arch-x86/syscalls/getresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresuid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getrlimit.S b/libc/arch-x86/syscalls/getrlimit.S
index fdb5a03..4587a2e 100644
--- a/libc/arch-x86/syscalls/getrlimit.S
+++ b/libc/arch-x86/syscalls/getrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrlimit)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getrusage.S b/libc/arch-x86/syscalls/getrusage.S
index ae5f796..4b2e38b 100644
--- a/libc/arch-x86/syscalls/getrusage.S
+++ b/libc/arch-x86/syscalls/getrusage.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrusage)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getsid.S b/libc/arch-x86/syscalls/getsid.S
index e1dc87f..eac9f2c 100644
--- a/libc/arch-x86/syscalls/getsid.S
+++ b/libc/arch-x86/syscalls/getsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getsockname.S b/libc/arch-x86/syscalls/getsockname.S
index 254b755..738fa6d 100644
--- a/libc/arch-x86/syscalls/getsockname.S
+++ b/libc/arch-x86/syscalls/getsockname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockname)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getsockopt.S b/libc/arch-x86/syscalls/getsockopt.S
index 2ef630c..f8338f5 100644
--- a/libc/arch-x86/syscalls/getsockopt.S
+++ b/libc/arch-x86/syscalls/getsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockopt)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/gettimeofday.S b/libc/arch-x86/syscalls/gettimeofday.S
index 709a17b..96c1e11 100644
--- a/libc/arch-x86/syscalls/gettimeofday.S
+++ b/libc/arch-x86/syscalls/gettimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(gettimeofday)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/getuid.S b/libc/arch-x86/syscalls/getuid.S
index c375d30..cde5da8 100644
--- a/libc/arch-x86/syscalls/getuid.S
+++ b/libc/arch-x86/syscalls/getuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getuid)
     movl    $__NR_getuid32, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/getxattr.S b/libc/arch-x86/syscalls/getxattr.S
index db9c9dd..7679cbf 100644
--- a/libc/arch-x86/syscalls/getxattr.S
+++ b/libc/arch-x86/syscalls/getxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/init_module.S b/libc/arch-x86/syscalls/init_module.S
index 543b31e..02e55f0 100644
--- a/libc/arch-x86/syscalls/init_module.S
+++ b/libc/arch-x86/syscalls/init_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(init_module)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/inotify_add_watch.S b/libc/arch-x86/syscalls/inotify_add_watch.S
index f58c6d1..74a59f3 100644
--- a/libc/arch-x86/syscalls/inotify_add_watch.S
+++ b/libc/arch-x86/syscalls/inotify_add_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_add_watch)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/inotify_init1.S b/libc/arch-x86/syscalls/inotify_init1.S
index 2c7b100..de714c9 100644
--- a/libc/arch-x86/syscalls/inotify_init1.S
+++ b/libc/arch-x86/syscalls/inotify_init1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_init1)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/inotify_rm_watch.S b/libc/arch-x86/syscalls/inotify_rm_watch.S
index c453478..3edc152 100644
--- a/libc/arch-x86/syscalls/inotify_rm_watch.S
+++ b/libc/arch-x86/syscalls/inotify_rm_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_rm_watch)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/kill.S b/libc/arch-x86/syscalls/kill.S
index 0c1e24a..0cf38a9 100644
--- a/libc/arch-x86/syscalls/kill.S
+++ b/libc/arch-x86/syscalls/kill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(kill)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/klogctl.S b/libc/arch-x86/syscalls/klogctl.S
index 869324a..52b04e1 100644
--- a/libc/arch-x86/syscalls/klogctl.S
+++ b/libc/arch-x86/syscalls/klogctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(klogctl)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/lgetxattr.S b/libc/arch-x86/syscalls/lgetxattr.S
index 3ed4f11..8c2eb47 100644
--- a/libc/arch-x86/syscalls/lgetxattr.S
+++ b/libc/arch-x86/syscalls/lgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lgetxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/linkat.S b/libc/arch-x86/syscalls/linkat.S
index e0c7e5f..56b8368 100644
--- a/libc/arch-x86/syscalls/linkat.S
+++ b/libc/arch-x86/syscalls/linkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(linkat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/listen.S b/libc/arch-x86/syscalls/listen.S
index c65f970..2c8cc76 100644
--- a/libc/arch-x86/syscalls/listen.S
+++ b/libc/arch-x86/syscalls/listen.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listen)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/listxattr.S b/libc/arch-x86/syscalls/listxattr.S
index 98a5114..f43ab3c 100644
--- a/libc/arch-x86/syscalls/listxattr.S
+++ b/libc/arch-x86/syscalls/listxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/llistxattr.S b/libc/arch-x86/syscalls/llistxattr.S
index a5ab636..d326526 100644
--- a/libc/arch-x86/syscalls/llistxattr.S
+++ b/libc/arch-x86/syscalls/llistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(llistxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/lremovexattr.S b/libc/arch-x86/syscalls/lremovexattr.S
index 508abba..b4f4817 100644
--- a/libc/arch-x86/syscalls/lremovexattr.S
+++ b/libc/arch-x86/syscalls/lremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lremovexattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/lseek.S b/libc/arch-x86/syscalls/lseek.S
index 5f77831..1115be8 100644
--- a/libc/arch-x86/syscalls/lseek.S
+++ b/libc/arch-x86/syscalls/lseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lseek)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/lsetxattr.S b/libc/arch-x86/syscalls/lsetxattr.S
index d878684..fc62cdd 100644
--- a/libc/arch-x86/syscalls/lsetxattr.S
+++ b/libc/arch-x86/syscalls/lsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lsetxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/madvise.S b/libc/arch-x86/syscalls/madvise.S
index 3e8c7fd..1de4456 100644
--- a/libc/arch-x86/syscalls/madvise.S
+++ b/libc/arch-x86/syscalls/madvise.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(madvise)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mincore.S b/libc/arch-x86/syscalls/mincore.S
index 7096f6c..118063c 100644
--- a/libc/arch-x86/syscalls/mincore.S
+++ b/libc/arch-x86/syscalls/mincore.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mincore)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mkdirat.S b/libc/arch-x86/syscalls/mkdirat.S
index 862a18c..6969d2a 100644
--- a/libc/arch-x86/syscalls/mkdirat.S
+++ b/libc/arch-x86/syscalls/mkdirat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mkdirat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mknodat.S b/libc/arch-x86/syscalls/mknodat.S
index e03ba42..6c743d2 100644
--- a/libc/arch-x86/syscalls/mknodat.S
+++ b/libc/arch-x86/syscalls/mknodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mknodat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mlock.S b/libc/arch-x86/syscalls/mlock.S
index f582f77..5ec799e 100644
--- a/libc/arch-x86/syscalls/mlock.S
+++ b/libc/arch-x86/syscalls/mlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlock)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mlockall.S b/libc/arch-x86/syscalls/mlockall.S
index becca81..72a8da5 100644
--- a/libc/arch-x86/syscalls/mlockall.S
+++ b/libc/arch-x86/syscalls/mlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlockall)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mount.S b/libc/arch-x86/syscalls/mount.S
index 7be2811..1e06b8e 100644
--- a/libc/arch-x86/syscalls/mount.S
+++ b/libc/arch-x86/syscalls/mount.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mount)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mprotect.S b/libc/arch-x86/syscalls/mprotect.S
index 0516c45..11037c3 100644
--- a/libc/arch-x86/syscalls/mprotect.S
+++ b/libc/arch-x86/syscalls/mprotect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mprotect)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/mremap.S b/libc/arch-x86/syscalls/mremap.S
index 42e75ce..b7f96ff 100644
--- a/libc/arch-x86/syscalls/mremap.S
+++ b/libc/arch-x86/syscalls/mremap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mremap)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/msync.S b/libc/arch-x86/syscalls/msync.S
index 66722f2..e2549f7 100644
--- a/libc/arch-x86/syscalls/msync.S
+++ b/libc/arch-x86/syscalls/msync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(msync)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/munlock.S b/libc/arch-x86/syscalls/munlock.S
index 2fc3aa7..6b79e99 100644
--- a/libc/arch-x86/syscalls/munlock.S
+++ b/libc/arch-x86/syscalls/munlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlock)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/munlockall.S b/libc/arch-x86/syscalls/munlockall.S
index 1bc99ea..96e238b 100644
--- a/libc/arch-x86/syscalls/munlockall.S
+++ b/libc/arch-x86/syscalls/munlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlockall)
     movl    $__NR_munlockall, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/munmap.S b/libc/arch-x86/syscalls/munmap.S
index 878aae7..a77a777 100644
--- a/libc/arch-x86/syscalls/munmap.S
+++ b/libc/arch-x86/syscalls/munmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munmap)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/nanosleep.S b/libc/arch-x86/syscalls/nanosleep.S
index fe8af90..444aa7e 100644
--- a/libc/arch-x86/syscalls/nanosleep.S
+++ b/libc/arch-x86/syscalls/nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(nanosleep)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/personality.S b/libc/arch-x86/syscalls/personality.S
index 8c8e0ff..5344e1c 100644
--- a/libc/arch-x86/syscalls/personality.S
+++ b/libc/arch-x86/syscalls/personality.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(personality)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/pipe2.S b/libc/arch-x86/syscalls/pipe2.S
index 99c4e8b..62665a0 100644
--- a/libc/arch-x86/syscalls/pipe2.S
+++ b/libc/arch-x86/syscalls/pipe2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pipe2)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/prctl.S b/libc/arch-x86/syscalls/prctl.S
index 63ec899..28e84d8 100644
--- a/libc/arch-x86/syscalls/prctl.S
+++ b/libc/arch-x86/syscalls/prctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prctl)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/pread64.S b/libc/arch-x86/syscalls/pread64.S
index 6b3c8ad..e7502b9 100644
--- a/libc/arch-x86/syscalls/pread64.S
+++ b/libc/arch-x86/syscalls/pread64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pread64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/prlimit64.S b/libc/arch-x86/syscalls/prlimit64.S
index 6aa875f..2ca8b23 100644
--- a/libc/arch-x86/syscalls/prlimit64.S
+++ b/libc/arch-x86/syscalls/prlimit64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prlimit64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/pwrite64.S b/libc/arch-x86/syscalls/pwrite64.S
index 7d53095..b798a8e 100644
--- a/libc/arch-x86/syscalls/pwrite64.S
+++ b/libc/arch-x86/syscalls/pwrite64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pwrite64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/read.S b/libc/arch-x86/syscalls/read.S
index 9814c8f..483c5ef 100644
--- a/libc/arch-x86/syscalls/read.S
+++ b/libc/arch-x86/syscalls/read.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(read)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/readahead.S b/libc/arch-x86/syscalls/readahead.S
index 49a17d0..b1e0870 100644
--- a/libc/arch-x86/syscalls/readahead.S
+++ b/libc/arch-x86/syscalls/readahead.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readahead)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/readlinkat.S b/libc/arch-x86/syscalls/readlinkat.S
index 1a161c0..a06ae73 100644
--- a/libc/arch-x86/syscalls/readlinkat.S
+++ b/libc/arch-x86/syscalls/readlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readlinkat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/readv.S b/libc/arch-x86/syscalls/readv.S
index 8b5ff41..a0b46b8 100644
--- a/libc/arch-x86/syscalls/readv.S
+++ b/libc/arch-x86/syscalls/readv.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readv)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/recvfrom.S b/libc/arch-x86/syscalls/recvfrom.S
index 53d08f6..86f12c0 100644
--- a/libc/arch-x86/syscalls/recvfrom.S
+++ b/libc/arch-x86/syscalls/recvfrom.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvfrom)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/recvmmsg.S b/libc/arch-x86/syscalls/recvmmsg.S
index 3ef8740..f77f794 100644
--- a/libc/arch-x86/syscalls/recvmmsg.S
+++ b/libc/arch-x86/syscalls/recvmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmmsg)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/recvmsg.S b/libc/arch-x86/syscalls/recvmsg.S
index 150672d..5d25d7a 100644
--- a/libc/arch-x86/syscalls/recvmsg.S
+++ b/libc/arch-x86/syscalls/recvmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmsg)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/removexattr.S b/libc/arch-x86/syscalls/removexattr.S
index e7c55eb..cbbdf4e 100644
--- a/libc/arch-x86/syscalls/removexattr.S
+++ b/libc/arch-x86/syscalls/removexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(removexattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/renameat.S b/libc/arch-x86/syscalls/renameat.S
index 5dfe65f..e424daf 100644
--- a/libc/arch-x86/syscalls/renameat.S
+++ b/libc/arch-x86/syscalls/renameat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(renameat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_get_priority_max.S b/libc/arch-x86/syscalls/sched_get_priority_max.S
index d8debe2..eee6f92 100644
--- a/libc/arch-x86/syscalls/sched_get_priority_max.S
+++ b/libc/arch-x86/syscalls/sched_get_priority_max.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_max)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_get_priority_min.S b/libc/arch-x86/syscalls/sched_get_priority_min.S
index e9689fa..0edcab1 100644
--- a/libc/arch-x86/syscalls/sched_get_priority_min.S
+++ b/libc/arch-x86/syscalls/sched_get_priority_min.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_min)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_getparam.S b/libc/arch-x86/syscalls/sched_getparam.S
index 6b5e7c8..9a4ebbd 100644
--- a/libc/arch-x86/syscalls/sched_getparam.S
+++ b/libc/arch-x86/syscalls/sched_getparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getparam)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_getscheduler.S b/libc/arch-x86/syscalls/sched_getscheduler.S
index a2c5746..19a925e 100644
--- a/libc/arch-x86/syscalls/sched_getscheduler.S
+++ b/libc/arch-x86/syscalls/sched_getscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getscheduler)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_rr_get_interval.S b/libc/arch-x86/syscalls/sched_rr_get_interval.S
index f8012f3..c2592a9 100644
--- a/libc/arch-x86/syscalls/sched_rr_get_interval.S
+++ b/libc/arch-x86/syscalls/sched_rr_get_interval.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_rr_get_interval)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_setaffinity.S b/libc/arch-x86/syscalls/sched_setaffinity.S
index 76013f9..4a0ac86 100644
--- a/libc/arch-x86/syscalls/sched_setaffinity.S
+++ b/libc/arch-x86/syscalls/sched_setaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setaffinity)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_setparam.S b/libc/arch-x86/syscalls/sched_setparam.S
index aca4bd9..a99c0de 100644
--- a/libc/arch-x86/syscalls/sched_setparam.S
+++ b/libc/arch-x86/syscalls/sched_setparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setparam)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_setscheduler.S b/libc/arch-x86/syscalls/sched_setscheduler.S
index fad72c6..dbfd01e 100644
--- a/libc/arch-x86/syscalls/sched_setscheduler.S
+++ b/libc/arch-x86/syscalls/sched_setscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setscheduler)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sched_yield.S b/libc/arch-x86/syscalls/sched_yield.S
index 8b4a9be..87ebaf9 100644
--- a/libc/arch-x86/syscalls/sched_yield.S
+++ b/libc/arch-x86/syscalls/sched_yield.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_yield)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sendfile.S b/libc/arch-x86/syscalls/sendfile.S
index 7bd86d0..58433fb 100644
--- a/libc/arch-x86/syscalls/sendfile.S
+++ b/libc/arch-x86/syscalls/sendfile.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sendfile64.S b/libc/arch-x86/syscalls/sendfile64.S
index bd76043..97c7146 100644
--- a/libc/arch-x86/syscalls/sendfile64.S
+++ b/libc/arch-x86/syscalls/sendfile64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sendmmsg.S b/libc/arch-x86/syscalls/sendmmsg.S
index 4bc3c40..3c359ee 100644
--- a/libc/arch-x86/syscalls/sendmmsg.S
+++ b/libc/arch-x86/syscalls/sendmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmmsg)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sendmsg.S b/libc/arch-x86/syscalls/sendmsg.S
index eb8fc63..51288cc 100644
--- a/libc/arch-x86/syscalls/sendmsg.S
+++ b/libc/arch-x86/syscalls/sendmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmsg)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sendto.S b/libc/arch-x86/syscalls/sendto.S
index 8cb72c8..4b77f24 100644
--- a/libc/arch-x86/syscalls/sendto.S
+++ b/libc/arch-x86/syscalls/sendto.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendto)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setfsgid.S b/libc/arch-x86/syscalls/setfsgid.S
new file mode 100644
index 0000000..a8160c3
--- /dev/null
+++ b/libc/arch-x86/syscalls/setfsgid.S
@@ -0,0 +1,23 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsgid)
+    pushl   %ebx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    mov     8(%esp), %ebx
+    movl    $__NR_setfsgid, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+1:
+    popl    %ebx
+    ret
+END(setfsgid)
diff --git a/libc/arch-x86/syscalls/setfsuid.S b/libc/arch-x86/syscalls/setfsuid.S
new file mode 100644
index 0000000..abcf0b3
--- /dev/null
+++ b/libc/arch-x86/syscalls/setfsuid.S
@@ -0,0 +1,23 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsuid)
+    pushl   %ebx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    mov     8(%esp), %ebx
+    movl    $__NR_setfsuid, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+1:
+    popl    %ebx
+    ret
+END(setfsuid)
diff --git a/libc/arch-x86/syscalls/setgid.S b/libc/arch-x86/syscalls/setgid.S
index baa1b1a..47c011e 100644
--- a/libc/arch-x86/syscalls/setgid.S
+++ b/libc/arch-x86/syscalls/setgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setgroups.S b/libc/arch-x86/syscalls/setgroups.S
index 364aaad..7a58910 100644
--- a/libc/arch-x86/syscalls/setgroups.S
+++ b/libc/arch-x86/syscalls/setgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgroups)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setitimer.S b/libc/arch-x86/syscalls/setitimer.S
index 409c4c6..e87a26e 100644
--- a/libc/arch-x86/syscalls/setitimer.S
+++ b/libc/arch-x86/syscalls/setitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setitimer)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setns.S b/libc/arch-x86/syscalls/setns.S
index ddbe758..75f23fa 100644
--- a/libc/arch-x86/syscalls/setns.S
+++ b/libc/arch-x86/syscalls/setns.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setns)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setpgid.S b/libc/arch-x86/syscalls/setpgid.S
index ac1b12d..c20b789 100644
--- a/libc/arch-x86/syscalls/setpgid.S
+++ b/libc/arch-x86/syscalls/setpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpgid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setpriority.S b/libc/arch-x86/syscalls/setpriority.S
index 93c1e07..4606c23 100644
--- a/libc/arch-x86/syscalls/setpriority.S
+++ b/libc/arch-x86/syscalls/setpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpriority)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setregid.S b/libc/arch-x86/syscalls/setregid.S
index 0ecfa9a..ff6cf36 100644
--- a/libc/arch-x86/syscalls/setregid.S
+++ b/libc/arch-x86/syscalls/setregid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setregid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setresgid.S b/libc/arch-x86/syscalls/setresgid.S
index a6914c4..a4846ae 100644
--- a/libc/arch-x86/syscalls/setresgid.S
+++ b/libc/arch-x86/syscalls/setresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresgid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setresuid.S b/libc/arch-x86/syscalls/setresuid.S
index c33c1ca..6ed0fad 100644
--- a/libc/arch-x86/syscalls/setresuid.S
+++ b/libc/arch-x86/syscalls/setresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresuid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setreuid.S b/libc/arch-x86/syscalls/setreuid.S
index 4244988..57d7540 100644
--- a/libc/arch-x86/syscalls/setreuid.S
+++ b/libc/arch-x86/syscalls/setreuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setreuid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setrlimit.S b/libc/arch-x86/syscalls/setrlimit.S
index 3e86504..9ca6134 100644
--- a/libc/arch-x86/syscalls/setrlimit.S
+++ b/libc/arch-x86/syscalls/setrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setrlimit)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setsid.S b/libc/arch-x86/syscalls/setsid.S
index 398c110..5c933b3 100644
--- a/libc/arch-x86/syscalls/setsid.S
+++ b/libc/arch-x86/syscalls/setsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsid)
     movl    $__NR_setsid, %eax
     int     $0x80
diff --git a/libc/arch-x86/syscalls/setsockopt.S b/libc/arch-x86/syscalls/setsockopt.S
index 6ef168f..f002344 100644
--- a/libc/arch-x86/syscalls/setsockopt.S
+++ b/libc/arch-x86/syscalls/setsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsockopt)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/settimeofday.S b/libc/arch-x86/syscalls/settimeofday.S
index 37e11c5..b35791d 100644
--- a/libc/arch-x86/syscalls/settimeofday.S
+++ b/libc/arch-x86/syscalls/settimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(settimeofday)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setuid.S b/libc/arch-x86/syscalls/setuid.S
index fcea66d..f5b8315 100644
--- a/libc/arch-x86/syscalls/setuid.S
+++ b/libc/arch-x86/syscalls/setuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setuid)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/setxattr.S b/libc/arch-x86/syscalls/setxattr.S
index d6473cd..24eb2c4 100644
--- a/libc/arch-x86/syscalls/setxattr.S
+++ b/libc/arch-x86/syscalls/setxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setxattr)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/shutdown.S b/libc/arch-x86/syscalls/shutdown.S
index 32fa17a..e5497e6 100644
--- a/libc/arch-x86/syscalls/shutdown.S
+++ b/libc/arch-x86/syscalls/shutdown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(shutdown)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sigaltstack.S b/libc/arch-x86/syscalls/sigaltstack.S
index 6882a78..150e398 100644
--- a/libc/arch-x86/syscalls/sigaltstack.S
+++ b/libc/arch-x86/syscalls/sigaltstack.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sigaltstack)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/socketpair.S b/libc/arch-x86/syscalls/socketpair.S
index 945faa0..f2188e3 100644
--- a/libc/arch-x86/syscalls/socketpair.S
+++ b/libc/arch-x86/syscalls/socketpair.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(socketpair)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/splice.S b/libc/arch-x86/syscalls/splice.S
index 46e2312..38d9ddf 100644
--- a/libc/arch-x86/syscalls/splice.S
+++ b/libc/arch-x86/syscalls/splice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(splice)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/swapoff.S b/libc/arch-x86/syscalls/swapoff.S
index 0e21033..a0cbc0e 100644
--- a/libc/arch-x86/syscalls/swapoff.S
+++ b/libc/arch-x86/syscalls/swapoff.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapoff)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/swapon.S b/libc/arch-x86/syscalls/swapon.S
index a4d5e03..5a2bc94 100644
--- a/libc/arch-x86/syscalls/swapon.S
+++ b/libc/arch-x86/syscalls/swapon.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapon)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/symlinkat.S b/libc/arch-x86/syscalls/symlinkat.S
index 618f5d8..7d7a9da 100644
--- a/libc/arch-x86/syscalls/symlinkat.S
+++ b/libc/arch-x86/syscalls/symlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(symlinkat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sync.S b/libc/arch-x86/syscalls/sync.S
index a1f1782..423c01d 100644
--- a/libc/arch-x86/syscalls/sync.S
+++ b/libc/arch-x86/syscalls/sync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sync)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/sysinfo.S b/libc/arch-x86/syscalls/sysinfo.S
index c3eabb0..0870761 100644
--- a/libc/arch-x86/syscalls/sysinfo.S
+++ b/libc/arch-x86/syscalls/sysinfo.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sysinfo)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/tee.S b/libc/arch-x86/syscalls/tee.S
index 9422660..85ff3cc 100644
--- a/libc/arch-x86/syscalls/tee.S
+++ b/libc/arch-x86/syscalls/tee.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tee)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/tgkill.S b/libc/arch-x86/syscalls/tgkill.S
index 385827b..aab80e1 100644
--- a/libc/arch-x86/syscalls/tgkill.S
+++ b/libc/arch-x86/syscalls/tgkill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tgkill)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/timerfd_create.S b/libc/arch-x86/syscalls/timerfd_create.S
index 343195e..f1bef4c 100644
--- a/libc/arch-x86/syscalls/timerfd_create.S
+++ b/libc/arch-x86/syscalls/timerfd_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_create)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/timerfd_gettime.S b/libc/arch-x86/syscalls/timerfd_gettime.S
index 9b3a314..d7ec28f 100644
--- a/libc/arch-x86/syscalls/timerfd_gettime.S
+++ b/libc/arch-x86/syscalls/timerfd_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_gettime)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/timerfd_settime.S b/libc/arch-x86/syscalls/timerfd_settime.S
index 819b723..7e03edb 100644
--- a/libc/arch-x86/syscalls/timerfd_settime.S
+++ b/libc/arch-x86/syscalls/timerfd_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_settime)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/times.S b/libc/arch-x86/syscalls/times.S
index f5739d3..6a14cff 100644
--- a/libc/arch-x86/syscalls/times.S
+++ b/libc/arch-x86/syscalls/times.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(times)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/truncate.S b/libc/arch-x86/syscalls/truncate.S
index 427f95f..33ce47f 100644
--- a/libc/arch-x86/syscalls/truncate.S
+++ b/libc/arch-x86/syscalls/truncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/truncate64.S b/libc/arch-x86/syscalls/truncate64.S
index 2c49751..2168eb4 100644
--- a/libc/arch-x86/syscalls/truncate64.S
+++ b/libc/arch-x86/syscalls/truncate64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate64)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/umask.S b/libc/arch-x86/syscalls/umask.S
index 3affc8d..03bee20 100644
--- a/libc/arch-x86/syscalls/umask.S
+++ b/libc/arch-x86/syscalls/umask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umask)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/umount2.S b/libc/arch-x86/syscalls/umount2.S
index d2b3549..9701e03 100644
--- a/libc/arch-x86/syscalls/umount2.S
+++ b/libc/arch-x86/syscalls/umount2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umount2)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/uname.S b/libc/arch-x86/syscalls/uname.S
index e996805..6de3b41 100644
--- a/libc/arch-x86/syscalls/uname.S
+++ b/libc/arch-x86/syscalls/uname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(uname)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/unlinkat.S b/libc/arch-x86/syscalls/unlinkat.S
index 6417d2b..93ea201 100644
--- a/libc/arch-x86/syscalls/unlinkat.S
+++ b/libc/arch-x86/syscalls/unlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unlinkat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/unshare.S b/libc/arch-x86/syscalls/unshare.S
index a289d4d..9d11466 100644
--- a/libc/arch-x86/syscalls/unshare.S
+++ b/libc/arch-x86/syscalls/unshare.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unshare)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/utimensat.S b/libc/arch-x86/syscalls/utimensat.S
index d8c9080..62e1525 100644
--- a/libc/arch-x86/syscalls/utimensat.S
+++ b/libc/arch-x86/syscalls/utimensat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(utimensat)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/vmsplice.S b/libc/arch-x86/syscalls/vmsplice.S
index 2afba60..4707635 100644
--- a/libc/arch-x86/syscalls/vmsplice.S
+++ b/libc/arch-x86/syscalls/vmsplice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(vmsplice)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/wait4.S b/libc/arch-x86/syscalls/wait4.S
index fda75c0..137b721 100644
--- a/libc/arch-x86/syscalls/wait4.S
+++ b/libc/arch-x86/syscalls/wait4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(wait4)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/write.S b/libc/arch-x86/syscalls/write.S
index 115974e..2f040b2 100644
--- a/libc/arch-x86/syscalls/write.S
+++ b/libc/arch-x86/syscalls/write.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(write)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/syscalls/writev.S b/libc/arch-x86/syscalls/writev.S
index 77e5cd1..2840eea 100644
--- a/libc/arch-x86/syscalls/writev.S
+++ b/libc/arch-x86/syscalls/writev.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(writev)
     pushl   %ebx
     .cfi_def_cfa_offset 8
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index 8aa2645..a141548 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -25,12 +25,12 @@
 libc_bionic_src_files_x86 += \
     arch-x86/bionic/__bionic_clone.S \
     arch-x86/bionic/_exit_with_stack_teardown.S \
-    arch-x86/bionic/__get_sp.S \
     arch-x86/bionic/_setjmp.S \
     arch-x86/bionic/setjmp.S \
     arch-x86/bionic/__set_tls.c \
     arch-x86/bionic/sigsetjmp.S \
     arch-x86/bionic/syscall.S \
+    arch-x86/bionic/vfork.S \
 
 ## ARCH variant specific source files
 arch_variant_mk := $(LOCAL_PATH)/arch-x86/$(TARGET_ARCH_VARIANT)/$(TARGET_ARCH_VARIANT).mk
diff --git a/libc/arch-x86_64/bionic/setjmp.S b/libc/arch-x86_64/bionic/setjmp.S
index c81b573..f356877 100644
--- a/libc/arch-x86_64/bionic/setjmp.S
+++ b/libc/arch-x86_64/bionic/setjmp.S
@@ -52,11 +52,7 @@
 ENTRY(setjmp)
 	pushq	%rdi
 	xorq	%rdi,%rdi
-#ifdef __PIC__
 	call	PIC_PLT(sigblock)
-#else
-	call	sigblock
-#endif
 	popq	%rdi
 	movq	%rax,(_JB_SIGMASK * 8)(%rdi)
 
@@ -80,11 +76,7 @@
 
 	movq	(_JB_SIGMASK * 8)(%rdi),%rdi
 	pushq	%r8
-#ifdef __PIC__
 	call	PIC_PLT(sigsetmask)
-#else
-	call	sigsetmask
-#endif
 	popq	%r8
 	movq	(_JB_RBX * 8)(%r12),%rbx
 	movq	(_JB_RBP * 8)(%r12),%rbp
diff --git a/libc/arch-x86_64/bionic/sigsetjmp.S b/libc/arch-x86_64/bionic/sigsetjmp.S
index 718743f..571fea3 100644
--- a/libc/arch-x86_64/bionic/sigsetjmp.S
+++ b/libc/arch-x86_64/bionic/sigsetjmp.S
@@ -57,11 +57,7 @@
 
 	pushq	%rdi
 	xorq	%rdi,%rdi
-#ifdef __PIC__
 	call	PIC_PLT(sigblock)
-#else
-	call	sigblock
-#endif
 	popq	%rdi
 	movq	%rax,(_JB_SIGMASK * 8)(%rdi)
 
@@ -86,11 +82,7 @@
 	jz      2f
 
 	movq	(_JB_SIGMASK * 8)(%rdi),%rdi
-#ifdef __PIC__
 	call	PIC_PLT(sigsetmask)
-#else
-	call	sigsetmask
-#endif
 2:	popq	%rax
 	movq	(_JB_RBX * 8)(%r12),%rbx
 	movq	(_JB_RBP * 8)(%r12),%rbp
diff --git a/libc/arch-x86_64/bionic/__get_sp.S b/libc/arch-x86_64/bionic/vfork.S
similarity index 81%
rename from libc/arch-x86_64/bionic/__get_sp.S
rename to libc/arch-x86_64/bionic/vfork.S
index 49a2406..7c14cc0 100644
--- a/libc/arch-x86_64/bionic/__get_sp.S
+++ b/libc/arch-x86_64/bionic/vfork.S
@@ -28,7 +28,18 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY_PRIVATE(__get_sp)
-  mov  %rsp, %rax
+// This custom code preserves the return address across the system call.
+
+ENTRY(vfork)
+  popq    %rdi  // Grab the return address.
+  movl    $__NR_vfork, %eax
+  syscall
+  pushq   %rdi  // Restore the return address.
+  cmpq    $-MAX_ERRNO, %rax
+  jb      1f
+  negl    %eax
+  movl    %eax, %edi
+  call    __set_errno
+1:
   ret
-END(__get_sp)
+END(vfork)
diff --git a/libc/arch-x86_64/include/machine/asm.h b/libc/arch-x86_64/include/machine/asm.h
index 0af6dae..28cd08f 100644
--- a/libc/arch-x86_64/include/machine/asm.h
+++ b/libc/arch-x86_64/include/machine/asm.h
@@ -37,21 +37,9 @@
 #ifndef _AMD64_ASM_H_
 #define _AMD64_ASM_H_
 
-#ifdef __PIC__
 #define PIC_PLT(x)	x@PLT
 #define PIC_GOT(x)	x@GOTPCREL(%rip)
-#else
-#define PIC_PLT(x)	x
-#define PIC_GOT(x)	x
-#endif
 
-/* let kernels and others override entrypoint alignment */
-#ifndef _ALIGN_TEXT
-# ifdef _STANDALONE
-#  define _ALIGN_TEXT .align 4
-# else
-#  define _ALIGN_TEXT .align 16
-# endif
-#endif
+#define __bionic_asm_align 16
 
 #endif /* !_AMD64_ASM_H_ */
diff --git a/libc/arch-x86_64/syscalls/__accept4.S b/libc/arch-x86_64/syscalls/__accept4.S
index 375a78b..774cdd5 100644
--- a/libc/arch-x86_64/syscalls/__accept4.S
+++ b/libc/arch-x86_64/syscalls/__accept4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__accept4)
     movq    %rcx, %r10
     movl    $__NR_accept4, %eax
diff --git a/libc/arch-x86_64/syscalls/__arch_prctl.S b/libc/arch-x86_64/syscalls/__arch_prctl.S
index 6c72a6c..c0dad45 100644
--- a/libc/arch-x86_64/syscalls/__arch_prctl.S
+++ b/libc/arch-x86_64/syscalls/__arch_prctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__arch_prctl)
     movl    $__NR_arch_prctl, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__brk.S b/libc/arch-x86_64/syscalls/__brk.S
index 18ebc10..df942a1 100644
--- a/libc/arch-x86_64/syscalls/__brk.S
+++ b/libc/arch-x86_64/syscalls/__brk.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__brk)
     movl    $__NR_brk, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__clock_gettime.S b/libc/arch-x86_64/syscalls/__clock_gettime.S
index 7e553b8..6c11fb6 100644
--- a/libc/arch-x86_64/syscalls/__clock_gettime.S
+++ b/libc/arch-x86_64/syscalls/__clock_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__clock_gettime)
     movl    $__NR_clock_gettime, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__connect.S b/libc/arch-x86_64/syscalls/__connect.S
index a7d2e93..05a8202 100644
--- a/libc/arch-x86_64/syscalls/__connect.S
+++ b/libc/arch-x86_64/syscalls/__connect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__connect)
     movl    $__NR_connect, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__epoll_pwait.S b/libc/arch-x86_64/syscalls/__epoll_pwait.S
index 4271b53..b0aee80 100644
--- a/libc/arch-x86_64/syscalls/__epoll_pwait.S
+++ b/libc/arch-x86_64/syscalls/__epoll_pwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__epoll_pwait)
     movq    %rcx, %r10
     movl    $__NR_epoll_pwait, %eax
diff --git a/libc/arch-x86_64/syscalls/__exit.S b/libc/arch-x86_64/syscalls/__exit.S
index bcbaffc..e552f04 100644
--- a/libc/arch-x86_64/syscalls/__exit.S
+++ b/libc/arch-x86_64/syscalls/__exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__exit)
     movl    $__NR_exit, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__getcpu.S b/libc/arch-x86_64/syscalls/__getcpu.S
index c25f294..c415fd7 100644
--- a/libc/arch-x86_64/syscalls/__getcpu.S
+++ b/libc/arch-x86_64/syscalls/__getcpu.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcpu)
     movl    $__NR_getcpu, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__getcwd.S b/libc/arch-x86_64/syscalls/__getcwd.S
index 1743838..1ea5651 100644
--- a/libc/arch-x86_64/syscalls/__getcwd.S
+++ b/libc/arch-x86_64/syscalls/__getcwd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getcwd)
     movl    $__NR_getcwd, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__getdents64.S b/libc/arch-x86_64/syscalls/__getdents64.S
index 64f82fd..42c130c 100644
--- a/libc/arch-x86_64/syscalls/__getdents64.S
+++ b/libc/arch-x86_64/syscalls/__getdents64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getdents64)
     movl    $__NR_getdents64, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__getpid.S b/libc/arch-x86_64/syscalls/__getpid.S
index bd1bf1e..ae6bb49 100644
--- a/libc/arch-x86_64/syscalls/__getpid.S
+++ b/libc/arch-x86_64/syscalls/__getpid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpid)
     movl    $__NR_getpid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__getpriority.S b/libc/arch-x86_64/syscalls/__getpriority.S
index 349f574..c82b008 100644
--- a/libc/arch-x86_64/syscalls/__getpriority.S
+++ b/libc/arch-x86_64/syscalls/__getpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__getpriority)
     movl    $__NR_getpriority, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__gettimeofday.S b/libc/arch-x86_64/syscalls/__gettimeofday.S
index a38eb64..e4b2409 100644
--- a/libc/arch-x86_64/syscalls/__gettimeofday.S
+++ b/libc/arch-x86_64/syscalls/__gettimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__gettimeofday)
     movl    $__NR_gettimeofday, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__ioctl.S b/libc/arch-x86_64/syscalls/__ioctl.S
index 2775911..aa2f538 100644
--- a/libc/arch-x86_64/syscalls/__ioctl.S
+++ b/libc/arch-x86_64/syscalls/__ioctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ioctl)
     movl    $__NR_ioctl, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__openat.S b/libc/arch-x86_64/syscalls/__openat.S
index dce4c7c..e7f5dc4 100644
--- a/libc/arch-x86_64/syscalls/__openat.S
+++ b/libc/arch-x86_64/syscalls/__openat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__openat)
     movq    %rcx, %r10
     movl    $__NR_openat, %eax
diff --git a/libc/arch-x86_64/syscalls/__ppoll.S b/libc/arch-x86_64/syscalls/__ppoll.S
index 31ba7e9..eb741ce 100644
--- a/libc/arch-x86_64/syscalls/__ppoll.S
+++ b/libc/arch-x86_64/syscalls/__ppoll.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ppoll)
     movq    %rcx, %r10
     movl    $__NR_ppoll, %eax
diff --git a/libc/arch-x86_64/syscalls/__pselect6.S b/libc/arch-x86_64/syscalls/__pselect6.S
index a212c4e..75ea416 100644
--- a/libc/arch-x86_64/syscalls/__pselect6.S
+++ b/libc/arch-x86_64/syscalls/__pselect6.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__pselect6)
     movq    %rcx, %r10
     movl    $__NR_pselect6, %eax
diff --git a/libc/arch-x86_64/syscalls/__ptrace.S b/libc/arch-x86_64/syscalls/__ptrace.S
index 0a64fee..45724e4 100644
--- a/libc/arch-x86_64/syscalls/__ptrace.S
+++ b/libc/arch-x86_64/syscalls/__ptrace.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__ptrace)
     movq    %rcx, %r10
     movl    $__NR_ptrace, %eax
diff --git a/libc/arch-x86_64/syscalls/__reboot.S b/libc/arch-x86_64/syscalls/__reboot.S
index 398d078..bbff3f2 100644
--- a/libc/arch-x86_64/syscalls/__reboot.S
+++ b/libc/arch-x86_64/syscalls/__reboot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__reboot)
     movq    %rcx, %r10
     movl    $__NR_reboot, %eax
diff --git a/libc/arch-x86_64/syscalls/__rt_sigaction.S b/libc/arch-x86_64/syscalls/__rt_sigaction.S
index f146b02..7ce3d8c 100644
--- a/libc/arch-x86_64/syscalls/__rt_sigaction.S
+++ b/libc/arch-x86_64/syscalls/__rt_sigaction.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigaction)
     movq    %rcx, %r10
     movl    $__NR_rt_sigaction, %eax
diff --git a/libc/arch-x86_64/syscalls/__rt_sigpending.S b/libc/arch-x86_64/syscalls/__rt_sigpending.S
index 9d1698b..78c10ed 100644
--- a/libc/arch-x86_64/syscalls/__rt_sigpending.S
+++ b/libc/arch-x86_64/syscalls/__rt_sigpending.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigpending)
     movl    $__NR_rt_sigpending, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__rt_sigprocmask.S b/libc/arch-x86_64/syscalls/__rt_sigprocmask.S
index 1ac9b81..bf2841c 100644
--- a/libc/arch-x86_64/syscalls/__rt_sigprocmask.S
+++ b/libc/arch-x86_64/syscalls/__rt_sigprocmask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigprocmask)
     movq    %rcx, %r10
     movl    $__NR_rt_sigprocmask, %eax
diff --git a/libc/arch-x86_64/syscalls/__rt_sigsuspend.S b/libc/arch-x86_64/syscalls/__rt_sigsuspend.S
index 1059f0b..a82b052 100644
--- a/libc/arch-x86_64/syscalls/__rt_sigsuspend.S
+++ b/libc/arch-x86_64/syscalls/__rt_sigsuspend.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigsuspend)
     movl    $__NR_rt_sigsuspend, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__rt_sigtimedwait.S b/libc/arch-x86_64/syscalls/__rt_sigtimedwait.S
index de2e4cb..aceacb2 100644
--- a/libc/arch-x86_64/syscalls/__rt_sigtimedwait.S
+++ b/libc/arch-x86_64/syscalls/__rt_sigtimedwait.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__rt_sigtimedwait)
     movq    %rcx, %r10
     movl    $__NR_rt_sigtimedwait, %eax
diff --git a/libc/arch-x86_64/syscalls/__sched_getaffinity.S b/libc/arch-x86_64/syscalls/__sched_getaffinity.S
index 410954c..fd1f607 100644
--- a/libc/arch-x86_64/syscalls/__sched_getaffinity.S
+++ b/libc/arch-x86_64/syscalls/__sched_getaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__sched_getaffinity)
     movl    $__NR_sched_getaffinity, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__set_tid_address.S b/libc/arch-x86_64/syscalls/__set_tid_address.S
index c59c8b8..7e5226d 100644
--- a/libc/arch-x86_64/syscalls/__set_tid_address.S
+++ b/libc/arch-x86_64/syscalls/__set_tid_address.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__set_tid_address)
     movl    $__NR_set_tid_address, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__signalfd4.S b/libc/arch-x86_64/syscalls/__signalfd4.S
index 6ddcf5a..d27f63c 100644
--- a/libc/arch-x86_64/syscalls/__signalfd4.S
+++ b/libc/arch-x86_64/syscalls/__signalfd4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__signalfd4)
     movq    %rcx, %r10
     movl    $__NR_signalfd4, %eax
diff --git a/libc/arch-x86_64/syscalls/__socket.S b/libc/arch-x86_64/syscalls/__socket.S
index 209e329..3b573e8 100644
--- a/libc/arch-x86_64/syscalls/__socket.S
+++ b/libc/arch-x86_64/syscalls/__socket.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__socket)
     movl    $__NR_socket, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__timer_create.S b/libc/arch-x86_64/syscalls/__timer_create.S
index 3450d2b..920c935 100644
--- a/libc/arch-x86_64/syscalls/__timer_create.S
+++ b/libc/arch-x86_64/syscalls/__timer_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_create)
     movl    $__NR_timer_create, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__timer_delete.S b/libc/arch-x86_64/syscalls/__timer_delete.S
index fd60a16..c76830e 100644
--- a/libc/arch-x86_64/syscalls/__timer_delete.S
+++ b/libc/arch-x86_64/syscalls/__timer_delete.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_delete)
     movl    $__NR_timer_delete, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__timer_getoverrun.S b/libc/arch-x86_64/syscalls/__timer_getoverrun.S
index f5309a3..e35ee93 100644
--- a/libc/arch-x86_64/syscalls/__timer_getoverrun.S
+++ b/libc/arch-x86_64/syscalls/__timer_getoverrun.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_getoverrun)
     movl    $__NR_timer_getoverrun, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__timer_gettime.S b/libc/arch-x86_64/syscalls/__timer_gettime.S
index 7e2bc92..8bb41d9 100644
--- a/libc/arch-x86_64/syscalls/__timer_gettime.S
+++ b/libc/arch-x86_64/syscalls/__timer_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_gettime)
     movl    $__NR_timer_gettime, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/__timer_settime.S b/libc/arch-x86_64/syscalls/__timer_settime.S
index f5401a0..0eace4b 100644
--- a/libc/arch-x86_64/syscalls/__timer_settime.S
+++ b/libc/arch-x86_64/syscalls/__timer_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__timer_settime)
     movq    %rcx, %r10
     movl    $__NR_timer_settime, %eax
diff --git a/libc/arch-x86_64/syscalls/__waitid.S b/libc/arch-x86_64/syscalls/__waitid.S
index 229f20c..47bf7b3 100644
--- a/libc/arch-x86_64/syscalls/__waitid.S
+++ b/libc/arch-x86_64/syscalls/__waitid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(__waitid)
     movq    %rcx, %r10
     movl    $__NR_waitid, %eax
diff --git a/libc/arch-x86_64/syscalls/_exit.S b/libc/arch-x86_64/syscalls/_exit.S
index 9c80f00..06465c4 100644
--- a/libc/arch-x86_64/syscalls/_exit.S
+++ b/libc/arch-x86_64/syscalls/_exit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(_exit)
     movl    $__NR_exit_group, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/acct.S b/libc/arch-x86_64/syscalls/acct.S
index 91ecf5b..6bf59e3 100644
--- a/libc/arch-x86_64/syscalls/acct.S
+++ b/libc/arch-x86_64/syscalls/acct.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(acct)
     movl    $__NR_acct, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/bind.S b/libc/arch-x86_64/syscalls/bind.S
index 5d426cb..4300c00 100644
--- a/libc/arch-x86_64/syscalls/bind.S
+++ b/libc/arch-x86_64/syscalls/bind.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(bind)
     movl    $__NR_bind, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/capget.S b/libc/arch-x86_64/syscalls/capget.S
index d3d151e..8ce1846 100644
--- a/libc/arch-x86_64/syscalls/capget.S
+++ b/libc/arch-x86_64/syscalls/capget.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capget)
     movl    $__NR_capget, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/capset.S b/libc/arch-x86_64/syscalls/capset.S
index 421f156..3aff07c 100644
--- a/libc/arch-x86_64/syscalls/capset.S
+++ b/libc/arch-x86_64/syscalls/capset.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(capset)
     movl    $__NR_capset, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/chdir.S b/libc/arch-x86_64/syscalls/chdir.S
index 7a6f651..f22b40d 100644
--- a/libc/arch-x86_64/syscalls/chdir.S
+++ b/libc/arch-x86_64/syscalls/chdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chdir)
     movl    $__NR_chdir, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/chroot.S b/libc/arch-x86_64/syscalls/chroot.S
index 0f53fd9..eb8a463 100644
--- a/libc/arch-x86_64/syscalls/chroot.S
+++ b/libc/arch-x86_64/syscalls/chroot.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(chroot)
     movl    $__NR_chroot, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/clock_getres.S b/libc/arch-x86_64/syscalls/clock_getres.S
index bad0d78..00b4ed6 100644
--- a/libc/arch-x86_64/syscalls/clock_getres.S
+++ b/libc/arch-x86_64/syscalls/clock_getres.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_getres)
     movl    $__NR_clock_getres, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/clock_nanosleep.S b/libc/arch-x86_64/syscalls/clock_nanosleep.S
index 2ef0d05..8bc87ae 100644
--- a/libc/arch-x86_64/syscalls/clock_nanosleep.S
+++ b/libc/arch-x86_64/syscalls/clock_nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_nanosleep)
     movq    %rcx, %r10
     movl    $__NR_clock_nanosleep, %eax
diff --git a/libc/arch-x86_64/syscalls/clock_settime.S b/libc/arch-x86_64/syscalls/clock_settime.S
index 6a3b75b..5225770 100644
--- a/libc/arch-x86_64/syscalls/clock_settime.S
+++ b/libc/arch-x86_64/syscalls/clock_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(clock_settime)
     movl    $__NR_clock_settime, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/close.S b/libc/arch-x86_64/syscalls/close.S
index 41c8403..029d09a 100644
--- a/libc/arch-x86_64/syscalls/close.S
+++ b/libc/arch-x86_64/syscalls/close.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(close)
     movl    $__NR_close, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/delete_module.S b/libc/arch-x86_64/syscalls/delete_module.S
index d3f3862..fc146bb 100644
--- a/libc/arch-x86_64/syscalls/delete_module.S
+++ b/libc/arch-x86_64/syscalls/delete_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(delete_module)
     movl    $__NR_delete_module, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/dup.S b/libc/arch-x86_64/syscalls/dup.S
index bf2ca51..53f06b0 100644
--- a/libc/arch-x86_64/syscalls/dup.S
+++ b/libc/arch-x86_64/syscalls/dup.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup)
     movl    $__NR_dup, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/dup3.S b/libc/arch-x86_64/syscalls/dup3.S
index f5c929c..fb99941 100644
--- a/libc/arch-x86_64/syscalls/dup3.S
+++ b/libc/arch-x86_64/syscalls/dup3.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(dup3)
     movl    $__NR_dup3, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/epoll_create1.S b/libc/arch-x86_64/syscalls/epoll_create1.S
index 196a3c7..6aa1915 100644
--- a/libc/arch-x86_64/syscalls/epoll_create1.S
+++ b/libc/arch-x86_64/syscalls/epoll_create1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_create1)
     movl    $__NR_epoll_create1, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/epoll_ctl.S b/libc/arch-x86_64/syscalls/epoll_ctl.S
index 2a3517c..c9dda01 100644
--- a/libc/arch-x86_64/syscalls/epoll_ctl.S
+++ b/libc/arch-x86_64/syscalls/epoll_ctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(epoll_ctl)
     movq    %rcx, %r10
     movl    $__NR_epoll_ctl, %eax
diff --git a/libc/arch-x86_64/syscalls/eventfd.S b/libc/arch-x86_64/syscalls/eventfd.S
index 3ed4baf..ac7537f 100644
--- a/libc/arch-x86_64/syscalls/eventfd.S
+++ b/libc/arch-x86_64/syscalls/eventfd.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(eventfd)
     movl    $__NR_eventfd2, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/execve.S b/libc/arch-x86_64/syscalls/execve.S
index 1fe29c7..a699303 100644
--- a/libc/arch-x86_64/syscalls/execve.S
+++ b/libc/arch-x86_64/syscalls/execve.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(execve)
     movl    $__NR_execve, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/faccessat.S b/libc/arch-x86_64/syscalls/faccessat.S
index 3ea905c..9426dd5 100644
--- a/libc/arch-x86_64/syscalls/faccessat.S
+++ b/libc/arch-x86_64/syscalls/faccessat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(faccessat)
     movq    %rcx, %r10
     movl    $__NR_faccessat, %eax
diff --git a/libc/arch-x86_64/syscalls/fallocate.S b/libc/arch-x86_64/syscalls/fallocate.S
index abaa303..91a2e65 100644
--- a/libc/arch-x86_64/syscalls/fallocate.S
+++ b/libc/arch-x86_64/syscalls/fallocate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fallocate)
     movq    %rcx, %r10
     movl    $__NR_fallocate, %eax
diff --git a/libc/arch-x86_64/syscalls/fchdir.S b/libc/arch-x86_64/syscalls/fchdir.S
index b01bb57..01c5030 100644
--- a/libc/arch-x86_64/syscalls/fchdir.S
+++ b/libc/arch-x86_64/syscalls/fchdir.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchdir)
     movl    $__NR_fchdir, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fchmod.S b/libc/arch-x86_64/syscalls/fchmod.S
index 868638f..1f4d02b 100644
--- a/libc/arch-x86_64/syscalls/fchmod.S
+++ b/libc/arch-x86_64/syscalls/fchmod.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmod)
     movl    $__NR_fchmod, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fchmodat.S b/libc/arch-x86_64/syscalls/fchmodat.S
index e045a13..cee05e3 100644
--- a/libc/arch-x86_64/syscalls/fchmodat.S
+++ b/libc/arch-x86_64/syscalls/fchmodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchmodat)
     movq    %rcx, %r10
     movl    $__NR_fchmodat, %eax
diff --git a/libc/arch-x86_64/syscalls/fchown.S b/libc/arch-x86_64/syscalls/fchown.S
index 9ba775b..1c43991 100644
--- a/libc/arch-x86_64/syscalls/fchown.S
+++ b/libc/arch-x86_64/syscalls/fchown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchown)
     movl    $__NR_fchown, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fchownat.S b/libc/arch-x86_64/syscalls/fchownat.S
index 7789d2d..8f77888 100644
--- a/libc/arch-x86_64/syscalls/fchownat.S
+++ b/libc/arch-x86_64/syscalls/fchownat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fchownat)
     movq    %rcx, %r10
     movl    $__NR_fchownat, %eax
diff --git a/libc/arch-x86_64/syscalls/fcntl.S b/libc/arch-x86_64/syscalls/fcntl.S
index a20d938..d415467 100644
--- a/libc/arch-x86_64/syscalls/fcntl.S
+++ b/libc/arch-x86_64/syscalls/fcntl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fcntl)
     movl    $__NR_fcntl, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fdatasync.S b/libc/arch-x86_64/syscalls/fdatasync.S
index 5ea8ebd..8ec4193 100644
--- a/libc/arch-x86_64/syscalls/fdatasync.S
+++ b/libc/arch-x86_64/syscalls/fdatasync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fdatasync)
     movl    $__NR_fdatasync, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fgetxattr.S b/libc/arch-x86_64/syscalls/fgetxattr.S
index 096c30f..9aacdbd 100644
--- a/libc/arch-x86_64/syscalls/fgetxattr.S
+++ b/libc/arch-x86_64/syscalls/fgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fgetxattr)
     movq    %rcx, %r10
     movl    $__NR_fgetxattr, %eax
diff --git a/libc/arch-x86_64/syscalls/flistxattr.S b/libc/arch-x86_64/syscalls/flistxattr.S
index e0e5b8b..53c58d0 100644
--- a/libc/arch-x86_64/syscalls/flistxattr.S
+++ b/libc/arch-x86_64/syscalls/flistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flistxattr)
     movl    $__NR_flistxattr, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/flock.S b/libc/arch-x86_64/syscalls/flock.S
index 981d86e..fe57b47 100644
--- a/libc/arch-x86_64/syscalls/flock.S
+++ b/libc/arch-x86_64/syscalls/flock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(flock)
     movl    $__NR_flock, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fremovexattr.S b/libc/arch-x86_64/syscalls/fremovexattr.S
index 655bdef..c37cc93 100644
--- a/libc/arch-x86_64/syscalls/fremovexattr.S
+++ b/libc/arch-x86_64/syscalls/fremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fremovexattr)
     movl    $__NR_fremovexattr, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fsetxattr.S b/libc/arch-x86_64/syscalls/fsetxattr.S
index fa2bddc..cc3d7b7 100644
--- a/libc/arch-x86_64/syscalls/fsetxattr.S
+++ b/libc/arch-x86_64/syscalls/fsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsetxattr)
     movq    %rcx, %r10
     movl    $__NR_fsetxattr, %eax
diff --git a/libc/arch-x86_64/syscalls/fstat64.S b/libc/arch-x86_64/syscalls/fstat64.S
index 9e7aa2d..dbc6760 100644
--- a/libc/arch-x86_64/syscalls/fstat64.S
+++ b/libc/arch-x86_64/syscalls/fstat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstat64)
     movl    $__NR_fstat, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fstatat64.S b/libc/arch-x86_64/syscalls/fstatat64.S
index 5418cd0..28b91fa 100644
--- a/libc/arch-x86_64/syscalls/fstatat64.S
+++ b/libc/arch-x86_64/syscalls/fstatat64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatat64)
     movq    %rcx, %r10
     movl    $__NR_newfstatat, %eax
diff --git a/libc/arch-x86_64/syscalls/fstatfs64.S b/libc/arch-x86_64/syscalls/fstatfs64.S
index ee2daa2..4b12afb 100644
--- a/libc/arch-x86_64/syscalls/fstatfs64.S
+++ b/libc/arch-x86_64/syscalls/fstatfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fstatfs64)
     movl    $__NR_fstatfs, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/fsync.S b/libc/arch-x86_64/syscalls/fsync.S
index 12eabd3..820502e 100644
--- a/libc/arch-x86_64/syscalls/fsync.S
+++ b/libc/arch-x86_64/syscalls/fsync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(fsync)
     movl    $__NR_fsync, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/ftruncate.S b/libc/arch-x86_64/syscalls/ftruncate.S
index 11161a7..0b14403 100644
--- a/libc/arch-x86_64/syscalls/ftruncate.S
+++ b/libc/arch-x86_64/syscalls/ftruncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(ftruncate)
     movl    $__NR_ftruncate, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getegid.S b/libc/arch-x86_64/syscalls/getegid.S
index 6f9c2a8..155d37b 100644
--- a/libc/arch-x86_64/syscalls/getegid.S
+++ b/libc/arch-x86_64/syscalls/getegid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getegid)
     movl    $__NR_getegid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/geteuid.S b/libc/arch-x86_64/syscalls/geteuid.S
index 88000ef..9ffa3cd 100644
--- a/libc/arch-x86_64/syscalls/geteuid.S
+++ b/libc/arch-x86_64/syscalls/geteuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(geteuid)
     movl    $__NR_geteuid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getgid.S b/libc/arch-x86_64/syscalls/getgid.S
index 8f8eaa6..d9c9da9 100644
--- a/libc/arch-x86_64/syscalls/getgid.S
+++ b/libc/arch-x86_64/syscalls/getgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgid)
     movl    $__NR_getgid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getgroups.S b/libc/arch-x86_64/syscalls/getgroups.S
index 5358a3e..9f0701a 100644
--- a/libc/arch-x86_64/syscalls/getgroups.S
+++ b/libc/arch-x86_64/syscalls/getgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getgroups)
     movl    $__NR_getgroups, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getitimer.S b/libc/arch-x86_64/syscalls/getitimer.S
index b6a6e8e..2d76430 100644
--- a/libc/arch-x86_64/syscalls/getitimer.S
+++ b/libc/arch-x86_64/syscalls/getitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getitimer)
     movl    $__NR_getitimer, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getpeername.S b/libc/arch-x86_64/syscalls/getpeername.S
index 98e06fb..b6de183 100644
--- a/libc/arch-x86_64/syscalls/getpeername.S
+++ b/libc/arch-x86_64/syscalls/getpeername.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpeername)
     movl    $__NR_getpeername, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getpgid.S b/libc/arch-x86_64/syscalls/getpgid.S
index 158f14d..e321b66 100644
--- a/libc/arch-x86_64/syscalls/getpgid.S
+++ b/libc/arch-x86_64/syscalls/getpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getpgid)
     movl    $__NR_getpgid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getppid.S b/libc/arch-x86_64/syscalls/getppid.S
index e4853e0..4a238ad 100644
--- a/libc/arch-x86_64/syscalls/getppid.S
+++ b/libc/arch-x86_64/syscalls/getppid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getppid)
     movl    $__NR_getppid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getresgid.S b/libc/arch-x86_64/syscalls/getresgid.S
index d65fb13..4727d29 100644
--- a/libc/arch-x86_64/syscalls/getresgid.S
+++ b/libc/arch-x86_64/syscalls/getresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresgid)
     movl    $__NR_getresgid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getresuid.S b/libc/arch-x86_64/syscalls/getresuid.S
index 80d85c6..1098d56 100644
--- a/libc/arch-x86_64/syscalls/getresuid.S
+++ b/libc/arch-x86_64/syscalls/getresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getresuid)
     movl    $__NR_getresuid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getrlimit.S b/libc/arch-x86_64/syscalls/getrlimit.S
index ea0ca7d..60e5881 100644
--- a/libc/arch-x86_64/syscalls/getrlimit.S
+++ b/libc/arch-x86_64/syscalls/getrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrlimit)
     movl    $__NR_getrlimit, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getrusage.S b/libc/arch-x86_64/syscalls/getrusage.S
index 7a60738..0eb0176 100644
--- a/libc/arch-x86_64/syscalls/getrusage.S
+++ b/libc/arch-x86_64/syscalls/getrusage.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getrusage)
     movl    $__NR_getrusage, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getsid.S b/libc/arch-x86_64/syscalls/getsid.S
index 75e3fad..2543b10 100644
--- a/libc/arch-x86_64/syscalls/getsid.S
+++ b/libc/arch-x86_64/syscalls/getsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsid)
     movl    $__NR_getsid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getsockname.S b/libc/arch-x86_64/syscalls/getsockname.S
index 3c7c2f8..17cd5ea 100644
--- a/libc/arch-x86_64/syscalls/getsockname.S
+++ b/libc/arch-x86_64/syscalls/getsockname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockname)
     movl    $__NR_getsockname, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getsockopt.S b/libc/arch-x86_64/syscalls/getsockopt.S
index 725757c..988a2cb 100644
--- a/libc/arch-x86_64/syscalls/getsockopt.S
+++ b/libc/arch-x86_64/syscalls/getsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getsockopt)
     movq    %rcx, %r10
     movl    $__NR_getsockopt, %eax
diff --git a/libc/arch-x86_64/syscalls/getuid.S b/libc/arch-x86_64/syscalls/getuid.S
index d7306e1..9b7a1d9 100644
--- a/libc/arch-x86_64/syscalls/getuid.S
+++ b/libc/arch-x86_64/syscalls/getuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getuid)
     movl    $__NR_getuid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/getxattr.S b/libc/arch-x86_64/syscalls/getxattr.S
index 7c66b0e..4d6aecf 100644
--- a/libc/arch-x86_64/syscalls/getxattr.S
+++ b/libc/arch-x86_64/syscalls/getxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(getxattr)
     movq    %rcx, %r10
     movl    $__NR_getxattr, %eax
diff --git a/libc/arch-x86_64/syscalls/init_module.S b/libc/arch-x86_64/syscalls/init_module.S
index 187f5a2..2c51414 100644
--- a/libc/arch-x86_64/syscalls/init_module.S
+++ b/libc/arch-x86_64/syscalls/init_module.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(init_module)
     movl    $__NR_init_module, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/inotify_add_watch.S b/libc/arch-x86_64/syscalls/inotify_add_watch.S
index 47e15ab..da5aa36 100644
--- a/libc/arch-x86_64/syscalls/inotify_add_watch.S
+++ b/libc/arch-x86_64/syscalls/inotify_add_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_add_watch)
     movl    $__NR_inotify_add_watch, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/inotify_init1.S b/libc/arch-x86_64/syscalls/inotify_init1.S
index 160b0d5..46e5014 100644
--- a/libc/arch-x86_64/syscalls/inotify_init1.S
+++ b/libc/arch-x86_64/syscalls/inotify_init1.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_init1)
     movl    $__NR_inotify_init1, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/inotify_rm_watch.S b/libc/arch-x86_64/syscalls/inotify_rm_watch.S
index 4c5874e..5920c9d 100644
--- a/libc/arch-x86_64/syscalls/inotify_rm_watch.S
+++ b/libc/arch-x86_64/syscalls/inotify_rm_watch.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(inotify_rm_watch)
     movl    $__NR_inotify_rm_watch, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/kill.S b/libc/arch-x86_64/syscalls/kill.S
index f234585..dff2da6 100644
--- a/libc/arch-x86_64/syscalls/kill.S
+++ b/libc/arch-x86_64/syscalls/kill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(kill)
     movl    $__NR_kill, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/klogctl.S b/libc/arch-x86_64/syscalls/klogctl.S
index 057b066..8560d28 100644
--- a/libc/arch-x86_64/syscalls/klogctl.S
+++ b/libc/arch-x86_64/syscalls/klogctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(klogctl)
     movl    $__NR_syslog, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/lgetxattr.S b/libc/arch-x86_64/syscalls/lgetxattr.S
index 525ee3b..b4bc204 100644
--- a/libc/arch-x86_64/syscalls/lgetxattr.S
+++ b/libc/arch-x86_64/syscalls/lgetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lgetxattr)
     movq    %rcx, %r10
     movl    $__NR_lgetxattr, %eax
diff --git a/libc/arch-x86_64/syscalls/linkat.S b/libc/arch-x86_64/syscalls/linkat.S
index 815af86..509b579 100644
--- a/libc/arch-x86_64/syscalls/linkat.S
+++ b/libc/arch-x86_64/syscalls/linkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(linkat)
     movq    %rcx, %r10
     movl    $__NR_linkat, %eax
diff --git a/libc/arch-x86_64/syscalls/listen.S b/libc/arch-x86_64/syscalls/listen.S
index d3d7103..6bd46a5 100644
--- a/libc/arch-x86_64/syscalls/listen.S
+++ b/libc/arch-x86_64/syscalls/listen.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listen)
     movl    $__NR_listen, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/listxattr.S b/libc/arch-x86_64/syscalls/listxattr.S
index 89fd63c..102518f 100644
--- a/libc/arch-x86_64/syscalls/listxattr.S
+++ b/libc/arch-x86_64/syscalls/listxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(listxattr)
     movl    $__NR_listxattr, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/llistxattr.S b/libc/arch-x86_64/syscalls/llistxattr.S
index cfff2e7..74d58a8 100644
--- a/libc/arch-x86_64/syscalls/llistxattr.S
+++ b/libc/arch-x86_64/syscalls/llistxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(llistxattr)
     movl    $__NR_llistxattr, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/lremovexattr.S b/libc/arch-x86_64/syscalls/lremovexattr.S
index 0b6994a..2566e33 100644
--- a/libc/arch-x86_64/syscalls/lremovexattr.S
+++ b/libc/arch-x86_64/syscalls/lremovexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lremovexattr)
     movl    $__NR_lremovexattr, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/lseek.S b/libc/arch-x86_64/syscalls/lseek.S
index b2e8c16..93e5f0c 100644
--- a/libc/arch-x86_64/syscalls/lseek.S
+++ b/libc/arch-x86_64/syscalls/lseek.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lseek)
     movl    $__NR_lseek, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/lsetxattr.S b/libc/arch-x86_64/syscalls/lsetxattr.S
index fdaf98a..905bd3b 100644
--- a/libc/arch-x86_64/syscalls/lsetxattr.S
+++ b/libc/arch-x86_64/syscalls/lsetxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(lsetxattr)
     movq    %rcx, %r10
     movl    $__NR_lsetxattr, %eax
diff --git a/libc/arch-x86_64/syscalls/madvise.S b/libc/arch-x86_64/syscalls/madvise.S
index 3f567fd..c565ca3 100644
--- a/libc/arch-x86_64/syscalls/madvise.S
+++ b/libc/arch-x86_64/syscalls/madvise.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(madvise)
     movl    $__NR_madvise, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/mincore.S b/libc/arch-x86_64/syscalls/mincore.S
index e6b2521..f8acdeb 100644
--- a/libc/arch-x86_64/syscalls/mincore.S
+++ b/libc/arch-x86_64/syscalls/mincore.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mincore)
     movl    $__NR_mincore, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/mkdirat.S b/libc/arch-x86_64/syscalls/mkdirat.S
index abba2d5..b554d12 100644
--- a/libc/arch-x86_64/syscalls/mkdirat.S
+++ b/libc/arch-x86_64/syscalls/mkdirat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mkdirat)
     movl    $__NR_mkdirat, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/mknodat.S b/libc/arch-x86_64/syscalls/mknodat.S
index d3d78c9..dd6496a 100644
--- a/libc/arch-x86_64/syscalls/mknodat.S
+++ b/libc/arch-x86_64/syscalls/mknodat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mknodat)
     movq    %rcx, %r10
     movl    $__NR_mknodat, %eax
diff --git a/libc/arch-x86_64/syscalls/mlock.S b/libc/arch-x86_64/syscalls/mlock.S
index 0c69eb7..78389e2 100644
--- a/libc/arch-x86_64/syscalls/mlock.S
+++ b/libc/arch-x86_64/syscalls/mlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlock)
     movl    $__NR_mlock, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/mlockall.S b/libc/arch-x86_64/syscalls/mlockall.S
index 89ba9b6..3ac878a 100644
--- a/libc/arch-x86_64/syscalls/mlockall.S
+++ b/libc/arch-x86_64/syscalls/mlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mlockall)
     movl    $__NR_mlockall, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/mmap.S b/libc/arch-x86_64/syscalls/mmap.S
index 7b9f6e0..44189a9 100644
--- a/libc/arch-x86_64/syscalls/mmap.S
+++ b/libc/arch-x86_64/syscalls/mmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mmap)
     movq    %rcx, %r10
     movl    $__NR_mmap, %eax
diff --git a/libc/arch-x86_64/syscalls/mount.S b/libc/arch-x86_64/syscalls/mount.S
index 04534c9..369e8df 100644
--- a/libc/arch-x86_64/syscalls/mount.S
+++ b/libc/arch-x86_64/syscalls/mount.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mount)
     movq    %rcx, %r10
     movl    $__NR_mount, %eax
diff --git a/libc/arch-x86_64/syscalls/mprotect.S b/libc/arch-x86_64/syscalls/mprotect.S
index d849bb1..44888da 100644
--- a/libc/arch-x86_64/syscalls/mprotect.S
+++ b/libc/arch-x86_64/syscalls/mprotect.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mprotect)
     movl    $__NR_mprotect, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/mremap.S b/libc/arch-x86_64/syscalls/mremap.S
index 8af367e..74a05e2 100644
--- a/libc/arch-x86_64/syscalls/mremap.S
+++ b/libc/arch-x86_64/syscalls/mremap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(mremap)
     movq    %rcx, %r10
     movl    $__NR_mremap, %eax
diff --git a/libc/arch-x86_64/syscalls/msync.S b/libc/arch-x86_64/syscalls/msync.S
index c0ff0f9..1d0e785 100644
--- a/libc/arch-x86_64/syscalls/msync.S
+++ b/libc/arch-x86_64/syscalls/msync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(msync)
     movl    $__NR_msync, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/munlock.S b/libc/arch-x86_64/syscalls/munlock.S
index d669f54..17e368b 100644
--- a/libc/arch-x86_64/syscalls/munlock.S
+++ b/libc/arch-x86_64/syscalls/munlock.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlock)
     movl    $__NR_munlock, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/munlockall.S b/libc/arch-x86_64/syscalls/munlockall.S
index b7a9abc..6bb7aa6 100644
--- a/libc/arch-x86_64/syscalls/munlockall.S
+++ b/libc/arch-x86_64/syscalls/munlockall.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munlockall)
     movl    $__NR_munlockall, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/munmap.S b/libc/arch-x86_64/syscalls/munmap.S
index 4360bd0..f423a66 100644
--- a/libc/arch-x86_64/syscalls/munmap.S
+++ b/libc/arch-x86_64/syscalls/munmap.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(munmap)
     movl    $__NR_munmap, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/nanosleep.S b/libc/arch-x86_64/syscalls/nanosleep.S
index 2eced5b..caa1ae6 100644
--- a/libc/arch-x86_64/syscalls/nanosleep.S
+++ b/libc/arch-x86_64/syscalls/nanosleep.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(nanosleep)
     movl    $__NR_nanosleep, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/personality.S b/libc/arch-x86_64/syscalls/personality.S
index 17ad7ee..a742dbf 100644
--- a/libc/arch-x86_64/syscalls/personality.S
+++ b/libc/arch-x86_64/syscalls/personality.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(personality)
     movl    $__NR_personality, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/pipe2.S b/libc/arch-x86_64/syscalls/pipe2.S
index 83eb0a6..e34ca69 100644
--- a/libc/arch-x86_64/syscalls/pipe2.S
+++ b/libc/arch-x86_64/syscalls/pipe2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pipe2)
     movl    $__NR_pipe2, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/prctl.S b/libc/arch-x86_64/syscalls/prctl.S
index c79220d..b4cdaa5 100644
--- a/libc/arch-x86_64/syscalls/prctl.S
+++ b/libc/arch-x86_64/syscalls/prctl.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prctl)
     movq    %rcx, %r10
     movl    $__NR_prctl, %eax
diff --git a/libc/arch-x86_64/syscalls/pread64.S b/libc/arch-x86_64/syscalls/pread64.S
index 1c4dc68..1d042ef 100644
--- a/libc/arch-x86_64/syscalls/pread64.S
+++ b/libc/arch-x86_64/syscalls/pread64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pread64)
     movq    %rcx, %r10
     movl    $__NR_pread64, %eax
diff --git a/libc/arch-x86_64/syscalls/prlimit64.S b/libc/arch-x86_64/syscalls/prlimit64.S
index 823feba..52151a8 100644
--- a/libc/arch-x86_64/syscalls/prlimit64.S
+++ b/libc/arch-x86_64/syscalls/prlimit64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(prlimit64)
     movq    %rcx, %r10
     movl    $__NR_prlimit64, %eax
diff --git a/libc/arch-x86_64/syscalls/pwrite64.S b/libc/arch-x86_64/syscalls/pwrite64.S
index 13bcb58..2fb0f16 100644
--- a/libc/arch-x86_64/syscalls/pwrite64.S
+++ b/libc/arch-x86_64/syscalls/pwrite64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(pwrite64)
     movq    %rcx, %r10
     movl    $__NR_pwrite64, %eax
diff --git a/libc/arch-x86_64/syscalls/read.S b/libc/arch-x86_64/syscalls/read.S
index 400c87a..3f2862e 100644
--- a/libc/arch-x86_64/syscalls/read.S
+++ b/libc/arch-x86_64/syscalls/read.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(read)
     movl    $__NR_read, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/readahead.S b/libc/arch-x86_64/syscalls/readahead.S
index 2a2978b..df3aba1 100644
--- a/libc/arch-x86_64/syscalls/readahead.S
+++ b/libc/arch-x86_64/syscalls/readahead.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readahead)
     movl    $__NR_readahead, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/readlinkat.S b/libc/arch-x86_64/syscalls/readlinkat.S
index 51d1f0c..554b8b6 100644
--- a/libc/arch-x86_64/syscalls/readlinkat.S
+++ b/libc/arch-x86_64/syscalls/readlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readlinkat)
     movq    %rcx, %r10
     movl    $__NR_readlinkat, %eax
diff --git a/libc/arch-x86_64/syscalls/readv.S b/libc/arch-x86_64/syscalls/readv.S
index 4199751..75d04e9 100644
--- a/libc/arch-x86_64/syscalls/readv.S
+++ b/libc/arch-x86_64/syscalls/readv.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(readv)
     movl    $__NR_readv, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/recvfrom.S b/libc/arch-x86_64/syscalls/recvfrom.S
index 61ca1b2..4ee5631 100644
--- a/libc/arch-x86_64/syscalls/recvfrom.S
+++ b/libc/arch-x86_64/syscalls/recvfrom.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvfrom)
     movq    %rcx, %r10
     movl    $__NR_recvfrom, %eax
diff --git a/libc/arch-x86_64/syscalls/recvmmsg.S b/libc/arch-x86_64/syscalls/recvmmsg.S
index ce14ba5..3279325 100644
--- a/libc/arch-x86_64/syscalls/recvmmsg.S
+++ b/libc/arch-x86_64/syscalls/recvmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmmsg)
     movq    %rcx, %r10
     movl    $__NR_recvmmsg, %eax
diff --git a/libc/arch-x86_64/syscalls/recvmsg.S b/libc/arch-x86_64/syscalls/recvmsg.S
index 8655d07..7c186fd 100644
--- a/libc/arch-x86_64/syscalls/recvmsg.S
+++ b/libc/arch-x86_64/syscalls/recvmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(recvmsg)
     movl    $__NR_recvmsg, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/removexattr.S b/libc/arch-x86_64/syscalls/removexattr.S
index 9736463..9091647 100644
--- a/libc/arch-x86_64/syscalls/removexattr.S
+++ b/libc/arch-x86_64/syscalls/removexattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(removexattr)
     movl    $__NR_removexattr, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/renameat.S b/libc/arch-x86_64/syscalls/renameat.S
index 0be2ef9..7258712 100644
--- a/libc/arch-x86_64/syscalls/renameat.S
+++ b/libc/arch-x86_64/syscalls/renameat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(renameat)
     movq    %rcx, %r10
     movl    $__NR_renameat, %eax
diff --git a/libc/arch-x86_64/syscalls/sched_get_priority_max.S b/libc/arch-x86_64/syscalls/sched_get_priority_max.S
index 0f92739..604d6c8 100644
--- a/libc/arch-x86_64/syscalls/sched_get_priority_max.S
+++ b/libc/arch-x86_64/syscalls/sched_get_priority_max.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_max)
     movl    $__NR_sched_get_priority_max, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_get_priority_min.S b/libc/arch-x86_64/syscalls/sched_get_priority_min.S
index 8450e9d..eaeb765 100644
--- a/libc/arch-x86_64/syscalls/sched_get_priority_min.S
+++ b/libc/arch-x86_64/syscalls/sched_get_priority_min.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_get_priority_min)
     movl    $__NR_sched_get_priority_min, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_getparam.S b/libc/arch-x86_64/syscalls/sched_getparam.S
index a784640..e269c7d 100644
--- a/libc/arch-x86_64/syscalls/sched_getparam.S
+++ b/libc/arch-x86_64/syscalls/sched_getparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getparam)
     movl    $__NR_sched_getparam, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_getscheduler.S b/libc/arch-x86_64/syscalls/sched_getscheduler.S
index 090b322..0cf3b54 100644
--- a/libc/arch-x86_64/syscalls/sched_getscheduler.S
+++ b/libc/arch-x86_64/syscalls/sched_getscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_getscheduler)
     movl    $__NR_sched_getscheduler, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_rr_get_interval.S b/libc/arch-x86_64/syscalls/sched_rr_get_interval.S
index 0977f2e..662a28c 100644
--- a/libc/arch-x86_64/syscalls/sched_rr_get_interval.S
+++ b/libc/arch-x86_64/syscalls/sched_rr_get_interval.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_rr_get_interval)
     movl    $__NR_sched_rr_get_interval, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_setaffinity.S b/libc/arch-x86_64/syscalls/sched_setaffinity.S
index af8e7a2..79b43fd 100644
--- a/libc/arch-x86_64/syscalls/sched_setaffinity.S
+++ b/libc/arch-x86_64/syscalls/sched_setaffinity.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setaffinity)
     movl    $__NR_sched_setaffinity, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_setparam.S b/libc/arch-x86_64/syscalls/sched_setparam.S
index 2964607..871b492 100644
--- a/libc/arch-x86_64/syscalls/sched_setparam.S
+++ b/libc/arch-x86_64/syscalls/sched_setparam.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setparam)
     movl    $__NR_sched_setparam, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_setscheduler.S b/libc/arch-x86_64/syscalls/sched_setscheduler.S
index 333d1b8..0dcb47d 100644
--- a/libc/arch-x86_64/syscalls/sched_setscheduler.S
+++ b/libc/arch-x86_64/syscalls/sched_setscheduler.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_setscheduler)
     movl    $__NR_sched_setscheduler, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sched_yield.S b/libc/arch-x86_64/syscalls/sched_yield.S
index a972154..12de511 100644
--- a/libc/arch-x86_64/syscalls/sched_yield.S
+++ b/libc/arch-x86_64/syscalls/sched_yield.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sched_yield)
     movl    $__NR_sched_yield, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sendfile.S b/libc/arch-x86_64/syscalls/sendfile.S
index c1b6497..0255bf2 100644
--- a/libc/arch-x86_64/syscalls/sendfile.S
+++ b/libc/arch-x86_64/syscalls/sendfile.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendfile)
     movq    %rcx, %r10
     movl    $__NR_sendfile, %eax
diff --git a/libc/arch-x86_64/syscalls/sendmmsg.S b/libc/arch-x86_64/syscalls/sendmmsg.S
index 940c0b6..47b2e3a 100644
--- a/libc/arch-x86_64/syscalls/sendmmsg.S
+++ b/libc/arch-x86_64/syscalls/sendmmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmmsg)
     movq    %rcx, %r10
     movl    $__NR_sendmmsg, %eax
diff --git a/libc/arch-x86_64/syscalls/sendmsg.S b/libc/arch-x86_64/syscalls/sendmsg.S
index 6d94bb6..e9eecf6 100644
--- a/libc/arch-x86_64/syscalls/sendmsg.S
+++ b/libc/arch-x86_64/syscalls/sendmsg.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendmsg)
     movl    $__NR_sendmsg, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sendto.S b/libc/arch-x86_64/syscalls/sendto.S
index bfe4636..f8cc149 100644
--- a/libc/arch-x86_64/syscalls/sendto.S
+++ b/libc/arch-x86_64/syscalls/sendto.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sendto)
     movq    %rcx, %r10
     movl    $__NR_sendto, %eax
diff --git a/libc/arch-x86_64/syscalls/setfsgid.S b/libc/arch-x86_64/syscalls/setfsgid.S
new file mode 100644
index 0000000..bfc9c5d
--- /dev/null
+++ b/libc/arch-x86_64/syscalls/setfsgid.S
@@ -0,0 +1,17 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsgid)
+    movl    $__NR_setfsgid, %eax
+    syscall
+    cmpq    $-MAX_ERRNO, %rax
+    jb      1f
+    negl    %eax
+    movl    %eax, %edi
+    call    __set_errno
+1:
+    ret
+END(setfsgid)
diff --git a/libc/arch-x86_64/syscalls/setfsuid.S b/libc/arch-x86_64/syscalls/setfsuid.S
new file mode 100644
index 0000000..2540a36
--- /dev/null
+++ b/libc/arch-x86_64/syscalls/setfsuid.S
@@ -0,0 +1,17 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+    .hidden __set_errno
+
+ENTRY(setfsuid)
+    movl    $__NR_setfsuid, %eax
+    syscall
+    cmpq    $-MAX_ERRNO, %rax
+    jb      1f
+    negl    %eax
+    movl    %eax, %edi
+    call    __set_errno
+1:
+    ret
+END(setfsuid)
diff --git a/libc/arch-x86_64/syscalls/setgid.S b/libc/arch-x86_64/syscalls/setgid.S
index ef4fb31..8f9ce53 100644
--- a/libc/arch-x86_64/syscalls/setgid.S
+++ b/libc/arch-x86_64/syscalls/setgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgid)
     movl    $__NR_setgid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setgroups.S b/libc/arch-x86_64/syscalls/setgroups.S
index 65e6180..81023ab 100644
--- a/libc/arch-x86_64/syscalls/setgroups.S
+++ b/libc/arch-x86_64/syscalls/setgroups.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setgroups)
     movl    $__NR_setgroups, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setitimer.S b/libc/arch-x86_64/syscalls/setitimer.S
index bee4996..6882564 100644
--- a/libc/arch-x86_64/syscalls/setitimer.S
+++ b/libc/arch-x86_64/syscalls/setitimer.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setitimer)
     movl    $__NR_setitimer, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setns.S b/libc/arch-x86_64/syscalls/setns.S
index 521769b..15dc51c 100644
--- a/libc/arch-x86_64/syscalls/setns.S
+++ b/libc/arch-x86_64/syscalls/setns.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setns)
     movl    $__NR_setns, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setpgid.S b/libc/arch-x86_64/syscalls/setpgid.S
index 348612b..0cbb9a3 100644
--- a/libc/arch-x86_64/syscalls/setpgid.S
+++ b/libc/arch-x86_64/syscalls/setpgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpgid)
     movl    $__NR_setpgid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setpriority.S b/libc/arch-x86_64/syscalls/setpriority.S
index 0940368..e2ee775 100644
--- a/libc/arch-x86_64/syscalls/setpriority.S
+++ b/libc/arch-x86_64/syscalls/setpriority.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setpriority)
     movl    $__NR_setpriority, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setregid.S b/libc/arch-x86_64/syscalls/setregid.S
index 0338ecf..1d53e4c 100644
--- a/libc/arch-x86_64/syscalls/setregid.S
+++ b/libc/arch-x86_64/syscalls/setregid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setregid)
     movl    $__NR_setregid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setresgid.S b/libc/arch-x86_64/syscalls/setresgid.S
index 10e1244..7663cc6 100644
--- a/libc/arch-x86_64/syscalls/setresgid.S
+++ b/libc/arch-x86_64/syscalls/setresgid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresgid)
     movl    $__NR_setresgid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setresuid.S b/libc/arch-x86_64/syscalls/setresuid.S
index 229b11b..96e691f 100644
--- a/libc/arch-x86_64/syscalls/setresuid.S
+++ b/libc/arch-x86_64/syscalls/setresuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setresuid)
     movl    $__NR_setresuid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setreuid.S b/libc/arch-x86_64/syscalls/setreuid.S
index e96e2d3..9ee7208 100644
--- a/libc/arch-x86_64/syscalls/setreuid.S
+++ b/libc/arch-x86_64/syscalls/setreuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setreuid)
     movl    $__NR_setreuid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setrlimit.S b/libc/arch-x86_64/syscalls/setrlimit.S
index 662587d..393a5c1 100644
--- a/libc/arch-x86_64/syscalls/setrlimit.S
+++ b/libc/arch-x86_64/syscalls/setrlimit.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setrlimit)
     movl    $__NR_setrlimit, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setsid.S b/libc/arch-x86_64/syscalls/setsid.S
index 293ecf5..bed06c9 100644
--- a/libc/arch-x86_64/syscalls/setsid.S
+++ b/libc/arch-x86_64/syscalls/setsid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsid)
     movl    $__NR_setsid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setsockopt.S b/libc/arch-x86_64/syscalls/setsockopt.S
index aee6613..3c12cd6 100644
--- a/libc/arch-x86_64/syscalls/setsockopt.S
+++ b/libc/arch-x86_64/syscalls/setsockopt.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setsockopt)
     movq    %rcx, %r10
     movl    $__NR_setsockopt, %eax
diff --git a/libc/arch-x86_64/syscalls/settimeofday.S b/libc/arch-x86_64/syscalls/settimeofday.S
index 0d00c89..317946a 100644
--- a/libc/arch-x86_64/syscalls/settimeofday.S
+++ b/libc/arch-x86_64/syscalls/settimeofday.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(settimeofday)
     movl    $__NR_settimeofday, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setuid.S b/libc/arch-x86_64/syscalls/setuid.S
index 19e2a10..8da7d86 100644
--- a/libc/arch-x86_64/syscalls/setuid.S
+++ b/libc/arch-x86_64/syscalls/setuid.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setuid)
     movl    $__NR_setuid, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/setxattr.S b/libc/arch-x86_64/syscalls/setxattr.S
index 3e4d50b..2abaa76 100644
--- a/libc/arch-x86_64/syscalls/setxattr.S
+++ b/libc/arch-x86_64/syscalls/setxattr.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(setxattr)
     movq    %rcx, %r10
     movl    $__NR_setxattr, %eax
diff --git a/libc/arch-x86_64/syscalls/shutdown.S b/libc/arch-x86_64/syscalls/shutdown.S
index 346be33..b5840d7 100644
--- a/libc/arch-x86_64/syscalls/shutdown.S
+++ b/libc/arch-x86_64/syscalls/shutdown.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(shutdown)
     movl    $__NR_shutdown, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sigaltstack.S b/libc/arch-x86_64/syscalls/sigaltstack.S
index 271fafc..2dd6aa4 100644
--- a/libc/arch-x86_64/syscalls/sigaltstack.S
+++ b/libc/arch-x86_64/syscalls/sigaltstack.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sigaltstack)
     movl    $__NR_sigaltstack, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/socketpair.S b/libc/arch-x86_64/syscalls/socketpair.S
index 5466dc9..cb32a8a 100644
--- a/libc/arch-x86_64/syscalls/socketpair.S
+++ b/libc/arch-x86_64/syscalls/socketpair.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(socketpair)
     movq    %rcx, %r10
     movl    $__NR_socketpair, %eax
diff --git a/libc/arch-x86_64/syscalls/splice.S b/libc/arch-x86_64/syscalls/splice.S
index 3c245a5..351e1c7 100644
--- a/libc/arch-x86_64/syscalls/splice.S
+++ b/libc/arch-x86_64/syscalls/splice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(splice)
     movq    %rcx, %r10
     movl    $__NR_splice, %eax
diff --git a/libc/arch-x86_64/syscalls/statfs64.S b/libc/arch-x86_64/syscalls/statfs64.S
index 6a2637c..26c3d53 100644
--- a/libc/arch-x86_64/syscalls/statfs64.S
+++ b/libc/arch-x86_64/syscalls/statfs64.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(statfs64)
     movl    $__NR_statfs, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/swapoff.S b/libc/arch-x86_64/syscalls/swapoff.S
index 7e55758..1bf331c 100644
--- a/libc/arch-x86_64/syscalls/swapoff.S
+++ b/libc/arch-x86_64/syscalls/swapoff.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapoff)
     movl    $__NR_swapoff, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/swapon.S b/libc/arch-x86_64/syscalls/swapon.S
index d2f5f66..7405ccb 100644
--- a/libc/arch-x86_64/syscalls/swapon.S
+++ b/libc/arch-x86_64/syscalls/swapon.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(swapon)
     movl    $__NR_swapon, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/symlinkat.S b/libc/arch-x86_64/syscalls/symlinkat.S
index 5bbf1cb..bea2da8 100644
--- a/libc/arch-x86_64/syscalls/symlinkat.S
+++ b/libc/arch-x86_64/syscalls/symlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(symlinkat)
     movl    $__NR_symlinkat, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sync.S b/libc/arch-x86_64/syscalls/sync.S
index 9911715..97aa427 100644
--- a/libc/arch-x86_64/syscalls/sync.S
+++ b/libc/arch-x86_64/syscalls/sync.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sync)
     movl    $__NR_sync, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/sysinfo.S b/libc/arch-x86_64/syscalls/sysinfo.S
index 104bb2c..de8fb8f 100644
--- a/libc/arch-x86_64/syscalls/sysinfo.S
+++ b/libc/arch-x86_64/syscalls/sysinfo.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(sysinfo)
     movl    $__NR_sysinfo, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/tee.S b/libc/arch-x86_64/syscalls/tee.S
index ad5698c..41e2370 100644
--- a/libc/arch-x86_64/syscalls/tee.S
+++ b/libc/arch-x86_64/syscalls/tee.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tee)
     movq    %rcx, %r10
     movl    $__NR_tee, %eax
diff --git a/libc/arch-x86_64/syscalls/tgkill.S b/libc/arch-x86_64/syscalls/tgkill.S
index e3b9972..00b2b42 100644
--- a/libc/arch-x86_64/syscalls/tgkill.S
+++ b/libc/arch-x86_64/syscalls/tgkill.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(tgkill)
     movl    $__NR_tgkill, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/timerfd_create.S b/libc/arch-x86_64/syscalls/timerfd_create.S
index 3f1b23a..eef3208 100644
--- a/libc/arch-x86_64/syscalls/timerfd_create.S
+++ b/libc/arch-x86_64/syscalls/timerfd_create.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_create)
     movl    $__NR_timerfd_create, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/timerfd_gettime.S b/libc/arch-x86_64/syscalls/timerfd_gettime.S
index b1017ad..9f11c5a 100644
--- a/libc/arch-x86_64/syscalls/timerfd_gettime.S
+++ b/libc/arch-x86_64/syscalls/timerfd_gettime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_gettime)
     movl    $__NR_timerfd_gettime, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/timerfd_settime.S b/libc/arch-x86_64/syscalls/timerfd_settime.S
index 8610a1d..65a17e1 100644
--- a/libc/arch-x86_64/syscalls/timerfd_settime.S
+++ b/libc/arch-x86_64/syscalls/timerfd_settime.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(timerfd_settime)
     movq    %rcx, %r10
     movl    $__NR_timerfd_settime, %eax
diff --git a/libc/arch-x86_64/syscalls/times.S b/libc/arch-x86_64/syscalls/times.S
index 07590b9..5ee21be 100644
--- a/libc/arch-x86_64/syscalls/times.S
+++ b/libc/arch-x86_64/syscalls/times.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(times)
     movl    $__NR_times, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/truncate.S b/libc/arch-x86_64/syscalls/truncate.S
index db2121f..2dc1793 100644
--- a/libc/arch-x86_64/syscalls/truncate.S
+++ b/libc/arch-x86_64/syscalls/truncate.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(truncate)
     movl    $__NR_truncate, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/umask.S b/libc/arch-x86_64/syscalls/umask.S
index badea76..ad102bd 100644
--- a/libc/arch-x86_64/syscalls/umask.S
+++ b/libc/arch-x86_64/syscalls/umask.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umask)
     movl    $__NR_umask, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/umount2.S b/libc/arch-x86_64/syscalls/umount2.S
index 93e6fa0..31588de 100644
--- a/libc/arch-x86_64/syscalls/umount2.S
+++ b/libc/arch-x86_64/syscalls/umount2.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(umount2)
     movl    $__NR_umount2, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/uname.S b/libc/arch-x86_64/syscalls/uname.S
index 4b0d1c5..ad2d8f4 100644
--- a/libc/arch-x86_64/syscalls/uname.S
+++ b/libc/arch-x86_64/syscalls/uname.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(uname)
     movl    $__NR_uname, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/unlinkat.S b/libc/arch-x86_64/syscalls/unlinkat.S
index f322f7d..e6aac2e 100644
--- a/libc/arch-x86_64/syscalls/unlinkat.S
+++ b/libc/arch-x86_64/syscalls/unlinkat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unlinkat)
     movl    $__NR_unlinkat, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/unshare.S b/libc/arch-x86_64/syscalls/unshare.S
index b5395c1..6594df0 100644
--- a/libc/arch-x86_64/syscalls/unshare.S
+++ b/libc/arch-x86_64/syscalls/unshare.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(unshare)
     movl    $__NR_unshare, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/utimensat.S b/libc/arch-x86_64/syscalls/utimensat.S
index f90caf2..5eaac1b 100644
--- a/libc/arch-x86_64/syscalls/utimensat.S
+++ b/libc/arch-x86_64/syscalls/utimensat.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(utimensat)
     movq    %rcx, %r10
     movl    $__NR_utimensat, %eax
diff --git a/libc/arch-x86_64/syscalls/vmsplice.S b/libc/arch-x86_64/syscalls/vmsplice.S
index cc94cc6..6f9e5d1 100644
--- a/libc/arch-x86_64/syscalls/vmsplice.S
+++ b/libc/arch-x86_64/syscalls/vmsplice.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(vmsplice)
     movq    %rcx, %r10
     movl    $__NR_vmsplice, %eax
diff --git a/libc/arch-x86_64/syscalls/wait4.S b/libc/arch-x86_64/syscalls/wait4.S
index 7948331..141fe19 100644
--- a/libc/arch-x86_64/syscalls/wait4.S
+++ b/libc/arch-x86_64/syscalls/wait4.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(wait4)
     movq    %rcx, %r10
     movl    $__NR_wait4, %eax
diff --git a/libc/arch-x86_64/syscalls/write.S b/libc/arch-x86_64/syscalls/write.S
index 7e3a563..498fca7 100644
--- a/libc/arch-x86_64/syscalls/write.S
+++ b/libc/arch-x86_64/syscalls/write.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(write)
     movl    $__NR_write, %eax
     syscall
diff --git a/libc/arch-x86_64/syscalls/writev.S b/libc/arch-x86_64/syscalls/writev.S
index 5fc040a..ef80eb8 100644
--- a/libc/arch-x86_64/syscalls/writev.S
+++ b/libc/arch-x86_64/syscalls/writev.S
@@ -2,6 +2,8 @@
 
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(writev)
     movl    $__NR_writev, %eax
     syscall
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 234cf67..b001b5e 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -30,13 +30,13 @@
 libc_bionic_src_files_x86_64 := \
     arch-x86_64/bionic/__bionic_clone.S \
     arch-x86_64/bionic/_exit_with_stack_teardown.S \
-    arch-x86_64/bionic/__get_sp.S \
     arch-x86_64/bionic/__rt_sigreturn.S \
     arch-x86_64/bionic/_setjmp.S \
     arch-x86_64/bionic/setjmp.S \
     arch-x86_64/bionic/__set_tls.c \
     arch-x86_64/bionic/sigsetjmp.S \
     arch-x86_64/bionic/syscall.S \
+    arch-x86_64/bionic/vfork.S \
 
 libc_bionic_src_files_x86_64 += \
     arch-x86_64/string/sse2-memcpy-slm.S \
diff --git a/libc/bionic/vfork.cpp b/libc/bionic/__gnu_basename.cpp
similarity index 87%
copy from libc/bionic/vfork.cpp
copy to libc/bionic/__gnu_basename.cpp
index b706a7f..1eb3f65 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/bionic/__gnu_basename.cpp
@@ -26,10 +26,10 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#define _GNU_SOURCE 1
+#include <string.h>
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
+extern "C" const char* __gnu_basename(const char* path) {
+  const char* last_slash = strrchr(path, '/');
+  return (last_slash != NULL) ? last_slash + 1 : path;
 }
diff --git a/libc/bionic/arc4random.c b/libc/bionic/arc4random.c
deleted file mode 100644
index 9bdf341..0000000
--- a/libc/bionic/arc4random.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*	$OpenBSD: arc4random.c,v 1.33 2014/06/13 18:58:58 deraadt Exp $	*/
-
-/*
- * Copyright (c) 1996, David Mazieres <dm@uun.org>
- * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
- * Copyright (c) 2013, Markus Friedl <markus@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.
- */
-
-/*
- * ChaCha based random number generator for OpenBSD.
- */
-
-#include <fcntl.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-
-#if defined(__ANDROID__)
-#include <sys/stat.h>
-#include <linux/random.h>
-#include "private/libc_logging.h"
-#include "private/thread_private.h"
-
-#define explicit_bzero(p, s) memset(p, 0, s)
-
-#undef MAP_ANON
-#define MAP_ANON (MAP_PRIVATE | MAP_ANONYMOUS)
-
-/*
- * XXX Should be replaced with a proper entropy measure.
- */
-static int
-gotdata(u_char *buf, size_t len)
-{
-	char	any_set = 0;
-	size_t	i;
-
-	for (i = 0; i < len; ++i)
-		any_set |= buf[i];
-	if (any_set == 0)
-		return -1;
-	return 0;
-}
-
-static int
-getentropy/*_urandom*/(u_char *buf, size_t len)
-{
-	int save_errno = errno;
-
-	int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOFOLLOW, 0));
-	if (fd == -1) {
-		__libc_fatal("getentropy_urandom failed to open \"/dev/urandom\": %s",
-				strerror(errno));
-	}
-
-	/* Lightly verify that the device node looks sane */
-	struct stat st;
-	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
-		__libc_fatal("getentropy_urandom failed to fstat \"/dev/urandom\": %s",
-				strerror(errno));
-	}
-	int cnt;
-	if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
-		__libc_fatal("getentropy_urandom failed to ioctl \"/dev/urandom\": %s",
-				strerror(errno));
-	}
-	for (size_t i = 0; i < len; ) {
-		size_t wanted = len - i;
-		ssize_t ret = TEMP_FAILURE_RETRY(read(fd, buf + i, wanted));
-
-		if (ret == -1) {
-			__libc_fatal("getentropy_urandom failed to read \"/dev/urandom\": %s",
-					strerror(errno));
-		}
-		i += ret;
-	}
-	close(fd);
-	if (gotdata(buf, len) == -1) {
-		__libc_fatal("getentropy_urandom failed to get enough entropy: %s",
-				strerror(errno));
-	}
-
-	errno = save_errno;
-	return 0;
-}
-#endif /* __ANDROID__ */
-
-#define KEYSTREAM_ONLY
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include "../upstream-openbsd/lib/libc/crypt/chacha_private.h"
-#pragma GCC diagnostic pop
-
-#ifdef __GNUC__
-#define inline __inline
-#else				/* !__GNUC__ */
-#define inline
-#endif				/* !__GNUC__ */
-
-#define KEYSZ	32
-#define IVSZ	8
-#define BLOCKSZ	64
-#define RSBUFSZ	(16*BLOCKSZ)
-static int rs_initialized;
-static pid_t rs_stir_pid;
-static chacha_ctx *rs;		/* chacha context for random keystream */
-static u_char *rs_buf;		/* keystream blocks */
-static size_t rs_have;		/* valid bytes at end of rs_buf */
-static size_t rs_count;		/* bytes till reseed */
-
-static inline void _rs_rekey(u_char *dat, size_t datlen);
-
-static inline void
-_rs_init(u_char *buf, size_t n)
-{
-	if (n < KEYSZ + IVSZ)
-		return;
-
-	if (rs == NULL && (rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
-	    MAP_ANON, -1, 0)) == MAP_FAILED)
-		abort();
-	if (rs_buf == NULL && (rs_buf = mmap(NULL, RSBUFSZ, PROT_READ|PROT_WRITE,
-	    MAP_ANON, -1, 0)) == MAP_FAILED)
-		abort();
-
-	chacha_keysetup(rs, buf, KEYSZ * 8, 0);
-	chacha_ivsetup(rs, buf + KEYSZ);
-}
-
-static void
-_rs_stir(void)
-{
-	u_char rnd[KEYSZ + IVSZ];
-
-	/* XXX */
-	(void) getentropy(rnd, sizeof rnd);
-
-	if (!rs_initialized) {
-		rs_initialized = 1;
-		_rs_init(rnd, sizeof(rnd));
-	} else
-		_rs_rekey(rnd, sizeof(rnd));
-	explicit_bzero(rnd, sizeof(rnd));
-
-	/* invalidate rs_buf */
-	rs_have = 0;
-	memset(rs_buf, 0, RSBUFSZ);
-
-	rs_count = 1600000;
-}
-
-static inline void
-_rs_stir_if_needed(size_t len)
-{
-	pid_t pid = getpid();
-
-	if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
-		rs_stir_pid = pid;
-		_rs_stir();
-	} else
-		rs_count -= len;
-}
-
-static inline void
-_rs_rekey(u_char *dat, size_t datlen)
-{
-#ifndef KEYSTREAM_ONLY
-	memset(rs_buf, 0,RSBUFSZ);
-#endif
-	/* fill rs_buf with the keystream */
-	chacha_encrypt_bytes(rs, rs_buf, rs_buf, RSBUFSZ);
-	/* mix in optional user provided data */
-	if (dat) {
-		size_t i, m;
-
-		m = MIN(datlen, KEYSZ + IVSZ);
-		for (i = 0; i < m; i++)
-			rs_buf[i] ^= dat[i];
-	}
-	/* immediately reinit for backtracking resistance */
-	_rs_init(rs_buf, KEYSZ + IVSZ);
-	memset(rs_buf, 0, KEYSZ + IVSZ);
-	rs_have = RSBUFSZ - KEYSZ - IVSZ;
-}
-
-static inline void
-_rs_random_buf(void *_buf, size_t n)
-{
-	u_char *buf = (u_char *)_buf;
-	size_t m;
-
-	_rs_stir_if_needed(n);
-	while (n > 0) {
-		if (rs_have > 0) {
-			m = MIN(n, rs_have);
-			memcpy(buf, rs_buf + RSBUFSZ - rs_have, m);
-			memset(rs_buf + RSBUFSZ - rs_have, 0, m);
-			buf += m;
-			n -= m;
-			rs_have -= m;
-		}
-		if (rs_have == 0)
-			_rs_rekey(NULL, 0);
-	}
-}
-
-static inline void
-_rs_random_u32(u_int32_t *val)
-{
-	_rs_stir_if_needed(sizeof(*val));
-	if (rs_have < sizeof(*val))
-		_rs_rekey(NULL, 0);
-	memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val));
-	memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val));
-	rs_have -= sizeof(*val);
-}
-
-u_int32_t
-arc4random(void)
-{
-	u_int32_t val;
-
-	_ARC4_LOCK();
-	_rs_random_u32(&val);
-	_ARC4_UNLOCK();
-	return val;
-}
-
-void
-arc4random_buf(void *buf, size_t n)
-{
-	_ARC4_LOCK();
-	_rs_random_buf(buf, n);
-	_ARC4_UNLOCK();
-}
-
-/*
- * Calculate a uniformly distributed random number less than upper_bound
- * avoiding "modulo bias".
- *
- * Uniformity is achieved by generating new random numbers until the one
- * returned is outside the range [0, 2**32 % upper_bound).  This
- * guarantees the selected random number will be inside
- * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
- * after reduction modulo upper_bound.
- */
-u_int32_t
-arc4random_uniform(u_int32_t upper_bound)
-{
-	u_int32_t r, min;
-
-	if (upper_bound < 2)
-		return 0;
-
-	/* 2**32 % x == (2**32 - x) % x */
-	min = -upper_bound % upper_bound;
-
-	/*
-	 * This could theoretically loop forever but each retry has
-	 * p > 0.5 (worst case, usually far better) of selecting a
-	 * number inside the range we need, so it should rarely need
-	 * to re-roll.
-	 */
-	for (;;) {
-		r = arc4random();
-		if (r >= min)
-			break;
-	}
-
-	return r % upper_bound;
-}
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/clone.cpp b/libc/bionic/clone.cpp
index 0a0fdd5..9b5c9e7 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#define __GNU_SOURCE 1
+#define _GNU_SOURCE 1
 #include <sched.h>
 #include <stdlib.h>
 #include <stdarg.h>
diff --git a/libc/bionic/debug_mapinfo.cpp b/libc/bionic/debug_mapinfo.cpp
index 17276ce..698ab6b 100644
--- a/libc/bionic/debug_mapinfo.cpp
+++ b/libc/bionic/debug_mapinfo.cpp
@@ -26,43 +26,52 @@
  * 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);
-  FILE* fp = fopen(data, "r");
+  FILE* fp = fopen(data, "re");
   if (fp != NULL) {
     while (fgets(data, sizeof(data), fp) != NULL) {
       mapinfo_t* mi = parse_maps_line(data);
@@ -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/dlmalloc.c b/libc/bionic/dlmalloc.c
index d582071..5853e7c 100644
--- a/libc/bionic/dlmalloc.c
+++ b/libc/bionic/dlmalloc.c
@@ -16,6 +16,8 @@
 
 #include "dlmalloc.h"
 
+#include "malloc.h"
+#include "private/bionic_prctl.h"
 #include "private/libc_logging.h"
 
 // Send dlmalloc errors to the log.
@@ -30,11 +32,6 @@
 #define MMAP(s) named_anonymous_mmap(s)
 #define DIRECT_MMAP(s) named_anonymous_mmap(s)
 
-// Local definitions of custom prctl arguments to set a vma name in Android kernels.
-#include <sys/prctl.h>
-#define PR_SET_VMA           0x53564d41
-#define PR_SET_VMA_ANON_NAME 0
-
 // Ugly inclusion of C file so that bionic specific #defines configure dlmalloc.
 #include "../upstream-dlmalloc/malloc.c"
 
@@ -58,3 +55,25 @@
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map, length, "libc_malloc");
   return map;
 }
+
+// Since dlmalloc isn't the default, we'll leave this unimplemented for now. If
+// we decide we need it later, we can fill it in.
+size_t __mallinfo_narenas() {
+  return 0;
+}
+
+size_t __mallinfo_nbins() {
+  return 0;
+}
+
+struct mallinfo __mallinfo_arena_info(size_t aidx __unused) {
+  struct mallinfo mi;
+  memset(&mi, 0, sizeof(mi));
+  return mi;
+}
+
+struct mallinfo __mallinfo_bin_info(size_t aidx __unused, size_t bidx __unused) {
+  struct mallinfo mi;
+  memset(&mi, 0, sizeof(mi));
+  return mi;
+}
diff --git a/libc/bionic/getentropy_linux.c b/libc/bionic/getentropy_linux.c
new file mode 100644
index 0000000..409bd7d
--- /dev/null
+++ b/libc/bionic/getentropy_linux.c
@@ -0,0 +1,565 @@
+/*	$OpenBSD: getentropy_linux.c,v 1.28 2014/07/20 03:24:10 deraadt Exp $	*/
+
+/*
+ * 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
+ */
+
+#define	_POSIX_C_SOURCE	199309L
+#define	_GNU_SOURCE	1
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#include <sys/statvfs.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <link.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#ifdef HAVE_OPENSSL
+#include <openssl/sha.h>
+#endif
+
+#include <linux/random.h>
+#include <linux/sysctl.h>
+#ifdef HAVE_GETAUXVAL
+#include <sys/auxv.h>
+#endif
+#include <sys/vfs.h>
+
+#define REPEAT 5
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+	do { \
+		if ((a)) \
+			HD(errno); \
+		else \
+			HD(b); \
+	} while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int	getentropy(void *buf, size_t len);
+
+static int gotdata(char *buf, size_t len);
+#ifdef SYS__getrandom
+static int getentropy_getrandom(void *buf, size_t len);
+#endif
+static int getentropy_urandom(void *buf, size_t len);
+#ifdef SYS__sysctl
+static int getentropy_sysctl(void *buf, size_t len);
+#endif
+#ifdef HAVE_OPENSSL
+static int getentropy_fallback(void *buf, size_t len);
+static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
+#endif
+
+int
+getentropy(void *buf, size_t len)
+{
+	int ret = -1;
+
+	if (len > 256) {
+		errno = EIO;
+		return -1;
+	}
+
+#ifdef SYS__getrandom
+	/*
+	 * Try descriptor-less getrandom()
+	 */
+	ret = getentropy_getrandom(buf, len);
+	if (ret != -1)
+		return (ret);
+#endif
+
+	/*
+	 * Try to get entropy with /dev/urandom
+	 *
+	 * This can fail if the process is inside a chroot or if file
+	 * descriptors are exhausted.
+	 */
+	ret = getentropy_urandom(buf, len);
+	if (ret != -1)
+		return (ret);
+
+#ifdef SYS__sysctl
+	/*
+	 * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
+	 * sysctl is a failsafe API, so it guarantees a result.  This
+	 * should work inside a chroot, or when file descriptors are
+	 * exhuasted.
+	 *
+	 * However this can fail if the Linux kernel removes support
+	 * for sysctl.  Starting in 2007, there have been efforts to
+	 * deprecate the sysctl API/ABI, and push callers towards use
+	 * of the chroot-unavailable fd-using /proc mechanism --
+	 * essentially the same problems as /dev/urandom.
+	 *
+	 * Numerous setbacks have been encountered in their deprecation
+	 * schedule, so as of June 2014 the kernel ABI still exists on
+	 * most Linux architectures. The sysctl() stub in libc is missing
+	 * on some systems.  There are also reports that some kernels
+	 * spew messages to the console.
+	 */
+	ret = getentropy_sysctl(buf, len);
+	if (ret != -1)
+		return (ret);
+#endif /* SYS__sysctl */
+
+	/*
+	 * Entropy collection via /dev/urandom and sysctl have failed.
+	 *
+	 * No other API exists for collecting entropy.  See the large
+	 * comment block above.
+	 *
+	 * We have very few options:
+	 *     - Even syslog_r is unsafe to call at this low level, so
+	 *	 there is no way to alert the user or program.
+	 *     - Cannot call abort() because some systems have unsafe
+	 *	 corefiles.
+	 *     - Could raise(SIGKILL) resulting in silent program termination.
+	 *     - Return EIO, to hint that arc4random's stir function
+	 *       should raise(SIGKILL)
+	 *     - Do the best under the circumstances....
+	 *
+	 * This code path exists to bring light to the issue that Linux
+	 * does not provide a failsafe API for entropy collection.
+	 *
+	 * We hope this demonstrates that Linux should either retain their
+	 * sysctl ABI, or consider providing a new failsafe API which
+	 * works in a chroot or when file descriptors are exhausted.
+	 */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+	raise(SIGKILL);
+#endif
+#ifdef HAVE_OPENSSL
+	ret = getentropy_fallback(buf, len);
+	if (ret != -1)
+		return (ret);
+#endif
+
+	errno = EIO;
+	return (ret);
+}
+
+/*
+ * Basic sanity checking; wish we could do better.
+ */
+static int
+gotdata(char *buf, size_t len)
+{
+	char	any_set = 0;
+	size_t	i;
+
+	for (i = 0; i < len; ++i)
+		any_set |= buf[i];
+	if (any_set == 0)
+		return -1;
+	return 0;
+}
+
+#ifdef SYS__getrandom
+static int
+getentropy_getrandom(void *buf, size_t len)
+{
+#if 0
+
+/* Hand-definitions until the API becomes commonplace */
+#ifndef SYS__getrandom
+#ifdef __LP64__
+#define SYS__getrandom 317
+#else
+#define SYS__getrandom 354
+#endif
+#endif
+	struct __getrandom_args args = {
+		.buf = buf;
+		.len = len;
+		.flags = 0;
+	};
+
+	if (len > 256)
+		return (-1);
+	ret = syscall(SYS__getrandom, &args);
+	if (ret == len)
+		return (0);
+#endif
+	return -1;
+}
+#endif
+
+static int
+getentropy_urandom(void *buf, size_t len)
+{
+	struct stat st;
+	size_t i;
+	int fd, cnt, flags;
+	int save_errno = errno;
+
+start:
+
+	flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+	flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+	flags |= O_CLOEXEC;
+#endif
+	fd = open("/dev/urandom", flags, 0);
+	if (fd == -1) {
+		if (errno == EINTR)
+			goto start;
+		goto nodevrandom;
+	}
+#ifndef O_CLOEXEC
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+	/* Lightly verify that the device node looks sane */
+	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+		close(fd);
+		goto nodevrandom;
+	}
+	if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
+		close(fd);
+		goto nodevrandom;
+	}
+	for (i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = read(fd, (char *)buf + i, wanted);
+
+		if (ret == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			close(fd);
+			goto nodevrandom;
+		}
+		i += ret;
+	}
+	close(fd);
+	if (gotdata(buf, len) == 0) {
+		errno = save_errno;
+		return 0;		/* satisfied */
+	}
+nodevrandom:
+	errno = EIO;
+	return -1;
+}
+
+#ifdef SYS__sysctl
+static int
+getentropy_sysctl(void *buf, size_t len)
+{
+	static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
+	size_t i;
+	int save_errno = errno;
+
+	for (i = 0; i < len; ) {
+		size_t chunk = min(len - i, 16);
+
+		/* SYS__sysctl because some systems already removed sysctl() */
+		struct __sysctl_args args = {
+			.name = mib,
+			.nlen = 3,
+			.oldval = (char*) buf + i,
+			.oldlenp = &chunk,
+		};
+		if (syscall(SYS__sysctl, &args) != 0)
+			goto sysctlfailed;
+		i += chunk;
+	}
+	if (gotdata(buf, len) == 0) {
+		errno = save_errno;
+		return (0);			/* satisfied */
+	}
+sysctlfailed:
+	errno = EIO;
+	return -1;
+}
+#endif /* SYS__sysctl */
+
+#ifdef HAVE_OPENSSL
+
+static int cl[] = {
+	CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+	CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+	CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+	CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+	CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+	CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+	CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+	CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+
+static int
+getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
+{
+	SHA512_CTX *ctx = data;
+
+	SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
+	return 0;
+}
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+	uint8_t results[SHA512_DIGEST_LENGTH];
+	int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+	static int cnt;
+	struct timespec ts;
+	struct timeval tv;
+	struct rusage ru;
+	sigset_t sigset;
+	struct stat st;
+	SHA512_CTX ctx;
+	static pid_t lastpid;
+	pid_t pid;
+	size_t i, ii, m;
+	char *p;
+
+	pid = getpid();
+	if (lastpid == pid) {
+		faster = 1;
+		repeat = 2;
+	} else {
+		faster = 0;
+		lastpid = pid;
+		repeat = REPEAT;
+	}
+	for (i = 0; i < len; ) {
+		int j;
+		SHA512_Init(&ctx);
+		for (j = 0; j < repeat; j++) {
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			dl_iterate_phdr(getentropy_phdr, &ctx);
+
+			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+				HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
+			HX((pid = getpid()) == -1, pid);
+			HX((pid = getsid(pid)) == -1, pid);
+			HX((pid = getppid()) == -1, pid);
+			HX((pid = getpgid(0)) == -1, pid);
+			HX((e = getpriority(0, 0)) == -1, e);
+
+			if (!faster) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 1;
+				(void) nanosleep(&ts, NULL);
+			}
+
+			HX(sigpending(&sigset) == -1, sigset);
+			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+			    sigset);
+
+			HF(getentropy);	/* an addr in this library */
+			HF(printf);		/* an addr in libc */
+			p = (char *)&p;
+			HD(p);		/* an addr on stack */
+			p = (char *)&errno;
+			HD(p);		/* the addr of errno */
+
+			if (i == 0) {
+				struct sockaddr_storage ss;
+				struct statvfs stvfs;
+				struct termios tios;
+				struct statfs stfs;
+				socklen_t ssl;
+				off_t off;
+
+				/*
+				 * Prime-sized mappings encourage fragmentation;
+				 * thus exposing some address entropy.
+				 */
+				struct mm {
+					size_t	npg;
+					void	*p;
+				} mm[] =	 {
+					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
+					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
+					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
+				};
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					HX(mm[m].p = mmap(NULL,
+					    mm[m].npg * pgs,
+					    PROT_READ|PROT_WRITE,
+					    MAP_PRIVATE|MAP_ANON, -1,
+					    (off_t)0), mm[m].p);
+					if (mm[m].p != MAP_FAILED) {
+						size_t mo;
+
+						/* Touch some memory... */
+						p = mm[m].p;
+						mo = cnt %
+						    (mm[m].npg * pgs - 1);
+						p[mo] = 1;
+						cnt += (int)((long)(mm[m].p)
+						    / pgs);
+					}
+
+					/* Check cnts and times... */
+					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+					    ii++) {
+						HX((e = clock_gettime(cl[ii],
+						    &ts)) == -1, ts);
+						if (e != -1)
+							cnt += (int)ts.tv_nsec;
+					}
+
+					HX((e = getrusage(RUSAGE_SELF,
+					    &ru)) == -1, ru);
+					if (e != -1) {
+						cnt += (int)ru.ru_utime.tv_sec;
+						cnt += (int)ru.ru_utime.tv_usec;
+					}
+				}
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					if (mm[m].p != MAP_FAILED)
+						munmap(mm[m].p, mm[m].npg * pgs);
+					mm[m].p = MAP_FAILED;
+				}
+
+				HX(stat(".", &st) == -1, st);
+				HX(statvfs(".", &stvfs) == -1, stvfs);
+				HX(statfs(".", &stfs) == -1, stfs);
+
+				HX(stat("/", &st) == -1, st);
+				HX(statvfs("/", &stvfs) == -1, stvfs);
+				HX(statfs("/", &stfs) == -1, stfs);
+
+				HX((e = fstat(0, &st)) == -1, st);
+				if (e == -1) {
+					if (S_ISREG(st.st_mode) ||
+					    S_ISFIFO(st.st_mode) ||
+					    S_ISSOCK(st.st_mode)) {
+						HX(fstatvfs(0, &stvfs) == -1,
+						    stvfs);
+						HX(fstatfs(0, &stfs) == -1,
+						    stfs);
+						HX((off = lseek(0, (off_t)0,
+						    SEEK_CUR)) < 0, off);
+					}
+					if (S_ISCHR(st.st_mode)) {
+						HX(tcgetattr(0, &tios) == -1,
+						    tios);
+					} else if (S_ISSOCK(st.st_mode)) {
+						memset(&ss, 0, sizeof ss);
+						ssl = sizeof(ss);
+						HX(getpeername(0,
+						    (void *)&ss, &ssl) == -1,
+						    ss);
+					}
+				}
+
+				HX((e = getrusage(RUSAGE_CHILDREN,
+				    &ru)) == -1, ru);
+				if (e != -1) {
+					cnt += (int)ru.ru_utime.tv_sec;
+					cnt += (int)ru.ru_utime.tv_usec;
+				}
+			} else {
+				/* Subsequent hashes absorb previous result */
+				HD(results);
+			}
+
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HD(cnt);
+		}
+#ifdef HAVE_GETAUXVAL
+#ifdef AT_RANDOM
+		/* Not as random as you think but we take what we are given */
+		p = (char *) getauxval(AT_RANDOM);
+		if (p)
+			HR(p, 16);
+#endif
+#ifdef AT_SYSINFO_EHDR
+		p = (char *) getauxval(AT_SYSINFO_EHDR);
+		if (p)
+			HR(p, pgs);
+#endif
+#ifdef AT_BASE
+		p = (char *) getauxval(AT_BASE);
+		if (p)
+			HD(p);
+#endif
+#endif
+
+		SHA512_Final(results, &ctx);
+		memcpy((char *)buf + i, results, min(sizeof(results), len - i));
+		i += min(sizeof(results), len - i);
+	}
+	memset(results, 0, sizeof results);
+	if (gotdata(buf, len) == 0) {
+		errno = save_errno;
+		return 0;		/* satisfied */
+	}
+	errno = EIO;
+	return -1;
+}
+
+#endif /* HAVE_OPENSSL */
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_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 9e4eecd..2a6a03b 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -36,7 +36,6 @@
 #include <stdlib.h>
 #include <sys/auxv.h>
 #include <sys/time.h>
-#include <sys/resource.h>
 #include <unistd.h>
 
 #include "private/bionic_auxv.h"
@@ -46,12 +45,11 @@
 #include "pthread_internal.h"
 
 extern "C" abort_msg_t** __abort_message_ptr;
-extern "C" uintptr_t __get_sp(void);
 extern "C" int __system_properties_init(void);
 extern "C" int __set_tls(void* ptr);
 extern "C" int __set_tid_address(int* tid_address);
 
-void __libc_init_vdso();
+__LIBC_HIDDEN__ void __libc_init_vdso();
 
 // Not public, but well-known in the BSDs.
 const char* __progname;
@@ -62,17 +60,6 @@
 // Declared in "private/bionic_ssp.h".
 uintptr_t __stack_chk_guard = 0;
 
-static size_t get_main_thread_stack_size() {
-  rlimit stack_limit;
-  int rlimit_result = getrlimit(RLIMIT_STACK, &stack_limit);
-  if ((rlimit_result == 0) &&
-      (stack_limit.rlim_cur != RLIM_INFINITY) &&
-      (stack_limit.rlim_cur > PTHREAD_STACK_MIN)) {
-    return (stack_limit.rlim_cur & ~(PAGE_SIZE - 1));
-  }
-  return PTHREAD_STACK_SIZE_DEFAULT;
-}
-
 /* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
  * in memory. Beware: all writes to libc globals from this function will
  * apply to linker-private copies and will not be visible from libc later on.
@@ -96,16 +83,15 @@
   main_thread.tid = __set_tid_address(&main_thread.tid);
   main_thread.set_cached_pid(main_thread.tid);
 
-  // Work out the extent of the main thread's stack.
-  uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
-  size_t stack_size = get_main_thread_stack_size();
-  void* stack_bottom = reinterpret_cast<void*>(stack_top - stack_size);
-
   // We don't want to free the main thread's stack even when the main thread exits
   // because things like environment variables with global scope live on it.
+  // We also can't free the pthread_internal_t itself, since that lives on the main
+  // thread's stack rather than on the heap.
   pthread_attr_init(&main_thread.attr);
-  pthread_attr_setstack(&main_thread.attr, stack_bottom, stack_size);
   main_thread.attr.flags = PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK | PTHREAD_ATTR_FLAG_MAIN_THREAD;
+  main_thread.attr.guard_size = 0; // The main thread has no guard page.
+  main_thread.attr.stack_size = 0; // User code should never see this; we'll compute it when asked.
+  // TODO: the main thread's sched_policy and sched_priority need to be queried.
 
   __init_thread(&main_thread, false);
   __init_tls(&main_thread);
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index d0172ed..5655526 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -29,6 +29,7 @@
 #include "../private/libc_logging.h" // Relative path so we can #include this .cpp file for testing.
 #include "../private/ScopedPthreadMutexLocker.h"
 
+#include <android/set_abort_message.h>
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -629,7 +630,7 @@
   // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
   __libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
 
-  __android_set_abort_message(msg);
+  android_set_abort_message(msg);
 }
 
 void __libc_fatal_no_abort(const char* format, ...) {
@@ -647,7 +648,7 @@
   abort();
 }
 
-void __android_set_abort_message(const char* msg) {
+void android_set_abort_message(const char* msg) {
   ScopedPthreadMutexLocker locker(&g_abort_msg_lock);
 
   if (__abort_message_ptr == NULL) {
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 5a1da43..ddb49ce 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -30,10 +30,27 @@
 #include <pthread.h>
 #include <stdlib.h>
 
+#include "private/bionic_macros.h"
+
 // We currently support a single locale, the "C" locale (also known as "POSIX").
 
+static bool __bionic_current_locale_is_utf8 = true;
+
 struct __locale_t {
-  // Because we only support one locale, these are just tokens with no data.
+  size_t mb_cur_max;
+
+  __locale_t(size_t mb_cur_max) : mb_cur_max(mb_cur_max) {
+  }
+
+  __locale_t(const __locale_t* other) {
+    if (other == LC_GLOBAL_LOCALE) {
+      mb_cur_max = __bionic_current_locale_is_utf8 ? 4 : 1;
+    } else {
+      mb_cur_max = other->mb_cur_max;
+    }
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(__locale_t);
 };
 
 static pthread_once_t g_locale_once = PTHREAD_ONCE_INIT;
@@ -75,33 +92,34 @@
   g_locale.int_n_sign_posn = CHAR_MAX;
 }
 
-static bool __bionic_current_locale_is_utf8 = false;
+size_t __ctype_get_mb_cur_max() {
+  locale_t l = reinterpret_cast<locale_t>(pthread_getspecific(g_uselocale_key));
+  if (l == nullptr || l == LC_GLOBAL_LOCALE) {
+    return __bionic_current_locale_is_utf8 ? 4 : 1;
+  } else {
+    return l->mb_cur_max;
+  }
+}
 
 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);
 }
 
-static locale_t __new_locale() {
-  return reinterpret_cast<locale_t>(malloc(sizeof(__locale_t)));
-}
-
 lconv* localeconv() {
   pthread_once(&g_locale_once, __locale_init);
   return &g_locale;
 }
 
 locale_t duplocale(locale_t l) {
-  locale_t clone = __new_locale();
-  if (clone != NULL && l != LC_GLOBAL_LOCALE) {
-    *clone = *l;
-  }
-  return clone;
+  return new __locale_t(l);
 }
 
 void freelocale(locale_t l) {
-  free(l);
+  delete l;
 }
 
 locale_t newlocale(int category_mask, const char* locale_name, locale_t /*base*/) {
@@ -116,7 +134,7 @@
     return NULL;
   }
 
-  return __new_locale();
+  return new __locale_t(strstr(locale_name, "UTF-8") != NULL ? 4 : 1);
 }
 
 char* setlocale(int category, const char* locale_name) {
diff --git a/libc/bionic/vfork.cpp b/libc/bionic/malloc_debug_backtrace.h
similarity index 85%
copy from libc/bionic/vfork.cpp
copy to libc/bionic/malloc_debug_backtrace.h
index b706a7f..774548b 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/bionic/malloc_debug_backtrace.h
@@ -26,10 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#ifndef MALLOC_DEBUG_BACKTRACE_H
+#define MALLOC_DEBUG_BACKTRACE_H
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+extern bool g_backtrace_enabled;
+
+#define GET_BACKTRACE(bt, depth) \
+  (g_backtrace_enabled ? get_backtrace(bt, depth) : 0)
+
+#endif  // MALLOC_DEBUG_BACKTRACE_H
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index 1c63d4d..dee03fa 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -48,7 +48,9 @@
 
 #include "debug_mapinfo.h"
 #include "debug_stacktrace.h"
+#include "malloc_debug_backtrace.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"
@@ -122,6 +124,10 @@
 // It determines the size of the backlog we use to detect multiple frees.
 static unsigned g_malloc_debug_backlog = 100;
 
+// This variable is set to false if the property libc.debug.malloc.nobacktrace
+// is set to non-zero.
+__LIBC_HIDDEN__ bool g_backtrace_enabled = true;
+
 __LIBC_HIDDEN__ HashTable* g_hash_table;
 __LIBC_HIDDEN__ const MallocDebug* g_malloc_dispatch;
 
@@ -272,7 +278,7 @@
         valid = check_guards(hdr, safe);
     }
 
-    if (!valid && *safe) {
+    if (!valid && *safe && g_backtrace_enabled) {
         log_message("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
                         user(hdr), hdr->size);
         log_backtrace(hdr->bt, hdr->bt_depth);
@@ -331,6 +337,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
@@ -340,7 +349,7 @@
     hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->malloc(size));
     if (hdr) {
         hdr->base = hdr;
-        hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
+        hdr->bt_depth = GET_BACKTRACE(hdr->bt, MAX_BACKTRACE_DEPTH);
         add(hdr, bytes);
         return user(hdr);
     }
@@ -348,6 +357,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);
     }
@@ -377,7 +390,7 @@
 
         hdr_t* hdr = meta(reinterpret_cast<void*>(ptr));
         hdr->base = base;
-        hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
+        hdr->bt_depth = GET_BACKTRACE(hdr->bt, MAX_BACKTRACE_DEPTH);
         add(hdr, bytes);
         return user(hdr);
     }
@@ -386,6 +399,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;
@@ -394,33 +410,40 @@
 
     if (del(hdr) < 0) {
         uintptr_t bt[MAX_BACKTRACE_DEPTH];
-        int depth = get_backtrace(bt, MAX_BACKTRACE_DEPTH);
+        int depth = GET_BACKTRACE(bt, MAX_BACKTRACE_DEPTH);
         if (hdr->tag == BACKLOG_TAG) {
             log_message("+++ ALLOCATION %p SIZE %d BYTES MULTIPLY FREED!\n",
                        user(hdr), hdr->size);
-            log_message("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
-                       user(hdr), hdr->size);
-            log_backtrace(hdr->bt, hdr->bt_depth);
-            /* hdr->freed_bt_depth should be nonzero here */
-            log_message("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n",
-                       user(hdr), hdr->size);
-            log_backtrace(hdr->freed_bt, hdr->freed_bt_depth);
-            log_message("+++ ALLOCATION %p SIZE %d NOW BEING FREED HERE:\n",
-                       user(hdr), hdr->size);
-            log_backtrace(bt, depth);
+            if (g_backtrace_enabled) {
+                log_message("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
+                          user(hdr), hdr->size);
+                log_backtrace(hdr->bt, hdr->bt_depth);
+                /* hdr->freed_bt_depth should be nonzero here */
+                log_message("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n",
+                          user(hdr), hdr->size);
+                log_backtrace(hdr->freed_bt, hdr->freed_bt_depth);
+                log_message("+++ ALLOCATION %p SIZE %d NOW BEING FREED HERE:\n",
+                          user(hdr), hdr->size);
+                log_backtrace(bt, depth);
+            }
         } else {
             log_message("+++ ALLOCATION %p IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n",
                        user(hdr));
-            log_backtrace(bt, depth);
+            if (g_backtrace_enabled) {
+                log_backtrace(bt, depth);
+            }
         }
     } else {
-        hdr->freed_bt_depth = get_backtrace(hdr->freed_bt, MAX_BACKTRACE_DEPTH);
+        hdr->freed_bt_depth = GET_BACKTRACE(hdr->freed_bt, MAX_BACKTRACE_DEPTH);
         add_to_backlog(hdr);
     }
 }
 
 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);
@@ -437,22 +460,24 @@
 
     if (del(hdr) < 0) {
         uintptr_t bt[MAX_BACKTRACE_DEPTH];
-        int depth = get_backtrace(bt, MAX_BACKTRACE_DEPTH);
+        int depth = GET_BACKTRACE(bt, MAX_BACKTRACE_DEPTH);
         if (hdr->tag == BACKLOG_TAG) {
             log_message("+++ REALLOCATION %p SIZE %d OF FREED MEMORY!\n",
                        user(hdr), bytes, hdr->size);
-            log_message("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
-                       user(hdr), hdr->size);
-            log_backtrace(hdr->bt, hdr->bt_depth);
-            /* hdr->freed_bt_depth should be nonzero here */
-            log_message("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n",
-                       user(hdr), hdr->size);
-            log_backtrace(hdr->freed_bt, hdr->freed_bt_depth);
-            log_message("+++ ALLOCATION %p SIZE %d NOW BEING REALLOCATED HERE:\n",
-                       user(hdr), hdr->size);
-            log_backtrace(bt, depth);
+            if (g_backtrace_enabled) {
+                log_message("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
+                          user(hdr), hdr->size);
+                log_backtrace(hdr->bt, hdr->bt_depth);
+                /* hdr->freed_bt_depth should be nonzero here */
+                log_message("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n",
+                          user(hdr), hdr->size);
+                log_backtrace(hdr->freed_bt, hdr->freed_bt_depth);
+                log_message("+++ ALLOCATION %p SIZE %d NOW BEING REALLOCATED HERE:\n",
+                          user(hdr), hdr->size);
+                log_backtrace(bt, depth);
+            }
 
-             /* We take the memory out of the backlog and fall through so the
+            /* We take the memory out of the backlog and fall through so the
              * reallocation below succeeds.  Since we didn't really free it, we
              * can default to this behavior.
              */
@@ -460,7 +485,9 @@
         } else {
             log_message("+++ REALLOCATION %p SIZE %d IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n",
                        user(hdr), bytes);
-            log_backtrace(bt, depth);
+            if (g_backtrace_enabled) {
+                log_backtrace(bt, depth);
+            }
             // just get a whole new allocation and leak the old one
             return g_malloc_dispatch->realloc(0, bytes);
             // return realloc(user(hdr), bytes); // assuming it was allocated externally
@@ -487,7 +514,7 @@
     }
     if (hdr) {
         hdr->base = hdr;
-        hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
+        hdr->bt_depth = GET_BACKTRACE(hdr->bt, MAX_BACKTRACE_DEPTH);
         add(hdr, bytes);
         return user(hdr);
     }
@@ -496,6 +523,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
@@ -505,7 +536,7 @@
     hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->calloc(1, size));
     if (hdr) {
         hdr->base = hdr;
-        hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
+        hdr->bt_depth = GET_BACKTRACE(hdr->bt, MAX_BACKTRACE_DEPTH);
         add(hdr, total_bytes);
         return user(hdr);
     }
@@ -513,6 +544,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 +564,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 +577,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 +592,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];
@@ -574,7 +624,7 @@
     hdr_t* block = head;
     log_message("+++ %s leaked block of size %d at %p (leak %d of %d)",
                 exe, block->size, user(block), index++, total);
-    if (del_leak(block, &safe)) {
+    if (del_leak(block, &safe) && g_backtrace_enabled) {
       /* safe == 1, because the allocation is valid */
       log_backtrace(block->bt, block->bt_depth);
     }
@@ -585,17 +635,31 @@
   }
 }
 
+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);
     info_log("%s: setting backlog length to %d\n", getprogname(), g_malloc_debug_backlog);
   }
 
-  backtrace_startup();
+  // Check if backtracing should be disabled.
+  char env[PROP_VALUE_MAX];
+  if (__system_property_get("libc.debug.malloc.nobacktrace", env) && atoi(env) != 0) {
+    g_backtrace_enabled = false;
+    __libc_format_log(ANDROID_LOG_INFO, "libc", "not gathering backtrace information\n");
+  }
+
+  if (g_backtrace_enabled) {
+    backtrace_startup();
+  }
+
   return true;
 }
 
@@ -604,5 +668,9 @@
   if (malloc_debug_level == 10) {
     ReportMemoryLeaks();
   }
-  backtrace_shutdown();
+  if (g_backtrace_enabled) {
+    backtrace_shutdown();
+  }
+
+  pthread_setspecific(g_debug_calls_disabled, NULL);
 }
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index be16625..0b6a142 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -81,8 +81,7 @@
 };
 
 // Selector of dispatch table to use for dispatching malloc calls.
-// TODO: fix http://b/15432753 and make this static again.
-const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
+static const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
 
 // Handle to shared library where actual memory allocation is implemented.
 // This library is loaded and memory allocation calls are redirected there
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..df0f997 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -47,7 +47,9 @@
 #include <unwind.h>
 
 #include "debug_stacktrace.h"
+#include "malloc_debug_backtrace.h"
 #include "malloc_debug_common.h"
+#include "malloc_debug_disable.h"
 
 #include "private/bionic_macros.h"
 #include "private/libc_logging.h"
@@ -267,6 +269,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 +282,7 @@
 extern "C" void* fill_valloc(size_t size) {
   return fill_memalign(getpagesize(), size);
 }
+#endif
 
 // =============================================================================
 // malloc leak functions
@@ -287,6 +291,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!
 
@@ -304,7 +312,7 @@
         ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 
         uintptr_t backtrace[BACKTRACE_SIZE];
-        size_t numEntries = get_backtrace(backtrace, BACKTRACE_SIZE);
+        size_t numEntries = GET_BACKTRACE(backtrace, BACKTRACE_SIZE);
 
         AllocationEntry* header = reinterpret_cast<AllocationEntry*>(base);
         header->entry = record_backtrace(backtrace, numEntries, bytes);
@@ -319,6 +327,10 @@
 }
 
 extern "C" void leak_free(void* mem) {
+  if (DebugCallsDisabled()) {
+    return g_malloc_dispatch->free(mem);
+  }
+
   if (mem == NULL) {
     return;
   }
@@ -355,6 +367,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) {
@@ -369,7 +385,41 @@
     return ptr;
 }
 
+extern "C" size_t leak_malloc_usable_size(const void* mem) {
+    if (DebugCallsDisabled()) {
+        return g_malloc_dispatch->malloc_usable_size(mem);
+    }
+
+    if (mem == NULL) {
+        return 0;
+    }
+
+    // Check the guard to make sure it is valid.
+    const AllocationEntry* header = const_to_header(mem);
+
+    if (header->guard == MEMALIGN_GUARD) {
+        // If this is a memalign'd pointer, then grab the header from
+        // entry.
+        header = const_to_header(header->entry);
+    } else if (header->guard != GUARD) {
+        debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
+                  header->guard, header->entry);
+        return 0;
+    }
+
+    size_t ret = g_malloc_dispatch->malloc_usable_size(header);
+    if (ret != 0) {
+        // The usable area starts at 'mem' and stops at 'header+ret'.
+        return reinterpret_cast<uintptr_t>(header) + ret - reinterpret_cast<uintptr_t>(mem);
+    }
+    return 0;
+}
+
 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);
     }
@@ -388,7 +438,7 @@
 
     newMem = leak_malloc(bytes);
     if (newMem != NULL) {
-        size_t oldSize = header->entry->size & ~SIZE_FLAG_MASK;
+        size_t oldSize = leak_malloc_usable_size(oldMem);
         size_t copySize = (oldSize <= bytes) ? oldSize : bytes;
         memcpy(newMem, oldMem, copySize);
         leak_free(oldMem);
@@ -398,6 +448,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);
@@ -438,35 +492,15 @@
     return base;
 }
 
-extern "C" size_t leak_malloc_usable_size(const void* mem) {
-    if (mem != NULL) {
-        // Check the guard to make sure it is valid.
-        const AllocationEntry* header = const_to_header((void*)mem);
-
-        if (header->guard == MEMALIGN_GUARD) {
-            // If this is a memalign'd pointer, then grab the header from
-            // entry.
-            header = const_to_header(header->entry);
-        } else if (header->guard != GUARD) {
-            debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
-                      header->guard, header->entry);
-            return 0;
-        }
-
-        size_t ret = g_malloc_dispatch->malloc_usable_size(header);
-        if (ret != 0) {
-            // The usable area starts at 'mem' and stops at 'header+ret'.
-            return reinterpret_cast<uintptr_t>(header) + ret - reinterpret_cast<uintptr_t>(mem);
-        }
-    }
-    return 0;
-}
-
 extern "C" struct mallinfo leak_mallinfo() {
   return g_malloc_dispatch->mallinfo();
 }
 
 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 +510,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 +525,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/malloc_info.cpp b/libc/bionic/malloc_info.cpp
new file mode 100644
index 0000000..99caedb
--- /dev/null
+++ b/libc/bionic/malloc_info.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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 "malloc_info.h"
+
+#include <errno.h>
+#include "private/bionic_macros.h"
+
+class __LIBC_HIDDEN__ Elem {
+public:
+  // name must be valid throughout lifetime of the object.
+  explicit Elem(FILE* fp, const char* name,
+                const char* attr_fmt = nullptr, ...) {
+    this->fp = fp;
+    this->name = name;
+
+    fprintf(fp, "<%s", name);
+    if (attr_fmt != nullptr) {
+      va_list args;
+      va_start(args, attr_fmt);
+      fputc(' ', fp);
+      vfprintf(fp, attr_fmt, args);
+      va_end(args);
+    }
+    fputc('>', fp);
+  }
+
+  ~Elem() noexcept {
+    fprintf(fp, "</%s>", name);
+  }
+
+  void contents(const char* fmt, ...) {
+      va_list args;
+      va_start(args, fmt);
+      vfprintf(fp, fmt, args);
+      va_end(args);
+  }
+
+private:
+  FILE* fp;
+  const char* name;
+
+  DISALLOW_COPY_AND_ASSIGN(Elem);
+};
+
+int malloc_info(int options, FILE* fp) {
+  if (options != 0) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  Elem root(fp, "malloc", "version=\"jemalloc-1\"");
+
+  // Dump all of the large allocations in the arenas.
+  for (size_t i = 0; i < __mallinfo_narenas(); i++) {
+    struct mallinfo mi = __mallinfo_arena_info(i);
+    if (mi.hblkhd != 0) {
+      Elem arena_elem(fp, "heap", "nr=\"%d\"", i);
+      {
+        Elem(fp, "allocated-large").contents("%zu", mi.ordblks);
+        Elem(fp, "allocated-huge").contents("%zu", mi.uordblks);
+        Elem(fp, "allocated-bins").contents("%zu", mi.fsmblks);
+
+        size_t total = 0;
+        for (size_t j = 0; j < __mallinfo_nbins(); j++) {
+          struct mallinfo mi = __mallinfo_bin_info(i, j);
+          if (mi.ordblks != 0) {
+            Elem bin_elem(fp, "bin", "nr=\"%d\"", j);
+            Elem(fp, "allocated").contents("%zu", mi.ordblks);
+            Elem(fp, "nmalloc").contents("%zu", mi.uordblks);
+            Elem(fp, "ndalloc").contents("%zu", mi.fordblks);
+            total += mi.ordblks;
+          }
+        }
+        Elem(fp, "bins-total").contents("%zu", total);
+      }
+    }
+  }
+
+  return 0;
+}
diff --git a/tests/libs/dlsym_local_symbol_private.cpp b/libc/bionic/malloc_info.h
similarity index 60%
copy from tests/libs/dlsym_local_symbol_private.cpp
copy to libc/bionic/malloc_info.h
index 2587508..5fffae9 100644
--- a/tests/libs/dlsym_local_symbol_private.cpp
+++ b/libc/bionic/malloc_info.h
@@ -14,11 +14,19 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <stdio.h>
+#ifndef LIBC_BIONIC_MALLOC_INFO_H_
+#define LIBC_BIONIC_MALLOC_INFO_H_
 
-// This symbol is declared local in
-// the linker version map: libdlsym_local_symbol.map.
-// It should not be visible from the outside.
-extern "C" const uint32_t __attribute__ ((visibility ("protected"))) private_taxicab_number = 1729;
+#include <malloc.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+__LIBC_HIDDEN__ size_t __mallinfo_narenas();
+__LIBC_HIDDEN__ size_t __mallinfo_nbins();
+__LIBC_HIDDEN__ struct mallinfo __mallinfo_arena_info(size_t);
+__LIBC_HIDDEN__ struct mallinfo __mallinfo_bin_info(size_t, size_t);
+
+__END_DECLS
+
+#endif // LIBC_BIONIC_MALLOC_INFO_H_
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index e3e640a..0c72019 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -225,6 +225,7 @@
   return syscall(__NR_tkill, tid, sig);
 }
 
+// This was removed from POSIX 2008.
 extern "C" wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) {
   return wcsstr(haystack, needle);
 }
@@ -267,7 +268,7 @@
   return r.rlim_cur;
 }
 
-// Only used by ftime, which was removed from POSIX.
+// Only used by ftime, which was removed from POSIX 2008.
 struct timeb {
   time_t          time;
   unsigned short  millitm;
diff --git a/libc/bionic/new.cpp b/libc/bionic/new.cpp
index fcfd1bd..cd84c2e 100644
--- a/libc/bionic/new.cpp
+++ b/libc/bionic/new.cpp
@@ -38,11 +38,11 @@
     return p;
 }
 
-void  operator delete(void* ptr) {
+void  operator delete(void* ptr) throw() {
     free(ptr);
 }
 
-void  operator delete[](void* ptr) {
+void  operator delete[](void* ptr) throw() {
     free(ptr);
 }
 
@@ -54,10 +54,10 @@
     return malloc(size);
 }
 
-void  operator delete(void* ptr, const std::nothrow_t&) {
+void  operator delete(void* ptr, const std::nothrow_t&) throw() {
     free(ptr);
 }
 
-void  operator delete[](void* ptr, const std::nothrow_t&) {
+void  operator delete[](void* ptr, const std::nothrow_t&) throw() {
     free(ptr);
 }
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index e1cd853..8df3bff 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -28,6 +28,13 @@
 
 #include <pthread.h>
 
+#include <inttypes.h>
+#include <stdio.h>
+#include <sys/resource.h>
+
+#include "private/bionic_string_utils.h"
+#include "private/ErrnoRestorer.h"
+#include "private/libc_logging.h"
 #include "pthread_internal.h"
 
 int pthread_attr_init(pthread_attr_t* attr) {
@@ -90,8 +97,8 @@
 }
 
 int pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stack_size) {
-  *stack_size = attr->stack_size;
-  return 0;
+  void* unused;
+  return pthread_attr_getstack(attr, &unused, stack_size);
 }
 
 int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_size) {
@@ -106,7 +113,42 @@
   return 0;
 }
 
+static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) {
+  ErrnoRestorer errno_restorer;
+
+  // It doesn't matter which thread we are; we're just looking for "[stack]".
+  FILE* fp = fopen("/proc/self/maps", "re");
+  if (fp == NULL) {
+    return errno;
+  }
+  char line[BUFSIZ];
+  while (fgets(line, sizeof(line), fp) != NULL) {
+    if (ends_with(line, " [stack]\n")) {
+      uintptr_t lo, hi;
+      if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) {
+        *stack_base = reinterpret_cast<void*>(lo);
+        *stack_size = hi - lo;
+
+        // Does our current RLIMIT_STACK mean we won't actually get everything /proc/maps promises?
+        rlimit stack_limit;
+        if (getrlimit(RLIMIT_STACK, &stack_limit) != -1) {
+          if (*stack_size > stack_limit.rlim_cur) {
+            *stack_size = stack_limit.rlim_cur;
+          }
+        }
+
+        fclose(fp);
+        return 0;
+      }
+    }
+  }
+  __libc_fatal("No [stack] line found in /proc/self/maps!");
+}
+
 int pthread_attr_getstack(const pthread_attr_t* attr, void** stack_base, size_t* stack_size) {
+  if ((attr->flags & PTHREAD_ATTR_FLAG_MAIN_THREAD) != 0) {
+    return __pthread_attr_getstack_main_thread(stack_base, stack_size);
+  }
   *stack_base = attr->stack_base;
   *stack_size = attr->stack_size;
   return 0;
@@ -122,9 +164,8 @@
   return 0;
 }
 
-int pthread_getattr_np(pthread_t thid, pthread_attr_t* attr) {
-  pthread_internal_t* thread = (pthread_internal_t*) thid;
-  *attr = thread->attr;
+int pthread_getattr_np(pthread_t t, pthread_attr_t* attr) {
+  *attr = reinterpret_cast<pthread_internal_t*>(t)->attr;
   return 0;
 }
 
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..6cd5311 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) {
@@ -112,6 +112,12 @@
   }
   pthread_mutex_unlock(&g_thread_list_lock);
 
+  // Perform a second key cleanup. When using jemalloc, a call to free from
+  // _pthread_internal_remove_locked causes the memory associated with a key
+  // to be reallocated.
+  // TODO: When b/16847284 is fixed this call can be removed.
+  pthread_key_clean_all();
+
   if (user_allocated_stack) {
     // Cleaning up this thread's stack is the creator's responsibility, not ours.
     __exit(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/pututline.c b/libc/bionic/pututline.c
index c8427f7..8cbf470 100644
--- a/libc/bionic/pututline.c
+++ b/libc/bionic/pututline.c
@@ -36,7 +36,7 @@
     struct utmp u;
     long i;
 
-    if (!(f = fopen(_PATH_UTMP, "w+")))
+    if (!(f = fopen(_PATH_UTMP, "w+e")))
         return;
 
     while (fread(&u, sizeof(struct utmp), 1, f) == 1)
@@ -55,7 +55,7 @@
 
     fclose(f);
 
-    if (!(f = fopen(_PATH_UTMP, "w+")))
+    if (!(f = fopen(_PATH_UTMP, "w+e")))
         return;
     fwrite(utmp, sizeof(struct utmp), 1, f);
 
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/sysconf.cpp b/libc/bionic/sysconf.cpp
index 8309f08..d8aac4f 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -95,7 +95,7 @@
 }
 
 static int __sysconf_nprocessors_onln() {
-  FILE* fp = fopen("/proc/stat", "r");
+  FILE* fp = fopen("/proc/stat", "re");
   if (fp == NULL) {
     return 1;
   }
@@ -118,7 +118,7 @@
 }
 
 static int __get_meminfo(const char* pattern) {
-  FILE* fp = fopen("/proc/meminfo", "r");
+  FILE* fp = fopen("/proc/meminfo", "re");
   if (fp == NULL) {
     return -1;
   }
diff --git a/libc/bionic/syslog.cpp b/libc/bionic/syslog.cpp
new file mode 100644
index 0000000..d8b8b19
--- /dev/null
+++ b/libc/bionic/syslog.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include "private/libc_logging.h"
+
+static const char* syslog_log_tag = NULL;
+static int syslog_priority_mask = 0xff;
+
+void closelog() {
+  syslog_log_tag = NULL;
+}
+
+void openlog(const char* log_tag, int /*options*/, int /*facility*/) {
+  syslog_log_tag = log_tag;
+}
+
+int setlogmask(int new_mask) {
+  int old_mask = syslog_priority_mask;
+  // 0 is used to query the current mask.
+  if (new_mask != 0) {
+    syslog_priority_mask = new_mask;
+  }
+  return old_mask;
+}
+
+void syslog(int priority, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  vsyslog(priority, fmt, args);
+  va_end(args);
+}
+
+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;
+  }
+
+  // What's our log tag?
+  const char* log_tag = syslog_log_tag;
+  if (log_tag == NULL) {
+    log_tag = getprogname();
+  }
+
+  // What's our Android log priority?
+  priority &= LOG_PRIMASK;
+  int android_log_priority;
+  if (priority <= LOG_ERR) {
+    android_log_priority = ANDROID_LOG_ERROR;
+  } else if (priority == LOG_WARNING) {
+    android_log_priority = ANDROID_LOG_WARN;
+  } else if (priority <= LOG_INFO) {
+    android_log_priority = ANDROID_LOG_INFO;
+  } else {
+    android_log_priority = ANDROID_LOG_DEBUG;
+  }
+
+  // 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/system_properties.cpp b/libc/bionic/system_properties.cpp
index a564c39..ad69cf5 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 #include <new>
+#include <stdatomic.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -45,7 +46,6 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <netinet/in.h>
-#include <unistd.h>
 
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
@@ -80,6 +80,16 @@
     uint8_t namelen;
     uint8_t reserved[3];
 
+    // TODO: The following fields should be declared as atomic_uint32_t.
+    // They should be assigned to with release semantics, instead of using
+    // explicit fences.  Unfortunately, the read accesses are generally
+    // followed by more dependent read accesses, and the dependence
+    // is assumed to enforce memory ordering.  Which it does on supported
+    // hardware.  This technically should use memory_order_consume, if
+    // that worked as intended.
+    // We should also avoid rereading these fields redundantly, since not
+    // all processor implementations ensure that multiple loads from the
+    // same field are carried out in the right order.
     volatile uint32_t prop;
 
     volatile uint32_t left;
@@ -93,7 +103,8 @@
         this->namelen = name_length;
         memcpy(this->name, name, name_length);
         this->name[name_length] = '\0';
-        ANDROID_MEMBAR_FULL();
+        ANDROID_MEMBAR_FULL();  // TODO: Instead use a release store
+                                // for subsequent pointer assignment.
     }
 
 private:
@@ -102,14 +113,15 @@
 
 struct prop_area {
     uint32_t bytes_used;
-    volatile uint32_t serial;
+    atomic_uint_least32_t serial;
     uint32_t magic;
     uint32_t version;
     uint32_t reserved[28];
     char data[0];
 
     prop_area(const uint32_t magic, const uint32_t version) :
-        serial(0), magic(magic), version(version) {
+        magic(magic), version(version) {
+        atomic_init(&serial, 0);
         memset(reserved, 0, sizeof(reserved));
         // Allocate enough space for the root node.
         bytes_used = sizeof(prop_bt);
@@ -120,7 +132,7 @@
 };
 
 struct prop_info {
-    volatile uint32_t serial;
+    atomic_uint_least32_t serial;
     char value[PROP_VALUE_MAX];
     char name[0];
 
@@ -128,10 +140,11 @@
               const uint8_t valuelen) {
         memcpy(this->name, name, namelen);
         this->name[namelen] = '\0';
-        this->serial = (valuelen << 24);
+        atomic_init(&this->serial, valuelen << 24);
         memcpy(this->value, value, valuelen);
         this->value[valuelen] = '\0';
-        ANDROID_MEMBAR_FULL();
+        ANDROID_MEMBAR_FULL();  // TODO: Instead use a release store
+                                // for subsequent point assignment.
     }
 private:
     DISALLOW_COPY_AND_ASSIGN(prop_info);
@@ -598,6 +611,14 @@
     return find_property(root_node(), name, strlen(name), NULL, 0, false);
 }
 
+// The C11 standard doesn't allow atomic loads from const fields,
+// though C++11 does.  Fudge it until standards get straightened out.
+static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s,
+                                               memory_order mo) {
+    atomic_uint_least32_t* non_const_s = const_cast<atomic_uint_least32_t*>(s);
+    return atomic_load_explicit(non_const_s, mo);
+}
+
 int __system_property_read(const prop_info *pi, char *name, char *value)
 {
     if (__predict_false(compat_mode)) {
@@ -605,11 +626,20 @@
     }
 
     while (true) {
-        uint32_t serial = __system_property_serial(pi);
+        uint32_t serial = __system_property_serial(pi); // acquire semantics
         size_t len = SERIAL_VALUE_LEN(serial);
         memcpy(value, pi->value, len + 1);
-        ANDROID_MEMBAR_FULL();
-        if (serial == pi->serial) {
+        // TODO: Fix the synchronization scheme here.
+        // There is no fully supported way to implement this kind
+        // of synchronization in C++11, since the memcpy races with
+        // updates to pi, and the data being accessed is not atomic.
+        // The following fence is unintuitive, but would be the
+        // correct one if memcpy used memory_order_relaxed atomic accesses.
+        // In practice it seems unlikely that the generated code would
+        // would be any different, so this should be OK.
+        atomic_thread_fence(memory_order_acquire);
+        if (serial ==
+                load_const_atomic(&(pi->serial), memory_order_relaxed)) {
             if (name != 0) {
                 strcpy(name, pi->name);
             }
@@ -658,14 +688,24 @@
     if (len >= PROP_VALUE_MAX)
         return -1;
 
-    pi->serial = pi->serial | 1;
-    ANDROID_MEMBAR_FULL();
+    uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
+    serial |= 1;
+    atomic_store_explicit(&pi->serial, serial, memory_order_relaxed);
+    // The memcpy call here also races.  Again pretend it
+    // used memory_order_relaxed atomics, and use the analogous
+    // counterintuitive fence.
+    atomic_thread_fence(memory_order_release);
     memcpy(pi->value, value, len + 1);
-    ANDROID_MEMBAR_FULL();
-    pi->serial = (len << 24) | ((pi->serial + 1) & 0xffffff);
+    atomic_store_explicit(
+        &pi->serial,
+        (len << 24) | ((serial + 1) & 0xffffff),
+        memory_order_release);
     __futex_wake(&pi->serial, INT32_MAX);
 
-    pa->serial++;
+    atomic_store_explicit(
+        &pa->serial,
+        atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
+        memory_order_release);
     __futex_wake(&pa->serial, INT32_MAX);
 
     return 0;
@@ -688,17 +728,25 @@
     if (!pi)
         return -1;
 
-    pa->serial++;
+    // There is only a single mutator, but we want to make sure that
+    // updates are visible to a reader waiting for the update.
+    atomic_store_explicit(
+        &pa->serial,
+        atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
+        memory_order_release);
     __futex_wake(&pa->serial, INT32_MAX);
     return 0;
 }
 
+// Wait for non-locked serial, and retrieve it with acquire semantics.
 unsigned int __system_property_serial(const prop_info *pi)
 {
-    uint32_t serial = pi->serial;
+    uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire);
     while (SERIAL_DIRTY(serial)) {
-        __futex_wait(const_cast<volatile uint32_t*>(&pi->serial), serial, NULL);
-        serial = pi->serial;
+        __futex_wait(const_cast<volatile void *>(
+                        reinterpret_cast<const void *>(&pi->serial)),
+                     serial, NULL);
+        serial = load_const_atomic(&pi->serial, memory_order_acquire);
     }
     return serial;
 }
@@ -706,12 +754,14 @@
 unsigned int __system_property_wait_any(unsigned int serial)
 {
     prop_area *pa = __system_property_area__;
+    uint32_t my_serial;
 
     do {
         __futex_wait(&pa->serial, serial, NULL);
-    } while (pa->serial == serial);
+        my_serial = atomic_load_explicit(&pa->serial, memory_order_acquire);
+    } while (my_serial == serial);
 
-    return pa->serial;
+    return my_serial;
 }
 
 const prop_info *__system_property_find_nth(unsigned n)
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/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 438ce03..524ba07 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -84,6 +84,7 @@
       if (static_cast<uint8_t>((*src)[i]) < 0x80) {
         // Fast path for plain ASCII characters.
         if ((*src)[i] == '\0') {
+          *src = nullptr;
           return reset_and_return(o, state);
         }
         r = 1;
@@ -96,6 +97,7 @@
           return reset_and_return_illegal(EILSEQ, state);
         }
         if (r == 0) {
+          *src = nullptr;
           return reset_and_return(o, state);
         }
       }
@@ -118,7 +120,8 @@
       dst[o] = (*src)[i];
       r = 1;
       if ((*src)[i] == '\0') {
-        break;
+        *src = nullptr;
+        return reset_and_return(o, state);
       }
     } else {
       r = mbrtowc(dst + o, *src + i, nmc - i, state);
diff --git a/libc/dns/gethnamaddr.c b/libc/dns/gethnamaddr.c
index 80fdcbe..cc33c61 100644
--- a/libc/dns/gethnamaddr.c
+++ b/libc/dns/gethnamaddr.c
@@ -899,7 +899,7 @@
     res_static  rs = __res_get_static();
     if (rs == NULL) return;
 	if (!rs->hostf)
-		rs->hostf = fopen(_PATH_HOSTS, "r" );
+		rs->hostf = fopen(_PATH_HOSTS, "re" );
 	else
 		rewind(rs->hostf);
 	rs->stayopen = f;
@@ -925,7 +925,7 @@
 	int af, len;
 	res_static  rs = __res_get_static();
 
-	if (!rs->hostf && !(rs->hostf = fopen(_PATH_HOSTS, "r" ))) {
+	if (!rs->hostf && !(rs->hostf = fopen(_PATH_HOSTS, "re" ))) {
 		h_errno = NETDB_INTERNAL;
 		return NULL;
 	}
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index 65fd1c1..a492318 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -2017,7 +2017,7 @@
 {
 
 	if (!*hostf)
-		*hostf = fopen(_PATH_HOSTS, "r" );
+		*hostf = fopen(_PATH_HOSTS, "re");
 	else
 		rewind(*hostf);
 }
@@ -2046,7 +2046,7 @@
 	assert(name != NULL);
 	assert(pai != NULL);
 
-	if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" )))
+	if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re")))
 		return (NULL);
  again:
 	if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
diff --git a/libc/dns/net/services.h b/libc/dns/net/services.h
index fa199d0..7f748f7 100644
--- a/libc/dns/net/services.h
+++ b/libc/dns/net/services.h
@@ -30,8 +30,8 @@
 \6tacacs\0\61u\0\
 \12re-mail-ck\0\62t\0\
 \12re-mail-ck\0\62u\0\
-\6domain\0\65t\1\12nameserver\
-\6domain\0\65u\1\12nameserver\
+\6domain\0\65t\0\
+\6domain\0\65u\0\
 \3mtp\0\71t\0\
 \11tacacs-ds\0\101t\0\
 \11tacacs-ds\0\101u\0\
@@ -44,8 +44,8 @@
 \6gopher\0\106u\0\
 \3rje\0\115t\1\6netrjs\
 \6finger\0\117t\0\
-\3www\0\120t\1\4http\
-\3www\0\120u\0\
+\4http\0\120t\1\3www\
+\4http\0\120u\0\
 \4link\0\127t\1\7ttylink\
 \10kerberos\0\130t\3\11kerberos5\4krb5\14kerberos-sec\
 \10kerberos\0\130u\3\11kerberos5\4krb5\14kerberos-sec\
@@ -138,12 +138,16 @@
 \4ldap\1\205u\0\
 \4imsp\1\226t\0\
 \4imsp\1\226u\0\
+\6svrloc\1\253t\0\
+\6svrloc\1\253u\0\
 \5https\1\273t\0\
 \5https\1\273u\0\
 \4snpp\1\274t\0\
 \4snpp\1\274u\0\
 \14microsoft-ds\1\275t\0\
 \14microsoft-ds\1\275u\0\
+\7kpasswd\1\320t\0\
+\7kpasswd\1\320u\0\
 \4saft\1\347t\0\
 \4saft\1\347u\0\
 \6isakmp\1\364t\0\
@@ -158,6 +162,8 @@
 \10npmp-gui\2\143u\1\14dqs313_execd\
 \10hmmp-ind\2\144t\1\20dqs313_intercell\
 \10hmmp-ind\2\144u\1\20dqs313_intercell\
+\4qmqp\2\164t\0\
+\4qmqp\2\164u\0\
 \3ipp\2\167t\0\
 \3ipp\2\167u\0\
 \4exec\2\0t\0\
@@ -181,8 +187,14 @@
 \4uucp\2\34t\1\5uucpd\
 \6klogin\2\37t\0\
 \6kshell\2\40t\1\5krcmd\
+\15dhcpv6-client\2\42t\0\
+\15dhcpv6-client\2\42u\0\
+\15dhcpv6-server\2\43t\0\
+\15dhcpv6-server\2\43u\0\
 \12afpovertcp\2\44t\0\
 \12afpovertcp\2\44u\0\
+\4idfp\2\45t\0\
+\4idfp\2\45u\0\
 \10remotefs\2\54t\2\12rfs_server\3rfs\
 \5nntps\2\63t\1\5snntp\
 \5nntps\2\63u\1\5snntp\
@@ -239,19 +251,33 @@
 \13sa-msg-port\6\156u\1\13old-radacct\
 \6kermit\6\161t\0\
 \6kermit\6\161u\0\
+\11groupwise\6\215t\0\
+\11groupwise\6\215u\0\
 \3l2f\6\245t\1\4l2tp\
 \3l2f\6\245u\1\4l2tp\
 \6radius\7\24t\0\
 \6radius\7\24u\0\
 \13radius-acct\7\25t\1\7radacct\
 \13radius-acct\7\25u\1\7radacct\
+\4msnp\7\107t\0\
+\4msnp\7\107u\0\
 \13unix-status\7\245t\0\
 \12log-server\7\246t\0\
 \12remoteping\7\247t\0\
+\12cisco-sccp\7\320t\0\
+\12cisco-sccp\7\320u\0\
+\6search\7\332t\1\4ndtp\
+\13pipe-server\7\332t\1\13pipe_server\
 \3nfs\10\1t\0\
 \3nfs\10\1u\0\
+\6gnunet\10\46t\0\
+\6gnunet\10\46u\0\
 \12rtcm-sc104\10\65t\0\
 \12rtcm-sc104\10\65u\0\
+\15gsigatekeeper\10\107t\0\
+\15gsigatekeeper\10\107u\0\
+\4gris\10\127t\0\
+\4gris\10\127u\0\
 \12cvspserver\11\141t\0\
 \12cvspserver\11\141u\0\
 \5venus\11\176t\0\
@@ -266,10 +292,14 @@
 \3mon\12\27u\0\
 \4dict\12\104t\0\
 \4dict\12\104u\0\
+\15f5-globalsite\12\350t\0\
+\15f5-globalsite\12\350u\0\
+\6gsiftp\12\373t\0\
+\6gsiftp\12\373u\0\
 \4gpsd\13\203t\0\
 \4gpsd\13\203u\0\
-\6gds_db\13\352t\0\
-\6gds_db\13\352u\0\
+\6gds-db\13\352t\1\6gds_db\
+\6gds-db\13\352u\1\6gds_db\
 \5icpv2\14\72t\1\3icp\
 \5icpv2\14\72u\1\3icp\
 \5mysql\14\352t\0\
@@ -282,24 +312,49 @@
 \4daap\16\151u\0\
 \3svn\16\152t\1\12subversion\
 \3svn\16\152u\1\12subversion\
+\5suucp\17\277t\0\
+\5suucp\17\277u\0\
+\6sysrqd\17\376t\0\
+\6sysrqd\17\376u\0\
+\5sieve\20\136t\0\
+\4epmd\21\21t\0\
+\4epmd\21\21u\0\
+\6remctl\21\25t\0\
+\6remctl\21\25u\0\
+\11f5-iquery\21\1t\0\
+\11f5-iquery\21\1u\0\
 \3iax\21\331t\0\
 \3iax\21\331u\0\
+\3mtn\22\123t\0\
+\3mtn\22\123u\0\
 \13radmin-port\23\43t\0\
 \13radmin-port\23\43u\0\
 \3rfe\23\212u\0\
 \3rfe\23\212t\0\
+\4mmcc\23\272t\0\
+\4mmcc\23\272u\0\
 \3sip\23\304t\0\
 \3sip\23\304u\0\
 \7sip-tls\23\305t\0\
 \7sip-tls\23\305u\0\
+\3aol\24\106t\0\
+\3aol\24\106u\0\
 \13xmpp-client\24\146t\1\15jabber-client\
 \13xmpp-client\24\146u\1\15jabber-client\
 \13xmpp-server\24\225t\1\15jabber-server\
 \13xmpp-server\24\225u\1\15jabber-server\
 \10cfengine\24\274t\0\
 \10cfengine\24\274u\0\
+\4mdns\24\351t\0\
+\4mdns\24\351u\0\
 \12postgresql\25\70t\1\10postgres\
 \12postgresql\25\70u\1\10postgres\
+\7freeciv\25\264t\1\4rptp\
+\7freeciv\25\264u\0\
+\4amqp\26\50t\0\
+\4amqp\26\50u\0\
+\3ggz\26\70t\0\
+\3ggz\26\70u\0\
 \3x11\27\160t\1\5x11-0\
 \3x11\27\160u\1\5x11-0\
 \5x11-1\27\161t\0\
@@ -320,6 +375,12 @@
 \14gnutella-svc\30\312u\0\
 \14gnutella-rtr\30\313t\0\
 \14gnutella-rtr\30\313u\0\
+\13sge-qmaster\31\54t\1\13sge_qmaster\
+\13sge-qmaster\31\54u\1\13sge_qmaster\
+\11sge-execd\31\55t\1\11sge_execd\
+\11sge-execd\31\55u\1\11sge_execd\
+\13mysql-proxy\31\56t\0\
+\13mysql-proxy\31\56u\0\
 \17afs3-fileserver\33\130t\1\3bbs\
 \17afs3-fileserver\33\130u\1\3bbs\
 \15afs3-callback\33\131t\0\
@@ -342,12 +403,21 @@
 \13afs3-rmtsys\33\141u\0\
 \14font-service\33\274t\1\3xfs\
 \14font-service\33\274u\1\3xfs\
+\10http-alt\37\220t\1\10webcache\
+\10http-alt\37\220u\0\
 \12bacula-dir\43\215t\0\
 \12bacula-dir\43\215u\0\
 \11bacula-fd\43\216t\0\
 \11bacula-fd\43\216u\0\
 \11bacula-sd\43\217t\0\
 \11bacula-sd\43\217u\0\
+\5xmms2\45\303t\0\
+\5xmms2\45\303u\0\
+\3nbd\52\71t\0\
+\14zabbix-agent\47\102t\0\
+\14zabbix-agent\47\102u\0\
+\16zabbix-trapper\47\103t\0\
+\16zabbix-trapper\47\103u\0\
 \6amanda\47\140t\0\
 \6amanda\47\140u\0\
 \3hkp\54\153t\0\
@@ -364,16 +434,17 @@
 \4bpcd\65\326u\0\
 \6vopied\65\327t\0\
 \6vopied\65\327u\0\
+\4dcap\126\155t\0\
+\7gsidcap\126\160t\0\
 \4wnn6\127\1t\0\
 \4wnn6\127\1u\0\
 \11kerberos4\2\356u\2\13kerberos-iv\3kdc\
 \11kerberos4\2\356t\2\13kerberos-iv\3kdc\
-\17kerberos_master\2\357u\0\
-\17kerberos_master\2\357t\0\
-\15passwd_server\2\360u\0\
-\10krb_prop\2\362t\2\11krb5_prop\5hprop\
+\17kerberos-master\2\357u\1\17kerberos_master\
+\17kerberos-master\2\357t\0\
+\15passwd-server\2\360u\1\15passwd_server\
+\10krb-prop\2\362t\3\10krb_prop\11krb5_prop\5hprop\
 \11krbupdate\2\370t\1\4kreg\
-\7kpasswd\2\371t\1\4kpwd\
 \4swat\3\205t\0\
 \4kpop\4\125t\0\
 \5knetd\10\5t\0\
@@ -389,9 +460,9 @@
 \10poppassd\0\152t\0\
 \10poppassd\0\152u\0\
 \5ssmtp\1\321t\1\5smtps\
-\10moira_db\3\7t\0\
-\14moira_update\3\11t\0\
-\12moira_ureg\3\13u\0\
+\10moira-db\3\7t\1\10moira_db\
+\14moira-update\3\11t\1\14moira_update\
+\12moira-ureg\3\13u\1\12moira_ureg\
 \5spamd\3\17t\0\
 \5omirr\3\50t\1\6omirrd\
 \5omirr\3\50u\1\6omirrd\
@@ -404,9 +475,7 @@
 \4xtel\5\41t\0\
 \5xtelw\5\42t\0\
 \7support\5\371t\0\
-\5sieve\7\320t\0\
 \7cfinger\7\323t\0\
-\4ndtp\7\332t\0\
 \4frox\10\111t\0\
 \10ninstall\10\146t\0\
 \10ninstall\10\146u\0\
@@ -436,9 +505,7 @@
 \7hostmon\24\353t\0\
 \7hostmon\24\353u\0\
 \5rplay\25\263u\0\
-\5rplay\25\263t\0\
-\4rptp\25\264u\0\
-\4rptp\25\264t\0\
+\4nrpe\26\42t\0\
 \4nsca\26\43t\0\
 \4mrtd\26\52t\0\
 \6bgpsim\26\53t\0\
@@ -446,14 +513,15 @@
 \11sane-port\31\246t\2\4sane\5saned\
 \4ircd\32\13t\0\
 \10zope-ftp\37\125t\0\
-\10webcache\37\220t\0\
 \6tproxy\37\221t\0\
 \7omniorb\37\230t\0\
 \7omniorb\37\230u\0\
 \20clc-build-daemon\43\36t\0\
 \6xinetd\43\212t\0\
 \13mandelspawn\44\217u\1\12mandelbrot\
+\3git\44\312t\0\
 \4zope\45\311t\0\
+\6webmin\47\20t\0\
 \7kamanda\47\141t\0\
 \7kamanda\47\141u\0\
 \11amandaidx\47\142t\0\
@@ -473,6 +541,7 @@
 \5binkp\137\352t\0\
 \3asp\152\356t\0\
 \3asp\152\356u\0\
+\6csync2\170\221t\0\
 \11dircproxy\336\250t\0\
 \5tfido\353\21t\0\
 \4fido\353\23t\0\
diff --git a/libc/dns/resolv/__dn_comp.c b/libc/dns/resolv/__dn_comp.c
deleted file mode 100644
index 93d3f19..0000000
--- a/libc/dns/resolv/__dn_comp.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*	$NetBSD: __dn_comp.c,v 1.4 2005/09/13 01:44:10 christos Exp $	*/
-
-/*
- * written by matthew green, 22/04/97.
- * public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: __dn_comp.c,v 1.4 2005/09/13 01:44:10 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#if defined(__indr_reference)
-__indr_reference(__dn_comp,dn_comp)
-#else
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#ifdef ANDROID_CHANGES
-#include "resolv_private.h"
-#else
-#include <resolv.h>
-#endif
-
-/* XXX THIS IS A MESS!  SEE <resolv.h> XXX */
-
-#undef dn_comp
-int	dn_comp(const char *, u_char *, int, u_char **, u_char **);
-
-int
-dn_comp(const char *exp_dn, u_char *comp_dn, u_char **dnptrs,
-    u_char **lastdnptr, int length)
-{
-
-	return __dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr);
-}
-
-#endif
diff --git a/libc/dns/resolv/__res_close.c b/libc/dns/resolv/__res_close.c
deleted file mode 100644
index 3af50b0..0000000
--- a/libc/dns/resolv/__res_close.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*	$NetBSD: __res_close.c,v 1.4 2005/09/13 01:44:10 christos Exp $	*/
-
-/*
- * written by matthew green, 22/04/97.
- * public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: __res_close.c,v 1.4 2005/09/13 01:44:10 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#if defined(__indr_reference)
-__indr_reference(__res_close, res_close)
-#else
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include "resolv_private.h"
-
-/* XXX THIS IS A MESS!  SEE <resolv.h> XXX */
-
-#undef res_close
-void	res_close(void);
-
-void
-res_close(void)
-{
-
-	__res_close();
-}
-
-#endif
diff --git a/libc/dns/resolv/__res_send.c b/libc/dns/resolv/__res_send.c
deleted file mode 100644
index 198b05c..0000000
--- a/libc/dns/resolv/__res_send.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*	$NetBSD: __res_send.c,v 1.4 2005/09/13 01:44:10 christos Exp $	*/
-
-/*
- * written by matthew green, 22/04/97.
- * public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: __res_send.c,v 1.4 2005/09/13 01:44:10 christos Exp $");
-#endif
-
-#if defined(__indr_reference)
-__indr_reference(__res_send, res_send)
-#else
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#ifdef ANDROID_CHANGES
-#include "resolv_private.h"
-#else
-#include <resolv.h>
-#endif
-
-/* XXX THIS IS A MESS!  SEE <resolv.h> XXX */
-
-#undef res_send
-int	res_send(const u_char *, int, u_char *, int);
-
-int
-res_send(const u_char *buf, int buflen, u_char *ans, int anssiz)
-{
-
-	return __res_send(buf, buflen, ans, anssiz);
-}
-
-#endif
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index 77a1b4d..0201aa8 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -1436,7 +1436,7 @@
     char* buf;
     int fileLen;
 
-    fp = fopen("/data/reslog.txt", "w+");
+    fp = fopen("/data/reslog.txt", "w+e");
     if (fp != NULL) {
         statep = __res_get_state();
 
diff --git a/libc/dns/resolv/res_init.c b/libc/dns/resolv/res_init.c
index ab5db13..713b6e0 100644
--- a/libc/dns/resolv/res_init.c
+++ b/libc/dns/resolv/res_init.c
@@ -289,7 +289,7 @@
 	 line[sizeof(name) - 1] == '\t'))
 
 	nserv = 0;
-	if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+	if ((fp = fopen(_PATH_RESCONF, "re")) != NULL) {
 	    /* read the config file */
 	    while (fgets(buf, sizeof(buf), fp) != NULL) {
 		/* skip comments */
diff --git a/libc/bionic/vfork.cpp b/libc/include/android/set_abort_message.h
similarity index 87%
rename from libc/bionic/vfork.cpp
rename to libc/include/android/set_abort_message.h
index b706a7f..4b3d82b 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/include/android/set_abort_message.h
@@ -26,10 +26,15 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#ifndef _SET_ABORT_MESSAGE_H
+#define _SET_ABORT_MESSAGE_H
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+void android_set_abort_message(const char* msg);
+
+__END_DECLS
+
+#endif // _SET_ABORT_MESSAGE_H
diff --git a/libc/include/arpa/inet.h b/libc/include/arpa/inet.h
index 067be1f..86265bf 100644
--- a/libc/include/arpa/inet.h
+++ b/libc/include/arpa/inet.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _ARPA_INET_H_
 #define _ARPA_INET_H_
 
@@ -34,8 +35,6 @@
 
 __BEGIN_DECLS
 
-typedef uint32_t in_addr_t;
-
 in_addr_t inet_addr(const char*);
 int inet_aton(const char*, struct in_addr*);
 in_addr_t inet_lnaof(struct in_addr);
diff --git a/libc/include/elf.h b/libc/include/elf.h
index 0975b7a..7a9485a 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -69,14 +69,15 @@
 
 #define PT_GNU_RELRO 0x6474e552
 
-#define STB_LOOS   10
-#define STB_HIOS   12
-#define STB_LOPROC 13
-#define STB_HIPROC 15
+#define STB_LOOS      10
+#define STB_HIOS      12
+#define STB_LOPROC    13
+#define STB_HIPROC    15
 
-#define STT_LOOS   10
-#define STT_HIOS   12
-#define STT_LOPROC 13
-#define STT_HIPROC 15
+#define STT_GNU_IFUNC 10
+#define STT_LOOS      10
+#define STT_HIOS      12
+#define STT_LOPROC    13
+#define STT_HIPROC    15
 
 #endif /* _ELF_H */
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 4450bb6..32557d9 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -82,9 +82,9 @@
 #if defined(__BIONIC_FORTIFY)
 
 extern int __open_2(const char*, int);
-extern int __open_real(const char*, int, ...) __asm__(__USER_LABEL_PREFIX__ "open");
+extern int __open_real(const char*, int, ...) __RENAME(open);
 extern int __openat_2(int, const char*, int);
-extern int __openat_real(int, const char*, int, ...) __asm__(__USER_LABEL_PREFIX__ "openat");
+extern int __openat_real(int, const char*, int, ...) __RENAME(openat);
 __errordecl(__creat_missing_mode, "called with O_CREAT, but missing mode");
 __errordecl(__creat_too_many_args, "too many arguments");
 
diff --git a/libc/include/features.h b/libc/include/features.h
index 343c84d..a279c7f 100644
--- a/libc/include/features.h
+++ b/libc/include/features.h
@@ -25,34 +25,11 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _FEATURES_H_
 #define _FEATURES_H_
 
-/* certain Linux-specific programs expect a <features.h> header file
- * that defines various features macros
- */
-
-/* we do include a number of BSD extensions */
-#define  _BSD_SOURCE  1
-
-/* we do include a number of GNU extensions */
-#define  _GNU_SOURCE  1
-
-/* C95 support */
-#undef __USE_ISOC95
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199409L
-# define __USE_ISOC95   1
-#endif
-
-/* C99 support */
-#undef __USE_ISOC99
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
-# define __USE_ISOC99   1
-#endif
-
-/* Posix support */
-#define  __USE_POSIX   1
-#define  __USE_POSIX2  1
-#define  __USE_XPG     1
+/* Our <features.h> macro fun is all in <sys/cdefs.h>. */
+#include <sys/cdefs.h>
 
 #endif /* _FEATURES_H_ */
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/libgen.h b/libc/include/libgen.h
index c5fc76a..4caf8b9 100644
--- a/libc/include/libgen.h
+++ b/libc/include/libgen.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _LIBGEN_H
 #define _LIBGEN_H
 
@@ -33,9 +34,18 @@
 
 __BEGIN_DECLS
 
+#if !defined(__bionic_using_gnu_basename)
+/*
+ * <string.h> gets you the GNU basename.
+ * <libgen.h> the POSIX one.
+ * Note that our "POSIX" one has the wrong argument cv-qualifiers.
+ */
+extern char* basename(const char*);
+#define __bionic_using_posix_basename
+#endif
+
 /* our version of dirname/basename don't modify the input path */
 extern char*  dirname (const char*  path);
-extern char*  basename(const char*  path);
 
 /* special thread-safe Bionic versions
  *
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index e6ea276..cb1dd3b 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -24,6 +24,7 @@
  */
 #include <sys/cdefs.h>
 #include <stddef.h>
+#include <stdio.h>
 
 __BEGIN_DECLS
 
@@ -53,6 +54,27 @@
 
 extern struct mallinfo mallinfo(void);
 
+/*
+ * XML structure for malloc_info(3) is in the following format:
+ *
+ * <malloc version="jemalloc-1">
+ *   <heap nr="INT">
+ *     <allocated-large>INT</allocated-large>
+ *     <allocated-huge>INT</allocated-huge>
+ *     <allocated-bins>INT</allocated-bins>
+ *     <bins-total>INT</bins-total>
+ *     <bin nr="INT">
+ *       <allocated>INT</allocated>
+ *       <nmalloc>INT</nmalloc>
+ *       <ndalloc>INT</ndalloc>
+ *     </bin>
+ *     <!-- more bins -->
+ *   </heap>
+ *   <!-- more heaps -->
+ * </malloc>
+ */
+extern int malloc_info(int, FILE *);
+
 __END_DECLS
 
 #endif  /* LIBC_INCLUDE_MALLOC_H_ */
diff --git a/libc/include/netinet/in.h b/libc/include/netinet/in.h
index bf3b498..44c7fc1 100644
--- a/libc/include/netinet/in.h
+++ b/libc/include/netinet/in.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _NETINET_IN_H_
 #define _NETINET_IN_H_
 
@@ -43,6 +44,9 @@
 
 #define INET_ADDRSTRLEN 16
 
+typedef uint16_t in_port_t;
+typedef uint32_t in_addr_t;
+
 extern int bindresvport (int sd, struct sockaddr_in *sin);
 
 static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
diff --git a/libc/include/sched.h b/libc/include/sched.h
index e43b6cc..6155ab7 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -52,7 +52,7 @@
 extern int sched_getparam(pid_t, struct sched_param*);
 extern int sched_rr_get_interval(pid_t, struct timespec*);
 
-#ifdef _GNU_SOURCE
+#if defined(__USE_GNU)
 
 extern int clone(int (*)(void*), void*, int, void*, ...);
 extern int unshare(int);
@@ -146,7 +146,7 @@
 
 extern int __sched_cpucount(size_t setsize, cpu_set_t* set);
 
-#endif /* _GNU_SOURCE */
+#endif /* __USE_GNU */
 
 __END_DECLS
 
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/stdatomic.h b/libc/include/stdatomic.h
index 669cefd..adf60bb 100644
--- a/libc/include/stdatomic.h
+++ b/libc/include/stdatomic.h
@@ -31,9 +31,104 @@
 #define	_STDATOMIC_H_
 
 #include <sys/cdefs.h>
+
+#if defined(__cplusplus) && defined(_USING_LIBCXX) && \
+    (__has_feature(cxx_atomic) || _GNUC_VER >= 407)
+
+/* We have a usable C++ <atomic>; use it instead.  */
+
+#include <atomic>
+
+#define _Atomic(t) std::atomic<t>
+
+using std::atomic_is_lock_free;
+using std::atomic_init;
+using std::atomic_store;
+using std::atomic_store_explicit;
+using std::atomic_load;
+using std::atomic_load_explicit;
+using std::atomic_exchange;
+using std::atomic_exchange_explicit;
+using std::atomic_compare_exchange_strong;
+using std::atomic_compare_exchange_strong_explicit;
+using std::atomic_compare_exchange_weak;
+using std::atomic_compare_exchange_weak_explicit;
+using std::atomic_fetch_add;
+using std::atomic_fetch_add_explicit;
+using std::atomic_fetch_sub;
+using std::atomic_fetch_sub_explicit;
+using std::atomic_fetch_or;
+using std::atomic_fetch_or_explicit;
+using std::atomic_fetch_xor;
+using std::atomic_fetch_xor_explicit;
+using std::atomic_fetch_and;
+using std::atomic_fetch_and_explicit;
+using std::atomic_thread_fence;
+using std::atomic_signal_fence;
+
+using std::memory_order;
+using std::memory_order_relaxed;
+using std::memory_order_consume;
+using std::memory_order_release;
+using std::memory_order_acq_rel;
+using std::memory_order_seq_cst;
+
+using std::atomic_bool;
+using std::atomic_char;
+using std::atomic_schar;
+using std::atomic_uchar;
+using std::atomic_short;
+using std::atomic_ushort;
+using std::atomic_int;
+using std::atomic_uint;
+using std::atomic_long;
+using std::atomic_ulong;
+using std::atomic_llong;
+using std::atomic_ullong;
+using std::atomic_char16_t;
+using std::atomic_char32_t;
+using std::atomic_wchar_t;
+using std::atomic_int_least8_t;
+using std::atomic_uint_least8_t;
+using std::atomic_int_least16_t;
+using std::atomic_uint_least16_t;
+using std::atomic_int_least32_t;
+using std::atomic_uint_least32_t;
+using std::atomic_int_least64_t;
+using std::atomic_uint_least64_t;
+using std::atomic_int_fast8_t;
+using std::atomic_uint_fast8_t;
+using std::atomic_int_fast16_t;
+using std::atomic_uint_fast16_t;
+using std::atomic_int_fast32_t;
+using std::atomic_uint_fast32_t;
+using std::atomic_int_fast64_t;
+using std::atomic_uint_fast64_t;
+using std::atomic_intptr_t;
+using std::atomic_uintptr_t;
+using std::atomic_size_t;
+using std::atomic_ptrdiff_t;
+using std::atomic_intmax_t;
+using std::atomic_uintmax_t;
+
+#else /* <atomic> unavailable, possibly because this is C, not C++ */
+
 #include <sys/types.h>
 #include <stdbool.h>
 
+/*
+ * C: Do it ourselves.
+ * Note that the runtime representation defined here should be compatible
+ * with the C++ one, i.e. an _Atomic(T) needs to contain the same
+ * bits as a T.
+ */
+
+#include <stddef.h>  /* For ptrdiff_t.                          */
+#include <stdint.h>  /* TODO: Should pollute namespace less.    */
+#if __STDC_VERSION__ >= 201112L
+# include <uchar.h>  /* For char16_t and char32_t.              */
+#endif
+
 #if __has_extension(c_atomic) || __has_extension(cxx_atomic)
 #define	__CLANG_ATOMICS
 #elif __GNUC_PREREQ__(4, 7)
@@ -121,6 +216,8 @@
  *
  * The memory_order_* constants that denote the barrier behaviour of the
  * atomic operations.
+ * The enum values must be identical to those used by the
+ * C++ <atomic> header.
  */
 
 typedef enum {
@@ -137,7 +234,7 @@
  */
 
 static __inline void
-atomic_thread_fence(memory_order __order __unused)
+atomic_thread_fence(memory_order __order __attribute__((unused)))
 {
 
 #ifdef __CLANG_ATOMICS
@@ -150,7 +247,7 @@
 }
 
 static __inline void
-atomic_signal_fence(memory_order __order __unused)
+atomic_signal_fence(memory_order __order __attribute__((unused)))
 {
 
 #ifdef __CLANG_ATOMICS
@@ -172,7 +269,7 @@
 	((void)(obj), (_Bool)1)
 #elif defined(__CLANG_ATOMICS)
 #define	atomic_is_lock_free(obj) \
-	__atomic_is_lock_free(sizeof(*(obj)), obj)
+	__c11_atomic_is_lock_free(sizeof(*(obj)))
 #elif defined(__GNUC_ATOMICS)
 #define	atomic_is_lock_free(obj) \
 	__atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val)
@@ -386,7 +483,7 @@
 	atomic_bool	__flag;
 } atomic_flag;
 
-#define	ATOMIC_FLAG_INIT		{ ATOMIC_VAR_INIT(0) }
+#define	ATOMIC_FLAG_INIT		{ ATOMIC_VAR_INIT(false) }
 
 static __inline bool
 atomic_flag_test_and_set_explicit(volatile atomic_flag *__object,
@@ -419,4 +516,6 @@
 }
 #endif /* !_KERNEL */
 
+#endif /* <atomic> unavailable */
+
 #endif /* !_STDATOMIC_H_ */
diff --git a/libc/include/stdint.h b/libc/include/stdint.h
index f34843c..a6f8505 100644
--- a/libc/include/stdint.h
+++ b/libc/include/stdint.h
@@ -203,7 +203,7 @@
 
 #if defined(__WINT_UNSIGNED__)
 #  define WINT_MAX       UINT32_MAX
-#  define WINT_MIN       UINT32_MIN
+#  define WINT_MIN       0
 #else
 #  define WINT_MAX       INT32_MAX
 #  define WINT_MIN       INT32_MIN
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index e532de4..ce60fd7 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -38,6 +38,14 @@
 #ifndef	_STDIO_H_
 #define	_STDIO_H_
 
+/*
+ * This file must contain a reference to __gnuc_va_list so that GCC's
+ * fixincludes knows that that's what's being used for va_list, and so
+ * to leave our <stdio.h> alone. (fixincludes gets in the way of pointing
+ * one toolchain at various different sets of platform headers.)
+ * If you alter this comment, be sure to keep "__gnuc_va_list" in it!
+ */
+
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
@@ -223,12 +231,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 +302,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 *);
 
@@ -326,6 +325,11 @@
 int	 putchar_unlocked(int);
 #endif /* __POSIX_VISIBLE >= 199506 */
 
+#if __POSIX_VISIBLE >= 200809
+FILE* fmemopen(void*, size_t, const char*);
+FILE* open_memstream(char**, size_t*);
+#endif /* __POSIX_VISIBLE >= 200809 */
+
 __END_DECLS
 
 #endif /* __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE */
@@ -344,6 +348,11 @@
 int	 vasprintf(char ** __restrict, const char * __restrict,
     __va_list)
 		__printflike(2, 0);
+
+void clearerr_unlocked(FILE*);
+int feof_unlocked(FILE*);
+int ferror_unlocked(FILE*);
+
 __END_DECLS
 
 /*
@@ -409,7 +418,7 @@
 #endif
 
 extern char* __fgets_chk(char*, int, FILE*, size_t);
-extern char* __fgets_real(char*, int, FILE*) __asm__(__USER_LABEL_PREFIX__ "fgets");
+extern char* __fgets_real(char*, int, FILE*) __RENAME(fgets);
 __errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
 __errordecl(__fgets_too_small_error, "fgets called with size less than zero");
 
diff --git a/libc/bionic/vfork.cpp b/libc/include/stdio_ext.h
similarity index 74%
copy from libc/bionic/vfork.cpp
copy to libc/include/stdio_ext.h
index b706a7f..f299e54 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/include/stdio_ext.h
@@ -26,10 +26,29 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#ifndef _STDIO_EXT_H
+#define _STDIO_EXT_H
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+#include <sys/cdefs.h>
+#include <stdio.h>
+
+#define FSETLOCKING_QUERY 0
+#define FSETLOCKING_INTERNAL 1
+#define FSETLOCKING_BYCALLER 2
+
+__BEGIN_DECLS
+
+size_t __fbufsize(FILE*);
+int __freading(FILE*);
+int __fwriting(FILE*);
+int __freadable(FILE*);
+int __fwritable(FILE*);
+int __flbf(FILE*);
+void __fpurge(FILE*);
+size_t __fpending(FILE*);
+void _flushlbf(void);
+int __fsetlocking(FILE*, int);
+
+__END_DECLS
+
+#endif /* _STDIO_EXT_H */
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 0dac650..52f71dd 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -111,12 +111,6 @@
 
 #define RAND_MAX 0x7fffffff
 
-/* Work around x86/x86-64 libvpx build breakage caused by postproc_x86.c. */
-#if (defined(__i386__) || defined(__x86_64__)) && defined(rand)
-#undef rand
-#define __rand lrand48
-#endif
-
 int rand(void);
 int rand_r(unsigned int*);
 void srand(unsigned int);
@@ -126,18 +120,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;
@@ -173,11 +161,8 @@
 extern int	wctomb(char *, wchar_t);
 extern size_t	wcstombs(char *, const wchar_t *, size_t);
 
-#define MB_CUR_MAX 4U
-
-#if 0 /* MISSING FROM BIONIC */
-extern int on_exit(void (*)(int, void *), void *);
-#endif /* MISSING */
+extern size_t __ctype_get_mb_cur_max(void);
+#define MB_CUR_MAX __ctype_get_mb_cur_max()
 
 __END_DECLS
 
diff --git a/libc/include/string.h b/libc/include/string.h
index af1c0c1..0a1d653 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -25,8 +25,9 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef _STRING_H_
-#define _STRING_H_
+
+#ifndef _STRING_H
+#define _STRING_H
 
 #include <sys/cdefs.h>
 #include <stddef.h>
@@ -92,10 +93,21 @@
 extern int    strcoll_l(const char *, const char *, locale_t) __purefunc;
 extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t);
 
-#if defined(__BIONIC_FORTIFY)
+#if defined(__USE_GNU) && !defined(__bionic_using_posix_basename)
+/*
+ * glibc has a basename in <string.h> that's different to the POSIX one in <libgen.h>.
+ * It doesn't modify its argument, and in C++ it's const-correct.
+ */
+#if defined(__cplusplus)
+extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1));
+extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
+#else
+extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
+#endif
+#define __bionic_using_gnu_basename
+#endif
 
-__errordecl(__memcpy_dest_size_error, "memcpy: prevented write past end of buffer");
-__errordecl(__memcpy_src_size_error, "memcpy: prevented read past end of buffer");
+#if defined(__BIONIC_FORTIFY)
 
 __BIONIC_FORTIFY_INLINE
 void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amount) {
@@ -104,14 +116,6 @@
     size_t s_len = __bos0(s);
     size_t d_len = __bos0(d);
 
-    if (__builtin_constant_p(copy_amount) && (copy_amount > d_len)) {
-        __memcpy_dest_size_error();
-    }
-
-    if (__builtin_constant_p(copy_amount) && (copy_amount > s_len)) {
-        __memcpy_src_size_error();
-    }
-
     return __builtin___memcpy_chk(dest, src, copy_amount, d_len);
 }
 
@@ -130,16 +134,12 @@
     return __builtin___strcpy_chk(dest, src, __bos(dest));
 }
 
-__errordecl(__stpncpy_error, "stpncpy: prevented write past end of buffer");
 extern char* __stpncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t);
 
 __BIONIC_FORTIFY_INLINE
 char* stpncpy(char* __restrict dest, const char* __restrict src, size_t n) {
     size_t bos_dest = __bos(dest);
     size_t bos_src = __bos(src);
-    if (__builtin_constant_p(n) && (n > bos_dest)) {
-        __stpncpy_error();
-    }
 
     if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __builtin___stpncpy_chk(dest, src, n, bos_dest);
@@ -157,16 +157,12 @@
     return __stpncpy_chk2(dest, src, n, bos_dest, bos_src);
 }
 
-__errordecl(__strncpy_error, "strncpy: prevented write past end of buffer");
 extern char* __strncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t);
 
 __BIONIC_FORTIFY_INLINE
 char* strncpy(char* __restrict dest, const char* __restrict src, size_t n) {
     size_t bos_dest = __bos(dest);
     size_t bos_src = __bos(src);
-    if (__builtin_constant_p(n) && (n > bos_dest)) {
-        __strncpy_error();
-    }
 
     if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __builtin___strncpy_chk(dest, src, n, bos_dest);
@@ -199,9 +195,7 @@
     return __builtin___memset_chk(s, c, n, __bos0(s));
 }
 
-extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t)
-    __asm__(__USER_LABEL_PREFIX__ "strlcpy");
-__errordecl(__strlcpy_error, "strlcpy: prevented write past end of buffer");
+extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t) __RENAME(strlcpy);
 extern size_t __strlcpy_chk(char *, const char *, size_t, size_t);
 
 __BIONIC_FORTIFY_INLINE
@@ -219,20 +213,12 @@
     if (__builtin_constant_p(size) && (size <= bos)) {
         return __strlcpy_real(dest, src, size);
     }
-
-    // Compiler can prove, at compile time, that the passed in size
-    // is always > the actual object size. Force a compiler error.
-    if (__builtin_constant_p(size) && (size > bos)) {
-        __strlcpy_error();
-    }
 #endif /* !defined(__clang__) */
 
     return __strlcpy_chk(dest, src, size, bos);
 }
 
-extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t)
-    __asm__(__USER_LABEL_PREFIX__ "strlcat");
-__errordecl(__strlcat_error, "strlcat: prevented write past end of buffer");
+extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t) __RENAME(strlcat);
 extern size_t __strlcat_chk(char* __restrict, const char* __restrict, size_t, size_t);
 
 
@@ -251,12 +237,6 @@
     if (__builtin_constant_p(size) && (size <= bos)) {
         return __strlcat_real(dest, src, size);
     }
-
-    // Compiler can prove, at compile time, that the passed in size
-    // is always > the actual object size. Force a compiler error.
-    if (__builtin_constant_p(size) && (size > bos)) {
-        __strlcat_error();
-    }
 #endif /* !defined(__clang__) */
 
     return __strlcat_chk(dest, src, size, bos);
@@ -324,4 +304,4 @@
 
 __END_DECLS
 
-#endif /* _STRING_H_ */
+#endif /* _STRING_H */
diff --git a/libc/include/sys/cachectl.h b/libc/include/sys/cachectl.h
index 57e6ae7..a302ff8 100644
--- a/libc/include/sys/cachectl.h
+++ b/libc/include/sys/cachectl.h
@@ -31,6 +31,5 @@
 #ifdef __mips__
 #include <asm/cachectl.h>
 extern int __cachectl (void *addr, __const int nbytes, __const int op);
-extern int _flush_cache (char *addr, __const int nbytes, __const int op);
 #endif
 #endif /* sys/cachectl.h */
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 0286616..79d8bca 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -267,20 +267,6 @@
 #endif /* NO_KERNEL_RCSIDS */
 #endif /* _KERNEL */
 
-#if !defined(_STANDALONE) && !defined(_KERNEL)
-#ifdef __GNUC__
-#define	__RENAME(x)	___RENAME(x)
-#else
-#ifdef __lint__
-#define	__RENAME(x)	__symbolrename(x)
-#else
-#error "No function renaming possible"
-#endif /* __lint__ */
-#endif /* __GNUC__ */
-#else /* _STANDALONE || _KERNEL */
-#define	__RENAME(x)	no renaming in kernel or standalone environment
-#endif
-
 /*
  * A barrier to stop the optimizer from moving code or assume live
  * register values. This is gcc specific, the version is more or less
@@ -359,64 +345,33 @@
 #endif
 
 /*
- * Macros for manipulating "link sets".  Link sets are arrays of pointers
- * to objects, which are gathered up by the linker.
- *
- * Object format-specific code has provided us with the following macros:
- *
- *	__link_set_add_text(set, sym)
- *		Add a reference to the .text symbol `sym' to `set'.
- *
- *	__link_set_add_rodata(set, sym)
- *		Add a reference to the .rodata symbol `sym' to `set'.
- *
- *	__link_set_add_data(set, sym)
- *		Add a reference to the .data symbol `sym' to `set'.
- *
- *	__link_set_add_bss(set, sym)
- *		Add a reference to the .bss symbol `sym' to `set'.
- *
- *	__link_set_decl(set, ptype)
- *		Provide an extern declaration of the set `set', which
- *		contains an array of the pointer type `ptype'.  This
- *		macro must be used by any code which wishes to reference
- *		the elements of a link set.
- *
- *	__link_set_start(set)
- *		This points to the first slot in the link set.
- *
- *	__link_set_end(set)
- *		This points to the (non-existent) slot after the last
- *		entry in the link set.
- *
- *	__link_set_count(set)
- *		Count the number of entries in link set `set'.
- *
- * In addition, we provide the following macros for accessing link sets:
- *
- *	__link_set_foreach(pvar, set)
- *		Iterate over the link set `set'.  Because a link set is
- *		an array of pointers, pvar must be declared as "type **pvar",
- *		and the actual entry accessed as "*pvar".
- *
- *	__link_set_entry(set, idx)
- *		Access the link set entry at index `idx' from set `set'.
+ * Some BSD source needs these macros.
+ * Originally they embedded the rcs versions of each source file
+ * in the generated binary. We strip strings during build anyway,.
  */
-#define	__link_set_foreach(pvar, set)					\
-	for (pvar = __link_set_start(set); pvar < __link_set_end(set); pvar++)
-
-#define	__link_set_entry(set, idx)	(__link_set_begin(set)[idx])
+#define __IDSTRING(_prefix,_s) /* nothing */
+#define __COPYRIGHT(_s) /* nothing */
+#define __FBSDID(_s) /* nothing */
+#define __RCSID(_s) /* nothing */
+#define __SCCSID(_s) /* nothing */
 
 /*
- * Some of the FreeBSD sources used in Bionic need this.
- * Originally, this is used to embed the rcs versions of each source file
- * in the generated binary. We certainly don't want this in Bionic.
+ * _BSD_SOURCE and _GNU_SOURCE are expected to be defined by callers before
+ * any standard header file is included. In those header files we test
+ * against __USE_BSD and __USE_GNU. glibc does this in <features.h> but we
+ * do it in <sys/cdefs.h> instead because that's where our existing
+ * _POSIX_C_SOURCE tests were, and we're already confident that <sys/cdefs.h>
+ * is included everywhere it should be.
  */
-#define __FBSDID(s) /* nothing */
+#if defined(_BSD_SOURCE)
+# define __USE_BSD 1
+#endif
+
+#if defined(_GNU_SOURCE)
+# define __USE_GNU 1
+#endif
 
 /*-
- * The following definitions are an extension of the behavior originally
- * implemented in <sys/_posix.h>, but with a different level of granularity.
  * POSIX.1 requires that the macros we test be defined before any standard
  * header file is included.
  *
@@ -570,11 +525,24 @@
 #endif
 #define __bos0(s) __builtin_object_size((s), 0)
 
-#define __BIONIC_FORTIFY_INLINE \
-    extern __inline__ \
-    __attribute__ ((always_inline)) \
-    __attribute__ ((gnu_inline))
+#define __BIONIC_FORTIFY_INLINE extern __inline__ __always_inline __attribute__((gnu_inline))
 #endif
 #define __BIONIC_FORTIFY_UNKNOWN_SIZE ((size_t) -1)
 
+/* Used to tag non-static symbols that are private and never exposed by the shared library. */
+#define __LIBC_HIDDEN__ __attribute__((visibility("hidden")))
+
+/* Like __LIBC_HIDDEN__, but preserves binary compatibility for LP32. */
+#ifdef __LP64__
+#define __LIBC64_HIDDEN__ __LIBC_HIDDEN__
+#else
+#define __LIBC64_HIDDEN__ __LIBC_ABI_PUBLIC__
+#endif
+
+/* Used to tag non-static symbols that are public and exposed by the shared library. */
+#define __LIBC_ABI_PUBLIC__ __attribute__((visibility ("default")))
+
+/* Used to rename functions so that the compiler emits a call to 'x' rather than the function this was applied to. */
+#define __RENAME(x) __asm__(#x)
+
 #endif /* !_SYS_CDEFS_H_ */
diff --git a/libc/include/sys/cdefs_elf.h b/libc/include/sys/cdefs_elf.h
index b5db13e..6bb0a57 100644
--- a/libc/include/sys/cdefs_elf.h
+++ b/libc/include/sys/cdefs_elf.h
@@ -30,27 +30,13 @@
 #ifndef _SYS_CDEFS_ELF_H_
 #define	_SYS_CDEFS_ELF_H_
 
-#ifdef __LEADING_UNDERSCORE
-#define	_C_LABEL(x)	__CONCAT(_,x)
-#define _C_LABEL_STRING(x)	"_"x
-#else
-#define	_C_LABEL(x)	x
-#define _C_LABEL_STRING(x)	x
-#endif
+#define __strong_alias(alias, sym) \
+    __asm__(".global " #alias "\n" \
+            #alias " = " #sym);
 
-#define	___RENAME(x)	__asm__(___STRING(_C_LABEL(x)))
-
-#define	__indr_reference(sym,alias)	/* nada, since we do weak refs */
-
-#define	__strong_alias(alias,sym)	       				\
-    __asm__(".global " _C_LABEL_STRING(#alias) "\n"			\
-	    _C_LABEL_STRING(#alias) " = " _C_LABEL_STRING(#sym));
-
-#define	__weak_alias(alias,sym)						\
-    __asm__(".weak " _C_LABEL_STRING(#alias) "\n"			\
-	    _C_LABEL_STRING(#alias) " = " _C_LABEL_STRING(#sym));
-#define	__weak_extern(sym)						\
-    __asm__(".weak " _C_LABEL_STRING(#sym));
+#define __weak_alias(alias,sym) \
+    __asm__(".weak " #alias "\n" \
+            #alias " = " #sym);
 
 /* We use __warnattr instead of __warn_references.
  * TODO: remove this and put an empty definition in one of the upstream-* compatibility headers.
@@ -58,74 +44,4 @@
 #define	__warn_references(sym,msg)					\
     /*__asm__(".section .gnu.warning." #sym "\n\t.ascii \"" msg "\"\n\t.text");*/
 
-#define	__SECTIONSTRING(_sec, _str)					\
-	__asm__(".section " #_sec "\n\t.asciz \"" _str "\"\n\t.previous")
-
-/* Used to tag non-static symbols that are private and never exposed by the shared library. */
-#define __LIBC_HIDDEN__ __attribute__((visibility ("hidden")))
-
-/* Like __LIBC_HIDDEN__, but preserves binary compatibility for LP32. */
-#ifdef __LP64__
-#define __LIBC64_HIDDEN__ __LIBC_HIDDEN__
-#else
-#define __LIBC64_HIDDEN__
-#endif
-
-/* Used to tag non-static symbols that are public and exposed by the shared library. */
-#define __LIBC_ABI_PUBLIC__ __attribute__((visibility ("default")))
-
-#define	__IDSTRING(_n,_s)		__SECTIONSTRING(.ident,_s)
-
-#define	__RCSID(_s)			__IDSTRING(rcsid,_s)
-#define	__SCCSID(_s)
-#define __SCCSID2(_s)
-#if 0	/* XXX userland __COPYRIGHTs have \ns in them */
-#define	__COPYRIGHT(_s)			__SECTIONSTRING(.copyright,_s)
-#else
-#define	__COPYRIGHT(_s)							\
-	static const char copyright[]					\
-	    __attribute__((__unused__,__section__(".copyright"))) = _s
-#endif
-
-#define	__KERNEL_RCSID(_n, _s)		__RCSID(_s)
-#define	__KERNEL_SCCSID(_n, _s)
-#if 0	/* XXX see above */
-#define	__KERNEL_COPYRIGHT(_n, _s)	__COPYRIGHT(_s)
-#else
-#define	__KERNEL_COPYRIGHT(_n, _s)	__SECTIONSTRING(.copyright, _s)
-#endif
-
-#ifndef __lint__
-#define	__link_set_make_entry(set, sym)					\
-	static void const * const __link_set_##set##_sym_##sym		\
-	    __section("link_set_" #set) __used = &sym
-#define	__link_set_make_entry2(set, sym, n)				\
-	static void const * const __link_set_##set##_sym_##sym##_##n	\
-	    __section("link_set_" #set) __used = &sym[n]
-#else
-#define	__link_set_make_entry(set, sym)					\
-	extern void const * const __link_set_##set##_sym_##sym
-#define	__link_set_make_entry2(set, sym, n)				\
-	extern void const * const __link_set_##set##_sym_##sym##_##n
-#endif /* __lint__ */
-
-#define	__link_set_add_text(set, sym)	__link_set_make_entry(set, sym)
-#define	__link_set_add_rodata(set, sym)	__link_set_make_entry(set, sym)
-#define	__link_set_add_data(set, sym)	__link_set_make_entry(set, sym)
-#define	__link_set_add_bss(set, sym)	__link_set_make_entry(set, sym)
-#define	__link_set_add_text2(set, sym, n)   __link_set_make_entry2(set, sym, n)
-#define	__link_set_add_rodata2(set, sym, n) __link_set_make_entry2(set, sym, n)
-#define	__link_set_add_data2(set, sym, n)   __link_set_make_entry2(set, sym, n)
-#define	__link_set_add_bss2(set, sym, n)    __link_set_make_entry2(set, sym, n)
-
-#define	__link_set_decl(set, ptype)					\
-	extern ptype * const __start_link_set_##set[];			\
-	extern ptype * const __stop_link_set_##set[]			\
-
-#define	__link_set_start(set)	(__start_link_set_##set)
-#define	__link_set_end(set)	(__stop_link_set_##set)
-
-#define	__link_set_count(set)						\
-	(__link_set_end(set) - __link_set_start(set))
-
 #endif /* !_SYS_CDEFS_ELF_H_ */
diff --git a/libc/include/sys/fsuid.h b/libc/include/sys/fsuid.h
index bc47e3d..03355b7 100644
--- a/libc/include/sys/fsuid.h
+++ b/libc/include/sys/fsuid.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _SYS_FSUID_H_
 #define _SYS_FSUID_H_
 
@@ -33,10 +34,8 @@
 
 __BEGIN_DECLS
 
-#if 0 /* MISSING FROM BIONIC */
 extern int setfsuid(uid_t);
 extern int setfsgid(gid_t);
-#endif /* MISSING */
 
 __END_DECLS
 
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index ae2f238..a8840ff 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -294,8 +294,7 @@
 #if defined(__BIONIC_FORTIFY)
 __errordecl(__recvfrom_error, "recvfrom called with size bigger than buffer");
 extern ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, const struct sockaddr*, socklen_t*);
-extern ssize_t __recvfrom_real(int, void*, size_t, int, const struct sockaddr*, socklen_t*)
-    __asm__(__USER_LABEL_PREFIX__ "recvfrom");
+extern ssize_t __recvfrom_real(int, void*, size_t, int, const struct sockaddr*, socklen_t*) __RENAME(recvfrom);
 
 __BIONIC_FORTIFY_INLINE
 ssize_t recvfrom(int fd, void* buf, size_t len, int flags, const struct sockaddr* src_addr, socklen_t* addr_len) {
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index c0c168b..b56ffa4 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _SYS_STAT_H_
 #define _SYS_STAT_H_
 
@@ -162,7 +163,7 @@
 #if defined(__BIONIC_FORTIFY)
 
 extern mode_t __umask_chk(mode_t);
-extern mode_t __umask_real(mode_t) __asm__(__USER_LABEL_PREFIX__ "umask");
+extern mode_t __umask_real(mode_t) __RENAME(umask);
 __errordecl(__umask_invalid_mode, "umask called with invalid mode");
 
 __BIONIC_FORTIFY_INLINE
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 a52e811..cbceab2 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -35,59 +35,60 @@
 
 __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)
 
-#define LOG_PID    0x01    /* include pid with message */
-#define LOG_CONS   0x02    /* write to console on logger error */
-#define LOG_ODELAY 0x04    /* delay connection until syslog() */
-#define LOG_NDELAY 0x08    /* open connection immediately */
-#define LOG_NOWAIT 0x10    /* wait for child processes (unused on linux) */
-#define LOG_PERROR 0x20    /* additional logging to stderr */
+/* openlog(3) flags are currently ignored on Android. */
+#define LOG_PID    0x01
+#define LOG_CONS   0x02
+#define LOG_ODELAY 0x04
+#define LOG_NDELAY 0x08
+#define LOG_NOWAIT 0x10
+#define LOG_PERROR 0x20
 
-#define _PATH_LOG  "/dev/syslog"
-
-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..34ae2bc 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _UNISTD_H_
 #define _UNISTD_H_
 
@@ -112,7 +113,7 @@
 extern int fchdir(int);
 extern int rmdir(const char *);
 extern int pipe(int *);
-#ifdef _GNU_SOURCE
+#if defined(__USE_GNU)
 extern int pipe2(int *, int);
 #endif
 extern int chroot(const char *);
@@ -143,7 +144,7 @@
 
 extern int dup(int);
 extern int dup2(int, int);
-#ifdef _GNU_SOURCE
+#if defined(__USE_GNU)
 extern int dup3(int, int, int);
 #endif
 extern int fcntl(int, int, ...);
@@ -170,7 +171,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 +190,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;                   \
@@ -211,8 +202,7 @@
 extern ssize_t __read_chk(int, void*, size_t, size_t);
 __errordecl(__read_dest_size_error, "read called with size bigger than destination");
 __errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
-extern ssize_t __read_real(int, void*, size_t)
-    __asm__(__USER_LABEL_PREFIX__ "read");
+extern ssize_t __read_real(int, void*, size_t) __RENAME(read);
 
 __BIONIC_FORTIFY_INLINE
 ssize_t read(int fd, void* buf, size_t count) {
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 1898c7e..ae10d93 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -166,6 +166,7 @@
 extern wctrans_t wctrans(const char*);
 
 #if __POSIX_VISIBLE >= 200809
+FILE* open_wmemstream(wchar_t**, size_t*);
 wchar_t* wcsdup(const wchar_t*);
 size_t wcsnlen(const wchar_t*, size_t);
 #endif
diff --git a/libc/kernel/tools/clean_header.py b/libc/kernel/tools/clean_header.py
index 6601817..ebebe80 100755
--- a/libc/kernel/tools/clean_header.py
+++ b/libc/kernel/tools/clean_header.py
@@ -199,8 +199,7 @@
         if opt == '-u':
             noUpdate = 0
         elif opt == '-v':
-            verbose = 1
-            D_setlevel(1)
+            logging.basicConfig(level=logging.DEBUG)
         elif opt == '-k':
             kernel_original_path = arg
         elif opt == '-d':
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 2be9532..0c098de 100644
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1711,7 +1711,7 @@
         while j < n and not blocks[j].isIf():
             j += 1
         if j > i:
-            D2("appending lines %d to %d" % (blocks[i].lineno, blocks[j-1].lineno))
+            logging.debug("appending lines %d to %d" % (blocks[i].lineno, blocks[j-1].lineno))
             result += blocks[i:j]
         if j >= n:
             break
@@ -1730,17 +1730,17 @@
                 break
             dir = blocks[j].directive
             if dir == "endif":
-                D2("remove 'if 0' .. 'endif' (lines %d to %d)" % (blocks[i].lineno, blocks[j].lineno))
+                logging.debug("remove 'if 0' .. 'endif' (lines %d to %d)" % (blocks[i].lineno, blocks[j].lineno))
                 i = j + 1
             elif dir == "else":
                 # convert 'else' into 'if 1'
-                D2("convert 'if 0' .. 'else' into 'if 1' (lines %d to %d)" % (blocks[i].lineno, blocks[j-1].lineno))
+                logging.debug("convert 'if 0' .. 'else' into 'if 1' (lines %d to %d)" % (blocks[i].lineno, blocks[j-1].lineno))
                 blocks[j].directive = "if"
                 blocks[j].expr      = CppExpr( CppLineTokenizer("1").toTokenList() )
                 i = j
             elif dir == "elif":
                 # convert 'elif' into 'if'
-                D2("convert 'if 0' .. 'elif' into 'if'")
+                logging.debug("convert 'if 0' .. 'elif' into 'if'")
                 blocks[j].directive = "if"
                 i = j
             continue
@@ -1749,25 +1749,25 @@
         k = find_matching_endif( blocks, j+1 )
         if k >= n:
             # unterminated #if 1, finish here
-            D2("unterminated 'if 1'")
+            logging.debug("unterminated 'if 1'")
             result += blocks[j+1:k]
             break
 
         dir = blocks[k].directive
         if dir == "endif":
-            D2("convert 'if 1' .. 'endif' (lines %d to %d)"  % (blocks[j].lineno, blocks[k].lineno))
+            logging.debug("convert 'if 1' .. 'endif' (lines %d to %d)"  % (blocks[j].lineno, blocks[k].lineno))
             result += optimize_if01(blocks[j+1:k])
             i       = k+1
         elif dir == "else":
             # convert 'else' into 'if 0'
-            D2("convert 'if 1' .. 'else' (lines %d to %d)"  % (blocks[j].lineno, blocks[k].lineno))
+            logging.debug("convert 'if 1' .. 'else' (lines %d to %d)"  % (blocks[j].lineno, blocks[k].lineno))
             result += optimize_if01(blocks[j+1:k])
             blocks[k].directive = "if"
             blocks[k].expr      = CppExpr( CppLineTokenizer("0").toTokenList() )
             i = k
         elif dir == "elif":
             # convert 'elif' into 'if 0'
-            D2("convert 'if 1' .. 'elif' (lines %d to %d)" % (blocks[j].lineno, blocks[k].lineno))
+            logging.debug("convert 'if 1' .. 'elif' (lines %d to %d)" % (blocks[j].lineno, blocks[k].lineno))
             result += optimize_if01(blocks[j+1:k])
             blocks[k].expr      = CppExpr( CppLineTokenizer("0").toTokenList() )
             i = k
@@ -1835,7 +1835,6 @@
     out = StringOutput()
     lines = string.split(text, '\n')
     list = BlockParser().parse( CppLinesTokenizer(lines) )
-    #D_setlevel(2)
     list.replaceTokens( kernel_token_replacements )
     list.optimizeAll( {"__KERNEL__":kCppUndefinedMacro} )
     list.write(out)
diff --git a/libc/kernel/tools/utils.py b/libc/kernel/tools/utils.py
index 0478e93..e5a310e 100644
--- a/libc/kernel/tools/utils.py
+++ b/libc/kernel/tools/utils.py
@@ -1,59 +1,29 @@
 # common python utility routines for the Bionic tool scripts
 
-import sys, os, commands, string, commands
+import commands
+import logging
+import os
+import string
+import sys
 
-# basic debugging trace support
-# call D_setlevel to set the verbosity level
-# and D(), D2(), D3(), D4() to add traces
-#
-verbose = 0
 
 def panic(msg):
-    sys.stderr.write( find_program_name() + ": error: " )
-    sys.stderr.write( msg )
+    sys.stderr.write(os.path.basename(sys.argv[0]) + ": error: ")
+    sys.stderr.write(msg)
     sys.exit(1)
 
-def D(msg):
-    global verbose
-    if verbose > 0:
-        print msg
-
-def D2(msg):
-    global verbose
-    if verbose >= 2:
-        print msg
-
-def D3(msg):
-    global verbose
-    if verbose >= 3:
-        print msg
-
-def D4(msg):
-    global verbose
-    if verbose >= 4:
-        print msg
-
-def D_setlevel(level):
-    global verbose
-    verbose = level
-
-
-#  other stuff
-#
-#
-def find_program_name():
-    return os.path.basename(sys.argv[0])
 
 def find_program_dir():
     return os.path.dirname(sys.argv[0])
 
+
 class StringOutput:
     def __init__(self):
         self.line = ""
 
     def write(self,msg):
         self.line += msg
-        D2("write '%s'" % msg)
+        logging.debug("write '%s'" % msg)
 
     def get(self):
         return self.line
@@ -76,47 +46,6 @@
             continue
         os.mkdir(dir)
 
-def walk_source_files(paths,callback,args,excludes=[]):
-    """recursively walk a list of paths and files, only keeping the source files in directories"""
-    for path in paths:
-        if len(path) > 0 and path[0] == '@':
-            # this is the name of another file, include it and parse it
-            path = path[1:]
-            if os.path.exists(path):
-                for line in open(path):
-                    if len(line) > 0 and line[-1] == '\n':
-                        line = line[:-1]
-                    walk_source_files([line],callback,args,excludes)
-            continue
-        if not os.path.isdir(path):
-            callback(path,args)
-        else:
-            for root, dirs, files in os.walk(path):
-                #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
-                if len(excludes):
-                    for d in dirs[:]:
-                        if os.path.join(root,d) in excludes:
-                            dirs.remove(d)
-                for f in files:
-                    r, ext = os.path.splitext(f)
-                    if ext in [ ".h", ".c", ".cpp", ".S" ]:
-                        callback( "%s/%s" % (root,f), args )
-
-def cleanup_dir(path):
-    """create a directory if needed, and ensure that it is totally empty
-       by removing any existing content in it"""
-    if not os.path.exists(path):
-        os.mkdir(path)
-    else:
-        for root, dirs, files in os.walk(path, topdown=False):
-            if root.endswith("kernel_headers/"):
-                # skip 'kernel_headers'
-                continue
-            for name in files:
-                os.remove(os.path.join(root, name))
-            for name in dirs:
-                os.rmdir(os.path.join(root, name))
-
 
 class BatchFileUpdater:
     """a class used to edit several files at once"""
diff --git a/libc/private/bionic_asm.h b/libc/private/bionic_asm.h
index 7c2686f..d53ebba 100644
--- a/libc/private/bionic_asm.h
+++ b/libc/private/bionic_asm.h
@@ -41,7 +41,7 @@
 #define ENTRY(f) \
     .text; \
     .globl f; \
-    _ALIGN_TEXT; \
+    .align __bionic_asm_align; \
     .type f, __bionic_asm_function_type; \
     f: \
     __bionic_asm_custom_entry(f); \
diff --git a/tests/libs/dlsym_local_symbol.map b/libc/private/bionic_prctl.h
similarity index 71%
copy from tests/libs/dlsym_local_symbol.map
copy to libc/private/bionic_prctl.h
index 58a2299..103cccb 100644
--- a/tests/libs/dlsym_local_symbol.map
+++ b/libc/private/bionic_prctl.h
@@ -13,10 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-LIBTEST_LOCAL_SYMBOL_1.0 {
-  global:
-    dlsym_local_symbol_get_taxicab_number;
-    dlsym_local_symbol_get_taxicab_number_using_dlsym;
-  local:
-    *;
-};
+
+#ifndef BIONIC_PRCTL_H
+#define BIONIC_PRCTL_H
+
+#include <sys/prctl.h>
+
+// This is only supported by Android kernels, so it's not in the uapi headers.
+#define PR_SET_VMA   0x53564d41
+#define PR_SET_VMA_ANON_NAME    0
+
+#endif // BIONIC_PRCTL_H
diff --git a/tests/libs/dlsym_local_symbol_private.cpp b/libc/private/bionic_string_utils.h
similarity index 62%
rename from tests/libs/dlsym_local_symbol_private.cpp
rename to libc/private/bionic_string_utils.h
index 2587508..ab0eccf 100644
--- a/tests/libs/dlsym_local_symbol_private.cpp
+++ b/libc/private/bionic_string_utils.h
@@ -14,11 +14,18 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <stdio.h>
+#ifndef _BIONIC_STRING_UTILS_H_
+#define _BIONIC_STRING_UTILS_H_
 
-// This symbol is declared local in
-// the linker version map: libdlsym_local_symbol.map.
-// It should not be visible from the outside.
-extern "C" const uint32_t __attribute__ ((visibility ("protected"))) private_taxicab_number = 1729;
+#include <string.h>
+
+static inline bool ends_with(const char* s1, const char* s2) {
+  size_t s1_length = strlen(s1);
+  size_t s2_length = strlen(s2);
+  if (s2_length > s1_length) {
+    return false;
+  }
+  return memcmp(s1 + (s1_length - s2_length), s2, s2_length) == 0;
+}
+
+#endif // _BIONIC_STRING_UTILS_H_
diff --git a/libc/private/bionic_systrace.h b/libc/private/bionic_systrace.h
new file mode 100644
index 0000000..0b4560f
--- /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 __LIBC_HIDDEN__ 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/private/libc_logging.h b/libc/private/libc_logging.h
index 35c756b..da2192b 100644
--- a/libc/private/libc_logging.h
+++ b/libc/private/libc_logging.h
@@ -69,8 +69,6 @@
   char msg[0];
 };
 
-void __android_set_abort_message(const char* msg);
-
 //
 // Formats a message to the log (priority 'fatal'), then aborts.
 //
diff --git a/libc/private/thread_private.h b/libc/private/thread_private.h
index b8b1a81..2e3ac3d 100644
--- a/libc/private/thread_private.h
+++ b/libc/private/thread_private.h
@@ -46,8 +46,9 @@
 __LIBC_HIDDEN__ void    _thread_arc4_lock(void);
 __LIBC_HIDDEN__ void    _thread_arc4_unlock(void);
 
-#define  _ARC4_LOCK() _thread_arc4_lock()
-#define  _ARC4_UNLOCK() _thread_arc4_unlock()
+#define _ARC4_LOCK() _thread_arc4_lock()
+#define _ARC4_UNLOCK() _thread_arc4_unlock()
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
 
 __END_DECLS
 
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
new file mode 100644
index 0000000..bfdecb8
--- /dev/null
+++ b/libc/stdio/stdio_ext.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio_ext.h>
+
+#include <stdio.h>
+#include "local.h"
+
+#define FSETLOCKING_QUERY 0
+#define FSETLOCKING_INTERNAL 1
+#define FSETLOCKING_BYCALLER 2
+
+size_t __fbufsize(FILE* fp) {
+  return fp->_bf._size;
+}
+
+/* For a _SRW stream, we don't know whether we last read or wrote.
+int __freading(FILE* fp) {
+  return (fp->_flags & _SRD) != 0 || ...;
+}
+*/
+
+/* For a _SRW stream, we don't know whether we last read or wrote.
+int __fwriting(FILE*) {
+  return (fp->_flags & _SWR) != 0 || ...;
+}
+*/
+
+int __freadable(FILE* fp) {
+  return (fp->_flags & (__SRD|__SRW)) != 0;
+}
+
+int __fwritable(FILE* fp) {
+  return (fp->_flags & (__SWR|__SRW)) != 0;
+}
+
+int __flbf(FILE* fp) {
+  return (fp->_flags & __SLBF) != 0;
+}
+
+void __fpurge(FILE* fp) {
+  fpurge(fp);
+}
+
+size_t __fpending(FILE* fp) {
+  return fp->_p - fp->_bf._base;
+}
+
+void _flushlbf() {
+  // If we flush all streams, we know we've flushed all the line-buffered streams.
+  fflush(NULL);
+}
+
+int __fsetlocking(FILE*, int) {
+  // We don't currently have an implementation that would obey this,
+  // so make setting the state a no-op and always return "we handle locking for you".
+  // http://b/17154740 suggests ways we could fix this.
+  return FSETLOCKING_INTERNAL;
+}
+
+void clearerr_unlocked(FILE* fp) {
+  return __sclearerr(fp);
+}
+
+int feof_unlocked(FILE* fp) {
+  return __sfeof(fp);
+}
+
+int ferror_unlocked(FILE* fp) {
+  return __sferror(fp);
+}
diff --git a/libc/tools/bionic_utils.py b/libc/tools/bionic_utils.py
deleted file mode 100644
index c38efb5..0000000
--- a/libc/tools/bionic_utils.py
+++ /dev/null
@@ -1,165 +0,0 @@
-# common python utility routines for the Bionic tool scripts
-
-import sys, os, commands, string
-
-all_arches = [ "arm", "arm64", "mips", "mips64", "x86", "x86_64" ]
-
-# basic debugging trace support
-# call D_setlevel to set the verbosity level
-# and D(), D2(), D3(), D4() to add traces
-#
-verbose = 0
-
-def D(msg):
-    global verbose
-    if verbose > 0:
-        print msg
-
-def D2(msg):
-    global verbose
-    if verbose >= 2:
-        print msg
-
-def D3(msg):
-    global verbose
-    if verbose >= 3:
-        print msg
-
-def D4(msg):
-    global verbose
-    if verbose >= 4:
-        print msg
-
-def D_setlevel(level):
-    global verbose
-    verbose = level
-
-
-# parser for the SYSCALLS.TXT file
-#
-class SysCallsTxtParser:
-    def __init__(self):
-        self.syscalls = []
-        self.lineno   = 0
-
-    def E(self, msg):
-        print "%d: %s" % (self.lineno, msg)
-
-    def parse_line(self, line):
-        """ parse a syscall spec line.
-
-        line processing, format is
-           return type    func_name[|alias_list][:syscall_name[:socketcall_id]] ( [paramlist] ) architecture_list
-        """
-        pos_lparen = line.find('(')
-        E          = self.E
-        if pos_lparen < 0:
-            E("missing left parenthesis in '%s'" % line)
-            return
-
-        pos_rparen = line.rfind(')')
-        if pos_rparen < 0 or pos_rparen <= pos_lparen:
-            E("missing or misplaced right parenthesis in '%s'" % line)
-            return
-
-        return_type = line[:pos_lparen].strip().split()
-        if len(return_type) < 2:
-            E("missing return type in '%s'" % line)
-            return
-
-        syscall_func = return_type[-1]
-        return_type  = string.join(return_type[:-1],' ')
-        socketcall_id = -1
-
-        pos_colon = syscall_func.find(':')
-        if pos_colon < 0:
-            syscall_name = syscall_func
-        else:
-            if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
-                E("misplaced colon in '%s'" % line)
-                return
-
-            # now find if there is a socketcall_id for a dispatch-type syscall
-            # after the optional 2nd colon
-            pos_colon2 = syscall_func.find(':', pos_colon + 1)
-            if pos_colon2 < 0:
-                syscall_name = syscall_func[pos_colon+1:]
-                syscall_func = syscall_func[:pos_colon]
-            else:
-                if pos_colon2+1 >= len(syscall_func):
-                    E("misplaced colon2 in '%s'" % line)
-                    return
-                syscall_name = syscall_func[(pos_colon+1):pos_colon2]
-                socketcall_id = int(syscall_func[pos_colon2+1:])
-                syscall_func = syscall_func[:pos_colon]
-
-        alias_delim = syscall_func.find('|')
-        if alias_delim > 0:
-            alias_list = syscall_func[alias_delim+1:].strip()
-            syscall_func = syscall_func[:alias_delim]
-            alias_delim = syscall_name.find('|')
-            if alias_delim > 0:
-                syscall_name = syscall_name[:alias_delim]
-            syscall_aliases = string.split(alias_list, ',')
-        else:
-            syscall_aliases = []
-
-        if pos_rparen > pos_lparen+1:
-            syscall_params = line[pos_lparen+1:pos_rparen].split(',')
-            params         = string.join(syscall_params,',')
-        else:
-            syscall_params = []
-            params         = "void"
-
-        t = {
-              "name"    : syscall_name,
-              "func"    : syscall_func,
-              "aliases" : syscall_aliases,
-              "params"  : syscall_params,
-              "decl"    : "%-15s  %s (%s);" % (return_type, syscall_func, params),
-              "socketcall_id" : socketcall_id
-        }
-
-        # Parse the architecture list.
-        arch_list = line[pos_rparen+1:].strip()
-        if arch_list == "all":
-            for arch in all_arches:
-                t[arch] = True
-        else:
-            for arch in string.split(arch_list, ','):
-                if arch in all_arches:
-                    t[arch] = True
-                else:
-                    E("invalid syscall architecture '%s' in '%s'" % (arch, line))
-                    return
-
-        self.syscalls.append(t)
-
-        global verbose
-        if verbose >= 2:
-            print t
-
-
-    def parse_file(self, file_path):
-        D2("parse_file: %s" % file_path)
-        fp = open(file_path)
-        for line in fp.xreadlines():
-            self.lineno += 1
-            line = line.strip()
-            if not line: continue
-            if line[0] == '#': continue
-            self.parse_line(line)
-
-        fp.close()
-
-
-class StringOutput:
-    def __init__(self):
-        self.line = ""
-
-    def write(self,msg):
-        self.line += msg
-        D2("write '%s'" % msg)
-
-    def get(self):
-        return self.line
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 58a10e0..8bcf7fc 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -3,12 +3,18 @@
 import glob
 import os
 import re
-import string
 import subprocess
 import sys
 
+only_unwanted = False
+if len(sys.argv) > 1:
+  if sys.argv[1] in ('-u', '--unwanted'):
+    only_unwanted = True
+
 toolchain = os.environ['ANDROID_TOOLCHAIN']
 arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
+if arch == 'aarch64':
+  arch = 'arm64'
 
 def GetSymbolsFromSo(so_file):
   # Example readelf output:
@@ -50,15 +56,26 @@
     return glibc_to_bionic_names[name]
   return name
 
+def GetNdkIgnored():
+  global arch
+  symbols = set()
+  files = glob.glob('%s/ndk/build/tools/unwanted-symbols/%s/*' %
+                    (os.getenv('ANDROID_BUILD_TOP'), arch))
+  for f in files:
+    symbols |= set(open(f, 'r').read().splitlines())
+  return symbols
+
 glibc_to_bionic_names = {
   '__res_init': 'res_init',
   '__res_mkquery': 'res_mkquery',
   '__res_query': 'res_query',
   '__res_search': 'res_search',
+  '__xpg_basename': '__gnu_basename',
 }
 
 glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*')
 bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so')
+ndk_ignored = GetNdkIgnored()
 
 glibc = map(MangleGlibcNameToBionic, glibc)
 
@@ -100,6 +117,16 @@
   '__errno',
   '__fe_dfl_env',
   '__get_h_errno',
+  '__fpclassifyd',
+  '__isfinite',
+  '__isfinitef',
+  '__isfinitel',
+  '__isnormal',
+  '__isnormalf',
+  '__isnormall',
+  '__sF',
+  '__pthread_cleanup_pop',
+  '__pthread_cleanup_push',
 ])
 # bionic exposes various Linux features that glibc doesn't.
 linux_stuff = set([
@@ -133,21 +160,43 @@
   'mknodat',
   'stat',
   'stat64',
+  'optreset',
+  'sigsetjmp',
+])
+# These exist in glibc, but under slightly different names (generally one extra
+# or one fewer _). TODO: check against glibc names.
+libresolv_stuff = set([
+  '__res_send_setqhook',
+  '__res_send_setrhook',
+  '_resolv_flush_cache_for_net',
+  '_resolv_set_nameservers_for_net',
+  'dn_expand',
+  'nsdispatch',
+])
+# Implementation details we know we export (and can't get away from).
+known = set([
+  '_ctype_',
+  '__libc_init',
 ])
 
-print 'glibc:'
-for symbol in sorted(glibc):
-  print symbol
+if not only_unwanted:
+  print 'glibc:'
+  for symbol in sorted(glibc):
+    print symbol
 
-print
-print 'bionic:'
-for symbol in sorted(bionic):
-  print symbol
+  print
+  print 'bionic:'
+  for symbol in sorted(bionic):
+    print symbol
 
-print
-print 'in bionic but not glibc:'
-allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | std_stuff | weird_stuff)
+  print
+  print 'in bionic but not glibc:'
+
+allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff |
+                 std_stuff | weird_stuff | libresolv_stuff | known)
 for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
+  if symbol in ndk_ignored:
+    symbol += '*'
   print symbol
 
 sys.exit(0)
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/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 96583d6..929bec4 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -4,21 +4,29 @@
 # the header files listing all available system calls, and the
 # makefiles used to build all the stubs.
 
+import atexit
 import commands
 import filecmp
 import glob
+import logging
 import os.path
 import re
 import shutil
 import stat
+import string
 import sys
+import tempfile
 
-from bionic_utils import *
 
-bionic_libc_root = os.environ["ANDROID_BUILD_TOP"] + "/bionic/libc/"
+all_arches = [ "arm", "arm64", "mips", "mips64", "x86", "x86_64" ]
+
 
 # temp directory where we store all intermediate files
-bionic_temp = "/tmp/bionic_gensyscalls/"
+bionic_temp = tempfile.mkdtemp(prefix="bionic_gensyscalls");
+# Make sure the directory is deleted when the script exits.
+atexit.register(shutil.rmtree, bionic_temp)
+
+bionic_libc_root = os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libc")
 
 warning = "Generated by gensyscalls.py. Do not edit."
 
@@ -34,15 +42,18 @@
 
 
 def create_file(relpath):
-    dir = os.path.dirname(bionic_temp + relpath)
+    full_path = os.path.join(bionic_temp, relpath)
+    dir = os.path.dirname(full_path)
     make_dir(dir)
-    return open(bionic_temp + relpath, "w")
+    return open(full_path, "w")
 
 
 syscall_stub_header = "/* " + warning + " */\n" + \
 """
 #include <private/bionic_asm.h>
 
+    .hidden __set_errno
+
 ENTRY(%(func)s)
 """
 
@@ -265,7 +276,7 @@
 # This lets us support regular system calls like __NR_write and also weird
 # ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
 def make__NR_name(name):
-    if name.startswith("__"):
+    if name.startswith("__ARM_NR_"):
         return name
     else:
         return "__NR_%s" % (name)
@@ -380,6 +391,120 @@
     return result
 
 
+class SysCallsTxtParser:
+    def __init__(self):
+        self.syscalls = []
+        self.lineno   = 0
+
+    def E(self, msg):
+        print "%d: %s" % (self.lineno, msg)
+
+    def parse_line(self, line):
+        """ parse a syscall spec line.
+
+        line processing, format is
+           return type    func_name[|alias_list][:syscall_name[:socketcall_id]] ( [paramlist] ) architecture_list
+        """
+        pos_lparen = line.find('(')
+        E          = self.E
+        if pos_lparen < 0:
+            E("missing left parenthesis in '%s'" % line)
+            return
+
+        pos_rparen = line.rfind(')')
+        if pos_rparen < 0 or pos_rparen <= pos_lparen:
+            E("missing or misplaced right parenthesis in '%s'" % line)
+            return
+
+        return_type = line[:pos_lparen].strip().split()
+        if len(return_type) < 2:
+            E("missing return type in '%s'" % line)
+            return
+
+        syscall_func = return_type[-1]
+        return_type  = string.join(return_type[:-1],' ')
+        socketcall_id = -1
+
+        pos_colon = syscall_func.find(':')
+        if pos_colon < 0:
+            syscall_name = syscall_func
+        else:
+            if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
+                E("misplaced colon in '%s'" % line)
+                return
+
+            # now find if there is a socketcall_id for a dispatch-type syscall
+            # after the optional 2nd colon
+            pos_colon2 = syscall_func.find(':', pos_colon + 1)
+            if pos_colon2 < 0:
+                syscall_name = syscall_func[pos_colon+1:]
+                syscall_func = syscall_func[:pos_colon]
+            else:
+                if pos_colon2+1 >= len(syscall_func):
+                    E("misplaced colon2 in '%s'" % line)
+                    return
+                syscall_name = syscall_func[(pos_colon+1):pos_colon2]
+                socketcall_id = int(syscall_func[pos_colon2+1:])
+                syscall_func = syscall_func[:pos_colon]
+
+        alias_delim = syscall_func.find('|')
+        if alias_delim > 0:
+            alias_list = syscall_func[alias_delim+1:].strip()
+            syscall_func = syscall_func[:alias_delim]
+            alias_delim = syscall_name.find('|')
+            if alias_delim > 0:
+                syscall_name = syscall_name[:alias_delim]
+            syscall_aliases = string.split(alias_list, ',')
+        else:
+            syscall_aliases = []
+
+        if pos_rparen > pos_lparen+1:
+            syscall_params = line[pos_lparen+1:pos_rparen].split(',')
+            params         = string.join(syscall_params,',')
+        else:
+            syscall_params = []
+            params         = "void"
+
+        t = {
+              "name"    : syscall_name,
+              "func"    : syscall_func,
+              "aliases" : syscall_aliases,
+              "params"  : syscall_params,
+              "decl"    : "%-15s  %s (%s);" % (return_type, syscall_func, params),
+              "socketcall_id" : socketcall_id
+        }
+
+        # Parse the architecture list.
+        arch_list = line[pos_rparen+1:].strip()
+        if arch_list == "all":
+            for arch in all_arches:
+                t[arch] = True
+        else:
+            for arch in string.split(arch_list, ','):
+                if arch in all_arches:
+                    t[arch] = True
+                else:
+                    E("invalid syscall architecture '%s' in '%s'" % (arch, line))
+                    return
+
+        self.syscalls.append(t)
+
+        logging.debug(t)
+
+
+    def parse_file(self, file_path):
+        logging.debug("parse_file: %s" % file_path)
+        fp = open(file_path)
+        for line in fp.xreadlines():
+            self.lineno += 1
+            line = line.strip()
+            if not line: continue
+            if line[0] == '#': continue
+            self.parse_line(line)
+
+        fp.close()
+
+
 class State:
     def __init__(self):
         self.old_stubs = []
@@ -437,22 +562,22 @@
     def gen_glibc_syscalls_h(self):
         # TODO: generate a separate file for each architecture, like glibc's bits/syscall.h.
         glibc_syscalls_h_path = "include/sys/glibc-syscalls.h"
-        D("generating " + glibc_syscalls_h_path)
+        logging.info("generating " + glibc_syscalls_h_path)
         glibc_fp = create_file(glibc_syscalls_h_path)
         glibc_fp.write("/* %s */\n" % warning)
         glibc_fp.write("#ifndef _BIONIC_GLIBC_SYSCALLS_H_\n")
         glibc_fp.write("#define _BIONIC_GLIBC_SYSCALLS_H_\n")
 
         glibc_fp.write("#if defined(__aarch64__)\n")
-        self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/uapi/asm-generic/unistd.h")
+        self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-generic/unistd.h"))
         glibc_fp.write("#elif defined(__arm__)\n")
-        self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/uapi/asm-arm/asm/unistd.h")
+        self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-arm/asm/unistd.h"))
         glibc_fp.write("#elif defined(__mips__)\n")
-        self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/uapi/asm-mips/asm/unistd.h")
+        self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-mips/asm/unistd.h"))
         glibc_fp.write("#elif defined(__i386__)\n")
-        self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/uapi/asm-x86/asm/unistd_32.h")
+        self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-x86/asm/unistd_32.h"))
         glibc_fp.write("#elif defined(__x86_64__)\n")
-        self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/uapi/asm-x86/asm/unistd_64.h")
+        self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-x86/asm/unistd_64.h"))
         glibc_fp.write("#endif\n")
 
         glibc_fp.write("#endif /* _BIONIC_GLIBC_SYSCALLS_H_ */\n")
@@ -466,7 +591,7 @@
             for arch in all_arches:
                 if syscall.has_key("asm-%s" % arch):
                     filename = "arch-%s/syscalls/%s.S" % (arch, syscall["func"])
-                    D2(">>> generating " + filename)
+                    logging.info(">>> generating " + filename)
                     fp = create_file(filename)
                     fp.write(syscall["asm-%s" % arch])
                     fp.close()
@@ -474,48 +599,49 @@
 
 
     def regenerate(self):
-        D("scanning for existing architecture-specific stub files...")
-
-        bionic_libc_root_len = len(bionic_libc_root)
+        logging.info("scanning for existing architecture-specific stub files...")
 
         for arch in all_arches:
-            arch_path = bionic_libc_root + "arch-" + arch
-            D("scanning " + arch_path)
-            files = glob.glob(arch_path + "/syscalls/*.S")
-            for f in files:
-                self.old_stubs.append(f[bionic_libc_root_len:])
+            arch_dir = "arch-" + arch
+            logging.info("scanning " + os.path.join(bionic_libc_root, arch_dir))
+            rel_path = os.path.join(arch_dir, "syscalls")
+            for file in os.listdir(os.path.join(bionic_libc_root, rel_path)):
+                if file.endswith(".S"):
+                  self.old_stubs.append(os.path.join(rel_path, file))
 
-        D("found %d stub files" % len(self.old_stubs))
+        logging.info("found %d stub files" % len(self.old_stubs))
 
         if not os.path.exists(bionic_temp):
-            D("creating %s..." % bionic_temp)
+            logging.info("creating %s..." % bionic_temp)
             make_dir(bionic_temp)
 
-        D("re-generating stubs and support files...")
+        logging.info("re-generating stubs and support files...")
 
         self.gen_glibc_syscalls_h()
         self.gen_syscall_stubs()
 
-        D("comparing files...")
+        logging.info("comparing files...")
         adds    = []
         edits   = []
 
         for stub in self.new_stubs + self.other_files:
-            if not os.path.exists(bionic_libc_root + stub):
+            tmp_file = os.path.join(bionic_temp, stub)
+            libc_file = os.path.join(bionic_libc_root, stub)
+            if not os.path.exists(libc_file):
                 # new file, git add it
-                D("new file:     " + stub)
-                adds.append(bionic_libc_root + stub)
-                shutil.copyfile(bionic_temp + stub, bionic_libc_root + stub)
+                logging.info("new file:     " + stub)
+                adds.append(libc_file)
+                shutil.copyfile(tmp_file, libc_file)
 
-            elif not filecmp.cmp(bionic_temp + stub, bionic_libc_root + stub):
-                D("changed file: " + stub)
+            elif not filecmp.cmp(tmp_file, libc_file):
+                logging.info("changed file: " + stub)
                 edits.append(stub)
 
         deletes = []
         for stub in self.old_stubs:
             if not stub in self.new_stubs:
-                D("deleted file: " + stub)
-                deletes.append(bionic_libc_root + stub)
+                logging.info("deleted file: " + stub)
+                deletes.append(os.path.join(bionic_libc_root, stub))
 
         if not DRY_RUN:
             if adds:
@@ -524,18 +650,19 @@
                 commands.getoutput("git rm " + " ".join(deletes))
             if edits:
                 for file in edits:
-                    shutil.copyfile(bionic_temp + file, bionic_libc_root + file)
-                commands.getoutput("git add " + " ".join((bionic_libc_root + file) for file in edits))
+                    shutil.copyfile(os.path.join(bionic_temp, file),
+                                    os.path.join(bionic_libc_root, file))
+                commands.getoutput("git add " + " ".join((os.path.join(bionic_libc_root, file)) for file in edits))
 
-            commands.getoutput("git add %s%s" % (bionic_libc_root,"SYSCALLS.TXT"))
+            commands.getoutput("git add %s" % (os.path.join(bionic_libc_root, "SYSCALLS.TXT")))
 
         if (not adds) and (not deletes) and (not edits):
-            D("no changes detected!")
+            logging.info("no changes detected!")
         else:
-            D("ready to go!!")
+            logging.info("ready to go!!")
 
-D_setlevel(1)
+logging.basicConfig(level=logging.INFO)
 
 state = State()
-state.process_file(bionic_libc_root+"SYSCALLS.TXT")
+state.process_file(os.path.join(bionic_libc_root, "SYSCALLS.TXT"))
 state.regenerate()
diff --git a/libc/tools/zoneinfo/ZoneCompactor.java b/libc/tools/zoneinfo/ZoneCompactor.java
index f47afd1..bf3153e 100644
--- a/libc/tools/zoneinfo/ZoneCompactor.java
+++ b/libc/tools/zoneinfo/ZoneCompactor.java
@@ -1,9 +1,6 @@
 
 import java.io.*;
-import java.nio.ByteOrder;
 import java.util.*;
-import libcore.io.BufferIterator;
-import libcore.util.ZoneInfo;
 
 // usage: java ZoneCompiler <setup file> <data directory> <output directory> <tzdata version>
 //
@@ -27,66 +24,20 @@
 //
 
 public class ZoneCompactor {
-  public static class ByteArrayBufferIteratorBE extends BufferIterator {
-    private final byte[] bytes;
-    private int offset = 0;
-
-    public ByteArrayBufferIteratorBE(byte[] bytes) {
-      this.bytes = bytes;
-      this.offset = 0;
-    }
-
-    public void seek(int offset) {
-      this.offset = offset;
-    }
-
-    public void skip(int byteCount) {
-      this.offset += byteCount;
-    }
-
-    public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
-      System.arraycopy(bytes, offset, dst, dstOffset, byteCount);
-      offset += byteCount;
-    }
-
-    public byte readByte() {
-      return bytes[offset++];
-    }
-
-    public int readInt() {
-      return ((readByte() & 0xff) << 24) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 8) | (readByte() & 0xff);
-    }
-
-    public void readIntArray(int[] dst, int dstOffset, int intCount) {
-      for (int i = 0; i < intCount; ++i) {
-        dst[dstOffset++] = readInt();
-      }
-    }
-
-    public short readShort() {
-      throw new UnsupportedOperationException();
-    }
-  }
-
-  // Maximum number of characters in a zone name, including '\0' terminator
+  // Maximum number of characters in a zone name, including '\0' terminator.
   private static final int MAXNAME = 40;
 
-  // Zone name synonyms
+  // Zone name synonyms.
   private Map<String,String> links = new HashMap<String,String>();
 
-  // File starting bytes by zone name
-  private Map<String,Integer> starts = new HashMap<String,Integer>();
+  // File offsets by zone name.
+  private Map<String,Integer> offsets = new HashMap<String,Integer>();
 
-  // File lengths by zone name
+  // File lengths by zone name.
   private Map<String,Integer> lengths = new HashMap<String,Integer>();
 
-  // Raw GMT offsets by zone name
-  private Map<String,Integer> offsets = new HashMap<String,Integer>();
-  private int start = 0;
-
-  // Concatenate the contents of 'inFile' onto 'out'
-  // and return the contents as a byte array.
-  private static byte[] copyFile(File inFile, OutputStream out) throws Exception {
+  // Concatenate the contents of 'inFile' onto 'out'.
+  private static void copyFile(File inFile, OutputStream out) throws Exception {
     byte[] ret = new byte[0];
 
     InputStream in = new FileInputStream(inFile);
@@ -104,14 +55,14 @@
       ret = nret;
     }
     out.flush();
-    return ret;
   }
 
   public ZoneCompactor(String setupFile, String dataDirectory, String zoneTabFile, String outputDirectory, String version) throws Exception {
-    // Read the setup file, and concatenate all the data.
+    // Read the setup file and concatenate all the data.
     ByteArrayOutputStream allData = new ByteArrayOutputStream();
     BufferedReader reader = new BufferedReader(new FileReader(setupFile));
     String s;
+    int offset = 0;
     while ((s = reader.readLine()) != null) {
       s = s.trim();
       if (s.startsWith("Link")) {
@@ -125,16 +76,11 @@
         if (link == null) {
           File sourceFile = new File(dataDirectory, s);
           long length = sourceFile.length();
-          starts.put(s, start);
+          offsets.put(s, offset);
           lengths.put(s, (int) length);
 
-          start += length;
-          byte[] data = copyFile(sourceFile, allData);
-
-          BufferIterator it = new ByteArrayBufferIteratorBE(data);
-          TimeZone tz = ZoneInfo.makeTimeZone(s, it);
-          int gmtOffset = tz.getRawOffset();
-          offsets.put(s, gmtOffset);
+          offset += length;
+          copyFile(sourceFile, allData);
         }
       }
     }
@@ -146,9 +92,8 @@
       String from = it.next();
       String to = links.get(from);
 
-      starts.put(from, starts.get(to));
-      lengths.put(from, lengths.get(to));
       offsets.put(from, offsets.get(to));
+      lengths.put(from, lengths.get(to));
     }
 
     // Create/truncate the destination file.
@@ -178,7 +123,7 @@
 
     // Write the index.
     ArrayList<String> sortedOlsonIds = new ArrayList<String>();
-    sortedOlsonIds.addAll(starts.keySet());
+    sortedOlsonIds.addAll(offsets.keySet());
     Collections.sort(sortedOlsonIds);
     it = sortedOlsonIds.iterator();
     while (it.hasNext()) {
@@ -188,9 +133,9 @@
       }
 
       f.write(toAscii(new byte[MAXNAME], zoneName));
-      f.writeInt(starts.get(zoneName));
-      f.writeInt(lengths.get(zoneName));
       f.writeInt(offsets.get(zoneName));
+      f.writeInt(lengths.get(zoneName));
+      f.writeInt(0); // Used to be raw GMT offset. No longer used.
     }
 
     int data_offset = (int) f.getFilePointer();
diff --git a/libc/tools/zoneinfo/update-tzdata.py b/libc/tools/zoneinfo/update-tzdata.py
index 6b69a5a..e800e8f 100755
--- a/libc/tools/zoneinfo/update-tzdata.py
+++ b/libc/tools/zoneinfo/update-tzdata.py
@@ -115,7 +115,7 @@
   print 'Configuring ICU tools...'
   subprocess.check_call(['%s/runConfigureICU' % icu_dir, 'Linux'])
   print 'Making ICU tools...'
-  subprocess.check_call(['make', '-j6'])
+  subprocess.check_call(['make', '-j32'])
 
   # Run the ICU tools.
   os.chdir('tools/tzcode')
@@ -169,11 +169,8 @@
   WriteSetupFile()
 
   print 'Calling ZoneCompactor to update bionic to %s...' % new_version
-  libcore_src_dir = '%s/../libcore/luni/src/main/java/' % bionic_dir
   subprocess.check_call(['javac', '-d', '.',
-                         '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir,
-                         '%s/libcore/util/ZoneInfo.java' % libcore_src_dir,
-                         '%s/libcore/io/BufferIterator.java' % libcore_src_dir])
+                         '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir])
   subprocess.check_call(['java', 'ZoneCompactor',
                          'setup', 'data', 'extracted/zone.tab',
                          bionic_libc_zoneinfo_dir, new_version])
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 4dd7ab0..3bbed90 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2210,7 +2210,7 @@
     char buf[NAME_LENGTH];
     int32_t start;
     int32_t length;
-    int32_t raw_gmt_offset;
+    int32_t unused; // Was raw GMT offset; always 0 since tzdata2014f (L).
   };
 
   size_t id_count = (ntohl(header.data_offset) - ntohl(header.index_offset)) / sizeof(struct index_entry_t);
@@ -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/unistd/syslog.c b/libc/unistd/syslog.c
deleted file mode 100644
index 339df68..0000000
--- a/libc/unistd/syslog.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*	$OpenBSD: syslog.c,v 1.28 2005/08/08 08:05:34 espie Exp $ */
-/*
- * 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.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <syslog.h>
-#include <sys/un.h>
-#include <netdb.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <stdarg.h>
-
-struct syslog_data {
-  int log_file;
-  int connected;
-  int opened;
-  int log_stat;
-  const char* log_tag;
-  int log_fac;
-  int log_mask;
-};
-
-#define SYSLOG_DATA_INIT {-1, 0, 0, 0, (const char *)0, LOG_USER, 0xff}
-
-static struct syslog_data sdata = SYSLOG_DATA_INIT;
-
-extern const char	*__progname;		/* Program name, from crt0. */
-
-static void	disconnectlog_r(struct syslog_data *);	/* disconnect from syslogd */
-static void	connectlog_r(struct syslog_data *);	/* (re)connect to syslogd */
-
-#if defined(__LP64__)
-#define SYSLOG_R_VISIBILITY static
-#else
-#define SYSLOG_R_VISIBILITY extern
-#endif
-
-SYSLOG_R_VISIBILITY void closelog_r(struct syslog_data*);
-SYSLOG_R_VISIBILITY void openlog_r(const char*, int, int, struct syslog_data*);
-SYSLOG_R_VISIBILITY int setlogmask_r(int, struct syslog_data*);
-SYSLOG_R_VISIBILITY void syslog_r(int, struct syslog_data*, const char*, ...) __printflike(3, 4);
-SYSLOG_R_VISIBILITY void vsyslog_r(int, struct syslog_data*, const char*, va_list) __printflike(3, 0);
-
-/*
- * syslog, vsyslog --
- *	print message on log file; output is intended for syslogd(8).
- */
-void
-syslog(int pri, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	vsyslog(pri, fmt, ap);
-	va_end(ap);
-}
-
-void
-vsyslog(int pri, const char *fmt, va_list ap)
-{
-	vsyslog_r(pri, &sdata, fmt, ap);
-}
-
-void
-openlog(const char *ident, int logstat, int logfac)
-{
-	openlog_r(ident, logstat, logfac, &sdata);
-}
-
-void
-closelog(void)
-{
-	closelog_r(&sdata);
-}
-
-/* setlogmask -- set the log mask level */
-int
-setlogmask(int pmask)
-{
-	return setlogmask_r(pmask, &sdata);
-}
-
-/* Reentrant version of syslog, i.e. syslog_r() */
-
-void
-syslog_r(int pri, struct syslog_data *data, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	vsyslog_r(pri, data, fmt, ap);
-	va_end(ap);
-}
-
-void
-vsyslog_r(int pri, struct syslog_data *data, const char *fmt, va_list ap)
-{
-	int cnt;
-	char ch, *p, *t;
-	time_t now;
-	int fd, saved_errno, error;
-#define	TBUF_LEN	2048
-#define	FMT_LEN		1024
-	char *stdp = NULL, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN];
-	int tbuf_left, fmt_left, prlen;
-
-#define	INTERNALLOG	LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
-	/* Check for invalid bits. */
-	if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
-		if (data == &sdata) {
-			syslog(INTERNALLOG,
-			    "syslog: unknown facility/priority: %x", pri);
-		} else {
-			syslog_r(INTERNALLOG, data,
-			    "syslog_r: unknown facility/priority: %x", pri);
-		}
-		pri &= LOG_PRIMASK|LOG_FACMASK;
-	}
-
-	/* Check priority against setlogmask values. */
-	if (!(LOG_MASK(LOG_PRI(pri)) & data->log_mask))
-		return;
-
-	saved_errno = errno;
-
-	/* Set default facility if none specified. */
-	if ((pri & LOG_FACMASK) == 0)
-		pri |= data->log_fac;
-
-	/* If we have been called through syslog(), no need for reentrancy. */
-	if (data == &sdata)
-		(void)time(&now);
-
-	p = tbuf;
-	tbuf_left = TBUF_LEN;
-
-#define	DEC()	\
-	do {					\
-		if (prlen < 0)			\
-			prlen = 0;		\
-		if (prlen >= tbuf_left)		\
-			prlen = tbuf_left - 1;	\
-		p += prlen;			\
-		tbuf_left -= prlen;		\
-	} while (0)
-
-	prlen = snprintf(p, tbuf_left, "<%d>", pri);
-	DEC();
-
-	/*
-	 * syslogd will expand time automagically for reentrant case, and
-	 * for normal case, just do like before
-	 */
-	if (data == &sdata) {
-		prlen = strftime(p, tbuf_left, "%h %e %T ", localtime(&now));
-		DEC();
-	}
-
-	if (data->log_stat & LOG_PERROR)
-		stdp = p;
-	if (data->log_tag == NULL)
-		data->log_tag = __progname;
-	if (data->log_tag != NULL) {
-		prlen = snprintf(p, tbuf_left, "%s", data->log_tag);
-		DEC();
-	}
-	if (data->log_stat & LOG_PID) {
-		prlen = snprintf(p, tbuf_left, "[%ld]", (long)getpid());
-		DEC();
-	}
-	if (data->log_tag != NULL) {
-		if (tbuf_left > 1) {
-			*p++ = ':';
-			tbuf_left--;
-		}
-		if (tbuf_left > 1) {
-			*p++ = ' ';
-			tbuf_left--;
-		}
-	}
-
-	/* strerror() is not reentrant */
-
-	for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt); ++fmt) {
-		if (ch == '%' && fmt[1] == 'm') {
-			++fmt;
-			if (data == &sdata) {
-				prlen = snprintf(t, fmt_left, "%s",
-				    strerror(saved_errno));
-			} else {
-				prlen = snprintf(t, fmt_left, "Error %d",
-				    saved_errno);
-			}
-			if (prlen < 0)
-				prlen = 0;
-			if (prlen >= fmt_left)
-				prlen = fmt_left - 1;
-			t += prlen;
-			fmt_left -= prlen;
-		} else if (ch == '%' && fmt[1] == '%' && fmt_left > 2) {
-			*t++ = '%';
-			*t++ = '%';
-			fmt++;
-			fmt_left -= 2;
-		} else {
-			if (fmt_left > 1) {
-				*t++ = ch;
-				fmt_left--;
-			}
-		}
-	}
-	*t = '\0';
-
-	prlen = vsnprintf(p, tbuf_left, fmt_cpy, ap);
-	DEC();
-	cnt = p - tbuf;
-
-	/* Output to stderr if requested. */
-	if (data->log_stat & LOG_PERROR) {
-		struct iovec iov[2];
-
-		iov[0].iov_base = stdp;
-		iov[0].iov_len = cnt - (stdp - tbuf);
-		iov[1].iov_base = "\n";
-		iov[1].iov_len = 1;
-		(void)writev(STDERR_FILENO, iov, 2);
-	}
-
-	/* Get connected, output the message to the local logger. */
-	if (!data->opened)
-		openlog_r(data->log_tag, data->log_stat, 0, data);
-	connectlog_r(data);
-
-	/*
-	 * If the send() failed, there are two likely scenarios:
-	 *  1) syslogd was restarted
-	 *  2) /dev/log is out of socket buffer space
-	 * We attempt to reconnect to /dev/log to take care of
-	 * case #1 and keep send()ing data to cover case #2
-	 * to give syslogd a chance to empty its socket buffer.
-	 */
-	if ((error = send(data->log_file, tbuf, cnt, 0)) < 0) {
-		if (errno != ENOBUFS) {
-			disconnectlog_r(data);
-			connectlog_r(data);
-		}
-		do {
-			usleep(1);
-			if ((error = send(data->log_file, tbuf, cnt, 0)) >= 0)
-				break;
-		} while (errno == ENOBUFS);
-	}
-
-	/*
-	 * Output the message to the console; try not to block
-	 * as a blocking console should not stop other processes.
-	 * Make sure the error reported is the one from the syslogd failure.
-	 */
-	if (error == -1 && (data->log_stat & LOG_CONS) &&
-	    (fd = open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) {
-		struct iovec iov[2];
-
-		p = strchr(tbuf, '>') + 1;
-		iov[0].iov_base = p;
-		iov[0].iov_len = cnt - (p - tbuf);
-		iov[1].iov_base = "\r\n";
-		iov[1].iov_len = 2;
-		(void)writev(fd, iov, 2);
-		(void)close(fd);
-	}
-
-	if (data != &sdata)
-		closelog_r(data);
-}
-
-static void
-disconnectlog_r(struct syslog_data *data)
-{
-	/*
-	 * If the user closed the FD and opened another in the same slot,
-	 * that's their problem.  They should close it before calling on
-	 * system services.
-	 */
-	if (data->log_file != -1) {
-		close(data->log_file);
-		data->log_file = -1;
-	}
-	data->connected = 0;		/* retry connect */
-}
-
-static void
-connectlog_r(struct syslog_data *data)
-{
-    union {
-        struct sockaddr     syslogAddr;
-        struct sockaddr_un  syslogAddrUn;
-    } u;
-
-#define SyslogAddr   u.syslogAddrUn
-
-	if (data->log_file == -1) {
-		if ((data->log_file = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
-			return;
-		(void)fcntl(data->log_file, F_SETFD, 1);
-	}
-	if (data->log_file != -1 && !data->connected) {
-		memset(&SyslogAddr, '\0', sizeof(SyslogAddr));
-#if 0
-                /* BIONIC: no sun_len field to fill on Linux */
-		SyslogAddr.sun_len = sizeof(SyslogAddr);
-#endif
-		SyslogAddr.sun_family = AF_UNIX;
-		strlcpy(SyslogAddr.sun_path, _PATH_LOG,
-		    sizeof(SyslogAddr.sun_path));
-		if (connect(data->log_file, &u.syslogAddr,
-		    sizeof(SyslogAddr)) == -1) {
-			(void)close(data->log_file);
-			data->log_file = -1;
-		} else
-			data->connected = 1;
-	}
-}
-
-void
-openlog_r(const char *ident, int logstat, int logfac, struct syslog_data *data)
-{
-	if (ident != NULL)
-		data->log_tag = ident;
-	data->log_stat = logstat;
-	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
-		data->log_fac = logfac;
-
-	if (data->log_stat & LOG_NDELAY)	/* open immediately */
-		connectlog_r(data);
-
-	data->opened = 1;	/* ident and facility has been set */
-}
-
-void
-closelog_r(struct syslog_data *data)
-{
-	(void)close(data->log_file);
-	data->log_file = -1;
-	data->connected = 0;
-	data->log_tag = NULL;
-}
-
-/* setlogmask -- set the log mask level */
-int
-setlogmask_r(int pmask, struct syslog_data *data)
-{
-	int omask;
-
-	omask = data->log_mask;
-	if (pmask != 0)
-		data->log_mask = pmask;
-	return (omask);
-}
diff --git a/libc/upstream-freebsd/android/include/freebsd-compat.h b/libc/upstream-freebsd/android/include/freebsd-compat.h
index d5f1425..b44b94a 100644
--- a/libc/upstream-freebsd/android/include/freebsd-compat.h
+++ b/libc/upstream-freebsd/android/include/freebsd-compat.h
@@ -17,7 +17,7 @@
 #ifndef _BIONIC_FREEBSD_COMPAT_H_included
 #define _BIONIC_FREEBSD_COMPAT_H_included
 
-#define __USE_BSD
+#define _BSD_SOURCE
 #define REPLACE_GETOPT
 
 /*
diff --git a/libc/upstream-netbsd/android/include/netbsd-compat.h b/libc/upstream-netbsd/android/include/netbsd-compat.h
index 84be931..04bc728 100644
--- a/libc/upstream-netbsd/android/include/netbsd-compat.h
+++ b/libc/upstream-netbsd/android/include/netbsd-compat.h
@@ -17,6 +17,9 @@
 #ifndef _BIONIC_NETBSD_COMPAT_H_included
 #define _BIONIC_NETBSD_COMPAT_H_included
 
+#define _BSD_SOURCE
+#define _GNU_SOURCE
+
 // NetBSD uses _DIAGASSERT to null-check arguments and the like.
 #include <assert.h>
 #define _DIAGASSERT(e) ((e) ? (void) 0 : __assert2(__FILE__, __LINE__, __func__, #e))
@@ -24,9 +27,6 @@
 // TODO: update our <sys/cdefs.h> to support this properly.
 #define __type_fit(t, a) (0 == 0)
 
-#define _GNU_SOURCE
-#define __USE_BSD
-
 // TODO: we don't yet have thread-safe environment variables.
 #define __readlockenv() 0
 #define __unlockenv() 0
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-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
new file mode 100644
index 0000000..c07257d
--- /dev/null
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -0,0 +1,87 @@
+/*	$OpenBSD: arc4random_linux.h,v 1.7 2014/07/20 20:51:13 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@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.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include <sys/mman.h>
+
+#include <pthread.h>
+#include <signal.h>
+
+// Android gets these from "thread_private.h".
+#include "thread_private.h"
+//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+//#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+//#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+#ifdef __GLIBC__
+extern void *__dso_handle;
+extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
+#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
+#else
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+#endif
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsxp, sizeof(**rsxp));
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 5827a82..488b5f9 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -17,9 +17,10 @@
 #ifndef _BIONIC_OPENBSD_COMPAT_H_included
 #define _BIONIC_OPENBSD_COMPAT_H_included
 
-#include <sys/cdefs.h>
+#define _BSD_SOURCE
 
-#define __USE_BSD
+#include <sys/cdefs.h>
+#include <stddef.h> // For size_t.
 
 /* OpenBSD's <ctype.h> uses these names, which conflicted with stlport.
  * Additionally, we changed the numeric/digit type from N to D for libcxx.
@@ -36,6 +37,11 @@
 /* OpenBSD has this, but we can't really implement it correctly on Linux. */
 #define issetugid() 0
 
+#define explicit_bzero(p, s) memset(p, 0, s)
+
+/* We have OpenBSD's getentropy_linux.c, but we don't mention getentropy in any header. */
+__LIBC_HIDDEN__ extern int getentropy(void*, size_t);
+
 /* LP32 NDK ctype.h contained references to these. */
 __LIBC64_HIDDEN__ extern const short* _tolower_tab_;
 __LIBC64_HIDDEN__ extern const short* _toupper_tab_;
diff --git a/libc/upstream-openbsd/lib/libc/crypt/arc4random.c b/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
new file mode 100644
index 0000000..64248b6
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
@@ -0,0 +1,195 @@
+/*	$OpenBSD: arc4random.c,v 1.50 2014/07/21 18:13:12 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@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.
+ */
+
+/*
+ * ChaCha based random number generator for OpenBSD.
+ */
+
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+
+#define KEYSTREAM_ONLY
+#include "chacha_private.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#ifdef __GNUC__
+#define inline __inline
+#else				/* !__GNUC__ */
+#define inline
+#endif				/* !__GNUC__ */
+
+#define KEYSZ	32
+#define IVSZ	8
+#define BLOCKSZ	64
+#define RSBUFSZ	(16*BLOCKSZ)
+
+/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
+static struct _rs {
+	size_t		rs_have;	/* valid bytes at end of rs_buf */
+	size_t		rs_count;	/* bytes till reseed */
+} *rs;
+
+/* Maybe be preserved in fork children, if _rs_allocate() decides. */
+static struct _rsx {
+	chacha_ctx	rs_chacha;	/* chacha context for random keystream */
+	u_char		rs_buf[RSBUFSZ];	/* keystream blocks */
+} *rsx;
+
+static inline int _rs_allocate(struct _rs **, struct _rsx **);
+static inline void _rs_forkdetect(void);
+#include "arc4random.h"
+
+static inline void _rs_rekey(u_char *dat, size_t datlen);
+
+static inline void
+_rs_init(u_char *buf, size_t n)
+{
+	if (n < KEYSZ + IVSZ)
+		return;
+
+	if (rs == NULL) {
+		if (_rs_allocate(&rs, &rsx) == -1)
+			abort();
+	}
+
+	chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
+	chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
+}
+
+static void
+_rs_stir(void)
+{
+	u_char rnd[KEYSZ + IVSZ];
+
+	if (getentropy(rnd, sizeof rnd) == -1)
+		_getentropy_fail();
+
+	if (!rs)
+		_rs_init(rnd, sizeof(rnd));
+	else
+		_rs_rekey(rnd, sizeof(rnd));
+	explicit_bzero(rnd, sizeof(rnd));	/* discard source seed */
+
+	/* invalidate rs_buf */
+	rs->rs_have = 0;
+	memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
+
+	rs->rs_count = 1600000;
+}
+
+static inline void
+_rs_stir_if_needed(size_t len)
+{
+	_rs_forkdetect();
+	if (!rs || rs->rs_count <= len)
+		_rs_stir();
+	if (rs->rs_count <= len)
+		rs->rs_count = 0;
+	else
+		rs->rs_count -= len;
+}
+
+static inline void
+_rs_rekey(u_char *dat, size_t datlen)
+{
+#ifndef KEYSTREAM_ONLY
+	memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
+#endif
+	/* fill rs_buf with the keystream */
+	chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
+	    rsx->rs_buf, sizeof(rsx->rs_buf));
+	/* mix in optional user provided data */
+	if (dat) {
+		size_t i, m;
+
+		m = min(datlen, KEYSZ + IVSZ);
+		for (i = 0; i < m; i++)
+			rsx->rs_buf[i] ^= dat[i];
+	}
+	/* immediately reinit for backtracking resistance */
+	_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
+	memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
+	rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
+}
+
+static inline void
+_rs_random_buf(void *_buf, size_t n)
+{
+	u_char *buf = (u_char *)_buf;
+	u_char *keystream;
+	size_t m;
+
+	_rs_stir_if_needed(n);
+	while (n > 0) {
+		if (rs->rs_have > 0) {
+			m = min(n, rs->rs_have);
+			keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
+			    - rs->rs_have;
+			memcpy(buf, keystream, m);
+			memset(keystream, 0, m);
+			buf += m;
+			n -= m;
+			rs->rs_have -= m;
+		}
+		if (rs->rs_have == 0)
+			_rs_rekey(NULL, 0);
+	}
+}
+
+static inline void
+_rs_random_u32(uint32_t *val)
+{
+	u_char *keystream;
+
+	_rs_stir_if_needed(sizeof(*val));
+	if (rs->rs_have < sizeof(*val))
+		_rs_rekey(NULL, 0);
+	keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
+	memcpy(val, keystream, sizeof(*val));
+	memset(keystream, 0, sizeof(*val));
+	rs->rs_have -= sizeof(*val);
+}
+
+uint32_t
+arc4random(void)
+{
+	uint32_t val;
+
+	_ARC4_LOCK();
+	_rs_random_u32(&val);
+	_ARC4_UNLOCK();
+	return val;
+}
+
+void
+arc4random_buf(void *buf, size_t n)
+{
+	_ARC4_LOCK();
+	_rs_random_buf(buf, n);
+	_ARC4_UNLOCK();
+}
diff --git a/libc/upstream-openbsd/lib/libc/crypt/arc4random_uniform.c b/libc/upstream-openbsd/lib/libc/crypt/arc4random_uniform.c
new file mode 100644
index 0000000..1aa9a62
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/crypt/arc4random_uniform.c
@@ -0,0 +1,56 @@
+/*	$OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $	*/
+
+/*
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound).  This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+uint32_t
+arc4random_uniform(uint32_t upper_bound)
+{
+	uint32_t r, min;
+
+	if (upper_bound < 2)
+		return 0;
+
+	/* 2**32 % x == (2**32 - x) % x */
+	min = -upper_bound % upper_bound;
+
+	/*
+	 * This could theoretically loop forever but each retry has
+	 * p > 0.5 (worst case, usually far better) of selecting a
+	 * number inside the range we need, so it should rarely need
+	 * to re-roll.
+	 */
+	for (;;) {
+		r = arc4random();
+		if (r >= min)
+			break;
+	}
+
+	return r % upper_bound;
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c b/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c
new file mode 100644
index 0000000..8cda047
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c
@@ -0,0 +1,183 @@
+/*	$OpenBSD: fmemopen.c,v 1.2 2013/03/27 15:06:25 mpi Exp $	*/
+
+/*
+ * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
+ * Copyright (c) 2009 Ted Unangst
+ *
+ * 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.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+
+struct state {
+	char		*string;	/* actual stream */
+	size_t		 pos;		/* current position */
+	size_t		 size;		/* allocated size */
+	size_t		 len;		/* length of the data */
+	int		 update;	/* open for update */
+};
+
+static int
+fmemopen_read(void *v, char *b, int l)
+{
+	struct state	*st = v;
+	int		 i;
+
+	for (i = 0; i < l && i + st->pos < st->len; i++)
+		b[i] = st->string[st->pos + i];
+	st->pos += i;
+
+	return (i);
+}
+
+static int
+fmemopen_write(void *v, const char *b, int l)
+{
+	struct state	*st = v;
+	int		i;
+
+	for (i = 0; i < l && i + st->pos < st->size; i++)
+		st->string[st->pos + i] = b[i];
+	st->pos += i;
+
+	if (st->pos >= st->len) {
+		st->len = st->pos;
+
+		if (st->len < st->size)
+			st->string[st->len] = '\0';
+		else if (!st->update)
+			st->string[st->size - 1] = '\0';
+	}
+
+	return (i);
+}
+
+static fpos_t
+fmemopen_seek(void *v, fpos_t off, int whence)
+{
+	struct state	*st = v;
+	ssize_t		 base = 0;
+
+	switch (whence) {
+	case SEEK_SET:
+		break;
+	case SEEK_CUR:
+		base = st->pos;
+		break;
+	case SEEK_END:
+		base = st->len;
+		break;
+	}
+
+	if (off > st->size - base || off < -base) {
+		errno = EOVERFLOW;
+		return (-1);
+	}
+
+	st->pos = base + off;
+
+	return (st->pos);
+}
+
+static int
+fmemopen_close(void *v)
+{
+	free(v);
+
+	return (0);
+}
+
+static int
+fmemopen_close_free(void *v)
+{
+	struct state	*st = v;
+
+	free(st->string);
+	free(st);
+
+	return (0);
+}
+
+FILE *
+fmemopen(void *buf, size_t size, const char *mode)
+{
+	struct state	*st;
+	FILE		*fp;
+	int		 flags, oflags;
+
+	if (size == 0) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if ((flags = __sflags(mode, &oflags)) == 0) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (buf == NULL && ((oflags & O_RDWR) == 0)) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if ((st = malloc(sizeof(*st))) == NULL)
+		return (NULL);
+
+	if ((fp = __sfp()) == NULL) {
+		free(st);
+		return (NULL);
+	}
+
+	st->pos = 0;
+	st->len = (oflags & O_WRONLY) ? 0 : size;
+	st->size = size;
+	st->update = oflags & O_RDWR;
+
+	if (buf == NULL) {
+		if ((st->string = malloc(size)) == NULL) {
+			free(st);
+			fp->_flags = 0;
+			return (NULL);
+		}
+		*st->string = '\0';
+	} else {
+		st->string = (char *)buf;
+
+		if (oflags & O_TRUNC)
+			*st->string = '\0';
+
+		if (oflags & O_APPEND) {
+			char	*p;
+
+			if ((p = memchr(st->string, '\0', size)) != NULL)
+				st->pos = st->len = (p - st->string);
+			else
+				st->pos = st->len = size;
+		}
+	}
+
+	fp->_flags = (short)flags;
+	fp->_file = -1;
+	fp->_cookie = (void *)st;
+	fp->_read = (flags & __SWR) ? NULL : fmemopen_read;
+	fp->_write = (flags & __SRD) ? NULL : fmemopen_write;
+	fp->_seek = fmemopen_seek;
+	fp->_close = (buf == NULL) ? fmemopen_close_free : fmemopen_close;
+
+	return (fp);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c b/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
new file mode 100644
index 0000000..4610535
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
@@ -0,0 +1,158 @@
+/*	$OpenBSD: open_memstream.c,v 1.3 2013/04/03 03:11:53 guenther Exp $	*/
+
+/*
+ * Copyright (c) 2011 Martin Pieuchot <mpi@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.
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+
+struct state {
+	char		 *string;	/* actual stream */
+	char		**pbuf;		/* point to the stream */
+	size_t		 *psize;	/* point to min(pos, len) */
+	size_t		  pos;		/* current position */
+	size_t		  size;		/* number of allocated char */
+	size_t		  len;		/* length of the data */
+};
+
+static int
+memstream_write(void *v, const char *b, int l)
+{
+	struct state	*st = v;
+	char		*p;
+	size_t		 i, end;
+
+	end = (st->pos + l);
+
+	if (end >= st->size) {
+		/* 1.6 is (very) close to the golden ratio. */
+		size_t	sz = st->size * 8 / 5;
+
+		if (sz < end + 1)
+			sz = end + 1;
+		p = realloc(st->string, sz);
+		if (!p)
+			return (-1);
+		bzero(p + st->size, sz - st->size);
+		*st->pbuf = st->string = p;
+		st->size = sz;
+	}
+
+	for (i = 0; i < l; i++)
+		st->string[st->pos + i] = b[i];
+	st->pos += l;
+
+	if (st->pos > st->len) {
+		st->len = st->pos;
+		st->string[st->len] = '\0';
+	}
+
+	*st->psize = st->pos;
+
+	return (i);
+}
+
+static fpos_t
+memstream_seek(void *v, fpos_t off, int whence)
+{
+	struct state	*st = v;
+	ssize_t		 base = 0;
+
+	switch (whence) {
+	case SEEK_SET:
+		break;
+	case SEEK_CUR:
+		base = st->pos;
+		break;
+	case SEEK_END:
+		base = st->len;
+		break;
+	}
+
+	if (off > SIZE_MAX - base || off < -base) {
+		errno = EOVERFLOW;
+		return (-1);
+	}
+
+	st->pos = base + off;
+	*st->psize = MIN(st->pos, st->len);
+
+	return (st->pos);
+}
+
+static int
+memstream_close(void *v)
+{
+	struct state	*st = v;
+
+	free(st);
+
+	return (0);
+}
+
+FILE *
+open_memstream(char **pbuf, size_t *psize)
+{
+	struct state	*st;
+	FILE		*fp;
+
+	if (pbuf == NULL || psize == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if ((st = malloc(sizeof(*st))) == NULL)
+		return (NULL);
+
+	if ((fp = __sfp()) == NULL) {
+		free(st);
+		return (NULL);
+	}
+
+	st->size = BUFSIZ;
+	if ((st->string = calloc(1, st->size)) == NULL) {
+		free(st);
+		fp->_flags = 0;
+		return (NULL);
+	}
+
+	*st->string = '\0';
+	st->pos = 0;
+	st->len = 0;
+	st->pbuf = pbuf;
+	st->psize = psize;
+
+	*pbuf = st->string;
+	*psize = st->len;
+
+	fp->_flags = __SWR;
+	fp->_file = -1;
+	fp->_cookie = st;
+	fp->_read = NULL;
+	fp->_write = memstream_write;
+	fp->_seek = memstream_seek;
+	fp->_close = memstream_close;
+	_SET_ORIENTATION(fp, -1);
+
+	return (fp);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/open_wmemstream.c b/libc/upstream-openbsd/lib/libc/stdio/open_wmemstream.c
new file mode 100644
index 0000000..9414187
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/open_wmemstream.c
@@ -0,0 +1,169 @@
+/*	$OpenBSD: open_wmemstream.c,v 1.3 2014/03/06 07:28:21 gerhard Exp $	*/
+
+/*
+ * Copyright (c) 2011 Martin Pieuchot <mpi@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.
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "local.h"
+
+struct state {
+	wchar_t		 *string;	/* actual stream */
+	wchar_t		**pbuf;		/* point to the stream */
+	size_t		 *psize;	/* point to min(pos, len) */
+	size_t		  pos;		/* current position */
+	size_t		  size;		/* number of allocated wchar_t */
+	size_t		  len;		/* length of the data */
+	mbstate_t	  mbs;		/* conversion state of the stream */
+};
+
+static int
+wmemstream_write(void *v, const char *b, int l)
+{
+	struct state	*st = v;
+	wchar_t		*p;
+	size_t		 nmc, len, end;
+
+	end = (st->pos + l);
+
+	if (end >= st->size) {
+		/* 1.6 is (very) close to the golden ratio. */
+		size_t	sz = st->size * 8 / 5;
+
+		if (sz < end + 1)
+			sz = end + 1;
+		p = realloc(st->string, sz * sizeof(wchar_t));
+		if (!p)
+			return (-1);
+		bzero(p + st->size, (sz - st->size) * sizeof(wchar_t));
+		*st->pbuf = st->string = p;
+		st->size = sz;
+	}
+
+	nmc = (st->size - st->pos) * sizeof(wchar_t);
+	len = mbsnrtowcs(st->string + st->pos, &b, nmc, l, &st->mbs);
+	if (len == (size_t)-1)
+		return (-1);
+	st->pos += len;
+
+	if (st->pos > st->len) {
+		st->len = st->pos;
+		st->string[st->len] = L'\0';
+	}
+
+	*st->psize = st->pos;
+
+	return (len);
+}
+
+static fpos_t
+wmemstream_seek(void *v, fpos_t off, int whence)
+{
+	struct state	*st = v;
+	ssize_t		 base = 0;
+
+	switch (whence) {
+	case SEEK_SET:
+		break;
+	case SEEK_CUR:
+		base = st->pos;
+		break;
+	case SEEK_END:
+		base = st->len;
+		break;
+	}
+
+	if (off > (SIZE_MAX / sizeof(wchar_t)) - base || off < -base) {
+		errno = EOVERFLOW;
+		return (-1);
+	}
+
+	/*
+	 * XXX Clearing mbs here invalidates shift state for state-
+	 * dependent encodings, but they are not (yet) supported.
+	 */
+	bzero(&st->mbs, sizeof(st->mbs));
+
+	st->pos = base + off;
+	*st->psize = MIN(st->pos, st->len);
+
+	return (st->pos);
+}
+
+static int
+wmemstream_close(void *v)
+{
+	struct state	*st = v;
+
+	free(st);
+
+	return (0);
+}
+
+FILE *
+open_wmemstream(wchar_t **pbuf, size_t *psize)
+{
+	struct state	*st;
+	FILE		*fp;
+
+	if (pbuf == NULL || psize == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if ((st = malloc(sizeof(*st))) == NULL)
+		return (NULL);
+
+	if ((fp = __sfp()) == NULL) {
+		free(st);
+		return (NULL);
+	}
+
+	st->size = BUFSIZ * sizeof(wchar_t);
+	if ((st->string = calloc(1, st->size)) == NULL) {
+		free(st);
+		fp->_flags = 0;
+		return (NULL);
+	}
+
+	*st->string = L'\0';
+	st->pos = 0;
+	st->len = 0;
+	st->pbuf = pbuf;
+	st->psize = psize;
+	bzero(&st->mbs, sizeof(st->mbs));
+
+	*pbuf = st->string;
+	*psize = st->len;
+
+	fp->_flags = __SWR;
+	fp->_file = -1;
+	fp->_cookie = st;
+	fp->_read = NULL;
+	fp->_write = wmemstream_write;
+	fp->_seek = wmemstream_seek;
+	fp->_close = wmemstream_close;
+	_SET_ORIENTATION(fp, 1);
+
+	return (fp);
+}
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/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index a5ae1f6..9547f58 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ
diff --git a/libm/include/math.h b/libm/include/math.h
index 4faec33..c51f3af 100644
--- a/libm/include/math.h
+++ b/libm/include/math.h
@@ -462,11 +462,11 @@
 
 #endif /* __ISO_C_VISIBLE >= 1999 */
 
-#if defined(_GNU_SOURCE)
+#if defined(__USE_GNU)
 void sincos(double, double*, double*);
 void sincosf(float, float*, float*);
 void sincosl(long double, long double*, long double*);
-#endif /* _GNU_SOURCE */
+#endif /* __USE_GNU */
 
 #pragma GCC visibility pop
 __END_DECLS
diff --git a/libm/sincos.c b/libm/sincos.c
index ad75549..a5608cf 100644
--- a/libm/sincos.c
+++ b/libm/sincos.c
@@ -22,8 +22,8 @@
  * 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.
- *
  */
+
 #define _GNU_SOURCE 1
 #include <math.h>
 
diff --git a/libstdc++/Android.mk b/libstdc++/Android.mk
deleted file mode 100644
index ff9609a..0000000
--- a/libstdc++/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := src/libstdc++.cpp
-LOCAL_MODULE:= libstdc++
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_SYSTEM_SHARED_LIBRARIES := libc
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= src/libstdc++.cpp
-LOCAL_MODULE:= libstdc++
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_SYSTEM_SHARED_LIBRARIES := libc
-include $(BUILD_STATIC_LIBRARY)
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/libstdc++/include/new b/libstdc++/include/new
index 0253e8b..c5a43de 100644
--- a/libstdc++/include/new
+++ b/libstdc++/include/new
@@ -13,19 +13,19 @@
 
 void* operator new(std::size_t);
 void* operator new[](std::size_t);
-void  operator delete(void*);
-void  operator delete[](void*);
+void  operator delete(void*) throw();
+void  operator delete[](void*) throw();
 void* operator new(std::size_t, const std::nothrow_t&);
 void* operator new[](std::size_t, const std::nothrow_t&);
-void  operator delete(void*, const std::nothrow_t&);
-void  operator delete[](void*, const std::nothrow_t&);
+void  operator delete(void*, const std::nothrow_t&) throw();
+void  operator delete[](void*, const std::nothrow_t&) throw();
 
 inline void* operator new(std::size_t, void* p) { return p; }
 inline void* operator new[](std::size_t, void* p) { return p; }
 
 // these next two are not really required, since exceptions are off
-inline void  operator delete(void*, void*) { }
-inline void  operator delete[](void*, void*) { }
+inline void  operator delete(void*, void*) throw() { }
+inline void  operator delete[](void*, void*) throw() { }
 
 }  // extern C++
 
diff --git a/libstdc++/src/libstdc++.cpp b/libstdc++/src/libstdc++.cpp
deleted file mode 100644
index 3676aa1..0000000
--- a/libstdc++/src/libstdc++.cpp
+++ /dev/null
@@ -1 +0,0 @@
-extern "C" void __this_library_is_now_part_of_libc() {}
diff --git a/linker/Android.mk b/linker/Android.mk
index 68e801d..4298032 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -8,6 +8,7 @@
     linker.cpp \
     linker_allocator.cpp \
     linker_environ.cpp \
+    linker_libc_support.c \
     linker_phdr.cpp \
     rt.cpp \
 
@@ -57,6 +58,10 @@
 LOCAL_MODULE_STEM_64 := linker64
 LOCAL_MULTILIB := both
 
+# Leave the symbols in the shared library so that stack unwinders can produce
+# meaningful name resolution.
+LOCAL_STRIP_MODULE := keep_symbols
+
 include $(LOCAL_PATH)/linker_executable.mk
 ifdef TARGET_2ND_ARCH
 LOCAL_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX)
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..e15f54d 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -100,23 +100,29 @@
 
   soinfo* found = NULL;
   ElfW(Sym)* sym = NULL;
-  void* caller_addr = __builtin_return_address(0);
-  soinfo* caller_si = find_containing_library(caller_addr);
-
   if (handle == RTLD_DEFAULT) {
-    sym = dlsym_linear_lookup(symbol, &found, NULL, caller_si);
+    sym = dlsym_linear_lookup(symbol, &found, NULL);
   } else if (handle == RTLD_NEXT) {
+    void* caller_addr = __builtin_return_address(0);
+    soinfo* si = find_containing_library(caller_addr);
+
     sym = NULL;
-    if (caller_si && caller_si->next) {
-      sym = dlsym_linear_lookup(symbol, &found, caller_si->next, caller_si);
+    if (si && si->next) {
+      sym = dlsym_linear_lookup(symbol, &found, si->next);
     }
   } else {
-    found = reinterpret_cast<soinfo*>(handle);
-    sym = dlsym_handle_lookup(found, symbol, caller_si);
+    sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol);
   }
 
-  if (sym != NULL && sym->st_shndx != 0) {
-    return reinterpret_cast<void*>(sym->st_value + found->load_bias);
+  if (sym != NULL) {
+    unsigned bind = ELF_ST_BIND(sym->st_info);
+
+    if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
+      return reinterpret_cast<void*>(sym->st_value + found->load_bias);
+    }
+
+    __bionic_format_dlerror("symbol found but not global", symbol);
+    return NULL;
   } else {
     __bionic_format_dlerror("undefined symbol", symbol);
     return NULL;
@@ -226,17 +232,12 @@
 static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
 #endif
 
-// Defined as global because we do not yet have access
-// to synchronization functions __cxa_guard_* needed
-// to define statics inside functions.
-static soinfo __libdl_info;
+static soinfo __libdl_info("libdl.so", nullptr);
 
 // This is used by the dynamic linker. Every process gets these symbols for free.
 soinfo* get_libdl_info() {
-  if (__libdl_info.name[0] == '\0') {
-    // initialize
-    strncpy(__libdl_info.name, "libdl.so", sizeof(__libdl_info.name));
-    __libdl_info.flags = FLAG_LINKED | FLAG_NEW_SOINFO;
+  if ((__libdl_info.flags & FLAG_LINKED) == 0) {
+    __libdl_info.flags |= FLAG_LINKED;
     __libdl_info.strtab = ANDROID_LIBDL_STRTAB;
     __libdl_info.symtab = g_libdl_symtab;
     __libdl_info.nbucket = sizeof(g_libdl_buckets)/sizeof(unsigned);
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 52af0f1..e51eb9c 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -31,13 +31,48 @@
 template<typename T, typename Allocator>
 class LinkedList {
  public:
-  LinkedList() : head_(nullptr) {}
+  LinkedList() : head_(nullptr), tail_(nullptr) {}
+  ~LinkedList() {
+    clear();
+  }
 
   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 +81,8 @@
       head_ = head_->next;
       Allocator::free(p);
     }
+
+    tail_ = nullptr;
   }
 
   template<typename F>
@@ -66,8 +103,18 @@
     }
   }
 
+  bool contains(const T* el) {
+    for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
+      if (e->element != nullptr && e->element == el) {
+        return true;
+      }
+    }
+    return false;
+  }
+
  private:
   LinkedListEntry<T>* head_;
+  LinkedListEntry<T>* tail_;
   DISALLOW_COPY_AND_ASSIGN(LinkedList);
 };
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 04ffe59..5f5823b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -35,9 +35,10 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/stat.h>
 #include <unistd.h>
 
+#include <new>
+
 // Private C library headers.
 #include "private/bionic_tls.h"
 #include "private/KernelArgumentBlock.h"
@@ -125,11 +126,6 @@
     kRelocMax
 };
 
-enum class SymbolLookupScope {
-  kAllowLocal,
-  kExcludeLocal,
-};
-
 #if STATS
 struct linker_stats_t {
     int count[kRelocMax];
@@ -295,17 +291,7 @@
     return NULL;
   }
 
-  soinfo* si = g_soinfo_allocator.alloc();
-
-  // Initialize the new element.
-  memset(si, 0, sizeof(soinfo));
-  strlcpy(si->name, name, sizeof(si->name));
-  si->flags = FLAG_NEW_SOINFO;
-
-  if (file_stat != NULL) {
-    si->set_st_dev(file_stat->st_dev);
-    si->set_st_ino(file_stat->st_ino);
-  }
+  soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(name, file_stat);
 
   sonext->next = si;
   sonext = si;
@@ -433,7 +419,7 @@
     return rv;
 }
 
-static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name, const SymbolLookupScope& lookup_scope) {
+static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {
   ElfW(Sym)* symtab = si->symtab;
   const char* strtab = si->strtab;
 
@@ -444,6 +430,7 @@
     ElfW(Sym)* s = symtab + n;
     if (strcmp(strtab + s->st_name, name)) continue;
 
+    /* only concern ourselves with global and weak symbol definitions */
     switch (ELF_ST_BIND(s->st_info)) {
       case STB_GLOBAL:
       case STB_WEAK:
@@ -456,22 +443,59 @@
                  static_cast<size_t>(s->st_size));
         return s;
       case STB_LOCAL:
-        if (lookup_scope != SymbolLookupScope::kAllowLocal) {
-          continue;
-        }
-        TRACE_TYPE(LOOKUP, "FOUND LOCAL %s in %s (%p) %zd",
-                name, si->name, reinterpret_cast<void*>(s->st_value),
-                static_cast<size_t>(s->st_size));
-        return s;
+        continue;
       default:
         __libc_fatal("ERROR: Unexpected ST_BIND value: %d for '%s' in '%s'",
             ELF_ST_BIND(s->st_info), name, si->name);
     }
   }
 
+  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;
 }
 
+soinfo::soinfo(const char* name, const struct stat* file_stat) {
+  memset(this, 0, sizeof(*this));
+
+  strlcpy(this->name, name, sizeof(this->name));
+  flags = FLAG_NEW_SOINFO;
+  version = SOINFO_VERSION;
+
+  if (file_stat != NULL) {
+    set_st_dev(file_stat->st_dev);
+    set_st_ino(file_stat->st_ino);
+  }
+}
+
+void soinfo::resolve_ifunc_symbols() {
+  if (!get_has_ifuncs()) {
+    return;
+  }
+
+  phdr_table_unprotect_segments(phdr, phnum, load_bias);
+
+  TRACE_TYPE(IFUNC, "CHECKING FOR IFUNCS AND PERFORMING SYMBOL UPDATES");
+
+  for (size_t i = 0; i < nchain; ++i) {
+    ElfW(Sym)* s = &symtab[i];
+    if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
+      // The address of the ifunc in the symbol table is the address of the
+      // function that chooses the function to which the ifunc will refer.
+      // In order to return the proper value, we run the choosing function
+      // in the linker and then return its result (minus the base offset).
+      TRACE_TYPE(IFUNC, "FOUND IFUNC");
+      ElfW(Addr) (*ifunc_ptr)();
+      ifunc_ptr = reinterpret_cast<ElfW(Addr)(*)()>(s->st_value + base);
+      s->st_value = (ifunc_ptr() - base);
+      TRACE_TYPE(IFUNC, "NEW VALUE IS %p", (void*)s->st_value);
+    }
+  }
+  phdr_table_protect_segments(phdr, phnum, load_bias);
+}
+
 static unsigned elfhash(const char* _name) {
     const unsigned char* name = reinterpret_cast<const unsigned char*>(_name);
     unsigned h = 0, g;
@@ -496,7 +520,7 @@
          */
 
         if (si == somain) {
-            s = soinfo_elf_lookup(si, elf_hash, name, SymbolLookupScope::kAllowLocal);
+            s = soinfo_elf_lookup(si, elf_hash, name);
             if (s != NULL) {
                 *lsi = si;
                 goto done;
@@ -513,7 +537,7 @@
             if (!si->has_DT_SYMBOLIC) {
                 DEBUG("%s: looking up %s in executable %s",
                       si->name, name, somain->name);
-                s = soinfo_elf_lookup(somain, elf_hash, name, SymbolLookupScope::kExcludeLocal);
+                s = soinfo_elf_lookup(somain, elf_hash, name);
                 if (s != NULL) {
                     *lsi = somain;
                     goto done;
@@ -530,7 +554,7 @@
              * and some the first non-weak definition.   This is system dependent.
              * Here we return the first definition found for simplicity.  */
 
-            s = soinfo_elf_lookup(si, elf_hash, name, SymbolLookupScope::kAllowLocal);
+            s = soinfo_elf_lookup(si, elf_hash, name);
             if (s != NULL) {
                 *lsi = si;
                 goto done;
@@ -544,7 +568,7 @@
             if (si->has_DT_SYMBOLIC) {
                 DEBUG("%s: looking up %s in executable %s after local scope",
                       si->name, name, somain->name);
-                s = soinfo_elf_lookup(somain, elf_hash, name, SymbolLookupScope::kExcludeLocal);
+                s = soinfo_elf_lookup(somain, elf_hash, name);
                 if (s != NULL) {
                     *lsi = somain;
                     goto done;
@@ -555,7 +579,7 @@
 
     /* Next, look for it in the preloads list */
     for (int i = 0; g_ld_preloads[i] != NULL; i++) {
-        s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name, SymbolLookupScope::kExcludeLocal);
+        s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
         if (s != NULL) {
             *lsi = g_ld_preloads[i];
             goto done;
@@ -565,7 +589,7 @@
     for (int i = 0; needed[i] != NULL; i++) {
         DEBUG("%s: looking up %s in %s",
               si->name, name, needed[i]->name);
-        s = soinfo_elf_lookup(needed[i], elf_hash, name, SymbolLookupScope::kExcludeLocal);
+        s = soinfo_elf_lookup(needed[i], elf_hash, name);
         if (s != NULL) {
             *lsi = needed[i];
             goto done;
@@ -585,18 +609,46 @@
     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) {
+  LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
+  LinkedList<soinfo, SoinfoListAllocatorRW> visited;
+  visit_list.push_back(si);
+  soinfo* current_soinfo;
+  while ((current_soinfo = visit_list.pop_front()) != nullptr) {
+    if (visited.contains(current_soinfo)) {
+      continue;
+    }
+
+    ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name);
+
+    if (result != nullptr) {
+      *found = current_soinfo;
+      return result;
+    }
+    visited.push_back(current_soinfo);
+
+    current_soinfo->get_children().for_each([&](soinfo* child) {
+      visit_list.push_back(child);
+    });
+  }
+
+  return nullptr;
 }
 
 /* This is used by dlsym(3) to performs a global symbol lookup. If the
@@ -604,7 +656,7 @@
    beginning of the global solist. Otherwise the search starts at the
    specified soinfo (for RTLD_NEXT).
  */
-ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start, soinfo* caller) {
+ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) {
   unsigned elf_hash = elfhash(name);
 
   if (start == NULL) {
@@ -613,8 +665,7 @@
 
   ElfW(Sym)* s = NULL;
   for (soinfo* si = start; (s == NULL) && (si != NULL); si = si->next) {
-    s = soinfo_elf_lookup(si, elf_hash, name,
-        caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
+    s = soinfo_elf_lookup(si, elf_hash, name);
     if (s != NULL) {
       *found = si;
       break;
@@ -809,7 +860,7 @@
     TRACE("unloading '%s'", si->name);
     si->CallDestructors();
 
-    if ((si->flags | FLAG_NEW_SOINFO) != 0) {
+    if (si->has_min_version(0)) {
       si->get_children().for_each([&] (soinfo* child) {
         TRACE("%s needs to unload %s", si->name, child->name);
         soinfo_unload(child);
@@ -874,6 +925,53 @@
   protect_data(PROT_READ);
 }
 
+// ifuncs are only defined for x86
+#if defined(__i386__)
+static void soinfo_ifunc_relocate(soinfo* si, ElfW(Rel)* rel, unsigned count, soinfo* needed[]) {
+  for (size_t idx = 0; idx < count; ++idx, ++rel) {
+    ElfW(Sym)* s;
+    soinfo* lsi;
+    unsigned type = ELFW(R_TYPE)(rel->r_info);
+    unsigned sym = ELFW(R_SYM)(rel->r_info);
+    ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + si->load_bias);
+    ElfW(Addr) sym_addr = 0;
+    const char* sym_name = NULL;
+    sym_name = reinterpret_cast<const char*>(si->strtab + si->symtab[sym].st_name);
+    s = soinfo_do_lookup(si, sym_name, &lsi, needed);
+
+    if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC && type == R_386_JMP_SLOT) {
+      TRACE("IFUNC RELOCATION, PASS 2: %p",  (void*)(sym_addr));
+      ElfW(Addr) (*ifunc_ptr)();
+      ifunc_ptr = reinterpret_cast<ElfW(Addr)(*)()>(s->st_value + si->base);
+      *reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_ptr();
+    }
+  }
+}
+#endif
+
+#if defined(__x86_64__)
+static void soinfo_ifunc_relocate(soinfo* si, ElfW(Rela)* rela, unsigned count, soinfo* needed[]) {
+  for (size_t idx = 0; idx < count; ++idx, ++rela) {
+    ElfW(Sym)* s;
+    soinfo* lsi;
+    unsigned type = ELFW(R_TYPE)(rela->r_info);
+    unsigned sym = ELFW(R_SYM)(rela->r_info);
+    ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rela->r_offset + si->load_bias);
+    ElfW(Addr) sym_addr = 0;
+    const char* sym_name = NULL;
+    sym_name = reinterpret_cast<const char*>(si->strtab + si->symtab[sym].st_name);
+    s = soinfo_do_lookup(si, sym_name, &lsi, needed);
+
+    if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC && type == R_X86_64_JUMP_SLOT) {
+      TRACE("IFUNC RELOCATION, PASS 2: %p",  (void*)(sym_addr + rela->r_addend));
+      ElfW(Addr) (*ifunc_ptr)();
+      ifunc_ptr = reinterpret_cast<ElfW(Addr)(*)()>(s->st_value + si->base);
+      *reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_ptr();
+    }
+  }
+}
+#endif
+
 #if defined(USE_RELA)
 static int soinfo_relocate(soinfo* si, ElfW(Rela)* rela, unsigned count, soinfo* needed[]) {
   ElfW(Sym)* s;
@@ -1085,7 +1183,11 @@
       MARK(rela->r_offset);
       TRACE_TYPE(RELO, "RELO JMP_SLOT %08zx <- %08zx %s", static_cast<size_t>(reloc),
                  static_cast<size_t>(sym_addr + rela->r_addend), sym_name);
-      *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + rela->r_addend;
+      if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
+        si->set_has_ifuncs(true);
+      } else {
+        *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + rela->r_addend;
+      }
       break;
     case R_X86_64_GLOB_DAT:
       count_relocation(kRelocAbsolute);
@@ -1264,7 +1366,11 @@
             count_relocation(kRelocAbsolute);
             MARK(rel->r_offset);
             TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name);
-            *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr;
+            if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
+              si->set_has_ifuncs(true);
+            } else {
+              *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr;
+            }
             break;
         case R_386_GLOB_DAT:
             count_relocation(kRelocAbsolute);
@@ -1460,6 +1566,8 @@
   // DT_INIT should be called before DT_INIT_ARRAY if both are present.
   CallFunction("DT_INIT", init_func);
   CallArray("DT_INIT_ARRAY", init_array, init_array_count, false);
+
+  resolve_ifunc_symbols();
 }
 
 void soinfo::CallDestructors() {
@@ -1477,16 +1585,14 @@
 }
 
 void soinfo::add_child(soinfo* child) {
-  if ((this->flags & FLAG_NEW_SOINFO) == 0) {
-    return;
+  if (has_min_version(0)) {
+    this->children.push_front(child);
+    child->parents.push_front(this);
   }
-
-  this->children.push_front(child);
-  child->parents.push_front(this);
 }
 
 void soinfo::remove_all_links() {
-  if ((this->flags & FLAG_NEW_SOINFO) == 0) {
+  if (!has_min_version(0)) {
     return;
   }
 
@@ -1509,35 +1615,45 @@
 }
 
 void soinfo::set_st_dev(dev_t dev) {
-  if ((this->flags & FLAG_NEW_SOINFO) == 0) {
-    return;
+  if (has_min_version(0)) {
+    st_dev = dev;
   }
-
-  st_dev = dev;
 }
 
 void soinfo::set_st_ino(ino_t ino) {
-  if ((this->flags & FLAG_NEW_SOINFO) == 0) {
-    return;
+  if (has_min_version(0)) {
+    st_ino = ino;
   }
+}
 
-  st_ino = ino;
+void soinfo::set_has_ifuncs(bool ifuncs) {
+  if (has_min_version(1)) {
+    has_ifuncs = ifuncs;
+  }
 }
 
 dev_t soinfo::get_st_dev() {
-  if ((this->flags & FLAG_NEW_SOINFO) == 0) {
-    return 0;
+  if (has_min_version(0)) {
+    return st_dev;
   }
 
-  return st_dev;
+  return 0;
 };
 
 ino_t soinfo::get_st_ino() {
-  if ((this->flags & FLAG_NEW_SOINFO) == 0) {
-    return 0;
+  if (has_min_version(0)) {
+    return st_ino;
   }
 
-  return st_ino;
+  return 0;
+}
+
+bool soinfo::get_has_ifuncs() {
+  if (has_min_version(1)) {
+    return has_ifuncs;
+  }
+
+  return false;
 }
 
 // This is a return on get_children() in case
@@ -1545,11 +1661,11 @@
 static soinfo::soinfo_list_t g_empty_list;
 
 soinfo::soinfo_list_t& soinfo::get_children() {
-  if ((this->flags & FLAG_NEW_SOINFO) == 0) {
-    return g_empty_list;
+  if (has_min_version(0)) {
+    return this->children;
   }
 
-  return this->children;
+  return g_empty_list;
 }
 
 /* Force any of the closed stdin, stdout and stderr to be associated with
@@ -1924,6 +2040,18 @@
     }
 #endif
 
+    // if there are ifuncs, we need to do an additional relocation pass.
+    // they cannot be resolved until the rest of the relocations are done
+    // because we need to call the resolution function which may be waiting
+    // on relocations.
+    if(si->get_has_ifuncs()) {
+#if defined(__i386__)
+      soinfo_ifunc_relocate(si, si->plt_rel, si->plt_rel_count, needed);
+#elif defined(__x86_64__)
+      soinfo_ifunc_relocate(si, si->plt_rela, si->plt_rela_count, needed);
+#endif
+    }
+
 #if defined(__mips__)
     if (!mips_relocate_got(si, needed)) {
         return false;
@@ -1999,7 +2127,12 @@
 /*
  * This is linker soinfo for GDB. See details below.
  */
-static soinfo linker_soinfo_for_gdb;
+#if defined(__LP64__)
+#define LINKER_PATH "/system/bin/linker64"
+#else
+#define LINKER_PATH "/system/bin/linker"
+#endif
+static soinfo linker_soinfo_for_gdb(LINKER_PATH, nullptr);
 
 /* gdb expects the linker to be in the debug shared object list.
  * Without this, gdb has trouble locating the linker's ".text"
@@ -2009,12 +2142,6 @@
  * be on the soinfo list.
  */
 static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
-#if defined(__LP64__)
-  strlcpy(linker_soinfo_for_gdb.name, "/system/bin/linker64", sizeof(linker_soinfo_for_gdb.name));
-#else
-  strlcpy(linker_soinfo_for_gdb.name, "/system/bin/linker", sizeof(linker_soinfo_for_gdb.name));
-#endif
-  linker_soinfo_for_gdb.flags = FLAG_NEW_SOINFO;
   linker_soinfo_for_gdb.base = linker_base;
 
   /*
@@ -2036,16 +2163,6 @@
  * and other non-local data at this point.
  */
 static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(Addr) linker_base) {
-    /* NOTE: we store the args pointer on a special location
-     *       of the temporary TLS area in order to pass it to
-     *       the C Library's runtime initializer.
-     *
-     *       The initializer must clear the slot and reset the TLS
-     *       to point to a different location to ensure that no other
-     *       shared library constructor can access it.
-     */
-  __libc_init_tls(args);
-
 #if TIMING
     struct timeval t0, t1;
     gettimeofday(&t0, 0);
@@ -2077,12 +2194,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 +2338,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
@@ -2237,20 +2350,25 @@
  * function, or other GOT reference will generate a segfault.
  */
 extern "C" ElfW(Addr) __linker_init(void* raw_args) {
-  // Initialize static variables.
-  solist = get_libdl_info();
-  sonext = get_libdl_info();
-
   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));
+  soinfo linker_so("[dynamic linker]", nullptr);
 
-  strcpy(linker_so.name, "[dynamic linker]");
+  // 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]);
+  }
+
   linker_so.base = linker_addr;
   linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
   linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);
@@ -2271,6 +2389,17 @@
     _exit(EXIT_FAILURE);
   }
 
+  __libc_init_tls(args);
+
+  // Initialize the linker's own global variables
+  linker_so.CallConstructors();
+
+  // Initialize static variables. Note that in order to
+  // get correct libdl_info we need to call constructors
+  // before get_libdl_info().
+  solist = get_libdl_info();
+  sonext = get_libdl_info();
+
   // 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..5e21f70 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -30,6 +30,7 @@
 #define _LINKER_H_
 
 #include <elf.h>
+#include <inttypes.h>
 #include <link.h>
 #include <unistd.h>
 #include <android/dlext.h>
@@ -88,6 +89,8 @@
 #define FLAG_LINKER     0x00000010 // The linker itself
 #define FLAG_NEW_SOINFO 0x40000000 // new soinfo format
 
+#define SOINFO_VERSION 1
+
 #define SOINFO_NAME_LEN 128
 
 typedef void (*linker_function_t)();
@@ -195,6 +198,9 @@
   bool has_text_relocations;
 #endif
   bool has_DT_SYMBOLIC;
+
+  soinfo(const char* name, const struct stat* file_stat);
+
   void CallConstructors();
   void CallDestructors();
   void CallPreInitConstructors();
@@ -204,20 +210,27 @@
 
   void set_st_dev(dev_t st_dev);
   void set_st_ino(ino_t st_ino);
+  void set_has_ifuncs(bool ifunc);
   ino_t get_st_ino();
   dev_t get_st_dev();
+  bool get_has_ifuncs();
 
   soinfo_list_t& get_children();
 
+  bool inline has_min_version(uint32_t min_version) {
+    return (flags & FLAG_NEW_SOINFO) != 0 && version >= min_version;
+  }
  private:
   void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
   void CallFunction(const char* function_name, linker_function_t function);
+  void resolve_ifunc_symbols();
 
  private:
   // This part of the structure is only available
   // when FLAG_NEW_SOINFO is set in this->flags.
-  unsigned int version;
+  uint32_t version;
 
+  // version >= 0
   dev_t st_dev;
   ino_t st_ino;
 
@@ -225,6 +238,8 @@
   soinfo_list_t children;
   soinfo_list_t parents;
 
+  // version >= 1
+  bool has_ifuncs;
 };
 
 extern soinfo* get_libdl_info();
@@ -234,11 +249,11 @@
 soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
 void do_dlclose(soinfo* si);
 
-ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start, soinfo* caller_si);
+ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start);
 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);
 
 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..92220e8 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -18,6 +18,8 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
+#include "private/bionic_prctl.h"
+
 struct LinkerAllocatorPage {
   LinkerAllocatorPage* next;
   uint8_t bytes[PAGE_SIZE-sizeof(LinkerAllocatorPage*)];
@@ -28,17 +30,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();
@@ -101,6 +98,9 @@
   if (page == MAP_FAILED) {
     abort(); // oom
   }
+
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, PAGE_SIZE, "linker_alloc");
+
   memset(page, 0, PAGE_SIZE);
 
   FreeBlockInfo* first_block = reinterpret_cast<FreeBlockInfo*>(page->bytes);
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/linker_debug.h b/linker/linker_debug.h
index 3faa38e..0c7a784 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -42,6 +42,7 @@
 #define TRACE_DEBUG          1
 #define DO_TRACE_LOOKUP      1
 #define DO_TRACE_RELO        1
+#define DO_TRACE_IFUNC       1
 #define TIMING               0
 #define STATS                0
 #define COUNT_PAGES          0
diff --git a/tests/libs/dlsym_local_symbol.map b/linker/linker_libc_support.c
similarity index 79%
rename from tests/libs/dlsym_local_symbol.map
rename to linker/linker_libc_support.c
index 58a2299..17db6d4 100644
--- a/tests/libs/dlsym_local_symbol.map
+++ b/linker/linker_libc_support.c
@@ -13,10 +13,5 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-LIBTEST_LOCAL_SYMBOL_1.0 {
-  global:
-    dlsym_local_symbol_get_taxicab_number;
-    dlsym_local_symbol_get_taxicab_number_using_dlsym;
-  local:
-    *;
-};
+
+#include "../libc/arch-common/bionic/__dso_handle.h"
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..5179bfa 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -85,12 +85,14 @@
     pthread_test.cpp \
     regex_test.cpp \
     sched_test.cpp \
+    search_test.cpp \
     signal_test.cpp \
     stack_protector_test.cpp \
     stack_unwinding_test.cpp \
     stdatomic_test.cpp \
     stdint_test.cpp \
     stdio_test.cpp \
+    stdio_ext_test.cpp \
     stdlib_test.cpp \
     string_test.cpp \
     strings_test.cpp \
@@ -128,6 +130,7 @@
 
 libBionicStandardTests_c_includes := \
     bionic/libc \
+    external/tinyxml2 \
 
 libBionicStandardTests_ldlibs_host := \
     -lrt \
@@ -236,11 +239,16 @@
 
 # -----------------------------------------------------------------------------
 # Tests for the device using bionic's .so. Run with:
-#   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
+#   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
+#   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
 # -----------------------------------------------------------------------------
 bionic-unit-tests_whole_static_libraries := \
     libBionicTests \
 
+bionic-unit-tests_static_libraries := \
+    libtinyxml2 \
+    liblog \
+
 bionic-unit-tests_src_files := \
     atexit_test.cpp \
     dlext_test.cpp \
@@ -268,7 +276,8 @@
 
 # -----------------------------------------------------------------------------
 # Tests for the device linked against bionic's static library. Run with:
-#   adb shell /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static
+#   adb shell /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
+#   adb shell /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
 # -----------------------------------------------------------------------------
 bionic-unit-tests-static_whole_static_libraries := \
     libBionicTests \
@@ -278,6 +287,8 @@
     libm \
     libc \
     libstdc++ \
+    libtinyxml2 \
+    liblog \
 
 bionic-unit-tests-static_force_static_executable := true
 
@@ -353,6 +364,22 @@
 		$(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests$(NATIVE_TEST_SUFFIX) $(BIONIC_TEST_FLAGS)
 endif
 
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86_64))
+# add target to run lp32 tests
+bionic-unit-tests-run-on-host32: bionic-unit-tests_32 $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
+	if [ ! -d /system -o ! -d /system/bin ]; then \
+	  echo "Attempting to create /system/bin"; \
+	  sudo mkdir -p -m 0777 /system/bin; \
+	fi
+	mkdir -p $(TARGET_OUT_DATA)/local/tmp
+	cp $(TARGET_OUT_EXECUTABLES)/linker /system/bin
+	cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
+	ANDROID_DATA=$(TARGET_OUT_DATA) \
+	ANDROID_ROOT=$(TARGET_OUT) \
+	LD_LIBRARY_PATH=$(2ND_TARGET_OUT_SHARED_LIBRARIES) \
+		$(2ND_TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests32 $(BIONIC_TEST_FLAGS)
+endif
+
 endif # linux-x86
 
 include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/atexit_test.cpp b/tests/atexit_test.cpp
index e01220e..e92889d 100644
--- a/tests/atexit_test.cpp
+++ b/tests/atexit_test.cpp
@@ -24,20 +24,33 @@
 
 #include <string>
 
-TEST(atexit, dlclose) {
+TEST(atexit, sofile) {
   std::string atexit_call_sequence;
   bool valid_this_in_static_dtor = false;
+  bool attr_dtor_called = false;
+
   void* handle = dlopen("libtest_atexit.so", RTLD_NOW);
-  ASSERT_TRUE(handle != NULL);
+  ASSERT_TRUE(handle != nullptr);
+
+  typedef int (*int_fn)(void);
+  int_fn get_cxx_ctor_called, get_attr_ctor_called;
+  get_cxx_ctor_called = reinterpret_cast<int_fn>(dlsym(handle, "get_cxx_ctor_called"));
+  get_attr_ctor_called = reinterpret_cast<int_fn>(dlsym(handle, "get_attr_ctor_called"));
+  ASSERT_TRUE(get_cxx_ctor_called != nullptr);
+  ASSERT_TRUE(get_attr_ctor_called != nullptr);
+
+  ASSERT_EQ(1, get_cxx_ctor_called());
+  ASSERT_EQ(1, get_attr_ctor_called());
 
   void* sym = dlsym(handle, "register_atexit");
-  ASSERT_TRUE(sym != NULL);
-  reinterpret_cast<void (*)(std::string*, bool*)>(sym)(&atexit_call_sequence, &valid_this_in_static_dtor);
+  ASSERT_TRUE(sym != nullptr);
+  reinterpret_cast<void (*)(std::string*, bool*, bool*)>(sym)(&atexit_call_sequence, &valid_this_in_static_dtor, &attr_dtor_called);
 
   ASSERT_EQ(0, dlclose(handle));
   // this test verifies atexit call from atexit handler. as well as the order of calls
   ASSERT_EQ("Humpty Dumpty sat on a wall", atexit_call_sequence);
   ASSERT_TRUE(valid_this_in_static_dtor);
+  ASSERT_TRUE(attr_dtor_called);
 }
 
 class TestMainStaticDtorClass {
@@ -57,7 +70,7 @@
   static const TestMainStaticDtorClass* expected_this;
 };
 
-const TestMainStaticDtorClass* TestMainStaticDtorClass::expected_this = NULL;
+const TestMainStaticDtorClass* TestMainStaticDtorClass::expected_this = nullptr;
 
 static void atexit_func5() {
   fprintf(stderr, "5");
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index f056fb6..6de38c8 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -62,24 +62,18 @@
   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
-TEST(dlfcn, dlsym_local_symbol) {
-  void* handle = dlopen("libtest_local_symbol.so", RTLD_NOW);
+TEST(dlfcn, dlsym_with_dependencies) {
+  void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
   ASSERT_TRUE(handle != NULL);
   dlerror();
-  void* sym = dlsym(handle, "private_taxicab_number");
-  ASSERT_TRUE(sym == NULL);
-  ASSERT_STREQ("undefined symbol: private_taxicab_number", dlerror());
-
-  uint32_t (*f)(void);
-  f = reinterpret_cast<uint32_t (*)(void)>(dlsym(handle, "dlsym_local_symbol_get_taxicab_number_using_dlsym"));
-  ASSERT_TRUE(f != NULL);
-  ASSERT_EQ(1729U, f());
+  // 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);
 }
-#endif
 
 TEST(dlfcn, dlopen_noload) {
   void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
@@ -93,6 +87,49 @@
   ASSERT_EQ(0, dlclose(handle2));
 }
 
+// ifuncs are only supported on intel for now
+#if defined(__i386__) || defined(__x86_64__)
+TEST(dlfcn, ifunc) {
+  typedef const char* (*fn_ptr)();
+
+  // ifunc's choice depends on whether IFUNC_CHOICE has a value
+  // first check the set case
+  setenv("IFUNC_CHOICE", "set", 1);
+  void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
+  ASSERT_TRUE(handle != NULL);
+  fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
+  fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
+  ASSERT_TRUE(foo_ptr != NULL);
+  ASSERT_TRUE(foo_library_ptr != NULL);
+  ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
+  ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
+  dlclose(handle);
+
+  // then check the unset case
+  unsetenv("IFUNC_CHOICE");
+  handle = dlopen("libtest_ifunc.so", RTLD_NOW);
+  ASSERT_TRUE(handle != NULL);
+  foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
+  foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
+  ASSERT_TRUE(foo_ptr != NULL);
+  ASSERT_TRUE(foo_library_ptr != NULL);
+  ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
+  ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0);
+  dlclose(handle);
+}
+
+TEST(dlfcn, ifunc_ctor_call) {
+  typedef const char* (*fn_ptr)();
+
+  void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
+  ASSERT_TRUE(handle != NULL) << dlerror();
+  fn_ptr is_ctor_called =  reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called"));
+  ASSERT_TRUE(is_ctor_called != NULL) << dlerror();
+  ASSERT_STREQ("true", is_ctor_called());
+  dlclose(handle);
+}
+#endif
+
 TEST(dlfcn, dlopen_failure) {
   void* self = dlopen("/does/not/exist", RTLD_NOW);
   ASSERT_TRUE(self == NULL);
@@ -194,10 +231,8 @@
   // Look in /proc/pid/maps to find out what address we were loaded at.
   // TODO: factor /proc/pid/maps parsing out into a class and reuse all over bionic.
   void* base_address = NULL;
-  char path[PATH_MAX];
-  snprintf(path, sizeof(path), "/proc/%d/maps", getpid());
   char line[BUFSIZ];
-  FILE* fp = fopen(path, "r");
+  FILE* fp = fopen("/proc/self/maps", "r");
   ASSERT_TRUE(fp != NULL);
   while (fgets(line, sizeof(line), fp) != NULL) {
     uintptr_t start = strtoul(line, 0, 16);
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/getauxval_test.cpp b/tests/getauxval_test.cpp
index 51c9db8..b331150 100644
--- a/tests/getauxval_test.cpp
+++ b/tests/getauxval_test.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <sys/cdefs.h>
-#include <features.h>
 #include <gtest/gtest.h>
 
 // getauxval() was only added as of glibc version 2.16.
diff --git a/tests/libgen_test.cpp b/tests/libgen_test.cpp
index cae646f..d0402db 100644
--- a/tests/libgen_test.cpp
+++ b/tests/libgen_test.cpp
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
 #include <libgen.h>
 
 #include <errno.h>
+#include <gtest/gtest.h>
 
 static void TestBasename(const char* in, const char* expected_out) {
   char* writable_in = (in != NULL) ? strdup(in) : NULL;
@@ -40,7 +39,7 @@
 
 // Do not use basename as the test name, it's defined to another value in glibc
 // so leads to a differently named test on host versus target architectures.
-TEST(libgen, basename_smoke) {
+TEST(libgen, posix_basename) {
   TestBasename(NULL, ".");
   TestBasename("", ".");
   TestBasename("/usr/lib", "lib");
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index a374e48..b1cc836 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -17,6 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 TEST_PATH := $(LOCAL_PATH)/..
 
+common_cppflags += -std=gnu++11
 # -----------------------------------------------------------------------------
 # Library used by dlfcn tests.
 # -----------------------------------------------------------------------------
@@ -102,21 +103,33 @@
 include $(TEST_PATH)/Android.build.mk
 
 # -----------------------------------------------------------------------------
-# Library used to test local symbol lookup
+# Library with dependency used by dlfcn tests
 # -----------------------------------------------------------------------------
-libtest_local_symbol_src_files := \
-    dlsym_local_symbol_private.cpp \
-    dlsym_local_symbol_public.cpp
+libtest_with_dependency_src_files := \
+    dlopen_testlib_simple.cpp
 
-module := libtest_local_symbol
-build_target := SHARED_LIBRARY
-libtest_local_symbol_ldflags := -Wl,--version-script=$(LOCAL_PATH)/dlsym_local_symbol.map
-libtest_local_symbol_cppflags := -std=gnu++11
-libtest_local_symbol_shared_libraries_target := libdl
+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 by ifunc tests
+# -----------------------------------------------------------------------------
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
+    libtest_ifunc_src_files := \
+        dlopen_testlib_ifunc.c
+
+    LOCAL_SDK_VERSION := current
+    module := libtest_ifunc
+    build_type := target
+    build_target := SHARED_LIBRARY
+    include $(TEST_PATH)/Android.build.mk
+endif
+
+# -----------------------------------------------------------------------------
 # Library used by atexit tests
 # -----------------------------------------------------------------------------
 
diff --git a/tests/libs/atexit_testlib.cpp b/tests/libs/atexit_testlib.cpp
index d35f57b..314e8de 100644
--- a/tests/libs/atexit_testlib.cpp
+++ b/tests/libs/atexit_testlib.cpp
@@ -19,12 +19,19 @@
 #include <string>
 
 // use external control number from main test
-static std::string* atexit_sequence = NULL;
-static bool* atexit_valid_this_in_static_dtor = NULL;
+static std::string* atexit_sequence = nullptr;
+static bool* atexit_valid_this_in_static_dtor = nullptr;
+static bool* atexit_attr_dtor_called = nullptr;
+
+static int cxx_ctor_called = 0;
+static int attr_ctor_called = 0;
 
 static class AtExitStaticClass {
  public:
-  AtExitStaticClass() { expected_this = this; }
+  AtExitStaticClass() {
+    expected_this = this;
+    cxx_ctor_called = 1;
+  }
   ~AtExitStaticClass() {
     if (atexit_valid_this_in_static_dtor) {
       *atexit_valid_this_in_static_dtor = (expected_this == this);
@@ -35,7 +42,7 @@
 
 } static_obj;
 
-const AtExitStaticClass* AtExitStaticClass::expected_this = NULL;
+const AtExitStaticClass* AtExitStaticClass::expected_this = nullptr;
 
 // 4
 static void atexit_handler_from_atexit_from_atexit2() {
@@ -66,10 +73,30 @@
   *atexit_sequence += " a wall";
 }
 
-extern "C" void register_atexit(std::string* sequence, bool* valid_this_in_static_dtor) {
+// attribute c-tor and d-tor
+static void __attribute__((constructor)) atexit_attr_ctor() {
+  attr_ctor_called = 1;
+}
+
+static void __attribute__((destructor)) atexit_attr_dtor() {
+  if (atexit_attr_dtor_called) {
+    *atexit_attr_dtor_called = true;
+  }
+}
+
+extern "C" void register_atexit(std::string* sequence, bool* valid_this_in_static_dtor, bool* attr_dtor_called) {
   atexit_sequence = sequence;
   atexit_valid_this_in_static_dtor = valid_this_in_static_dtor;
+  atexit_attr_dtor_called = attr_dtor_called;
   atexit(atexit_handler_regular);
   atexit(atexit_handler_with_atexit);
 }
 
+extern "C" int get_cxx_ctor_called() {
+  return cxx_ctor_called;
+}
+
+extern "C" int get_attr_ctor_called() {
+  return attr_ctor_called;
+}
+
diff --git a/tests/libs/dlopen_testlib_ifunc.c b/tests/libs/dlopen_testlib_ifunc.c
new file mode 100644
index 0000000..4874841
--- /dev/null
+++ b/tests/libs/dlopen_testlib_ifunc.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int g_flag = 0;
+
+static void __attribute__((constructor)) init_flag() {
+  g_flag = 1;
+}
+
+const char* foo() __attribute__ ((ifunc ("foo_ifunc")));
+const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun")));
+
+const char* return_true() {
+  return "true";
+}
+
+const char* return_false() {
+  return "false";
+}
+
+const char* f1() {
+  return "unset";
+}
+
+const char* f2() {
+  return "set";
+}
+
+void* is_ctor_called_ifun() {
+  return g_flag == 0 ? return_false : return_true;
+}
+
+void* foo_ifunc() {
+   char* choice = getenv("IFUNC_CHOICE");
+   return choice == NULL ? f1 : f2;
+}
+
+const char* foo_library() {
+   return foo();
+}
diff --git a/tests/libs/dlsym_local_symbol_public.cpp b/tests/libs/dlsym_local_symbol_public.cpp
deleted file mode 100644
index d9da32a..0000000
--- a/tests/libs/dlsym_local_symbol_public.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 <stdlib.h>
-#include <dlfcn.h>
-#include <stdio.h>
-
-extern const uint32_t private_taxicab_number;
-
-extern "C" {
-uint32_t dlsym_local_symbol_get_taxicab_number();
-uint32_t dlsym_local_symbol_get_taxicab_number_using_dlsym();
-}
-
-uint32_t dlsym_local_symbol_get_taxicab_number() {
-  return private_taxicab_number;
-}
-
-// Let's make sure that dlsym works correctly for local symbol
-uint32_t dlsym_local_symbol_get_taxicab_number_using_dlsym() {
-  dlerror();
-  uint32_t* ptr = reinterpret_cast<uint32_t*>(dlsym(RTLD_DEFAULT, "private_taxicab_number"));
-  if (ptr == nullptr) {
-    const char* dlerr = dlerror();
-    if (dlerr != nullptr) {
-      fprintf(stderr, "dlsym error: %s\n", dlerr);
-    } else {
-      fprintf(stderr, "dlsym returned NULL with no dlerror.\n");
-    }
-    return 0;
-  }
-
-  return *ptr;
-}
diff --git a/tests/locale_test.cpp b/tests/locale_test.cpp
index 7d063f9..325f6ce 100644
--- a/tests/locale_test.cpp
+++ b/tests/locale_test.cpp
@@ -48,8 +48,8 @@
 }
 
 TEST(locale, setlocale) {
-  EXPECT_STREQ("C", setlocale(LC_ALL, NULL));
-  EXPECT_STREQ("C", setlocale(LC_CTYPE, NULL));
+  EXPECT_STREQ("C.UTF-8", setlocale(LC_ALL, NULL));
+  EXPECT_STREQ("C.UTF-8", setlocale(LC_CTYPE, NULL));
 
   errno = 0;
   EXPECT_EQ(NULL, setlocale(-1, NULL));
@@ -105,3 +105,20 @@
 
   EXPECT_EQ(n, uselocale(NULL));
 }
+
+TEST(locale, mb_cur_max) {
+  // We can't reliably test the behavior with setlocale(3) or the behavior for
+  // initial program conditions because (unless we're the only test that was
+  // run), another test has almost certainly called uselocale(3) in this thread.
+  // See b/16685652.
+  locale_t cloc = newlocale(LC_ALL, "C", 0);
+  locale_t cloc_utf8 = newlocale(LC_ALL, "C.UTF-8", 0);
+
+  uselocale(cloc);
+  ASSERT_EQ(1U, MB_CUR_MAX);
+  uselocale(cloc_utf8);
+  ASSERT_EQ(4U, MB_CUR_MAX);
+
+  freelocale(cloc);
+  freelocale(cloc_utf8);
+}
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 6b7a28b..b76625a 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -22,6 +22,8 @@
 #include <malloc.h>
 #include <unistd.h>
 
+#include <tinyxml2.h>
+
 #include "private/bionic_config.h"
 
 TEST(malloc, malloc_std) {
@@ -322,3 +324,51 @@
   ASSERT_EQ(NULL, valloc(SIZE_MAX));
 }
 #endif
+
+TEST(malloc, malloc_info) {
+#ifdef __BIONIC__
+  char* buf;
+  size_t bufsize;
+  FILE* memstream = open_memstream(&buf, &bufsize);
+  ASSERT_NE(nullptr, memstream);
+  ASSERT_EQ(0, malloc_info(0, memstream));
+  ASSERT_EQ(0, fclose(memstream));
+
+  tinyxml2::XMLDocument doc;
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buf));
+
+  auto root = doc.FirstChildElement();
+  ASSERT_NE(nullptr, root);
+  ASSERT_STREQ("malloc", root->Name());
+  ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
+
+  auto arena = root->FirstChildElement();
+  for (; arena != nullptr; arena = arena->NextSiblingElement()) {
+    int val;
+
+    ASSERT_STREQ("heap", arena->Name());
+    ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
+    ASSERT_EQ(tinyxml2::XML_SUCCESS,
+              arena->FirstChildElement("allocated-large")->QueryIntText(&val));
+    ASSERT_EQ(tinyxml2::XML_SUCCESS,
+              arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
+    ASSERT_EQ(tinyxml2::XML_SUCCESS,
+              arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
+    ASSERT_EQ(tinyxml2::XML_SUCCESS,
+              arena->FirstChildElement("bins-total")->QueryIntText(&val));
+
+    auto bin = arena->FirstChildElement("bin");
+    for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
+      if (strcmp(bin->Name(), "bin") == 0) {
+        ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
+        ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                  bin->FirstChildElement("allocated")->QueryIntText(&val));
+        ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                  bin->FirstChildElement("nmalloc")->QueryIntText(&val));
+        ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                  bin->FirstChildElement("ndalloc")->QueryIntText(&val));
+      }
+    }
+  }
+#endif
+}
diff --git a/tests/math_sincos_test.cpp b/tests/math_sincos_test.cpp
index 0fab2c2..f2e30de 100644
--- a/tests/math_sincos_test.cpp
+++ b/tests/math_sincos_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define _GNU_SOURCE 1
+
 #include <math.h>
 
 #include <gtest/gtest.h>
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 36da481..5f74e38 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -23,6 +23,7 @@
 #include <pthread.h>
 #include <signal.h>
 #include <sys/mman.h>
+#include <sys/syscall.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -82,6 +83,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;
 }
@@ -349,27 +401,36 @@
 }
 
 TEST(pthread, pthread_detach__leak) {
-  size_t initial_bytes = mallinfo().uordblks;
+  size_t initial_bytes = 0;
+  // Run this loop more than once since the first loop causes some memory
+  // to be allocated permenantly. Run an extra loop to help catch any subtle
+  // memory leaks.
+  for (size_t loop = 0; loop < 3; loop++) {
+    // Set the initial bytes on the second loop since the memory in use
+    // should have stabilized.
+    if (loop == 1) {
+      initial_bytes = mallinfo().uordblks;
+    }
 
-  pthread_attr_t attr;
-  ASSERT_EQ(0, pthread_attr_init(&attr));
-  ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
+    pthread_attr_t attr;
+    ASSERT_EQ(0, pthread_attr_init(&attr));
+    ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
 
-  std::vector<pthread_t> threads;
-  for (size_t i = 0; i < 32; ++i) {
-    pthread_t t;
-    ASSERT_EQ(0, pthread_create(&t, &attr, IdFn, NULL));
-    threads.push_back(t);
-  }
+    std::vector<pthread_t> threads;
+    for (size_t i = 0; i < 32; ++i) {
+      pthread_t t;
+      ASSERT_EQ(0, pthread_create(&t, &attr, IdFn, NULL));
+      threads.push_back(t);
+    }
 
-  sleep(1);
+    sleep(1);
 
-  for (size_t i = 0; i < 32; ++i) {
-    ASSERT_EQ(0, pthread_detach(threads[i])) << i;
+    for (size_t i = 0; i < 32; ++i) {
+      ASSERT_EQ(0, pthread_detach(threads[i])) << i;
+    }
   }
 
   size_t final_bytes = mallinfo().uordblks;
-
   int leaked_bytes = (final_bytes - initial_bytes);
 
   // User code (like this test) doesn't know how large pthread_internal_t is.
@@ -756,3 +817,88 @@
   ASSERT_EQ(0, pthread_mutex_unlock(&m));
   ASSERT_EQ(0, pthread_mutex_destroy(&m));
 }
+
+TEST(pthread, pthread_attr_getstack__main_thread) {
+  // This test is only meaningful for the main thread, so make sure we're running on it!
+  ASSERT_EQ(getpid(), syscall(__NR_gettid));
+
+  // Get the main thread's attributes.
+  pthread_attr_t attributes;
+  ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes));
+
+  // Check that we correctly report that the main thread has no guard page.
+  size_t guard_size;
+  ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size));
+  ASSERT_EQ(0U, guard_size); // The main thread has no guard page.
+
+  // Get the stack base and the stack size (both ways).
+  void* stack_base;
+  size_t stack_size;
+  ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size));
+  size_t stack_size2;
+  ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2));
+
+  // The two methods of asking for the stack size should agree.
+  EXPECT_EQ(stack_size, stack_size2);
+
+  // What does /proc/self/maps' [stack] line say?
+  void* maps_stack_base = NULL;
+  size_t maps_stack_size = 0;
+  FILE* fp = fopen("/proc/self/maps", "r");
+  ASSERT_TRUE(fp != NULL);
+  char line[BUFSIZ];
+  while (fgets(line, sizeof(line), fp) != NULL) {
+    uintptr_t lo, hi;
+    char name[10];
+    sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d %10s", &lo, &hi, name);
+    if (strcmp(name, "[stack]") == 0) {
+      maps_stack_base = reinterpret_cast<void*>(lo);
+      maps_stack_size = hi - lo;
+      break;
+    }
+  }
+  fclose(fp);
+
+#if defined(__BIONIC__)
+  // bionic thinks that the stack base and size should correspond to the mapped region.
+  EXPECT_EQ(maps_stack_base, stack_base);
+  EXPECT_EQ(maps_stack_size, stack_size);
+#else
+  // glibc doesn't give the true extent for some reason.
+#endif
+
+  // Both bionic and glibc agree that the high address you can compute from the returned
+  // values should match what /proc/self/maps says.
+  void* stack_end = reinterpret_cast<uint8_t*>(stack_base) + stack_size;
+  void* maps_stack_end = reinterpret_cast<uint8_t*>(maps_stack_base) + maps_stack_size;
+  EXPECT_EQ(maps_stack_end, stack_end);
+
+  //
+  // What if the rlimit is smaller than the stack's current extent?
+  //
+  rlimit rl;
+  rl.rlim_cur = rl.rlim_max = 1024; // 1KiB. We know the stack must be at least a page already.
+  rl.rlim_max = RLIM_INFINITY;
+  ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+
+  ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes));
+  ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size));
+  ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2));
+
+  EXPECT_EQ(stack_size, stack_size2);
+  ASSERT_EQ(1024U, stack_size);
+
+  //
+  // What if the rlimit isn't a whole number of pages?
+  //
+  rl.rlim_cur = rl.rlim_max = 6666; // Not a whole number of pages.
+  rl.rlim_max = RLIM_INFINITY;
+  ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+
+  ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes));
+  ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size));
+  ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2));
+
+  EXPECT_EQ(stack_size, stack_size2);
+  ASSERT_EQ(6666U, stack_size);
+}
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..222bd9c 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
-#if !defined(__GLIBC__) /* TODO: fix our prebuilt toolchains! */
-
 #include <stdatomic.h>
+#include <gtest/gtest.h>
+#include <pthread.h>
+#include <stdint.h>
 
 TEST(stdatomic, LOCK_FREE) {
   ASSERT_TRUE(ATOMIC_BOOL_LOCK_FREE);
@@ -66,7 +65,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) {
@@ -162,4 +166,80 @@
   ASSERT_EQ(0x002, atomic_load(&i));
 }
 
-#endif
+// And a rudimentary test of acquire-release memory ordering:
+
+constexpr static uint_least32_t BIG = 10000000ul; // Assumed even below.
+
+struct three_atomics {
+  atomic_uint_least32_t x;
+  char a[123];  // Everything in different cache lines,
+                // increase chance of compiler getting alignment wrong.
+  atomic_uint_least32_t y;
+  char b[4013];
+  atomic_uint_least32_t z;
+};
+
+// Very simple acquire/release memory ordering sanity check.
+static void* writer(void* arg) {
+  three_atomics* a = reinterpret_cast<three_atomics*>(arg);
+  for (uint_least32_t i = 0; i <= BIG; i+=2) {
+    atomic_store_explicit(&a->x, i, memory_order_relaxed);
+    atomic_store_explicit(&a->z, i, memory_order_relaxed);
+    atomic_store_explicit(&a->y, i, memory_order_release);
+    atomic_store_explicit(&a->x, i+1, memory_order_relaxed);
+    atomic_store_explicit(&a->z, i+1, memory_order_relaxed);
+    atomic_store_explicit(&a->y, i+1, memory_order_release);
+  }
+  return 0;
+}
+
+static void* reader(void* arg) {
+  three_atomics* a = reinterpret_cast<three_atomics*>(arg);
+  uint_least32_t xval = 0, yval = 0, zval = 0;
+  size_t repeat = 0;
+  size_t repeat_limit = 1000;
+  while (yval != BIG + 1) {
+    yval = atomic_load_explicit(&a->y, memory_order_acquire);
+    zval = atomic_load_explicit(&a->z, memory_order_relaxed);
+    xval = atomic_load_explicit(&a->x, memory_order_relaxed);
+    // If we see a given value of y, the immediately preceding
+    // stores to z and x, or later ones, should also be visible.
+    if (zval < yval) {
+      // Cant just ASSERT, since we are in a non-void function.
+      ADD_FAILURE() << "acquire-release ordering violation: "
+                    << zval << " < " << yval << ", " << xval << "\n";
+      return 0; // Only report once.
+    }
+    if (xval < yval) {
+      // Cant just ASSERT, since we are in a non-void function.
+      ADD_FAILURE() << "acquire-release ordering violation: "
+                    << xval << " < " << yval << ", " << zval <<  "\n";
+      return 0; // Only report once.
+    }
+    if (repeat < repeat_limit) ++repeat;
+  }
+  // The following assertion is not technically guaranteed to hold.
+  // But if it fails to hold, this test was useless, and we have a
+  // serious scheduling issue that we should probably know about.
+  EXPECT_EQ(repeat, repeat_limit);
+  return 0;
+}
+
+TEST(stdatomic, ordering) {
+  // Run a memory ordering sanity test.
+  void* result;
+  three_atomics a;
+  atomic_init(&a.x, 0ul);
+  atomic_init(&a.y, 0ul);
+  atomic_init(&a.z, 0ul);
+  pthread_t t1,t2;
+  ASSERT_EQ(0, pthread_create(&t1, 0, reader, &a));
+  ASSERT_EQ(0, pthread_create(&t2, 0, writer, &a));
+  ASSERT_EQ(0, pthread_join(t1, &result));
+  EXPECT_EQ(0, result);
+  ASSERT_EQ(0, pthread_join(t2, &result));
+  EXPECT_EQ(0, result);
+  EXPECT_EQ(atomic_load_explicit(&a.x, memory_order_consume), BIG + 1);
+  EXPECT_EQ(atomic_load_explicit(&a.y, memory_order_seq_cst), BIG + 1);
+  EXPECT_EQ(atomic_load(&a.z), BIG + 1);
+}
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
new file mode 100644
index 0000000..3dbc485
--- /dev/null
+++ b/tests/stdio_ext_test.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio_ext.h>
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <locale.h>
+
+#include "TemporaryFile.h"
+
+TEST(stdio_ext, __fbufsize) {
+  FILE* fp = fopen("/proc/version", "r");
+
+  char buf[128];
+
+  ASSERT_EQ(0, setvbuf(fp, buf, _IOFBF, 1));
+  ASSERT_EQ(1U, __fbufsize(fp));
+
+  ASSERT_EQ(0, setvbuf(fp, buf, _IOFBF, 8));
+  ASSERT_EQ(8U, __fbufsize(fp));
+
+  fclose(fp);
+}
+
+TEST(stdio_ext, __flbf) {
+  FILE* fp = fopen("/proc/version", "r");
+
+  ASSERT_FALSE(__flbf(fp));
+
+  char buf[128];
+  ASSERT_EQ(0, setvbuf(fp, buf, _IOLBF, sizeof(buf)));
+
+  ASSERT_TRUE(__flbf(fp));
+
+  fclose(fp);
+}
+
+TEST(stdio_ext, __fpending) {
+  FILE* fp = fopen("/dev/null", "w");
+  ASSERT_EQ(0U, __fpending(fp));
+  ASSERT_EQ('x', fputc('x', fp));
+  ASSERT_EQ(1U, __fpending(fp));
+  ASSERT_EQ('y', fputc('y', fp));
+  ASSERT_EQ(2U, __fpending(fp));
+  fflush(fp);
+  ASSERT_EQ(0U, __fpending(fp));
+  fclose(fp);
+}
+
+TEST(stdio_ext, __fpurge) {
+  FILE* fp = tmpfile();
+
+  ASSERT_EQ('a', fputc('a', fp));
+  ASSERT_EQ(1U, __fpending(fp));
+  __fpurge(fp);
+  ASSERT_EQ(0U, __fpending(fp));
+
+  ASSERT_EQ('b', fputc('b', fp));
+  ASSERT_EQ('\n', fputc('\n', fp));
+  ASSERT_EQ(2U, __fpending(fp));
+
+  rewind(fp);
+
+  char buf[16];
+  char* s = fgets(buf, sizeof(buf), fp);
+  ASSERT_TRUE(s != NULL);
+  ASSERT_STREQ("b\n", s);
+
+  fclose(fp);
+}
+
+TEST(stdio_ext, _flushlbf) {
+  FILE* fp = fopen("/dev/null", "w");
+
+  char buf[128];
+  ASSERT_EQ(0, setvbuf(fp, buf, _IOLBF, sizeof(buf)));
+
+  ASSERT_EQ('a', fputc('a', fp));
+  ASSERT_EQ(1U, __fpending(fp));
+
+  _flushlbf();
+
+  ASSERT_EQ(0U, __fpending(fp));
+
+  fclose(fp);
+}
+
+TEST(stdio_ext, __freadable__fwritable) {
+  FILE* fp = fopen("/dev/null", "r");
+  ASSERT_TRUE(__freadable(fp));
+  ASSERT_FALSE(__fwritable(fp));
+  fclose(fp);
+
+  fp = fopen("/dev/null", "w");
+  ASSERT_FALSE(__freadable(fp));
+  ASSERT_TRUE(__fwritable(fp));
+  fclose(fp);
+
+  fp = fopen("/dev/null", "w+");
+  ASSERT_TRUE(__freadable(fp));
+  ASSERT_TRUE(__fwritable(fp));
+  fclose(fp);
+}
+
+TEST(stdio_ext, __fsetlocking) {
+  FILE* fp = fopen("/proc/version", "r");
+  // Android doesn't actually support the other modes.
+  ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
+  fclose(fp);
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 18dae9c..2cd0df2 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -427,6 +427,9 @@
 }
 
 TEST(stdio, snprintf_utf8_15439554) {
+  locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0);
+  uselocale(cloc);
+
   // http://b/15439554
   char buf[BUFSIZ];
 
@@ -442,6 +445,8 @@
   // 4-byte character.
   snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
   EXPECT_STREQ("1𤭢2", buf);
+
+  freelocale(cloc);
 }
 
 TEST(stdio, fprintf_failures_7229520) {
@@ -671,3 +676,82 @@
 
   fclose(fp);
 }
+
+TEST(stdio, fmemopen) {
+  char buf[16];
+  memset(buf, 0, sizeof(buf));
+  FILE* fp = fmemopen(buf, sizeof(buf), "r+");
+  ASSERT_EQ('<', fputc('<', fp));
+  ASSERT_NE(EOF, fputs("abc>\n", fp));
+  fflush(fp);
+
+  ASSERT_STREQ("<abc>\n", buf);
+
+  rewind(fp);
+
+  char line[16];
+  char* s = fgets(line, sizeof(line), fp);
+  ASSERT_TRUE(s != NULL);
+  ASSERT_STREQ("<abc>\n", s);
+
+  fclose(fp);
+}
+
+TEST(stdio, fmemopen_NULL) {
+  FILE* fp = fmemopen(nullptr, 128, "r+");
+  ASSERT_NE(EOF, fputs("xyz\n", fp));
+
+  rewind(fp);
+
+  char line[16];
+  char* s = fgets(line, sizeof(line), fp);
+  ASSERT_TRUE(s != NULL);
+  ASSERT_STREQ("xyz\n", s);
+
+  fclose(fp);
+}
+
+TEST(stdio, fmemopen_EINVAL) {
+  char buf[16];
+
+  // Invalid size.
+  errno = 0;
+  ASSERT_EQ(nullptr, fmemopen(buf, 0, "r+"));
+  ASSERT_EQ(EINVAL, errno);
+
+  // No '+' with NULL buffer.
+  errno = 0;
+  ASSERT_EQ(nullptr, fmemopen(nullptr, 0, "r"));
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(stdio, open_memstream) {
+  char* p = nullptr;
+  size_t size = 0;
+  FILE* fp = open_memstream(&p, &size);
+  ASSERT_NE(EOF, fputs("hello, world!", fp));
+  fclose(fp);
+
+  ASSERT_STREQ("hello, world!", p);
+  ASSERT_EQ(strlen("hello, world!"), size);
+  free(p);
+}
+
+TEST(stdio, open_memstream_EINVAL) {
+#if defined(__BIONIC__)
+  char* p;
+  size_t size;
+
+  // Invalid buffer.
+  errno = 0;
+  ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
+  ASSERT_EQ(EINVAL, errno);
+
+  // Invalid size.
+  errno = 0;
+  ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
+  ASSERT_EQ(EINVAL, errno);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
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/string_test.cpp b/tests/string_test.cpp
index bc2c05b..a3c6abb 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
+#include <string.h>
 
 #include <errno.h>
+#include <gtest/gtest.h>
 #include <malloc.h>
 #include <math.h>
-#include <string.h>
 
 #include "buffer_tests.h"
 
@@ -763,6 +763,14 @@
   }
 }
 
+TEST(string, memchr_zero) {
+  uint8_t* buffer;
+  ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&buffer), 64, 64));
+  memset(buffer, 10, 64);
+  ASSERT_TRUE(NULL == memchr(buffer, 5, 0));
+  ASSERT_TRUE(NULL == memchr(buffer, 10, 0));
+}
+
 TEST(string, memrchr) {
   int seek_char = random() & 255;
   StringTestState<char> state(SMALL);
@@ -1279,3 +1287,22 @@
 TEST(string, strchr_overread) {
   RunSingleBufferOverreadTest(DoStrchrTest);
 }
+
+static void TestBasename(const char* in, const char* expected_out) {
+  errno = 0;
+  const char* out = basename(in);
+  ASSERT_STREQ(expected_out, out) << in;
+  ASSERT_EQ(0, errno) << in;
+}
+
+TEST(string, __gnu_basename) {
+  TestBasename("", "");
+  TestBasename("/usr/lib", "lib");
+  TestBasename("/usr/", "");
+  TestBasename("usr", "usr");
+  TestBasename("/", "");
+  TestBasename(".", ".");
+  TestBasename("..", "..");
+  TestBasename("///", "");
+  TestBasename("//usr//lib//", "");
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 12b1ea7..c9ead8d 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -17,7 +17,6 @@
 #include <time.h>
 
 #include <errno.h>
-#include <features.h>
 #include <gtest/gtest.h>
 #include <pthread.h>
 #include <signal.h>
@@ -27,34 +26,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 +79,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 +86,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/uchar_test.cpp b/tests/uchar_test.cpp
index eca3c5e..c887f8a 100644
--- a/tests/uchar_test.cpp
+++ b/tests/uchar_test.cpp
@@ -19,7 +19,6 @@
 #if defined(__BIONIC__)
 #define HAVE_UCHAR 1
 #elif defined(__GLIBC__)
-#include <features.h>
 #define HAVE_UCHAR __GLIBC_PREREQ(2, 16)
 #endif
 
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 58c9ad9..8195ea8 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));
 }
@@ -422,6 +431,10 @@
 
   void* child_stack[1024];
   int clone_result = clone(GetPidCachingCloneStartRoutine, &child_stack[1024], CLONE_NEWNS | SIGCHLD, NULL);
+  if (clone_result == -1 && errno == EPERM && getuid() != 0) {
+    GTEST_LOG_(INFO) << "This test only works if you have permission to CLONE_NEWNS; try running as root.\n";
+    return;
+  }
   ASSERT_NE(clone_result, -1);
 
   ASSERT_EQ(parent_pid, getpid());
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index f052ce6..760475f 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -351,7 +351,7 @@
   // Check that we didn't clobber the rest of out.
   ASSERT_EQ(L'x', out[3]);
   // Check that valid has advanced to the end of the string.
-  ASSERT_EQ(L'\0', *valid);
+  ASSERT_EQ(nullptr, valid);
 
   const char* invalid = "A" "\xc2\x20" "ef";
   ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &invalid, 4, ps));
@@ -489,3 +489,34 @@
   EXPECT_EQ(4U, n);
   EXPECT_EQ(L'𤭢', wc);
 }
+
+TEST(wchar, open_wmemstream) {
+  wchar_t* p = nullptr;
+  size_t size = 0;
+  FILE* fp = open_wmemstream(&p, &size);
+  ASSERT_NE(EOF, fputws(L"hello, world!", fp));
+  fclose(fp);
+
+  ASSERT_STREQ(L"hello, world!", p);
+  ASSERT_EQ(wcslen(L"hello, world!"), size);
+  free(p);
+}
+
+TEST(stdio, open_wmemstream_EINVAL) {
+#if defined(__BIONIC__)
+  wchar_t* p;
+  size_t size;
+
+  // Invalid buffer.
+  errno = 0;
+  ASSERT_EQ(nullptr, open_wmemstream(nullptr, &size));
+  ASSERT_EQ(EINVAL, errno);
+
+  // Invalid size.
+  errno = 0;
+  ASSERT_EQ(nullptr, open_wmemstream(&p, nullptr));
+  ASSERT_EQ(EINVAL, errno);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}