Merge "Define atomic_charN_t only if charN_t is supported."
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index f9722ae..4d7ad96 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -54,7 +54,7 @@
 LOCAL_SRC_FILES := $(benchmark_src_files)
 include $(BUILD_EXECUTABLE)
 
-ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
+ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
 ifeq ($(TARGET_ARCH),x86)
 LINKER = linker
 NATIVE_SUFFIX=32
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index f330d7e..0802b4c 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -28,12 +28,14 @@
 
 extern void *__system_property_area__;
 
+// Do not exceed 512, that is about the largest number of properties
+// that can be created with the current property area size.
 #define TEST_NUM_PROPS \
-    Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)
+    Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
 
 struct LocalPropertyTestState {
     LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
-        static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_";
+        static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
 
         const char* android_data = getenv("ANDROID_DATA");
         if (android_data == NULL) {
@@ -66,18 +68,38 @@
         srandom(nprops);
 
         for (int i = 0; i < nprops; i++) {
-            name_lens[i] = random() % PROP_NAME_MAX;
+            // Make sure the name has at least 10 characters to make
+            // it very unlikely to generate the same random name.
+            name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
             names[i] = new char[PROP_NAME_MAX + 1];
+            size_t prop_name_len = sizeof(prop_name_chars) - 1;
             for (int j = 0; j < name_lens[i]; j++) {
-                names[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
+                if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
+                    // Certain values are not allowed:
+                    // - Don't start name with '.'
+                    // - Don't allow '.' to appear twice in a row
+                    // - Don't allow the name to end with '.'
+                    // This assumes that '.' is the last character in the
+                    // array so that decrementing the length by one removes
+                    // the value from the possible values.
+                    prop_name_len--;
+                }
+                names[i][j] = prop_name_chars[random() % prop_name_len];
             }
             names[i][name_lens[i]] = 0;
-            value_lens[i] = random() % PROP_VALUE_MAX;
+
+            // Make sure the value contains at least 1 character.
+            value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
             values[i] = new char[PROP_VALUE_MAX];
             for (int j = 0; j < value_lens[i]; j++) {
                 values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
             }
-            __system_property_add(names[i], name_lens[i], values[i], value_lens[i]);
+
+            if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
+                printf("Failed to add a property, terminating...\n");
+                printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
+                exit(1);
+            }
         }
 
         valid = true;
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 3bf8c07..0a146ae 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -16,6 +16,7 @@
 
 #include "benchmark.h"
 
+#include <sys/syscall.h>
 #include <time.h>
 
 #if defined(__BIONIC__)
@@ -41,7 +42,7 @@
 static void BM_time_clock_gettime(int iters) {
   StartBenchmarkTiming();
 
-  struct timespec t;
+  timespec t;
   for (int i = 0; i < iters; ++i) {
     clock_gettime(CLOCK_MONOTONIC, &t);
   }
@@ -49,3 +50,50 @@
   StopBenchmarkTiming();
 }
 BENCHMARK(BM_time_clock_gettime);
+
+static void BM_time_clock_gettime_syscall(int iters) {
+  StartBenchmarkTiming();
+
+  timespec t;
+  for (int i = 0; i < iters; ++i) {
+    syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
+  }
+
+  StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_clock_gettime_syscall);
+
+static void BM_time_gettimeofday(int iters) {
+  StartBenchmarkTiming();
+
+  timeval tv;
+  for (int i = 0; i < iters; ++i) {
+    gettimeofday(&tv, NULL);
+  }
+
+  StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_gettimeofday);
+
+static void BM_time_gettimeofday_syscall(int iters) {
+  StartBenchmarkTiming();
+
+  timeval tv;
+  for (int i = 0; i < iters; ++i) {
+    syscall(__NR_gettimeofday, &tv, NULL);
+  }
+
+  StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_gettimeofday_syscall);
+
+static void BM_time_time(int iters) {
+  StartBenchmarkTiming();
+
+  for (int i = 0; i < iters; ++i) {
+    time(NULL);
+  }
+
+  StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_time);
diff --git a/libc/Android.mk b/libc/Android.mk
index 765f4d2..0485d72 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -67,7 +67,6 @@
     bionic/unlockpt.c \
     stdio/snprintf.c\
     stdio/sprintf.c \
-    stdlib/atexit.c \
     unistd/syslog.c \
 
 # Fortify implementations of libc functions.
@@ -178,6 +177,7 @@
     bionic/pthread_sigmask.cpp \
     bionic/ptrace.cpp \
     bionic/raise.cpp \
+    bionic/rand.cpp \
     bionic/readlink.cpp \
     bionic/reboot.cpp \
     bionic/recv.cpp \
@@ -229,6 +229,7 @@
     bionic/umount.cpp \
     bionic/unlink.cpp \
     bionic/utimes.cpp \
+    bionic/vdso.cpp \
     bionic/vfork.cpp \
     bionic/wait.cpp \
     bionic/wchar.cpp \
@@ -295,7 +296,6 @@
     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.c \
     upstream-netbsd/lib/libc/stdlib/rand_r.c \
     upstream-netbsd/lib/libc/stdlib/seed48.c \
     upstream-netbsd/lib/libc/stdlib/srand48.c \
@@ -306,7 +306,6 @@
     upstream-netbsd/lib/libc/string/strcasestr.c \
     upstream-netbsd/lib/libc/string/strcoll.c \
     upstream-netbsd/lib/libc/string/strxfrm.c \
-    upstream-netbsd/lib/libc/thread-stub/__isthreaded.c \
     upstream-netbsd/lib/libc/unistd/killpg.c \
 
 libc_upstream_openbsd_gdtoa_src_files := \
@@ -463,6 +462,7 @@
     upstream-openbsd/lib/libc/stdio/wprintf.c \
     upstream-openbsd/lib/libc/stdio/wscanf.c \
     upstream-openbsd/lib/libc/stdio/wsetup.c \
+    upstream-openbsd/lib/libc/stdlib/atexit.c \
     upstream-openbsd/lib/libc/stdlib/atoi.c \
     upstream-openbsd/lib/libc/stdlib/atol.c \
     upstream-openbsd/lib/libc/stdlib/atoll.c \
@@ -549,7 +549,6 @@
 # Define some common includes
 # ========================================================
 libc_common_c_includes += \
-    $(LOCAL_PATH)/stdlib  \
     $(LOCAL_PATH)/stdio   \
 
 # ========================================================
@@ -735,6 +734,7 @@
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
     -Wno-sign-compare -Wno-uninitialized -Wno-unused-parameter \
+    -I$(LOCAL_PATH)/private \
     -I$(LOCAL_PATH)/upstream-openbsd/android/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/gdtoa/ \
@@ -767,6 +767,7 @@
     $(libc_common_cflags) \
     -Wno-sign-compare -Wno-uninitialized \
     -fvisibility=hidden \
+    -I$(LOCAL_PATH)/private \
     -I$(LOCAL_PATH)/upstream-openbsd/android/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
     -include openbsd-compat.h \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index b4c8134..7ae054e 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -194,11 +194,9 @@
 int     swapoff(const char*) all
 
 # time
-int           gettimeofday(struct timeval*, struct timezone*)       all
 int           settimeofday(const struct timeval*, const struct timezone*)   all
 clock_t       times(struct tms*)       all
 int           nanosleep(const struct timespec*, struct timespec*)   all
-int           clock_gettime(clockid_t clk_id, struct timespec* tp)    all
 int           clock_settime(clockid_t clk_id, const struct timespec* tp)  all
 int           clock_getres(clockid_t clk_id, struct timespec* res)   all
 int           clock_nanosleep(clockid_t clock_id, int flags, const struct timespec* req, struct timespec* rem)  all
@@ -320,3 +318,9 @@
 
 # x86-specific
 int     __set_thread_area:set_thread_area(void*) x86
+
+# vdso stuff.
+int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64,x86
+int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
+int gettimeofday(timeval*, timezone*)                   arm,mips,mips64,x86
+int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86_64
diff --git a/libc/arch-arm64/syscalls/clock_gettime.S b/libc/arch-arm64/syscalls/__clock_gettime.S
similarity index 76%
rename from libc/arch-arm64/syscalls/clock_gettime.S
rename to libc/arch-arm64/syscalls/__clock_gettime.S
index ffdde57..f346648 100644
--- a/libc/arch-arm64/syscalls/clock_gettime.S
+++ b/libc/arch-arm64/syscalls/__clock_gettime.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_gettime)
+ENTRY(__clock_gettime)
     mov     x8, __NR_clock_gettime
     svc     #0
 
@@ -11,4 +11,5 @@
     b.hi    __set_errno
 
     ret
-END(clock_gettime)
+END(__clock_gettime)
+.hidden __clock_gettime
diff --git a/libc/arch-arm64/syscalls/gettimeofday.S b/libc/arch-arm64/syscalls/__gettimeofday.S
similarity index 77%
rename from libc/arch-arm64/syscalls/gettimeofday.S
rename to libc/arch-arm64/syscalls/__gettimeofday.S
index 3b6104b..6582c49 100644
--- a/libc/arch-arm64/syscalls/gettimeofday.S
+++ b/libc/arch-arm64/syscalls/__gettimeofday.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(gettimeofday)
+ENTRY(__gettimeofday)
     mov     x8, __NR_gettimeofday
     svc     #0
 
@@ -11,4 +11,5 @@
     b.hi    __set_errno
 
     ret
-END(gettimeofday)
+END(__gettimeofday)
+.hidden __gettimeofday
diff --git a/libc/arch-x86_64/syscalls/clock_gettime.S b/libc/arch-x86_64/syscalls/__clock_gettime.S
similarity index 78%
rename from libc/arch-x86_64/syscalls/clock_gettime.S
rename to libc/arch-x86_64/syscalls/__clock_gettime.S
index 20850c8..7e553b8 100644
--- a/libc/arch-x86_64/syscalls/clock_gettime.S
+++ b/libc/arch-x86_64/syscalls/__clock_gettime.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_gettime)
+ENTRY(__clock_gettime)
     movl    $__NR_clock_gettime, %eax
     syscall
     cmpq    $-MAX_ERRNO, %rax
@@ -12,4 +12,5 @@
     call    __set_errno
 1:
     ret
-END(clock_gettime)
+END(__clock_gettime)
+.hidden __clock_gettime
diff --git a/libc/arch-x86_64/syscalls/gettimeofday.S b/libc/arch-x86_64/syscalls/__gettimeofday.S
similarity index 79%
rename from libc/arch-x86_64/syscalls/gettimeofday.S
rename to libc/arch-x86_64/syscalls/__gettimeofday.S
index 4867c30..a38eb64 100644
--- a/libc/arch-x86_64/syscalls/gettimeofday.S
+++ b/libc/arch-x86_64/syscalls/__gettimeofday.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(gettimeofday)
+ENTRY(__gettimeofday)
     movl    $__NR_gettimeofday, %eax
     syscall
     cmpq    $-MAX_ERRNO, %rax
@@ -12,4 +12,5 @@
     call    __set_errno
 1:
     ret
-END(gettimeofday)
+END(__gettimeofday)
+.hidden __gettimeofday
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index 69ac0e5..75413c6 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -30,7 +30,6 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include "atexit.h"
 
 #ifdef __arm__
 extern "C" __LIBC_HIDDEN__ void __libc_android_abort()
diff --git a/libc/bionic/ctype.cpp b/libc/bionic/ctype.cpp
index 3960d9d..2b31d52 100644
--- a/libc/bionic/ctype.cpp
+++ b/libc/bionic/ctype.cpp
@@ -36,10 +36,6 @@
   return isalpha(c);
 }
 
-int isascii_l(int c, locale_t) {
-  return isascii(c);
-}
-
 int isblank_l(int c, locale_t) {
   return isblank(c);
 }
diff --git a/libc/bionic/dl_iterate_phdr_static.cpp b/libc/bionic/dl_iterate_phdr_static.cpp
index 7e9eedd..155a7a0 100644
--- a/libc/bionic/dl_iterate_phdr_static.cpp
+++ b/libc/bionic/dl_iterate_phdr_static.cpp
@@ -27,6 +27,7 @@
  */
 
 #include <elf.h>
+#include <string.h>
 #include <sys/auxv.h>
 #include <sys/types.h>
 #include <link.h>
@@ -37,11 +38,9 @@
 int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
   ElfW(Ehdr)* ehdr = reinterpret_cast<ElfW(Ehdr)*>(&__executable_start);
 
-  // TODO: again, copied from linker.c. Find a better home for this later.
-  if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
-  if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
-  if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
-  if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
+  if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
+    return -1;
+  }
 
   // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but
   // static binaries get this. We don't have a list of shared objects to
@@ -54,7 +53,7 @@
   exe_info.dlpi_phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(ehdr) + ehdr->e_phoff);
   exe_info.dlpi_phnum = ehdr->e_phnum;
 
-#ifdef AT_SYSINFO_EHDR
+#if defined(AT_SYSINFO_EHDR)
   // Try the executable first.
   int rc = cb(&exe_info, sizeof(exe_info), data);
   if (rc != 0) {
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index fa61c3c..9e4eecd 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -39,7 +39,6 @@
 #include <sys/resource.h>
 #include <unistd.h>
 
-#include "atexit.h"
 #include "private/bionic_auxv.h"
 #include "private/bionic_ssp.h"
 #include "private/bionic_tls.h"
@@ -52,6 +51,8 @@
 extern "C" int __set_tls(void* ptr);
 extern "C" int __set_tid_address(int* tid_address);
 
+void __libc_init_vdso();
+
 // Not public, but well-known in the BSDs.
 const char* __progname;
 
@@ -130,6 +131,8 @@
   _pthread_internal_add(main_thread);
 
   __system_properties_init(); // Requires 'environ'.
+
+  __libc_init_vdso();
 }
 
 /* This function will be called during normal program termination
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 7c46364..78125f9 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -48,7 +48,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <elf.h>
-#include "atexit.h"
 #include "libc_init_common.h"
 
 #include "private/bionic_tls.h"
@@ -58,6 +57,7 @@
   extern void malloc_debug_init(void);
   extern void malloc_debug_fini(void);
   extern void netdClientInit(void);
+  extern int __cxa_atexit(void (*)(void *), void *, void *);
 };
 
 // We flag the __libc_preinit function as a constructor to ensure
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index ab0b3a6..bc11f3d 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -46,7 +46,6 @@
 #include <sys/auxv.h>
 #include <sys/mman.h>
 
-#include "atexit.h"
 #include "libc_init_common.h"
 #include "pthread_internal.h"
 
@@ -60,6 +59,8 @@
 // itself at the start of a page.
 #define PAGE_END(x)    PAGE_START((x) + (PAGE_SIZE-1))
 
+extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
+
 static void call_array(void(**list)()) {
   // First element is -1, list is null-terminated
   while (*++list) {
diff --git a/libc/bionic/ptrace.cpp b/libc/bionic/ptrace.cpp
index 5715b09..5156ec2 100644
--- a/libc/bionic/ptrace.cpp
+++ b/libc/bionic/ptrace.cpp
@@ -26,28 +26,30 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/types.h>
+#include <stdarg.h>
 #include <sys/ptrace.h>
 
-extern "C" long __ptrace(int request, pid_t pid, void* addr, void* data);
+extern "C" long __ptrace(int req, pid_t pid, void* addr, void* data);
 
-long ptrace(int request, pid_t pid, void* addr, void* data) {
-  switch (request) {
-    case PTRACE_PEEKUSR:
-    case PTRACE_PEEKTEXT:
-    case PTRACE_PEEKDATA:
-      {
-      long word;
-      long ret = __ptrace(request, pid, addr, &word);
-      if (ret == 0) {
-        return word;
-      } else {
-        // __ptrace already set errno for us.
-        return -1;
-      }
-    }
+long ptrace(int req, ...) {
+  bool is_peek = (req == PTRACE_PEEKUSR || req == PTRACE_PEEKTEXT || req == PTRACE_PEEKDATA);
+  long peek_result;
 
-    default:
-      return __ptrace(request, pid, addr, data);
+  va_list args;
+  va_start(args, req);
+  pid_t pid = va_arg(args, pid_t);
+  void* addr = va_arg(args, void*);
+  void* data;
+  if (is_peek) {
+    data = &peek_result;
+  } else {
+    data = va_arg(args, void*);
   }
+  va_end(args);
+
+  long result = __ptrace(req, pid, addr, data);
+  if (is_peek && result == 0) {
+    return peek_result;
+  }
+  return result;
 }
diff --git a/libc/upstream-openbsd/android/include/thread_private.h b/libc/bionic/rand.cpp
similarity index 64%
rename from libc/upstream-openbsd/android/include/thread_private.h
rename to libc/bionic/rand.cpp
index 10421e2..0074f2d 100644
--- a/libc/upstream-openbsd/android/include/thread_private.h
+++ b/libc/bionic/rand.cpp
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef _THREAD_PRIVATE_H_
-#define _THREAD_PRIVATE_H_
+#include <stdlib.h>
 
-#include <pthread.h>
+// The BSD rand/srand is very weak. glibc just uses random/srandom instead.
+// Since we're likely to run code intended for glibc, and POSIX doesn't seem
+// to disallow this, we go that route too.
 
-/* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */
-#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
-#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)
+int rand() {
+  return random();
+}
 
-#endif /* _THREAD_PRIVATE_H_ */
+void srand(unsigned int seed) {
+  return srandom(seed);
+}
diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp
new file mode 100644
index 0000000..0875ee6
--- /dev/null
+++ b/libc/bionic/vdso.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 <link.h>
+#include <sys/auxv.h>
+#include <unistd.h>
+
+// x86 has a vdso, but there's nothing useful to us in it.
+#if defined(__aarch64__) || defined(__x86_64__)
+
+#if defined(__aarch64__)
+#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
+#define VDSO_GETTIMEOFDAY_SYMBOL  "__kernel_gettimeofday"
+#elif defined(__x86_64__)
+#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
+#define VDSO_GETTIMEOFDAY_SYMBOL  "__vdso_gettimeofday"
+#endif
+
+#include <time.h>
+
+extern "C" int __clock_gettime(int, timespec*);
+extern "C" int __gettimeofday(timeval*, struct timezone*);
+
+struct vdso_entry {
+  const char* name;
+  void* fn;
+};
+
+enum {
+  VDSO_CLOCK_GETTIME = 0,
+  VDSO_GETTIMEOFDAY,
+  VDSO_END
+};
+
+static vdso_entry vdso_entries[] = {
+  [VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) },
+  [VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
+};
+
+int clock_gettime(int clock_id, timespec* tp) {
+  static int (*vdso_clock_gettime)(int, timespec*) =
+      (int (*)(int, timespec*)) vdso_entries[VDSO_CLOCK_GETTIME].fn;
+  return vdso_clock_gettime(clock_id, tp);
+}
+
+int gettimeofday(timeval* tv, struct timezone* tz) {
+  static int (*vdso_gettimeofday)(timeval*, struct timezone*) =
+      (int (*)(timeval*, struct timezone*)) vdso_entries[VDSO_GETTIMEOFDAY].fn;
+  return vdso_gettimeofday(tv, tz);
+}
+
+void __libc_init_vdso() {
+  // Do we have a vdso?
+  uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
+  ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
+  if (vdso_ehdr == NULL) {
+    return;
+  }
+
+  // How many symbols does it have?
+  size_t symbol_count = 0;
+  ElfW(Shdr)* vdso_shdr = reinterpret_cast<ElfW(Shdr)*>(vdso_ehdr_addr + vdso_ehdr->e_shoff);
+  for (size_t i = 0; i < vdso_ehdr->e_shnum; ++i) {
+    if (vdso_shdr[i].sh_type == SHT_DYNSYM) {
+      symbol_count = vdso_shdr[i].sh_size / sizeof(ElfW(Sym));
+    }
+  }
+  if (symbol_count == 0) {
+    return;
+  }
+
+  // Where's the dynamic table?
+  ElfW(Addr) vdso_addr = 0;
+  ElfW(Dyn)* vdso_dyn = NULL;
+  ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
+  for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
+    if (vdso_phdr[i].p_type == PT_DYNAMIC) {
+      vdso_dyn = reinterpret_cast<ElfW(Dyn)*>(vdso_ehdr_addr + vdso_phdr[i].p_offset);
+    } else if (vdso_phdr[i].p_type == PT_LOAD) {
+      vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
+    }
+  }
+  if (vdso_addr == 0 || vdso_dyn == NULL) {
+    return;
+  }
+
+  // Where are the string and symbol tables?
+  const char* strtab = NULL;
+  ElfW(Sym)* symtab = NULL;
+  for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
+    if (d->d_tag == DT_STRTAB) {
+      strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr);
+    } else if (d->d_tag == DT_SYMTAB) {
+      symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr);
+    }
+  }
+  if (strtab == NULL || symtab == NULL) {
+    return;
+  }
+
+  // Are there any symbols we want?
+  for (size_t i = 0; i < symbol_count; ++i) {
+    for (size_t j = 0; j < VDSO_END; ++j) {
+      if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) {
+        vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
+      }
+    }
+  }
+}
+
+#else
+
+void __libc_init_vdso() {
+}
+
+#endif
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index 19b1adf..d05a952 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -75,7 +75,6 @@
 
 int isalnum_l(int, locale_t);
 int isalpha_l(int, locale_t);
-int isascii_l(int, locale_t);
 int isblank_l(int, locale_t);
 int iscntrl_l(int, locale_t);
 int isdigit_l(int, locale_t);
diff --git a/libc/include/elf.h b/libc/include/elf.h
index 7a217b0..0975b7a 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -67,9 +67,6 @@
 
 #define ELFOSABI_SYSV 0 /* Synonym for ELFOSABI_NONE used by valgrind. */
 
-#define EM_ARM 40
-#define EM_AARCH64 183
-
 #define PT_GNU_RELRO 0x6474e552
 
 #define STB_LOOS   10
diff --git a/libc/include/sys/glibc-syscalls.h b/libc/include/sys/glibc-syscalls.h
index 3131b6b..459ee78 100644
--- a/libc/include/sys/glibc-syscalls.h
+++ b/libc/include/sys/glibc-syscalls.h
@@ -217,10 +217,12 @@
 #define SYS_sched_get_priority_max __NR_sched_get_priority_max
 #define SYS_sched_get_priority_min __NR_sched_get_priority_min
 #define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
 #define SYS_sched_getparam __NR_sched_getparam
 #define SYS_sched_getscheduler __NR_sched_getscheduler
 #define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
 #define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
 #define SYS_sched_setparam __NR_sched_setparam
 #define SYS_sched_setscheduler __NR_sched_setscheduler
 #define SYS_sched_yield __NR_sched_yield
@@ -545,10 +547,12 @@
 #define SYS_sched_get_priority_max __NR_sched_get_priority_max
 #define SYS_sched_get_priority_min __NR_sched_get_priority_min
 #define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
 #define SYS_sched_getparam __NR_sched_getparam
 #define SYS_sched_getscheduler __NR_sched_getscheduler
 #define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
 #define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
 #define SYS_sched_setparam __NR_sched_setparam
 #define SYS_sched_setscheduler __NR_sched_setscheduler
 #define SYS_sched_yield __NR_sched_yield
@@ -902,10 +906,12 @@
 #define SYS_sched_get_priority_max __NR_sched_get_priority_max
 #define SYS_sched_get_priority_min __NR_sched_get_priority_min
 #define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
 #define SYS_sched_getparam __NR_sched_getparam
 #define SYS_sched_getscheduler __NR_sched_getscheduler
 #define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
 #define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
 #define SYS_sched_setparam __NR_sched_setparam
 #define SYS_sched_setscheduler __NR_sched_setscheduler
 #define SYS_sched_yield __NR_sched_yield
@@ -1258,10 +1264,12 @@
 #define SYS_sched_get_priority_max __NR_sched_get_priority_max
 #define SYS_sched_get_priority_min __NR_sched_get_priority_min
 #define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
 #define SYS_sched_getparam __NR_sched_getparam
 #define SYS_sched_getscheduler __NR_sched_getscheduler
 #define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
 #define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
 #define SYS_sched_setparam __NR_sched_setparam
 #define SYS_sched_setscheduler __NR_sched_setscheduler
 #define SYS_sched_yield __NR_sched_yield
@@ -1586,10 +1594,12 @@
 #define SYS_sched_get_priority_max __NR_sched_get_priority_max
 #define SYS_sched_get_priority_min __NR_sched_get_priority_min
 #define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
 #define SYS_sched_getparam __NR_sched_getparam
 #define SYS_sched_getscheduler __NR_sched_getscheduler
 #define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
 #define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
 #define SYS_sched_setparam __NR_sched_setparam
 #define SYS_sched_setscheduler __NR_sched_setscheduler
 #define SYS_sched_yield __NR_sched_yield
diff --git a/libc/include/sys/prctl.h b/libc/include/sys/prctl.h
index 00e5837..391c22a 100644
--- a/libc/include/sys/prctl.h
+++ b/libc/include/sys/prctl.h
@@ -31,6 +31,25 @@
 #include <linux/prctl.h>
 #include <sys/cdefs.h>
 
+/* These should appear in the uapi headers at some point, but they're not there right now. */
+#if !defined(PR_SET_TIMERSLACK_PID)
+#define PR_SET_TIMERSLACK_PID 41
+#else
+#error PR_SET_TIMERSLACK_PID defined twice
+#endif
+
+#if !defined(PR_SET_VMA)
+#define PR_SET_VMA 0x53564d41
+#else
+#error PR_SET_VMA defined twice
+#endif
+
+#if !defined(PR_SET_VMA_ANON_NAME)
+#define PR_SET_VMA_ANON_NAME 0
+#else
+#error PR_SET_VMA_ANON_NAME defined twice
+#endif
+
 __BEGIN_DECLS
 
 /* IMPORTANT NOTE: This function is declared as taking a variable number
diff --git a/libc/include/sys/ptrace.h b/libc/include/sys/ptrace.h
index 848416b..8bba9fe 100644
--- a/libc/include/sys/ptrace.h
+++ b/libc/include/sys/ptrace.h
@@ -30,15 +30,15 @@
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
-/* For all of the defines */
 #include <linux/ptrace.h>
 
 __BEGIN_DECLS
 
-#define PTRACE_POKEUSER     PTRACE_POKEUSR
-#define PTRACE_PEEKUSER     PTRACE_PEEKUSR
+/* glibc uses different names from the kernel for these two... */
+#define PTRACE_POKEUSER PTRACE_POKEUSR
+#define PTRACE_PEEKUSER PTRACE_PEEKUSR
 
-extern long ptrace(int request, pid_t pid, void *addr, void *data);
+extern long ptrace(int, ...);
 
 __END_DECLS
 
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index ae2f238..3b11d20 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -40,6 +40,13 @@
 #include <linux/types.h>
 #include <linux/compiler.h>
 
+/* This is an Android extension that won't be in the uapi headers for the common kernel. */
+#if !defined(SIOCKILLADDR)
+#define SIOCKILLADDR 0x8939
+#else
+#error SIOCKILLADDR defined twice
+#endif
+
 __BEGIN_DECLS
 
 #define sockaddr_storage __kernel_sockaddr_storage
diff --git a/libc/kernel/README.TXT b/libc/kernel/README.TXT
index 0edbcc6..e7312ef 100644
--- a/libc/kernel/README.TXT
+++ b/libc/kernel/README.TXT
@@ -55,11 +55,15 @@
 
 Grab the latest headers from the android kernel by running this command:
 
-  bionic/kernel/tools/generate_uapi_headers.sh --download-kernel
+  bionic/libc/kernel/tools/generate_uapi_headers.sh --download-kernel
 
 Next, run this command to copy the parsed files to bionic/libc/kernel/uapi:
 
-  bionic/kernel/tools/update_all.py
+  bionic/libc/kernel/tools/update_all.py
+
+Finally, run this command to regenerate the syscalls list:
+
+  bionic/libc/tools/gensyscalls.py
 
 After this, you will need to build/test the tree to make sure that these
 changes do not introduce any errors.
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index a3a6985..61794bd 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -37,6 +37,8 @@
   (((value) + (alignment) - 1) & ~((alignment) - 1))
 
 #define BIONIC_ROUND_UP_POWER_OF_2(value) \
-  (1UL << (sizeof(value) * 8 - 1 - __builtin_clz(value)))
+  (sizeof(value) == 8) \
+    ? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
+    : (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value))))
 
 #endif // _BIONIC_MACROS_H_
diff --git a/libc/private/bionic_name_mem.h b/libc/private/bionic_name_mem.h
index 98716f4..1c7664e 100644
--- a/libc/private/bionic_name_mem.h
+++ b/libc/private/bionic_name_mem.h
@@ -34,7 +34,7 @@
 
 __BEGIN_DECLS
 
-int __bionic_name_mem(void* addr, size_t len, const char* name);
+__LIBC_HIDDEN__ int __bionic_name_mem(void* addr, size_t len, const char* name);
 
 __END_DECLS
 
diff --git a/libc/private/thread_private.h b/libc/private/thread_private.h
index 724808a..b8b1a81 100644
--- a/libc/private/thread_private.h
+++ b/libc/private/thread_private.h
@@ -33,8 +33,12 @@
 #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
 	pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock )
 
-__LIBC_HIDDEN__ void	_thread_atexit_lock(void);
-__LIBC_HIDDEN__ void	_thread_atexit_unlock(void);
+/* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */
+#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
+#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)
+
+__LIBC_HIDDEN__ void  _thread_atexit_lock(void);
+__LIBC_HIDDEN__ void  _thread_atexit_unlock(void);
 
 #define _ATEXIT_LOCK() _thread_atexit_lock()
 #define _ATEXIT_UNLOCK() _thread_atexit_unlock()
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 151e009..4511a71 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -49,14 +49,7 @@
  */
 __LIBC_HIDDEN__ int __srget(FILE*);
 __LIBC_HIDDEN__ int __swbuf(int, FILE*);
-
-/*
- * The NDK apparently includes an android_support.a library that
- * refers to __srefill in its copy of the vsnprintf implementation.
- */
-/* TODO(LP64): __LIBC_HIDDEN__ int __srefill(FILE*);*/
-/* http://b/15291317: the LP64 NDK needs to be fixed to remove that cruft. */
-__LIBC_ABI_PUBLIC__ int __srefill(FILE*);
+__LIBC_HIDDEN__ int __srefill(FILE*);
 #else
 __LIBC_ABI_PUBLIC__ int __srget(FILE*);
 __LIBC_ABI_PUBLIC__ int __swbuf(int, FILE*);
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
deleted file mode 100644
index e10238b..0000000
--- a/libc/stdlib/atexit.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*	$OpenBSD: atexit.c,v 1.14 2007/09/05 20:47:47 chl Exp $ */
-/*
- * Copyright (c) 2002 Daniel Hartmeier
- * 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 HOLDERS 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/mman.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "atexit.h"
-#include "private/thread_private.h"
-
-struct atexit *__atexit;
-
-/*
- * TODO: Read this before upstreaming:
- *
- * As of Apr 2014 there is a bug regaring function type detection logic in
- * Free/Open/NetBSD implementations of __cxa_finalize().
- *
- * What it is about:
- * First of all there are two kind of atexit handlers:
- *  1) void handler(void) - this is the regular type
- *     available for to user via atexit(.) function call.
- *
- *  2) void internal_handler(void*) - this is the type
- *     __cxa_atexit() function expects. This handler is used
- *     by C++ compiler to register static destructor calls.
- *     Note that calling this function as the handler of type (1)
- *     results in incorrect this pointer in static d-tors.
- *
- * What is wrong with BSD implementations:
- *
- *  They use dso argument to identify the handler type. The problem
- *  with it is dso is also used to identify the handlers associated
- *  with particular dynamic library and allow __cxa_finalize to call correct
- *  set of functions on dlclose(). And it cannot identify both.
- *
- * What is correct way to identify function type?
- *
- *  Consider this:
- *  1. __cxa_finalize and __cxa_atexit are part of libc and do not have access to hidden
- *     &__dso_handle.
- *  2. __cxa_atexit has only 3 arguments: function pointer, function argument, dso.
- *     none of them can be reliably used to pass information about handler type.
- *  3. following http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor (3.3.5.3 - B)
- *     translation of user atexit -> __cxa_atexit(f, NULL, NULL) results in crashes
- *     on exit() after dlclose() of a library with an atexit() call.
- *
- *  One way to resolve this is to always call second form of handler, which will
- *  result in storing unused argument in register/stack depending on architecture
- *  and should not present any problems.
- *
- *  Another way is to make them dso-local in one way or the other.
- */
-
-/*
- * Function pointers are stored in a linked list of pages. The list
- * is initially empty, and pages are allocated on demand. The first
- * function pointer in the first allocated page (the last one in
- * the linked list) was reserved for the cleanup function.
- *
- * Outside the following functions, all pages are mprotect()'ed
- * to prevent unintentional/malicious corruption.
- */
-
-/*
- * Register a function to be performed at exit or when a shared object
- * with the given dso handle is unloaded dynamically.  Also used as
- * the backend for atexit().  For more info on this API, see:
- *
- *	http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
- */
-int
-__cxa_atexit(void (*func)(void *), void *arg, void *dso)
-{
-	struct atexit *p = __atexit;
-	struct atexit_fn *fnp;
-	size_t pgsize = getpagesize();
-	int ret = -1;
-
-	if (pgsize < sizeof(*p))
-		return (-1);
-	_ATEXIT_LOCK();
-	p = __atexit;
-	if (p != NULL) {
-		if (p->ind + 1 >= p->max)
-			p = NULL;
-		else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
-			goto unlock;
-	}
-	if (p == NULL) {
-		p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
-		    MAP_ANON | MAP_PRIVATE, -1, 0);
-		if (p == MAP_FAILED)
-			goto unlock;
-		if (__atexit == NULL) {
-			memset(&p->fns[0], 0, sizeof(p->fns[0]));
-			p->ind = 1;
-		} else
-			p->ind = 0;
-		p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
-		    sizeof(p->fns[0]);
-		p->next = __atexit;
-		__atexit = p;
-	}
-	fnp = &p->fns[p->ind++];
-	fnp->cxa_func = func;
-	fnp->fn_arg = arg;
-	fnp->fn_dso = dso;
-	if (mprotect(p, pgsize, PROT_READ))
-		goto unlock;
-	ret = 0;
-unlock:
-	_ATEXIT_UNLOCK();
-	return (ret);
-}
-
-/*
- * Call all handlers registered with __cxa_atexit() for the shared
- * object owning 'dso'.
- * Note: if 'dso' is NULL, then all remaining handlers are called.
- */
-void
-__cxa_finalize(void *dso)
-{
-	struct atexit *p, *q, *original_atexit;
-	struct atexit_fn fn;
-	int n, pgsize = getpagesize(), original_ind;
-	static int call_depth;
-
-	_ATEXIT_LOCK();
-	call_depth++;
-
-	p = original_atexit = __atexit;
-	n = original_ind = p != NULL ? p->ind : 0;
-	while (p != NULL) {
-		if (p->fns[n].cxa_func != NULL /* not called */
-				&& (dso == NULL || dso == p->fns[n].fn_dso)) { /* correct DSO */
-			/*
-			 * Mark handler as having been already called to avoid
-			 * dupes and loops, then call the appropriate function.
-			 */
-			fn = p->fns[n];
-			if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
-				p->fns[n].cxa_func = NULL;
-				mprotect(p, pgsize, PROT_READ);
-			}
-
-			_ATEXIT_UNLOCK();
-			(*fn.cxa_func)(fn.fn_arg);
-			_ATEXIT_LOCK();
-			// check for new atexit handlers
-			if ((__atexit->ind != original_ind) || (__atexit != original_atexit)) {
-				// need to restart now to preserve correct
-				// call order - LIFO
-				p = original_atexit = __atexit;
-				n = original_ind = p->ind;
-				continue;
-			}
-		}
-		if (n == 0) {
-			p = p->next;
-			n = p != NULL ? p->ind : 0;
-		} else {
-			--n;
-		}
-	}
-
-	--call_depth;
-
-	/*
-	 * If called via exit(), unmap the pages since we have now run
-	 * all the handlers.  We defer this until calldepth == 0 so that
-	 * we don't unmap things prematurely if called recursively.
-	 */
-	if (dso == NULL && call_depth == 0) {
-		for (p = __atexit; p != NULL; ) {
-			q = p;
-			p = p->next;
-			munmap(q, pgsize);
-		}
-		__atexit = NULL;
-	}
-	_ATEXIT_UNLOCK();
-}
-
-/*
- * Register the cleanup function
- */
-void
-__atexit_register_cleanup(void (*func)(void))
-{
-        struct atexit *p;
-        size_t pgsize = getpagesize();
-
-        if (pgsize < sizeof(*p))
-                return;
-        _ATEXIT_LOCK();
-        p = __atexit;
-        while (p != NULL && p->next != NULL)
-                p = p->next;
-        if (p == NULL) {
-                p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
-                    MAP_ANON | MAP_PRIVATE, -1, 0);
-                if (p == MAP_FAILED)
-                        goto unlock;
-                p->ind = 1;
-                p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
-                    sizeof(p->fns[0]);
-                p->next = NULL;
-                __atexit = p;
-        } else {
-                if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
-                        goto unlock;
-        }
-        p->fns[0].cxa_func = (void (*)(void*))func;
-        p->fns[0].fn_arg = NULL;
-        p->fns[0].fn_dso = NULL;
-        mprotect(p, pgsize, PROT_READ);
-unlock:
-        _ATEXIT_UNLOCK();
-}
diff --git a/libc/upstream-freebsd/android/include/namespace.h b/libc/upstream-freebsd/android/include/namespace.h
index a980b57..a3f850e 100644
--- a/libc/upstream-freebsd/android/include/namespace.h
+++ b/libc/upstream-freebsd/android/include/namespace.h
@@ -17,6 +17,4 @@
 #ifndef _BIONIC_FREEBSD_NAMESPACE_H_included
 #define _BIONIC_FREEBSD_NAMESPACE_H_included
 
-__attribute__((visibility("hidden"))) char* _mktemp(char*);
-
 #endif
diff --git a/libc/upstream-netbsd/android/include/namespace.h b/libc/upstream-netbsd/android/include/namespace.h
index a4d4151..5df543c 100644
--- a/libc/upstream-netbsd/android/include/namespace.h
+++ b/libc/upstream-netbsd/android/include/namespace.h
@@ -22,4 +22,7 @@
 #undef __weak_alias
 #endif
 
+__LIBC_HIDDEN__ int __res_enable_mt(void);
+__LIBC_HIDDEN__ int __res_disable_mt(void);
+
 #endif
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/rand.c b/libc/upstream-netbsd/lib/libc/stdlib/rand.c
deleted file mode 100644
index 4909d14..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/rand.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*	$NetBSD: rand.c,v 1.12 2012/06/25 22:32:45 abs Exp $	*/
-
-/*-
- * Copyright (c) 1990, 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/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)rand.c	8.1 (Berkeley) 6/14/93";
-#else
-__RCSID("$NetBSD: rand.c,v 1.12 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <stdlib.h>
-
-static u_long next = 1;
-
-int
-rand(void)
-{
-	/* LINTED integer overflow */
-	return (int)((next = next * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
-}
-
-void
-srand(u_int seed)
-{
-	next = seed;
-}
diff --git a/libc/upstream-netbsd/lib/libc/thread-stub/__isthreaded.c b/libc/upstream-netbsd/lib/libc/thread-stub/__isthreaded.c
deleted file mode 100644
index 50c1b6f..0000000
--- a/libc/upstream-netbsd/lib/libc/thread-stub/__isthreaded.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*	$NetBSD: __isthreaded.c,v 1.3 2009/12/01 01:33:25 explorer Exp $	*/
-
-/*-
- * 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.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: __isthreaded.c,v 1.3 2009/12/01 01:33:25 explorer Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-int __isthreaded = 0;
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index f00d91a..5827a82 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -37,7 +37,17 @@
 #define issetugid() 0
 
 /* LP32 NDK ctype.h contained references to these. */
-__LIBC64_HIDDEN__ extern const short *_tolower_tab_;
-__LIBC64_HIDDEN__ extern const short *_toupper_tab_;
+__LIBC64_HIDDEN__ extern const short* _tolower_tab_;
+__LIBC64_HIDDEN__ extern const short* _toupper_tab_;
+
+__LIBC_HIDDEN__ extern struct atexit* __atexit;
+__LIBC_HIDDEN__ extern const char _C_ctype_[];
+__LIBC_HIDDEN__ extern const short _C_toupper_[];
+__LIBC_HIDDEN__ extern const short _C_tolower_[];
+__LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*);
+__LIBC_HIDDEN__ extern char* _mktemp(char*);
+
+/* TODO: hide this when android_support.a is fixed (http://b/16298580).*/
+/*__LIBC_HIDDEN__*/ extern int __isthreaded;
 
 #endif
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/atexit.c b/libc/upstream-openbsd/lib/libc/stdlib/atexit.c
new file mode 100644
index 0000000..6532b38
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/atexit.c
@@ -0,0 +1,202 @@
+/*	$OpenBSD: atexit.c,v 1.20 2014/07/11 09:51:37 kettenis Exp $ */
+/*
+ * Copyright (c) 2002 Daniel Hartmeier
+ * 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 HOLDERS 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/mman.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "atexit.h"
+#include "thread_private.h"
+
+struct atexit *__atexit;
+static int restartloop;
+
+/*
+ * Function pointers are stored in a linked list of pages. The list
+ * is initially empty, and pages are allocated on demand. The first
+ * function pointer in the first allocated page (the last one in
+ * the linked list) is reserved for the cleanup function.
+ *
+ * Outside the following functions, all pages are mprotect()'ed
+ * to prevent unintentional/malicious corruption.
+ */
+
+/*
+ * Register a function to be performed at exit or when a shared object
+ * with the given dso handle is unloaded dynamically.  Also used as
+ * the backend for atexit().  For more info on this API, see:
+ *
+ *	http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
+ */
+int
+__cxa_atexit(void (*func)(void *), void *arg, void *dso)
+{
+	struct atexit *p = __atexit;
+	struct atexit_fn *fnp;
+	int pgsize = getpagesize();
+	int ret = -1;
+
+	if (pgsize < sizeof(*p))
+		return (-1);
+	_ATEXIT_LOCK();
+	p = __atexit;
+	if (p != NULL) {
+		if (p->ind + 1 >= p->max)
+			p = NULL;
+		else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
+			goto unlock;
+	}
+	if (p == NULL) {
+		p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
+		    MAP_ANON | MAP_PRIVATE, -1, 0);
+		if (p == MAP_FAILED)
+			goto unlock;
+		if (__atexit == NULL) {
+			memset(&p->fns[0], 0, sizeof(p->fns[0]));
+			p->ind = 1;
+		} else
+			p->ind = 0;
+		p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
+		    sizeof(p->fns[0]);
+		p->next = __atexit;
+		__atexit = p;
+	}
+	fnp = &p->fns[p->ind++];
+	fnp->fn_ptr = func;
+	fnp->fn_arg = arg;
+	fnp->fn_dso = dso;
+	if (mprotect(p, pgsize, PROT_READ))
+		goto unlock;
+	restartloop = 1;
+	ret = 0;
+unlock:
+	_ATEXIT_UNLOCK();
+	return (ret);
+}
+
+/*
+ * Call all handlers registered with __cxa_atexit() for the shared
+ * object owning 'dso'.
+ * Note: if 'dso' is NULL, then all remaining handlers are called.
+ */
+void
+__cxa_finalize(void *dso)
+{
+	struct atexit *p, *q;
+	struct atexit_fn fn;
+	int n, pgsize = getpagesize();
+	static int call_depth;
+
+	_ATEXIT_LOCK();
+	call_depth++;
+
+restart:
+	restartloop = 0;
+	for (p = __atexit; p != NULL; p = p->next) {
+		for (n = p->ind; --n >= 0;) {
+			if (p->fns[n].fn_ptr == NULL)
+				continue;	/* already called */
+			if (dso != NULL && dso != p->fns[n].fn_dso)
+				continue;	/* wrong DSO */
+
+			/*
+			 * Mark handler as having been already called to avoid
+			 * dupes and loops, then call the appropriate function.
+			 */
+			fn = p->fns[n];
+			if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
+				p->fns[n].fn_ptr = NULL;
+				mprotect(p, pgsize, PROT_READ);
+			}
+			_ATEXIT_UNLOCK();
+			(*fn.fn_ptr)(fn.fn_arg);
+			_ATEXIT_LOCK();
+			if (restartloop)
+				goto restart;
+		}
+	}
+
+	call_depth--;
+
+	/*
+	 * If called via exit(), unmap the pages since we have now run
+	 * all the handlers.  We defer this until calldepth == 0 so that
+	 * we don't unmap things prematurely if called recursively.
+	 */
+	if (dso == NULL && call_depth == 0) {
+		for (p = __atexit; p != NULL; ) {
+			q = p;
+			p = p->next;
+			munmap(q, pgsize);
+		}
+		__atexit = NULL;
+	}
+	_ATEXIT_UNLOCK();
+}
+
+/*
+ * Register the cleanup function
+ */
+void
+__atexit_register_cleanup(void (*func)(void))
+{
+	struct atexit *p;
+	int pgsize = getpagesize();
+
+	if (pgsize < sizeof(*p))
+		return;
+	_ATEXIT_LOCK();
+	p = __atexit;
+	while (p != NULL && p->next != NULL)
+		p = p->next;
+	if (p == NULL) {
+		p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
+		    MAP_ANON | MAP_PRIVATE, -1, 0);
+		if (p == MAP_FAILED)
+			goto unlock;
+		p->ind = 1;
+		p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
+		    sizeof(p->fns[0]);
+		p->next = NULL;
+		__atexit = p;
+	} else {
+		if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
+			goto unlock;
+	}
+	p->fns[0].fn_ptr = (void (*)(void *))func;
+	p->fns[0].fn_arg = NULL;
+	p->fns[0].fn_dso = NULL;
+	mprotect(p, pgsize, PROT_READ);
+	restartloop = 1;
+unlock:
+	_ATEXIT_UNLOCK();
+}
diff --git a/libc/stdlib/atexit.h b/libc/upstream-openbsd/lib/libc/stdlib/atexit.h
similarity index 88%
rename from libc/stdlib/atexit.h
rename to libc/upstream-openbsd/lib/libc/stdlib/atexit.h
index b530ade..3de2aa3 100644
--- a/libc/stdlib/atexit.h
+++ b/libc/upstream-openbsd/lib/libc/stdlib/atexit.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: atexit.h,v 1.7 2007/09/03 14:40:16 millert Exp $ */
+/*	$OpenBSD: atexit.h,v 1.9 2014/06/18 19:01:10 kettenis Exp $ */
 
 /*
  * Copyright (c) 2002 Daniel Hartmeier
@@ -30,24 +30,18 @@
  *
  */
 
-#include <sys/cdefs.h>
-
 struct atexit {
 	struct atexit *next;		/* next in list */
 	int ind;			/* next index in this table */
 	int max;			/* max entries >= ATEXIT_SIZE */
 	struct atexit_fn {
-		void (*cxa_func)(void *);
+		void (*fn_ptr)(void *);
 		void *fn_arg;		/* argument for CXA callback */
 		void *fn_dso;		/* shared module handle */
 	} fns[1];			/* the table itself */
 };
 
-__BEGIN_DECLS
-
-__LIBC_HIDDEN__ extern struct atexit *__atexit;		/* points to head of LIFO stack */
+extern struct atexit *__atexit;		/* points to head of LIFO stack */
 
 int	__cxa_atexit(void (*)(void *), void *, void *);
 void	__cxa_finalize(void *);
-
-__END_DECLS
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/exit.c b/libc/upstream-openbsd/lib/libc/stdlib/exit.c
index ef8b335..83fe3d2 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/exit.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/exit.c
@@ -33,6 +33,16 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include "atexit.h"
+#include "thread_private.h"
+
+/*
+ * This variable is zero until a process has created a thread.
+ * It is used to avoid calling locking functions in libc when they
+ * are not required. By default, libc is intended to be(come)
+ * thread-safe, but without a (significant) penalty to non-threaded
+ * processes.
+ */
+int     __isthreaded    = 0;
 
 /*
  * Exit, flushing stdio buffers if necessary.
diff --git a/libc/upstream-openbsd/lib/libc/string/stpcpy.c b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
index d3d61e0..d88afac 100644
--- a/libc/upstream-openbsd/lib/libc/string/stpcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: stpcpy.c,v 1.1 2012/01/17 02:48:01 guenther Exp $	*/
+/*	$OpenBSD: stpcpy.c,v 1.2 2014/07/09 17:08:21 naddy Exp $	*/
 
 /*
  * Copyright (c) 1988 Regents of the University of California.
@@ -33,7 +33,7 @@
 
 #if defined(APIWARN)
 __warn_references(stpcpy,
-    "warning: stpcpy() is dangerous GNU crap; don't use it");
+    "warning: stpcpy() is dangerous; do not use it");
 #endif
 
 char *
diff --git a/libc/upstream-openbsd/lib/libc/string/strcat.c b/libc/upstream-openbsd/lib/libc/string/strcat.c
index 7cea522..646c9c2 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcat.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strcat.c,v 1.8 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strcat.c,v 1.9 2014/06/10 04:17:37 deraadt Exp $	*/
 
 /*
  * Copyright (c) 1988 Regents of the University of California.
@@ -29,11 +29,7 @@
  * SUCH DAMAGE.
  */
 
-#if !defined(_KERNEL) && !defined(_STANDALONE)
 #include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
 
 #if defined(APIWARN)
 __warn_references(strcat,
diff --git a/libc/upstream-openbsd/lib/libc/string/strcmp.c b/libc/upstream-openbsd/lib/libc/string/strcmp.c
index 816fd11..d1b6c50 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcmp.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcmp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strcmp.c,v 1.7 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strcmp.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -32,11 +32,7 @@
  * SUCH DAMAGE.
  */
 
-#if !defined(_KERNEL) && !defined(_STANDALONE)
 #include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
 
 /*
  * Compare strings.
diff --git a/libc/upstream-openbsd/lib/libc/string/strcpy.c b/libc/upstream-openbsd/lib/libc/string/strcpy.c
index 71d90d4..5a9001e 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcpy.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strcpy.c,v 1.8 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strcpy.c,v 1.9 2014/06/10 04:17:37 deraadt Exp $	*/
 
 /*
  * Copyright (c) 1988 Regents of the University of California.
@@ -29,11 +29,7 @@
  * SUCH DAMAGE.
  */
 
-#if !defined(_KERNEL) && !defined(_STANDALONE)
 #include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
 
 #if defined(APIWARN)
 __warn_references(strcpy,
diff --git a/libc/upstream-openbsd/lib/libc/string/strlen.c b/libc/upstream-openbsd/lib/libc/string/strlen.c
index 12d9ec4..7e0e27b 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlen.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlen.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strlen.c,v 1.7 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strlen.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -29,11 +29,7 @@
  * SUCH DAMAGE.
  */
 
-#if !defined(_KERNEL) && !defined(_STANDALONE)
 #include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
 
 size_t
 strlen(const char *str)
diff --git a/libc/upstream-openbsd/lib/libc/string/strncmp.c b/libc/upstream-openbsd/lib/libc/string/strncmp.c
index 0aea80d..0a4ddc1 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncmp.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncmp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strncmp.c,v 1.7 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strncmp.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $	*/
 
 /*
  * Copyright (c) 1989 The Regents of the University of California.
@@ -29,11 +29,7 @@
  * SUCH DAMAGE.
  */
 
-#if !defined(_KERNEL) && !defined(_STANDALONE)
 #include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
 
 int
 strncmp(const char *s1, const char *s2, size_t n)
diff --git a/libc/upstream-openbsd/lib/libc/string/strncpy.c b/libc/upstream-openbsd/lib/libc/string/strncpy.c
index 4426cbe..5003a19 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncpy.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strncpy.c,v 1.6 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strncpy.c,v 1.7 2014/06/10 04:17:37 deraadt Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -32,11 +32,7 @@
  * SUCH DAMAGE.
  */
 
-#if !defined(_KERNEL) && !defined(_STANDALONE)
 #include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
 
 /*
  * Copy src to dst, truncating or null-padding to always copy n bytes.
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 11585af..0b99d20 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -156,10 +156,7 @@
 }
 
 bool ElfReader::VerifyElfHeader() {
-  if (header_.e_ident[EI_MAG0] != ELFMAG0 ||
-      header_.e_ident[EI_MAG1] != ELFMAG1 ||
-      header_.e_ident[EI_MAG2] != ELFMAG2 ||
-      header_.e_ident[EI_MAG3] != ELFMAG3) {
+  if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
     DL_ERR("\"%s\" has bad ELF magic", name_);
     return false;
   }
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 7c86d76..6d29421 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -53,17 +53,10 @@
 
 TEST(stdlib, rand) {
   srand(0x01020304);
-#if defined(__BIONIC__)
-  EXPECT_EQ(1675538669, rand());
-  EXPECT_EQ(1678228258, rand());
-  EXPECT_EQ(1352350131, rand());
-  EXPECT_EQ(824068976, rand());
-#else
   EXPECT_EQ(55436735, rand());
   EXPECT_EQ(1399865117, rand());
   EXPECT_EQ(2032643283, rand());
   EXPECT_EQ(571329216, rand());
-#endif
 }
 
 TEST(stdlib, mrand48) {
diff --git a/tests/sys_time_test.cpp b/tests/sys_time_test.cpp
index 730992f..bb142bc 100644
--- a/tests/sys_time_test.cpp
+++ b/tests/sys_time_test.cpp
@@ -17,6 +17,7 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <sys/syscall.h>
 #include <sys/time.h>
 
 #include "TemporaryFile.h"
@@ -46,3 +47,23 @@
   TemporaryFile tf;
   ASSERT_EQ(0, utimes(tf.filename, NULL));
 }
+
+TEST(sys_time, gettimeofday) {
+  // Try to ensure that our vdso gettimeofday is working.
+  timeval tv1;
+  ASSERT_EQ(0, gettimeofday(&tv1, NULL));
+  timeval tv2;
+  ASSERT_EQ(0, syscall(__NR_gettimeofday, &tv2, NULL));
+
+  // What's the difference between the two?
+  tv2.tv_sec -= tv1.tv_sec;
+  tv2.tv_usec -= tv1.tv_usec;
+  if (tv2.tv_usec < 0) {
+    --tv2.tv_sec;
+    tv2.tv_usec += 1000000;
+  }
+
+  // Should be less than (a very generous, to try to avoid flakiness) 1000us.
+  ASSERT_EQ(0, tv2.tv_sec);
+  ASSERT_LT(tv2.tv_usec, 1000);
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 58cb374..12b1ea7 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -21,6 +21,7 @@
 #include <gtest/gtest.h>
 #include <pthread.h>
 #include <signal.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -419,3 +420,23 @@
   ASSERT_EQ(ESRCH, pthread_detach(tdd.thread_id));
 #endif
 }
+
+TEST(time, clock_gettime) {
+  // Try to ensure that our vdso clock_gettime is working.
+  timespec ts1;
+  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
+  timespec ts2;
+  ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
+
+  // What's the difference between the two?
+  ts2.tv_sec -= ts1.tv_sec;
+  ts2.tv_nsec -= ts1.tv_nsec;
+  if (ts2.tv_nsec < 0) {
+    --ts2.tv_sec;
+    ts2.tv_nsec += 1000000000;
+  }
+
+  // Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
+  ASSERT_EQ(0, ts2.tv_sec);
+  ASSERT_LT(ts2.tv_nsec, 1000000);
+}