Merge "Whitelist __NR__newselect."
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index 41306db..86a7c35 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -58,19 +58,42 @@
 }
 BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES;
 
-static void BM_string_memmove(benchmark::State& state) {
+static void BM_string_memmove_non_overlapping(benchmark::State& state) {
   const size_t nbytes = state.range(0);
-  char* buf = new char[nbytes + 64];
-  memset(buf, 'x', nbytes + 64);
+  std::vector<char> src(nbytes, 'x');
+  std::vector<char> dst(nbytes, 'x');
 
   while (state.KeepRunning()) {
-    memmove(buf, buf + 1, nbytes); // Worst-case overlap.
+    memmove(dst.data(), src.data(), nbytes);
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
-  delete[] buf;
 }
-BENCHMARK(BM_string_memmove)->AT_COMMON_SIZES;
+BENCHMARK(BM_string_memmove_non_overlapping)->AT_COMMON_SIZES;
+
+static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  std::vector<char> buf(nbytes + 1, 'x');
+
+  while (state.KeepRunning()) {
+    memmove(buf.data(), buf.data() + 1, nbytes); // Worst-case overlap.
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_memmove_overlap_dst_before_src)->AT_COMMON_SIZES;
+
+static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  std::vector<char> buf(nbytes + 1, 'x');
+
+  while (state.KeepRunning()) {
+    memmove(buf.data() + 1, buf.data(), nbytes); // Worst-case overlap.
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_memmove_overlap_src_before_dst)->AT_COMMON_SIZES;
 
 static void BM_string_memset(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -100,3 +123,83 @@
   delete[] s;
 }
 BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;
+
+static void BM_string_strcat_copy_only(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  std::vector<char> src(nbytes, 'x');
+  std::vector<char> dst(nbytes + 2);
+  src[nbytes - 1] = '\0';
+  dst[0] = 'y';
+  dst[1] = 'y';
+  dst[2] = '\0';
+
+  while (state.KeepRunning()) {
+    strcat(dst.data(), src.data());
+    dst[2] = '\0';
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcat_copy_only)->AT_COMMON_SIZES;
+
+static void BM_string_strcat_seek_only(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  std::vector<char> src(3, 'x');
+  std::vector<char> dst(nbytes + 2, 'y');
+  src[2] = '\0';
+  dst[nbytes - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    strcat(dst.data(), src.data());
+    dst[nbytes - 1] = '\0';
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcat_seek_only)->AT_COMMON_SIZES;
+
+static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  std::vector<char> src(nbytes / 2, 'x');
+  std::vector<char> dst(nbytes / 2, 'y');
+  src[nbytes / 2 - 1] = '\0';
+  dst[nbytes / 2 - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    strcat(dst.data(), src.data());
+    dst[nbytes / 2 - 1] = '\0';
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcat_half_copy_half_seek)->AT_COMMON_SIZES;
+
+static void BM_string_strcpy(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  std::vector<char> src(nbytes, 'x');
+  std::vector<char> dst(nbytes);
+  src[nbytes - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    strcpy(dst.data(), src.data());
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcpy)->AT_COMMON_SIZES;
+
+static void BM_string_strcmp(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  std::vector<char> s1(nbytes, 'x');
+  std::vector<char> s2(nbytes, 'x');
+  s1[nbytes - 1] = '\0';
+  s2[nbytes - 1] = '\0';
+
+  volatile int c __attribute__((unused));
+  while (state.KeepRunning()) {
+    c = strcmp(s1.data(), s2.data());
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcmp)->AT_COMMON_SIZES;
diff --git a/libc/Android.bp b/libc/Android.bp
index 5a1c287..4f6ff1a 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -123,6 +123,12 @@
     cflags: ["-fno-stack-protector"],
 }
 
+cc_library_static {
+    name: "libc_init_dynamic",
+    defaults: ["libc_defaults"],
+    srcs: ["bionic/libc_init_dynamic.cpp"],
+    cflags: ["-fno-stack-protector"],
+}
 
 // ========================================================
 // libc_tzcode.a - upstream 'tzcode' code
@@ -1757,10 +1763,10 @@
             "arch-common/bionic/crtbrand.S",
             "bionic/icu.cpp",
             "bionic/malloc_common.cpp",
-            "bionic/libc_init_dynamic.cpp",
             "bionic/NetdClient.cpp",
             "arch-common/bionic/crtend_so.S",
         ],
+        whole_static_libs: ["libc_init_dynamic"],
     },
 
     required: ["tzdata"],
diff --git a/libc/NOTICE b/libc/NOTICE
index fcc3c85..82df90a 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -110,25 +110,6 @@
 
 -------------------------------------------------------------------
 
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
-Copyright 2006, 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.
-
--------------------------------------------------------------------
-
 ====================================================
 Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 
diff --git a/libc/SECCOMP_WHITELIST.TXT b/libc/SECCOMP_WHITELIST.TXT
index 4d6897c..11485dd 100644
--- a/libc/SECCOMP_WHITELIST.TXT
+++ b/libc/SECCOMP_WHITELIST.TXT
@@ -36,6 +36,9 @@
 int	rt_tgsigqueueinfo:int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *uinfo)	all
 int	restart_syscall:int restart_syscall()	all
 int	getrandom:int getrandom(void *buf, size_t buflen, unsigned int flags) all
+int	fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)	mips64
+int	fstat64|fstat:fstat(int, struct stat*)	mips64
+int	_flush_cache:cacheflush(char* addr, const int nbytes, const int op)	mips64
 
 # Needed for performance tools
 int	perf_event_open:perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags)	all
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 5ff3c64..d674630 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -143,7 +143,7 @@
 int ___fchmodat:fchmodat(int, const char*, mode_t)  all
 int fchownat(int, const char*, uid_t, gid_t, int)  all
 int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int)   arm,mips,x86
-int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,mips64,x86_64
+int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,x86_64
 int linkat(int, const char*, int, const char*, int)  all
 int mkdirat(int, const char*, mode_t)  all
 int mknodat(int, const char*, mode_t, dev_t)  all
@@ -187,7 +187,7 @@
 int __statfs:statfs(const char*, struct statfs*)  arm64,mips64,x86_64
 
 int     fstat64|fstat:fstat64(int, struct stat*)    arm,mips,x86
-int     fstat64|fstat:fstat(int, struct stat*)    arm64,mips64,x86_64
+int     fstat64|fstat:fstat(int, struct stat*)    arm64,x86_64
 
 # file system
 int     chdir(const char*)              all
@@ -343,7 +343,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-mips64/bionic/stat.cpp b/libc/arch-mips64/bionic/stat.cpp
index 29a50ed..63b6cd1 100644
--- a/libc/arch-mips64/bionic/stat.cpp
+++ b/libc/arch-mips64/bionic/stat.cpp
@@ -43,11 +43,11 @@
   unsigned int st_pad1[3];
   __kernel_off_t st_size;
   unsigned int _st_atime;
-  unsigned int st_atime_nsec;
+  unsigned int _st_atime_nsec;
   unsigned int _st_mtime;
-  unsigned int st_mtime_nsec;
+  unsigned int _st_mtime_nsec;
   unsigned int _st_ctime;
-  unsigned int st_ctime_nsec;
+  unsigned int _st_ctime_nsec;
   unsigned int st_blksize;
   unsigned int st_pad2;
   unsigned long st_blocks;
@@ -65,11 +65,11 @@
   st->st_blksize = static_cast<int>(s->st_blksize);
   st->st_blocks = static_cast<long>(s->st_blocks);
   st->st_atim.tv_sec = static_cast<time_t>(s->_st_atime);
-  st->st_atim.tv_nsec = static_cast<long>(s->st_atime_nsec);
+  st->st_atim.tv_nsec = static_cast<long>(s->_st_atime_nsec);
   st->st_mtim.tv_sec = static_cast<time_t>(s->_st_mtime);
-  st->st_mtim.tv_nsec = static_cast<long>(s->st_mtime_nsec);
+  st->st_mtim.tv_nsec = static_cast<long>(s->_st_mtime_nsec);
   st->st_ctim.tv_sec = static_cast<time_t>(s->_st_ctime);
-  st->st_ctim.tv_nsec = static_cast<long>(s->st_ctime_nsec);
+  st->st_ctim.tv_nsec = static_cast<long>(s->_st_ctime_nsec);
 }
 
 int fstat(int fp, struct stat* st) {
diff --git a/libc/async_safe/Android.bp b/libc/async_safe/Android.bp
index 9e36d97..a835697 100644
--- a/libc/async_safe/Android.bp
+++ b/libc/async_safe/Android.bp
@@ -8,6 +8,7 @@
     ],
 
     name: "libasync_safe",
+    vendor_available: true,
 
     include_dirs: ["bionic/libc"],
 
diff --git a/libc/async_safe/async_safe_log.cpp b/libc/async_safe/async_safe_log.cpp
index 372f385..99ff0c7 100644
--- a/libc/async_safe/async_safe_log.cpp
+++ b/libc/async_safe/async_safe_log.cpp
@@ -567,10 +567,9 @@
   android_set_abort_message(msg);
 }
 
-void async_safe_fatal(const char* fmt, ...) {
+void async_safe_fatal_no_abort(const char* fmt, ...) {
   va_list args;
   va_start(args, fmt);
   async_safe_fatal_va_list(nullptr, fmt, args);
   va_end(args);
-  abort();
 }
diff --git a/libc/async_safe/include/async_safe/log.h b/libc/async_safe/include/async_safe/log.h
index f93f672..6fdb84f 100644
--- a/libc/async_safe/include/async_safe/log.h
+++ b/libc/async_safe/include/async_safe/log.h
@@ -33,6 +33,7 @@
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <stdlib.h>
 
 // These functions do not allocate memory to send data to the log.
 
@@ -65,9 +66,19 @@
 };
 
 // Formats a message to the log (priority 'fatal'), then aborts.
-__noreturn void async_safe_fatal(const char* _Nonnull fmt, ...) __printflike(1, 2);
+// Implemented as a macro so that async_safe_fatal isn't on the stack when we crash:
+// we appear to go straight from the caller to abort, saving an uninteresting stack
+// frame.
+#define async_safe_fatal(...) \
+  do { \
+    async_safe_fatal_no_abort(__VA_ARGS__); \
+    abort(); \
+  } while (0) \
 
-// This function does return, so callers that want to abort, must do so themselves.
+
+// These functions do return, so callers that want to abort, must do so themselves,
+// or use the macro above.
+void async_safe_fatal_no_abort(const char* _Nonnull fmt, ...) __printflike(1, 2);
 #if defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
 void async_safe_fatal_va_list(
     const char* _Nullable prefix, const char* _Nonnull fmt, va_list);
diff --git a/libc/bionic/__errno.cpp b/libc/bionic/__errno.cpp
index c9c1605..32e7a52 100644
--- a/libc/bionic/__errno.cpp
+++ b/libc/bionic/__errno.cpp
@@ -31,6 +31,6 @@
 
 #include "private/bionic_tls.h"
 
-volatile int*  __errno() {
+int*  __errno() {
   return reinterpret_cast<int*>(&(__get_tls()[TLS_SLOT_ERRNO]));
 }
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index 3ba83d1..f401cab 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -32,6 +32,26 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
+// We call tgkill(2) directly instead of raise (or even the libc tgkill wrapper), to reduce the
+// number of uninteresting stack frames at the top of a crash.
+static inline __always_inline void inline_tgkill(pid_t pid, pid_t tid, int sig) {
+#if defined(__arm__)
+  register int r0 __asm__("r0") = pid;
+  register int r1 __asm__("r1") = tid;
+  register int r2 __asm__("r2") = sig;
+  register int r7 __asm__("r7") = __NR_tgkill;
+  __asm__("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r7) : "memory");
+#elif defined(__aarch64__)
+  register long x0 __asm__("x0") = pid;
+  register long x1 __asm__("x1") = tid;
+  register long x2 __asm__("x2") = sig;
+  register long x8 __asm__("x8") = __NR_tgkill;
+  __asm__("svc #0" : "=r"(x0) : "r"(x0), "r"(x1), "r"(x2), "r"(x8) : "memory");
+#else
+  syscall(__NR_tgkill, pid, tid, sig);
+#endif
+}
+
 void abort() {
   // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
   // http://b/37769298
@@ -45,8 +65,7 @@
   sigdelset(&mask, SIGABRT);
   sigprocmask(SIG_SETMASK, &mask, NULL);
 
-  // Use tgkill directly instead of raise, to avoid inserting spurious stack frames.
-  tgkill(pid, tid, SIGABRT);
+  inline_tgkill(pid, tid, SIGABRT);
 
   // If SIGABRT ignored, or caught and the handler returns,
   // remove the SIGABRT signal handler and raise SIGABRT again.
@@ -57,7 +76,7 @@
   sigaction(SIGABRT, &sa, &sa);
   sigprocmask(SIG_SETMASK, &mask, NULL);
 
-  tgkill(pid, tid, SIGABRT);
+  inline_tgkill(pid, tid, SIGABRT);
 
   // If we get this far, just exit.
   _exit(127);
diff --git a/libc/bionic/bionic_arc4random.cpp b/libc/bionic/bionic_arc4random.cpp
index a4842f6..a339900 100644
--- a/libc/bionic/bionic_arc4random.cpp
+++ b/libc/bionic/bionic_arc4random.cpp
@@ -32,7 +32,6 @@
 #include <stdatomic.h>
 #include <stdlib.h>
 #include <sys/auxv.h>
-#include <syscall.h>
 #include <unistd.h>
 
 #include <async_safe/log.h>
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index 3a20aa9..d7ce37f 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -30,6 +30,7 @@
 #include <sched.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <sys/syscall.h>
 
 #include "pthread_internal.h"
 
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index 32ea255..efcbb8c 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -27,7 +27,6 @@
  */
 
 #include <unistd.h>
-#include <sys/syscall.h>
 
 #include "pthread_internal.h"
 
diff --git a/libc/bionic/gettid.cpp b/libc/bionic/gettid.cpp
index fe25a4d..eb5cfd6 100644
--- a/libc/bionic/gettid.cpp
+++ b/libc/bionic/gettid.cpp
@@ -27,6 +27,7 @@
  */
 
 #include <unistd.h>
+#include <sys/syscall.h>
 
 #include "pthread_internal.h"
 
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 43bca30..7c73950 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -61,6 +61,21 @@
   extern int __cxa_atexit(void (*)(void *), void *, void *);
 };
 
+// We need a helper function for __libc_preinit because compiling with LTO may
+// inline functions requiring a stack protector check, but __stack_chk_guard is
+// not initialized at the start of __libc_preinit. __libc_preinit_impl will run
+// after __stack_chk_guard is initialized and therefore can safely have a stack
+// protector.
+__attribute__((noinline))
+static void __libc_preinit_impl(KernelArgumentBlock& args) {
+  __libc_init_globals(args);
+  __libc_init_common(args);
+
+  // Hooks for various libraries to let them know that we're starting up.
+  __libc_globals.mutate(__libc_init_malloc);
+  netdClientInit();
+}
+
 // We flag the __libc_preinit function as a constructor to ensure
 // that its address is listed in libc.so's .init_array section.
 // This ensures that the function is called by the dynamic linker
@@ -79,12 +94,7 @@
   // thread's TLS slot with that value. Initialize the local global stack guard with its value.
   __stack_chk_guard = reinterpret_cast<uintptr_t>(tls[TLS_SLOT_STACK_GUARD]);
 
-  __libc_init_globals(*args);
-  __libc_init_common(*args);
-
-  // Hooks for various libraries to let them know that we're starting up.
-  __libc_globals.mutate(__libc_init_malloc);
-  netdClientInit();
+  __libc_preinit_impl(*args);
 }
 
 // This function is called from the executable's _start entry point
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index 77f8dde..8e2acef 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -36,6 +36,23 @@
 
 #include "private/icu.h"
 
+enum {
+  WC_TYPE_INVALID = 0,
+  WC_TYPE_ALNUM,
+  WC_TYPE_ALPHA,
+  WC_TYPE_BLANK,
+  WC_TYPE_CNTRL,
+  WC_TYPE_DIGIT,
+  WC_TYPE_GRAPH,
+  WC_TYPE_LOWER,
+  WC_TYPE_PRINT,
+  WC_TYPE_PUNCT,
+  WC_TYPE_SPACE,
+  WC_TYPE_UPPER,
+  WC_TYPE_XDIGIT,
+  WC_TYPE_MAX
+};
+
 static bool __icu_hasBinaryProperty(wint_t wc, UProperty property, int (*fallback)(int)) {
   typedef UBool (*FnT)(UChar32, UProperty);
   static auto u_hasBinaryProperty = reinterpret_cast<FnT>(__find_icu_symbol("u_hasBinaryProperty"));
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index a5d3a6f..09db2a6 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -37,10 +37,10 @@
 
 __BEGIN_DECLS
 
-sighandler_t bsd_signal(int signum, sighandler_t handler) __REMOVED_IN(21);
-
 #if __ANDROID_API__ < __ANDROID_API_L__
 
+sighandler_t bsd_signal(int signum, sighandler_t handler) __REMOVED_IN(21);
+
 /* These weren't introduced until L. */
 int __libc_current_sigrtmax() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
 int __libc_current_sigrtmin() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h
index b8f3cec..018482d 100644
--- a/libc/include/dlfcn.h
+++ b/libc/include/dlfcn.h
@@ -57,23 +57,20 @@
 void* dlvsym(void* handle, const char* _Nonnull symbol, const char* _Nonnull version) __INTRODUCED_IN(24);
 int dladdr(const void* addr, Dl_info* _Nonnull info);
 
-enum {
-#if defined(__LP64__)
-  RTLD_NOW  = 2,
-#else
-  RTLD_NOW  = 0,
-#endif
-  RTLD_LAZY = 1,
+#define RTLD_LOCAL    0
+#define RTLD_LAZY     0x00001
+#define RTLD_NOW      0x00002
+#define RTLD_NOLOAD   0x00004
+#define RTLD_GLOBAL   0x00100
+#define RTLD_NODELETE 0x01000
 
-  RTLD_LOCAL  = 0,
-#if defined(__LP64__)
-  RTLD_GLOBAL = 0x00100,
-#else
-  RTLD_GLOBAL = 2,
+#if !defined(__LP64__)
+/* LP32 is broken for historical reasons. */
+#undef RTLD_NOW
+#define RTLD_NOW      0x00000
+#undef RTLD_GLOBAL
+#define RTLD_GLOBAL   0x00002
 #endif
-  RTLD_NOLOAD = 4,
-  RTLD_NODELETE = 0x01000,
-};
 
 #if defined (__LP64__)
 #define RTLD_DEFAULT  __BIONIC_CAST(reinterpret_cast, void*, 0)
diff --git a/libc/include/errno.h b/libc/include/errno.h
index 3f4cff9..cbe67fa 100644
--- a/libc/include/errno.h
+++ b/libc/include/errno.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _ERRNO_H
 #define _ERRNO_H
 
@@ -33,18 +34,13 @@
 
 __BEGIN_DECLS
 
-/* on Linux, ENOTSUP and EOPNOTSUPP are defined as the same error code
- * even if 1000.3 states that they should be different
- */
-#ifndef  ENOTSUP
-#define  ENOTSUP  EOPNOTSUPP
+/* On Linux, ENOTSUP and EOPNOTSUPP are the same despite POSIX saying they should be distinct. */
+#ifndef ENOTSUP
+#define ENOTSUP EOPNOTSUPP
 #endif
 
-/* internal function returning the address of the thread-specific errno */
-volatile int* __errno(void) __attribute_const__;
-
-/* a macro expanding to the errno l-value */
-#define  errno   (*__errno())
+int* __errno(void) __attribute_const__;
+#define errno (*__errno())
 
 __END_DECLS
 
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index c34d1a3..20b6c5b 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -160,6 +160,18 @@
 int pthread_mutex_trylock(pthread_mutex_t* _Nonnull);
 int pthread_mutex_unlock(pthread_mutex_t* _Nonnull);
 
+#if defined(__LP32__) && __ANDROID_API__ < 21
+/*
+ * Cruft for supporting old API levels. Pre-L we didn't have
+ * pthread_mutex_timedlock, instead we had pthread_mutex_lock_timeout_np. NDK
+ * users targeting pre-L still need this, but anyone targeting L or newer (or
+ * LP64 code) should just use pthread_mutex_timedlock.
+ *
+ * https://github.com/android-ndk/ndk/issues/420
+ */
+int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex, unsigned msecs);
+#endif
+
 int pthread_once(pthread_once_t* _Nonnull, void (* _Nonnull init_routine)(void));
 
 int pthread_rwlockattr_init(pthread_rwlockattr_t* _Nonnull);
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 004c6b5..d62206d 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -303,13 +303,23 @@
 #define __pass_object_size __pass_object_size_n(__bos_level)
 #define __pass_object_size0 __pass_object_size_n(0)
 
-/* Used to support clangisms with FORTIFY. This isn't in the FORTIFY section
- * because these change how symbols are emitted. The linker must be kept happy.
+/*
+ * Used to support clangisms with FORTIFY. Because these change how symbols are
+ * emitted, we need to ensure that bionic itself is built fortified. But lots
+ * of external code (especially stuff using configure) likes to declare
+ * functions directly, and they can't know that the overloadable attribute
+ * exists. This leads to errors like:
+ *
+ * dcigettext.c:151:7: error: redeclaration of 'getcwd' must have the 'overloadable' attribute
+ * char *getcwd ();
+ *       ^
+ *
+ * To avoid this and keep such software building, don't use overloadable if
+ * we're not using fortify.
  */
-#ifdef __clang__
+#if defined(__clang__) && defined(__BIONIC_FORTIFY)
 #  define __overloadable __attribute__((overloadable))
-// Don't use __RENAME directly because on gcc, this could result in a number of
-// unnecessary renames.
+/* We don't use __RENAME directly because on gcc this could result in unnecessary renames. */
 #  define __RENAME_CLANG(x) __RENAME(x)
 #else
 #  define __overloadable
diff --git a/libc/include/sys/mtio.h b/libc/include/sys/mtio.h
new file mode 100644
index 0000000..8fb5655
--- /dev/null
+++ b/libc/include/sys/mtio.h
@@ -0,0 +1 @@
+#include <linux/mtio.h>
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index f8d854d..47ff5c4 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -127,6 +127,10 @@
 #define st_atimensec st_atim.tv_nsec
 #define st_mtimensec st_mtim.tv_nsec
 #define st_ctimensec st_ctim.tv_nsec
+/* Compatibility with Linux headers and old NDKs. */
+#define st_atime_nsec st_atim.tv_nsec
+#define st_mtime_nsec st_mtim.tv_nsec
+#define st_ctime_nsec st_ctim.tv_nsec
 
 #if defined(__USE_BSD)
 /* Permission macros provided by glibc for compatibility with BSDs. */
diff --git a/libc/include/sys/ucontext.h b/libc/include/sys/ucontext.h
index 4eddf23..4cc66eb 100644
--- a/libc/include/sys/ucontext.h
+++ b/libc/include/sys/ucontext.h
@@ -40,21 +40,37 @@
 
 enum {
   REG_R0 = 0,
+#define REG_R0 REG_R0
   REG_R1,
+#define REG_R1 REG_R1
   REG_R2,
+#define REG_R2 REG_R2
   REG_R3,
+#define REG_R3 REG_R3
   REG_R4,
+#define REG_R4 REG_R4
   REG_R5,
+#define REG_R5 REG_R5
   REG_R6,
+#define REG_R6 REG_R6
   REG_R7,
+#define REG_R7 REG_R7
   REG_R8,
+#define REG_R8 REG_R8
   REG_R9,
+#define REG_R9 REG_R9
   REG_R10,
+#define REG_R10 REG_R10
   REG_R11,
+#define REG_R11 REG_R11
   REG_R12,
+#define REG_R12 REG_R12
   REG_R13,
+#define REG_R13 REG_R13
   REG_R14,
+#define REG_R14 REG_R14
   REG_R15,
+#define REG_R15 REG_R15
 };
 
 #define NGREG 18 /* Like glibc. */
@@ -103,25 +119,45 @@
 
 enum {
   REG_GS = 0,
+#define REG_GS REG_GS
   REG_FS,
+#define REG_FS REG_FS
   REG_ES,
+#define REG_ES REG_ES
   REG_DS,
+#define REG_DS REG_DS
   REG_EDI,
+#define REG_EDI REG_EDI
   REG_ESI,
+#define REG_ESI REG_ESI
   REG_EBP,
+#define REG_EBP REG_EBP
   REG_ESP,
+#define REG_ESP REG_ESP
   REG_EBX,
+#define REG_EBX REG_EBX
   REG_EDX,
+#define REG_EDX REG_EDX
   REG_ECX,
+#define REG_ECX REG_ECX
   REG_EAX,
+#define REG_EAX REG_EAX
   REG_TRAPNO,
+#define REG_TRAPNO REG_TRAPNO
   REG_ERR,
+#define REG_ERR REG_ERR
   REG_EIP,
+#define REG_EIP REG_EIP
   REG_CS,
+#define REG_CS REG_CS
   REG_EFL,
+#define REG_EFL REG_EFL
   REG_UESP,
+#define REG_UESP REG_UESP
   REG_SS,
+#define REG_SS REG_SS
   NGREG
+#define NGREG NGREG
 };
 
 typedef int greg_t;
@@ -237,29 +273,53 @@
 
 enum {
   REG_R8 = 0,
+#define REG_R8 REG_R8
   REG_R9,
+#define REG_R9 REG_R9
   REG_R10,
+#define REG_R10 REG_R10
   REG_R11,
+#define REG_R11 REG_R11
   REG_R12,
+#define REG_R12 REG_R12
   REG_R13,
+#define REG_R13 REG_R13
   REG_R14,
+#define REG_R14 REG_R14
   REG_R15,
+#define REG_R15 REG_R15
   REG_RDI,
+#define REG_RDI REG_RDI
   REG_RSI,
+#define REG_RSI REG_RSI
   REG_RBP,
+#define REG_RBP REG_RBP
   REG_RBX,
+#define REG_RBX REG_RBX
   REG_RDX,
+#define REG_RDX REG_RDX
   REG_RAX,
+#define REG_RAX REG_RAX
   REG_RCX,
+#define REG_RCX REG_RCX
   REG_RSP,
+#define REG_RSP REG_RSP
   REG_RIP,
+#define REG_RIP REG_RIP
   REG_EFL,
+#define REG_EFL REG_EFL
   REG_CSGSFS,
+#define REG_CSGSFS REG_CSGSFS
   REG_ERR,
+#define REG_ERR REG_ERR
   REG_TRAPNO,
+#define REG_TRAPNO REG_TRAPNO
   REG_OLDMASK,
+#define REG_OLDMASK REG_OLDMASK
   REG_CR2,
+#define REG_CR2 REG_CR2
   NGREG
+#define NGREG NGREG
 };
 
 typedef long greg_t;
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index d3e9f5c..c9a78be 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -42,23 +42,6 @@
 
 __BEGIN_DECLS
 
-enum {
-    WC_TYPE_INVALID = 0,
-    WC_TYPE_ALNUM,
-    WC_TYPE_ALPHA,
-    WC_TYPE_BLANK,
-    WC_TYPE_CNTRL,
-    WC_TYPE_DIGIT,
-    WC_TYPE_GRAPH,
-    WC_TYPE_LOWER,
-    WC_TYPE_PRINT,
-    WC_TYPE_PUNCT,
-    WC_TYPE_SPACE,
-    WC_TYPE_UPPER,
-    WC_TYPE_XDIGIT,
-    WC_TYPE_MAX
-};
-
 wint_t            btowc(int);
 int               fwprintf(FILE *, const wchar_t *, ...);
 int               fwscanf(FILE *, const wchar_t *, ...);
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/qsort.c b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
index 93e22cd..1ccc518 100644
--- a/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
+++ b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
@@ -41,47 +41,53 @@
 typedef int		 cmp_t(const void *, const void *);
 #endif
 static inline char	*med3(char *, char *, char *, cmp_t *, void *);
-static inline void	 swapfunc(char *, char *, int, int);
+static inline void	 swapfunc(char *, char *, size_t, int, int);
 
-#define min(a, b)	(a) < (b) ? a : b
+#define	MIN(a, b)	((a) < (b) ? a : b)
 
 /*
  * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
  */
-#define swapcode(TYPE, parmi, parmj, n) { 		\
-	long i = (n) / sizeof (TYPE); 			\
-	TYPE *pi = (TYPE *) (parmi); 		\
-	TYPE *pj = (TYPE *) (parmj); 		\
+#define	swapcode(TYPE, parmi, parmj, n) {		\
+	size_t i = (n) / sizeof (TYPE);			\
+	TYPE *pi = (TYPE *) (parmi);		\
+	TYPE *pj = (TYPE *) (parmj);		\
 	do { 						\
 		TYPE	t = *pi;		\
 		*pi++ = *pj;				\
 		*pj++ = t;				\
-        } while (--i > 0);				\
+	} while (--i > 0);				\
 }
 
-#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
-	es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+#define	SWAPINIT(TYPE, a, es) swaptype_ ## TYPE =	\
+	((char *)a - (char *)0) % sizeof(TYPE) ||	\
+	es % sizeof(TYPE) ? 2 : es == sizeof(TYPE) ? 0 : 1;
 
 static inline void
-swapfunc(a, b, n, swaptype)
-	char *a, *b;
-	int n, swaptype;
+swapfunc(char *a, char *b, size_t n, int swaptype_long, int swaptype_int)
 {
-	if(swaptype <= 1)
+	if (swaptype_long <= 1)
 		swapcode(long, a, b, n)
+	else if (swaptype_int <= 1)
+		swapcode(int, a, b, n)
 	else
 		swapcode(char, a, b, n)
 }
 
-#define swap(a, b)					\
-	if (swaptype == 0) {				\
+#define	swap(a, b)					\
+	if (swaptype_long == 0) {			\
 		long t = *(long *)(a);			\
 		*(long *)(a) = *(long *)(b);		\
 		*(long *)(b) = t;			\
+	} else if (swaptype_int == 0) {			\
+		int t = *(int *)(a);			\
+		*(int *)(a) = *(int *)(b);		\
+		*(int *)(b) = t;			\
 	} else						\
-		swapfunc(a, b, es, swaptype)
+		swapfunc(a, b, es, swaptype_long, swaptype_int)
 
-#define vecswap(a, b, n) 	if ((n) > 0) swapfunc(a, b, n, swaptype)
+#define	vecswap(a, b, n)				\
+	if ((n) > 0) swapfunc(a, b, n, swaptype_long, swaptype_int)
 
 #ifdef I_AM_QSORT_R
 #define	CMP(t, x, y) (cmp((t), (x), (y)))
@@ -98,24 +104,25 @@
 {
 	return CMP(thunk, a, b) < 0 ?
 	       (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
-              :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+	      :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
 }
 
 #ifdef I_AM_QSORT_R
 void
 qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
 #else
-#define thunk NULL
+#define	thunk NULL
 void
 qsort(void *a, size_t n, size_t es, cmp_t *cmp)
 #endif
 {
 	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
-	size_t d, r;
+	size_t d1, d2;
 	int cmp_result;
-	int swaptype, swap_cnt;
+	int swaptype_long, swaptype_int, swap_cnt;
 
-loop:	SWAPINIT(a, es);
+loop:	SWAPINIT(long, a, es);
+	SWAPINIT(int, a, es);
 	swap_cnt = 0;
 	if (n < 7) {
 		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
@@ -130,7 +137,8 @@
 		pl = a;
 		pn = (char *)a + (n - 1) * es;
 		if (n > 40) {
-			d = (n / 8) * es;
+			size_t d = (n / 8) * es;
+
 			pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
 			pm = med3(pm - d, pm, pm + d, cmp, thunk);
 			pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
@@ -175,21 +183,43 @@
 	}
 
 	pn = (char *)a + n * es;
-	r = min(pa - (char *)a, pb - pa);
-	vecswap(a, pb - r, r);
-	r = min(pd - pc, pn - pd - es);
-	vecswap(pb, pn - r, r);
-	if ((r = pb - pa) > es)
+	d1 = MIN(pa - (char *)a, pb - pa);
+	vecswap(a, pb - d1, d1);
+	d1 = MIN(pd - pc, pn - pd - es);
+	vecswap(pb, pn - d1, d1);
+
+	d1 = pb - pa;
+	d2 = pd - pc;
+	if (d1 <= d2) {
+		/* Recurse on left partition, then iterate on right partition */
+		if (d1 > es) {
 #ifdef I_AM_QSORT_R
-		qsort_r(a, r / es, es, thunk, cmp);
+			qsort_r(a, d1 / es, es, thunk, cmp);
 #else
-		qsort(a, r / es, es, cmp);
+			qsort(a, d1 / es, es, cmp);
 #endif
-	if ((r = pd - pc) > es) {
-		/* Iterate rather than recurse to save stack space */
-		a = pn - r;
-		n = r / es;
-		goto loop;
+		}
+		if (d2 > es) {
+			/* Iterate rather than recurse to save stack space */
+			/* qsort(pn - d2, d2 / es, es, cmp); */
+			a = pn - d2;
+			n = d2 / es;
+			goto loop;
+		}
+	} else {
+		/* Recurse on right partition, then iterate on left partition */
+		if (d2 > es) {
+#ifdef I_AM_QSORT_R
+			qsort_r(pn - d2, d2 / es, es, thunk, cmp);
+#else
+			qsort(pn - d2, d2 / es, es, cmp);
+#endif
+		}
+		if (d1 > es) {
+			/* Iterate rather than recurse to save stack space */
+			/* qsort(a, d1 / es, es, cmp); */
+			n = d1 / es;
+			goto loop;
+		}
 	}
-/*		qsort(pn - r, r / es, es, cmp);*/
 }
diff --git a/libc/zoneinfo/Android.mk b/libc/zoneinfo/Android.mk
deleted file mode 100644
index faa1f06..0000000
--- a/libc/zoneinfo/Android.mk
+++ /dev/null
@@ -1,46 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := tzdata
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/zoneinfo
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := tzlookup.xml
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/zoneinfo
-include $(BUILD_PREBUILT)
-
-# The host build doesn't use bionic, but it does use bionic's zoneinfo data
-ifeq ($(WITH_HOST_DALVIK),true)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := tzdata-host
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_IS_HOST_MODULE := true
-LOCAL_SRC_FILES := tzdata
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_STEM := $(LOCAL_SRC_FILES)
-LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/zoneinfo
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := tzlookup.xml-host
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_IS_HOST_MODULE := true
-LOCAL_SRC_FILES := tzlookup.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_STEM := $(LOCAL_SRC_FILES)
-LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/zoneinfo
-include $(BUILD_PREBUILT)
-
-endif
diff --git a/libc/zoneinfo/MODULE_LICENSE_PUBLIC_DOMAIN b/libc/zoneinfo/MODULE_LICENSE_PUBLIC_DOMAIN
deleted file mode 100644
index e69de29..0000000
--- a/libc/zoneinfo/MODULE_LICENSE_PUBLIC_DOMAIN
+++ /dev/null
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
deleted file mode 100644
index c5932bc..0000000
--- a/libc/zoneinfo/tzdata
+++ /dev/null
Binary files differ
diff --git a/libc/zoneinfo/tzlookup.xml b/libc/zoneinfo/tzlookup.xml
deleted file mode 100644
index 5846f50..0000000
--- a/libc/zoneinfo/tzlookup.xml
+++ /dev/null
@@ -1,1622 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2006, 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.
-*/
--->
-<timezones>
-  <!-- Time zones by country.
-
-       Data in this file originates from IANA's zone.tab file.
-       The ordering of zones within each country is Android-specific and
-       affects Android behavior, see below for details.
-
-       The ordering of country elements is not important but is kept in ASCII
-       order by code for easier maintenance. There must only be one country
-       element per unique code. The code attribute is the (lower cased)
-       ISO 3166 2-character country code used in the IANA zones.tab file.
-
-       The <id> entries contain the IANA IDs for time zones used in a
-       country.
-
-       The file is used when picking a time zone for an Android device given
-       a known local time, offset from UTC and whether the local zone is
-       currently observing DST.
-
-       The ordering of <id> elements is important because it influence the
-       order that time zones in a country are considered.
-
-       Currently the <id> entries are mostly primarily ordered by raw (non-DST)
-       offset and then "desirability". This ordering is an historical artifact
-       that is likely to change in future.
-
-       The most sensible ordering for <id> entries for a country is by
-       population of users that observe the time zone to maximize the
-       probability of matching an arbitrary user. Then:
-
-       The first <id> entry for a given country should have the highest
-       likelihood of matching the user's needs when only the user's country
-       code is available.
-
-       The first zone that matches a user's country, offset and DST state
-       should have the highest likelihood of matching the user's needs when
-       country code, offset and DST state are available.
-    -->
-  <countryzones>
-
-    <!-- ANDORRA, 1:00 -->
-    <country code="ad">
-      <id>Europe/Andorra</id>
-    </country>
-
-    <!-- UNITED ARAB EMIRATES, 4:00 -->
-    <country code="ae">
-      <id>Asia/Dubai</id>
-    </country>
-
-    <!-- AFGHANISTAN, 4:30 -->
-    <country code="af">
-      <id>Asia/Kabul</id>
-    </country>
-
-    <!-- ANTIGUA AND BARBUDA, -4:00 -->
-    <country code="ag">
-      <id>America/Antigua</id>
-    </country>
-
-    <!-- ANGUILLA, -4:00 -->
-    <country code="ai">
-      <id>America/Anguilla</id>
-    </country>
-
-    <!-- ALBANIA, 1:00 -->
-    <country code="al">
-      <id>Europe/Tirane</id>
-    </country>
-
-    <!-- ARMENIA, 4:00 -->
-    <country code="am">
-      <id>Asia/Yerevan</id>
-    </country>
-
-    <!-- ANGOLA, 1:00 -->
-    <country code="ao">
-      <id>Africa/Luanda</id>
-    </country>
-
-    <!-- ANTARCTICA -->
-    <country code="aq">
-      <!-- 12:00 -->
-      <id>Antarctica/McMurdo</id>
-
-      <!-- 10:00 -->
-      <id>Antarctica/DumontDUrville</id>
-
-      <!-- 8:00 -->
-      <id>Antarctica/Casey</id>
-
-      <!-- 7:00 -->
-      <id>Antarctica/Davis</id>
-
-      <!-- 5:00 -->
-      <id>Antarctica/Mawson</id>
-
-      <!-- 6:00 -->
-      <id>Antarctica/Vostok</id>
-
-      <!-- 3:00 -->
-      <id>Antarctica/Syowa</id>
-
-      <!-- 0:00 -->
-      <id>Antarctica/Troll</id>
-
-      <!-- -3:00 -->
-      <id>Antarctica/Rothera</id>
-
-      <!-- -4:00 -->
-      <id>Antarctica/Palmer</id>
-    </country>
-
-    <!-- ARGENTINA, -3:00 -->
-    <country code="ar">
-      <id>America/Argentina/Buenos_Aires</id>
-      <id>America/Argentina/Cordoba</id>
-      <id>America/Argentina/Salta</id>
-      <id>America/Argentina/Jujuy</id>
-      <id>America/Argentina/Tucuman</id>
-      <id>America/Argentina/Catamarca</id>
-      <id>America/Argentina/La_Rioja</id>
-      <id>America/Argentina/San_Juan</id>
-      <id>America/Argentina/Mendoza</id>
-      <id>America/Argentina/San_Luis</id>
-      <id>America/Argentina/Rio_Gallegos</id>
-      <id>America/Argentina/Ushuaia</id>
-    </country>
-
-    <!-- AMERICAN SAMOA, -11:00 -->
-    <country code="as">
-      <id>Pacific/Pago_Pago</id>
-    </country>
-
-    <!-- AUSTRIA, 1:00 -->
-    <country code="at">
-      <id>Europe/Vienna</id>
-    </country>
-
-    <!-- AUSTRALIA -->
-    <country code="au">
-      <!-- 10:00 -->
-      <id>Australia/Sydney</id>
-      <id>Australia/Melbourne</id>
-      <id>Australia/Brisbane</id>
-      <id>Australia/Hobart</id>
-      <id>Australia/Currie</id>
-      <id>Australia/Lindeman</id>
-
-      <!-- 11:00 -->
-      <id>Antarctica/Macquarie</id>
-
-      <!-- 10:30 -->
-      <id>Australia/Lord_Howe</id>
-
-      <!-- 9:30 -->
-      <id>Australia/Adelaide</id>
-      <id>Australia/Broken_Hill</id>
-      <id>Australia/Darwin</id>
-
-      <!-- 8:00 -->
-      <id>Australia/Perth</id>
-
-      <!-- 8:45 -->
-      <id>Australia/Eucla</id>
-    </country>
-
-    <!-- ARUBA, -4:00 -->
-    <country code="aw">
-      <id>America/Aruba</id>
-    </country>
-
-    <!-- ALAND ISLANDS, 2:00 -->
-    <country code="ax">
-      <id>Europe/Mariehamn</id>
-    </country>
-
-    <!-- AZERBAIJAN, 4:00 -->
-    <country code="az">
-      <id>Asia/Baku</id>
-    </country>
-
-    <!-- BOSNIA AND HERZEGOVINA, 1:00 -->
-    <country code="ba">
-      <id>Europe/Sarajevo</id>
-    </country>
-
-    <!-- BARBADOS, -4:00 -->
-    <country code="bb">
-      <id>America/Barbados</id>
-    </country>
-
-    <!-- BANGLADESH, 6:00 -->
-    <country code="bd">
-      <id>Asia/Dhaka</id>
-    </country>
-
-    <!-- BELGIUM, 1:00 -->
-    <country code="be">
-      <id>Europe/Brussels</id>
-    </country>
-
-    <!-- BURKINA FASO, 0:00 -->
-    <country code="bf">
-      <id>Africa/Ouagadougou</id>
-    </country>
-
-    <!-- BULGARIA, 2:00 -->
-    <country code="bg">
-      <id>Europe/Sofia</id>
-    </country>
-
-    <!-- BAHRAIN, 3:00 -->
-    <country code="bh">
-      <id>Asia/Bahrain</id>
-    </country>
-
-    <!-- BURUNDI, 2:00 -->
-    <country code="bi">
-      <id>Africa/Bujumbura</id>
-    </country>
-
-    <!-- BENIN, 1:00 -->
-    <country code="bj">
-      <id>Africa/Porto-Novo</id>
-    </country>
-
-    <!-- Saint Barthélemy, -4:00 -->
-    <country code="bl">
-      <id>America/St_Barthelemy</id>
-    </country>
-
-    <!-- BERMUDA, -4:00 -->
-    <country code="bm">
-      <id>Atlantic/Bermuda</id>
-    </country>
-
-    <!-- BRUNEI DARUSSALAM, 8:00 -->
-    <country code="bn">
-      <id>Asia/Brunei</id>
-    </country>
-
-    <!-- BOLIVIA, -4:00 -->
-    <country code="bo">
-      <id>America/La_Paz</id>
-    </country>
-
-    <!-- Caribbean Netherlands, -4:00 -->
-    <country code="bq">
-      <id>America/Kralendijk</id>
-    </country>
-
-    <!-- BRAZIL -->
-    <country code="br">
-      <!-- -2:00 -->
-      <id>America/Noronha</id>
-
-      <!-- -3:00 -->
-      <id>America/Sao_Paulo</id>
-      <id>America/Belem</id>
-      <id>America/Fortaleza</id>
-      <id>America/Recife</id>
-      <id>America/Araguaina</id>
-      <id>America/Maceio</id>
-      <id>America/Bahia</id>
-      <id>America/Santarem</id>
-
-      <!-- -4:00 -->
-      <id>America/Manaus</id>
-      <id>America/Campo_Grande</id>
-      <id>America/Cuiaba</id>
-      <id>America/Porto_Velho</id>
-      <id>America/Boa_Vista</id>
-
-      <!-- -5:00 -->
-      <id>America/Eirunepe</id>
-      <id>America/Rio_Branco</id>
-    </country>
-
-    <!-- BAHAMAS, -5:00 -->
-    <country code="bs">
-      <id>America/Nassau</id>
-    </country>
-
-    <!-- BHUTAN, 6:00 -->
-    <country code="bt">
-      <id>Asia/Thimphu</id>
-    </country>
-
-    <!-- BOTSWANA, 2:00 -->
-    <country code="bw">
-      <id>Africa/Gaborone</id>
-    </country>
-
-    <!-- BELARUS, 3:00 -->
-    <country code="by">
-      <id>Europe/Minsk</id>
-    </country>
-
-    <!-- BELIZE, -6:00 -->
-    <country code="bz">
-      <id>America/Belize</id>
-    </country>
-
-    <!-- CANADA -->
-    <country code="ca">
-      <!-- -3:30 -->
-      <id>America/St_Johns</id>
-
-      <!-- -4:00 -->
-      <id>America/Halifax</id>
-      <id>America/Glace_Bay</id>
-      <id>America/Moncton</id>
-      <id>America/Goose_Bay</id>
-      <id>America/Blanc-Sablon</id>
-
-      <!-- -5:00 -->
-      <id>America/Toronto</id>
-      <id>America/Nipigon</id>
-      <id>America/Thunder_Bay</id>
-      <id>America/Iqaluit</id>
-      <id>America/Pangnirtung</id>
-      <id>America/Atikokan</id>
-
-      <!-- -6:00 -->
-      <id>America/Winnipeg</id>
-      <id>America/Regina</id>
-      <id>America/Rankin_Inlet</id>
-      <id>America/Rainy_River</id>
-      <id>America/Swift_Current</id>
-      <id>America/Resolute</id>
-
-      <!-- -7:00 -->
-      <id>America/Edmonton</id>
-      <id>America/Cambridge_Bay</id>
-      <id>America/Yellowknife</id>
-      <id>America/Inuvik</id>
-      <id>America/Dawson_Creek</id>
-      <id>America/Creston</id>
-      <id>America/Fort_Nelson</id>
-
-      <!-- -8:00 -->
-      <id>America/Vancouver</id>
-      <id>America/Whitehorse</id>
-      <id>America/Dawson</id>
-    </country>
-
-    <!-- COCOS (KEELING) ISLANDS, 6:30 -->
-    <country code="cc">
-      <id>Indian/Cocos</id>
-    </country>
-
-    <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE -->
-    <country code="cd">
-      <!-- 2:00 -->
-      <id>Africa/Lubumbashi</id>
-
-      <!-- 1:00 -->
-      <id>Africa/Kinshasa</id>
-    </country>
-
-    <!-- CENTRAL AFRICAN REPUBLIC, 1:00 -->
-    <country code="cf">
-      <id>Africa/Bangui</id>
-    </country>
-
-    <!-- CONGO, 1:00 -->
-    <country code="cg">
-      <id>Africa/Brazzaville</id>
-    </country>
-
-    <!-- SWITZERLAND, 1:00 -->
-    <country code="ch">
-      <id>Europe/Zurich</id>
-    </country>
-
-    <!-- COTE D'IVOIRE, 0:00 -->
-    <country code="ci">
-      <id>Africa/Abidjan</id>
-    </country>
-
-    <!-- COOK ISLANDS, -10:00 -->
-    <country code="ck">
-      <id>Pacific/Rarotonga</id>
-    </country>
-
-    <!-- CHILE -->
-    <country code="cl">
-      <!-- -3:00 -->
-      <id>America/Punta_Arenas</id>
-
-      <!-- -4:00 -->
-      <id>America/Santiago</id>
-
-      <!-- -6:00 -->
-      <id>Pacific/Easter</id>
-    </country>
-
-    <!-- CAMEROON, 1:00 -->
-    <country code="cm">
-      <id>Africa/Douala</id>
-    </country>
-
-    <!-- CHINA -->
-    <country code="cn">
-      <!-- 8:00 -->
-      <id>Asia/Shanghai</id>
-
-      <!-- 6:00 -->
-      <id>Asia/Urumqi</id>
-    </country>
-
-    <!-- COLOMBIA, -5:00 -->
-    <country code="co">
-      <id>America/Bogota</id>
-    </country>
-
-    <!-- COSTA RICA, -6:00 -->
-    <country code="cr">
-      <id>America/Costa_Rica</id>
-    </country>
-
-    <!-- CUBA, -5:00 -->
-    <country code="cu">
-      <id>America/Havana</id>
-    </country>
-
-    <!-- CAPE VERDE, -1:00 -->
-    <country code="cv">
-      <id>Atlantic/Cape_Verde</id>
-    </country>
-
-    <!-- Curaçao, -4:00 -->
-    <country code="cw">
-      <id>America/Curacao</id>
-    </country>
-
-    <!-- CHRISTMAS ISLAND, 7:00 -->
-    <country code="cx">
-      <id>Indian/Christmas</id>
-    </country>
-
-    <!-- CYPRUS -->
-    <country code="cy">
-      <!-- 2:00 -->
-      <id>Asia/Nicosia</id>
-
-      <!-- 3:00 -->
-      <id>Asia/Famagusta</id>
-    </country>
-
-    <!-- CZECH REPUBLIC, 1:00 -->
-    <country code="cz">
-      <id>Europe/Prague</id>
-    </country>
-
-    <!-- GERMANY, 1:00 -->
-    <country code="de">
-      <id>Europe/Berlin</id>
-      <id>Europe/Busingen</id>
-    </country>
-
-    <!-- DJIBOUTI, 3:00 -->
-    <country code="dj">
-      <id>Africa/Djibouti</id>
-    </country>
-
-    <!-- DENMARK, 1:00 -->
-    <country code="dk">
-      <id>Europe/Copenhagen</id>
-    </country>
-
-    <!-- DOMINICA, -4:00 -->
-    <country code="dm">
-      <id>America/Dominica</id>
-    </country>
-
-    <!-- DOMINICAN REPUBLIC, -4:00 -->
-    <country code="do">
-      <id>America/Santo_Domingo</id>
-    </country>
-
-    <!-- ALGERIA, 1:00 -->
-    <country code="dz">
-      <id>Africa/Algiers</id>
-    </country>
-
-    <!-- ECUADOR -->
-    <country code="ec">
-      <!-- -5:00 -->
-      <id>America/Guayaquil</id>
-
-      <!-- -6:00 -->
-      <id>Pacific/Galapagos</id>
-    </country>
-
-    <!-- ESTONIA, 2:00 -->
-    <country code="ee">
-      <id>Europe/Tallinn</id>
-    </country>
-
-    <!-- EGYPT, 2:00 -->
-    <country code="eg">
-      <id>Africa/Cairo</id>
-    </country>
-
-    <!-- WESTERN SAHARA, 0:00 -->
-    <country code="eh">
-      <id>Africa/El_Aaiun</id>
-    </country>
-
-    <!-- ERITREA, 3:00 -->
-    <country code="er">
-      <id>Africa/Asmara</id>
-    </country>
-
-    <!-- SPAIN -->
-    <country code="es">
-      <!-- 1:00 -->
-      <id>Europe/Madrid</id>
-      <id>Africa/Ceuta</id>
-
-      <!-- 0:00 -->
-      <id>Atlantic/Canary</id>
-    </country>
-
-    <!-- ETHIOPIA, 3:00 -->
-    <country code="et">
-      <id>Africa/Addis_Ababa</id>
-    </country>
-
-    <!-- FINLAND, 2:00 -->
-    <country code="fi">
-      <id>Europe/Helsinki</id>
-    </country>
-
-    <!-- FIJI, 12:00 -->
-    <country code="fj">
-      <id>Pacific/Fiji</id>
-    </country>
-
-    <!-- FALKLAND ISLANDS (MALVINAS), -3:00 -->
-    <country code="fk">
-      <id>Atlantic/Stanley</id>
-    </country>
-
-    <!-- MICRONESIA, FEDERATED STATES OF -->
-    <country code="fm">
-      <!-- 11:00 -->
-      <id>Pacific/Pohnpei</id>
-      <id>Pacific/Kosrae</id>
-
-      <!-- 10:00 -->
-      <id>Pacific/Chuuk</id>
-    </country>
-
-    <!-- FAROE ISLANDS, 0:00 -->
-    <country code="fo">
-      <id>Atlantic/Faroe</id>
-    </country>
-
-    <!-- FRANCE, 1:00 -->
-    <country code="fr">
-      <id>Europe/Paris</id>
-    </country>
-
-    <!-- GABON, 1:00 -->
-    <country code="ga">
-      <id>Africa/Libreville</id>
-    </country>
-
-    <!-- UNITED KINGDOM, 0:00 -->
-    <country code="gb">
-      <id>Europe/London</id>
-    </country>
-
-    <!-- GRENADA, -4:00 -->
-    <country code="gd">
-      <id>America/Grenada</id>
-    </country>
-
-    <!-- GEORGIA, 4:00 -->
-    <country code="ge">
-      <id>Asia/Tbilisi</id>
-    </country>
-
-    <!-- FRENCH GUIANA, -3:00 -->
-    <country code="gf">
-      <id>America/Cayenne</id>
-    </country>
-
-    <!-- GUERNSEY, 0:00 -->
-    <country code="gg">
-      <id>Europe/Guernsey</id>
-    </country>
-
-    <!-- GHANA, 0:00 -->
-    <country code="gh">
-      <id>Africa/Accra</id>
-    </country>
-
-    <!-- GIBRALTAR, 1:00 -->
-    <country code="gi">
-      <id>Europe/Gibraltar</id>
-    </country>
-
-    <!-- GREENLAND -->
-    <country code="gl">
-      <!-- 0:00 -->
-      <id>America/Danmarkshavn</id>
-
-      <!-- -1:00 -->
-      <id>America/Scoresbysund</id>
-
-      <!-- -3:00 -->
-      <id>America/Godthab</id>
-
-      <!-- -4:00 -->
-      <id>America/Thule</id>
-    </country>
-
-    <!-- GAMBIA, 0:00 -->
-    <country code="gm">
-      <id>Africa/Banjul</id>
-    </country>
-
-    <!-- GUINEA, 0:00 -->
-    <country code="gn">
-      <id>Africa/Conakry</id>
-    </country>
-
-    <!-- GUADELOUPE, -4:00 -->
-    <country code="gp">
-      <id>America/Guadeloupe</id>
-    </country>
-
-    <!-- EQUATORIAL GUINEA, 1:00 -->
-    <country code="gq">
-      <id>Africa/Malabo</id>
-    </country>
-
-    <!-- GREECE, 2:00 -->
-    <country code="gr">
-      <id>Europe/Athens</id>
-    </country>
-
-    <!-- SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS, -2:00 -->
-    <country code="gs">
-      <id>Atlantic/South_Georgia</id>
-    </country>
-
-    <!-- GUATEMALA, -6:00 -->
-    <country code="gt">
-      <id>America/Guatemala</id>
-    </country>
-
-    <!-- GUAM, 10:00 -->
-    <country code="gu">
-      <id>Pacific/Guam</id>
-    </country>
-
-    <!-- GUINEA-BISSAU, 0:00 -->
-    <country code="gw">
-      <id>Africa/Bissau</id>
-    </country>
-
-    <!-- GUYANA, -4:00 -->
-    <country code="gy">
-      <id>America/Guyana</id>
-    </country>
-
-    <!-- HONG KONG, 8:00 -->
-    <country code="hk">
-      <id>Asia/Hong_Kong</id>
-    </country>
-
-    <!-- HONDURAS, -6:00 -->
-    <country code="hn">
-      <id>America/Tegucigalpa</id>
-    </country>
-
-    <!-- CROATIA, 1:00 -->
-    <country code="hr">
-      <id>Europe/Zagreb</id>
-    </country>
-
-    <!-- HAITI, -5:00 -->
-    <country code="ht">
-      <id>America/Port-au-Prince</id>
-    </country>
-
-    <!-- HUNGARY, 1:00 -->
-    <country code="hu">
-      <id>Europe/Budapest</id>
-    </country>
-
-    <!-- INDONESIA -->
-    <country code="id">
-      <!-- 9:00 -->
-      <id>Asia/Jayapura</id>
-
-      <!-- 8:00 -->
-      <id>Asia/Makassar</id>
-
-      <!-- 7:00 -->
-      <id>Asia/Jakarta</id>
-      <id>Asia/Pontianak</id>
-    </country>
-
-    <!-- IRELAND, 0:00 -->
-    <country code="ie">
-      <id>Europe/Dublin</id>
-    </country>
-
-    <!-- ISRAEL, 2:00 -->
-    <country code="il">
-      <id>Asia/Jerusalem</id>
-    </country>
-
-    <!-- ISLE OF MAN, 0:00 -->
-    <country code="im">
-      <id>Europe/Isle_of_Man</id>
-    </country>
-
-    <!-- INDIA, 5:30 -->
-    <country code="in">
-      <id>Asia/Kolkata</id>
-    </country>
-
-    <!-- BRITISH INDIAN OCEAN TERRITORY, 6:00 -->
-    <country code="io">
-      <id>Indian/Chagos</id>
-    </country>
-
-    <!-- IRAQ, 3:00 -->
-    <country code="iq">
-      <id>Asia/Baghdad</id>
-    </country>
-
-    <!-- IRAN, ISLAMIC REPUBLIC OF, 3:30 -->
-    <country code="ir">
-      <id>Asia/Tehran</id>
-    </country>
-
-    <!-- ICELAND, 0:00 -->
-    <country code="is">
-      <id>Atlantic/Reykjavik</id>
-    </country>
-
-    <!-- ITALY, 1:00 -->
-    <country code="it">
-      <id>Europe/Rome</id>
-    </country>
-
-    <!-- JERSEY, 0:00 -->
-    <country code="je">
-      <id>Europe/Jersey</id>
-    </country>
-
-    <!-- JAMAICA, -5:00 -->
-    <country code="jm">
-      <id>America/Jamaica</id>
-    </country>
-
-    <!-- JORDAN, 2:00 -->
-    <country code="jo">
-      <id>Asia/Amman</id>
-    </country>
-
-    <!-- JAPAN, 9:00 -->
-    <country code="jp">
-      <id>Asia/Tokyo</id>
-    </country>
-
-    <!-- KENYA, 3:00 -->
-    <country code="ke">
-      <id>Africa/Nairobi</id>
-    </country>
-
-    <!-- KYRGYZSTAN, 6:00 -->
-    <country code="kg">
-      <id>Asia/Bishkek</id>
-    </country>
-
-    <!-- CAMBODIA, 7:00 -->
-    <country code="kh">
-      <id>Asia/Phnom_Penh</id>
-    </country>
-
-    <!-- KIRIBATI -->
-    <country code="ki">
-      <!-- 14:00 -->
-      <id>Pacific/Kiritimati</id>
-
-      <!-- 13:00 -->
-      <id>Pacific/Enderbury</id>
-
-      <!-- 12:00 -->
-      <id>Pacific/Tarawa</id>
-    </country>
-
-    <!-- COMOROS, 3:00 -->
-    <country code="km">
-      <id>Indian/Comoro</id>
-    </country>
-
-    <!-- SAINT KITTS AND NEVIS, -4:00 -->
-    <country code="kn">
-      <id>America/St_Kitts</id>
-    </country>
-
-    <!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 8:30 -->
-    <country code="kp">
-      <id>Asia/Pyongyang</id>
-    </country>
-
-    <!-- KOREA, REPUBLIC OF, 9:00 -->
-    <country code="kr">
-      <id>Asia/Seoul</id>
-    </country>
-
-    <!-- KUWAIT, 3:00 -->
-    <country code="kw">
-      <id>Asia/Kuwait</id>
-    </country>
-
-    <!-- CAYMAN ISLANDS, -5:00 -->
-    <country code="ky">
-      <id>America/Cayman</id>
-    </country>
-
-    <!-- KAZAKHSTAN -->
-    <country code="kz">
-      <!-- 6:00 -->
-      <id>Asia/Almaty</id>
-      <id>Asia/Qyzylorda</id>
-
-      <!-- 5:00 -->
-      <id>Asia/Aqtau</id>
-      <id>Asia/Oral</id>
-      <id>Asia/Aqtobe</id>
-      <id>Asia/Atyrau</id>
-    </country>
-
-    <!-- LAO PEOPLE'S DEMOCRATIC REPUBLIC, 7:00 -->
-    <country code="la">
-      <id>Asia/Vientiane</id>
-    </country>
-
-    <!-- LEBANON, 2:00 -->
-    <country code="lb">
-      <id>Asia/Beirut</id>
-    </country>
-
-    <!-- SAINT LUCIA, -4:00 -->
-    <country code="lc">
-      <id>America/St_Lucia</id>
-    </country>
-
-    <!-- LIECHTENSTEIN, 1:00 -->
-    <country code="li">
-      <id>Europe/Vaduz</id>
-    </country>
-
-    <!-- SRI LANKA, 5:30 -->
-    <country code="lk">
-      <id>Asia/Colombo</id>
-    </country>
-
-    <!-- LIBERIA, 0:00 -->
-    <country code="lr">
-      <id>Africa/Monrovia</id>
-    </country>
-
-    <!-- LESOTHO, 2:00 -->
-    <country code="ls">
-      <id>Africa/Maseru</id>
-    </country>
-
-    <!-- LITHUANIA, 2:00 -->
-    <country code="lt">
-      <id>Europe/Vilnius</id>
-    </country>
-
-    <!-- LUXEMBOURG, 1:00 -->
-    <country code="lu">
-      <id>Europe/Luxembourg</id>
-    </country>
-
-    <!-- LATVIA, 2:00 -->
-    <country code="lv">
-      <id>Europe/Riga</id>
-    </country>
-
-    <!-- LIBYAN ARAB JAMAHIRIYA, 2:00 -->
-    <country code="ly">
-      <id>Africa/Tripoli</id>
-    </country>
-
-    <!-- MOROCCO, 0:00 -->
-    <country code="ma">
-      <id>Africa/Casablanca</id>
-    </country>
-
-    <!-- MONACO, 1:00 -->
-    <country code="mc">
-      <id>Europe/Monaco</id>
-    </country>
-
-    <!-- MOLDOVA, 2:00 -->
-    <country code="md">
-      <id>Europe/Chisinau</id>
-    </country>
-
-    <!-- MONTENEGRO, 1:00 -->
-    <country code="me">
-      <id>Europe/Podgorica</id>
-    </country>
-
-    <!-- Collectivity of Saint Martin, -4:00 -->
-    <country code="mf">
-      <id>America/Marigot</id>
-    </country>
-
-    <!-- MADAGASCAR, 3:00 -->
-    <country code="mg">
-      <id>Indian/Antananarivo</id>
-    </country>
-
-    <!-- MARSHALL ISLANDS, 12:00 -->
-    <country code="mh">
-      <id>Pacific/Majuro</id>
-      <id>Pacific/Kwajalein</id>
-    </country>
-
-    <!-- MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF, 1:00 -->
-    <country code="mk">
-      <id>Europe/Skopje</id>
-    </country>
-
-    <!-- MALI, 0:00 -->
-    <country code="ml">
-      <id>Africa/Bamako</id>
-    </country>
-
-    <!-- MYANMAR, 6:30 -->
-    <country code="mm">
-      <id>Asia/Yangon</id>
-    </country>
-
-    <!-- MONGOLIA -->
-    <country code="mn">
-      <!-- 8:00 -->
-      <id>Asia/Choibalsan</id>
-      <id>Asia/Ulaanbaatar</id>
-
-      <!-- 7:00 -->
-      <id>Asia/Hovd</id>
-    </country>
-
-    <!-- MACAO, 8:00 -->
-    <country code="mo">
-      <id>Asia/Macau</id>
-    </country>
-
-    <!-- NORTHERN MARIANA ISLANDS, 10:00 -->
-    <country code="mp">
-      <id>Pacific/Saipan</id>
-    </country>
-
-    <!-- MARTINIQUE, -4:00 -->
-    <country code="mq">
-      <id>America/Martinique</id>
-    </country>
-
-    <!-- MAURITANIA, 0:00 -->
-    <country code="mr">
-      <id>Africa/Nouakchott</id>
-    </country>
-
-    <!-- MONTSERRAT, -4:00 -->
-    <country code="ms">
-      <id>America/Montserrat</id>
-    </country>
-
-    <!-- MALTA, 1:00 -->
-    <country code="mt">
-      <id>Europe/Malta</id>
-    </country>
-
-    <!-- MAURITIUS, 4:00 -->
-    <country code="mu">
-      <id>Indian/Mauritius</id>
-    </country>
-
-    <!-- MALDIVES, 5:00 -->
-    <country code="mv">
-      <id>Indian/Maldives</id>
-    </country>
-
-    <!-- MALAWI, 2:00 -->
-    <country code="mw">
-      <id>Africa/Blantyre</id>
-    </country>
-
-    <!-- MEXICO -->
-    <country code="mx">
-      <!-- -6:00 -->
-      <id>America/Mexico_City</id>
-      <id>America/Merida</id>
-      <id>America/Monterrey</id>
-      <id>America/Matamoros</id>
-      <id>America/Bahia_Banderas</id>
-
-      <!-- -5:00 -->
-      <id>America/Cancun</id>
-
-      <!-- -7:00 -->
-      <id>America/Chihuahua</id>
-      <id>America/Hermosillo</id>
-      <id>America/Mazatlan</id>
-      <id>America/Ojinaga</id>
-
-      <!-- -8:00 -->
-      <id>America/Tijuana</id>
-    </country>
-
-    <!-- MALAYSIA, 8:00 -->
-    <country code="my">
-      <id>Asia/Kuala_Lumpur</id>
-      <id>Asia/Kuching</id>
-    </country>
-
-    <!-- MOZAMBIQUE, 2:00 -->
-    <country code="mz">
-      <id>Africa/Maputo</id>
-    </country>
-
-    <!-- NAMIBIA, 1:00 -->
-    <country code="na">
-      <id>Africa/Windhoek</id>
-    </country>
-
-    <!-- NEW CALEDONIA, 11:00 -->
-    <country code="nc">
-      <id>Pacific/Noumea</id>
-    </country>
-
-    <!-- NIGER, 1:00 -->
-    <country code="ne">
-      <id>Africa/Niamey</id>
-    </country>
-
-    <!-- NORFOLK ISLAND, 11:30 -->
-    <country code="nf">
-      <id>Pacific/Norfolk</id>
-    </country>
-
-    <!-- NIGERIA, 1:00 -->
-    <country code="ng">
-      <id>Africa/Lagos</id>
-    </country>
-
-    <!-- NICARAGUA, -6:00 -->
-    <country code="ni">
-      <id>America/Managua</id>
-    </country>
-
-    <!-- NETHERLANDS, 1:00 -->
-    <country code="nl">
-      <id>Europe/Amsterdam</id>
-    </country>
-
-    <!-- NORWAY, 1:00 -->
-    <country code="no">
-      <id>Europe/Oslo</id>
-    </country>
-
-    <!-- NEPAL, 5:45 -->
-    <country code="np">
-      <id>Asia/Kathmandu</id>
-    </country>
-
-    <!-- NAURU, 12:00 -->
-    <country code="nr">
-      <id>Pacific/Nauru</id>
-    </country>
-
-    <!-- NIUE, -11:00 -->
-    <country code="nu">
-      <id>Pacific/Niue</id>
-    </country>
-
-    <!-- NEW ZEALAND, 12:00 -->
-    <country code="nz">
-      <!-- 12:00 -->
-      <id>Pacific/Auckland</id>
-
-      <!-- 12:45 -->
-      <id>Pacific/Chatham</id>
-    </country>
-
-    <!-- OMAN, 4:00 -->
-    <country code="om">
-      <id>Asia/Muscat</id>
-    </country>
-
-    <!-- PANAMA, -5:00 -->
-    <country code="pa">
-      <id>America/Panama</id>
-    </country>
-
-    <!-- PERU, -5:00 -->
-    <country code="pe">
-      <id>America/Lima</id>
-    </country>
-
-    <!-- FRENCH POLYNESIA -->
-    <country code="pf">
-      <!-- -9:00 -->
-      <id>Pacific/Gambier</id>
-
-      <!-- -9:30 -->
-      <id>Pacific/Marquesas</id>
-
-      <!-- -10:00 -->
-      <id>Pacific/Tahiti</id>
-    </country>
-
-    <!-- PAPUA NEW GUINEA -->
-    <country code="pg">
-      <!-- 10:00 -->
-      <id>Pacific/Port_Moresby</id>
-
-      <!-- 11:00 -->
-      <id>Pacific/Bougainville</id>
-    </country>
-
-    <!-- PHILIPPINES, 8:00 -->
-    <country code="ph">
-      <id>Asia/Manila</id>
-    </country>
-
-    <!-- PAKISTAN, 5:00 -->
-    <country code="pk">
-      <id>Asia/Karachi</id>
-    </country>
-
-    <!-- POLAND, 1:00 -->
-    <country code="pl">
-      <id>Europe/Warsaw</id>
-    </country>
-
-    <!-- SAINT PIERRE AND MIQUELON, -3:00 -->
-    <country code="pm">
-      <id>America/Miquelon</id>
-    </country>
-
-    <!-- PITCAIRN, -8:00 -->
-    <country code="pn">
-      <id>Pacific/Pitcairn</id>
-    </country>
-
-    <!-- PUERTO RICO, -4:00 -->
-    <country code="pr">
-      <id>America/Puerto_Rico</id>
-    </country>
-
-    <!-- PALESTINE, 2:00 -->
-    <country code="ps">
-      <id>Asia/Gaza</id>
-      <id>Asia/Hebron</id>
-    </country>
-
-    <!-- PORTUGAL -->
-    <country code="pt">
-      <!-- 0:00 -->
-      <id>Europe/Lisbon</id>
-      <id>Atlantic/Madeira</id>
-
-      <!-- -1:00 -->
-      <id>Atlantic/Azores</id>
-    </country>
-
-    <!-- PALAU, 9:00 -->
-    <country code="pw">
-      <id>Pacific/Palau</id>
-    </country>
-
-    <!-- PARAGUAY, -4:00 -->
-    <country code="py">
-      <id>America/Asuncion</id>
-    </country>
-
-    <!-- QATAR, 3:00 -->
-    <country code="qa">
-      <id>Asia/Qatar</id>
-    </country>
-
-    <!-- REUNION, 4:00 -->
-    <country code="re">
-      <id>Indian/Reunion</id>
-    </country>
-
-    <!-- ROMANIA, 2:00 -->
-    <country code="ro">
-      <id>Europe/Bucharest</id>
-    </country>
-
-    <!-- SERBIA, 1:00 -->
-    <country code="rs">
-      <id>Europe/Belgrade</id>
-    </country>
-
-    <!-- RUSSIAN FEDERATION -->
-    <country code="ru">
-      <!-- 12:00 -->
-      <id>Asia/Kamchatka</id>
-      <id>Asia/Anadyr</id>
-
-      <!-- 11:00 -->
-      <id>Asia/Magadan</id>
-      <id>Asia/Sakhalin</id>
-      <id>Asia/Srednekolymsk</id>
-
-      <!-- 10:00 -->
-      <id>Asia/Vladivostok</id>
-      <id>Asia/Ust-Nera</id>
-
-      <!-- 9:00 -->
-      <id>Asia/Yakutsk</id>
-      <id>Asia/Chita</id>
-      <id>Asia/Khandyga</id>
-
-      <!-- 8:00 -->
-      <id>Asia/Irkutsk</id>
-
-      <!-- 7:00 -->
-      <id>Asia/Krasnoyarsk</id>
-      <id>Asia/Novosibirsk</id>
-      <id>Asia/Barnaul</id>
-      <id>Asia/Novokuznetsk</id>
-      <id>Asia/Tomsk</id>
-
-      <!-- 6:00 -->
-      <id>Asia/Omsk</id>
-
-      <!-- 5:00 -->
-      <id>Asia/Yekaterinburg</id>
-
-      <!-- 4:00 -->
-      <id>Europe/Samara</id>
-      <id>Europe/Astrakhan</id>
-      <id>Europe/Ulyanovsk</id>
-      <id>Europe/Saratov</id>
-
-      <!-- 3:00 -->
-      <id>Europe/Moscow</id>
-      <id>Europe/Volgograd</id>
-      <id>Europe/Kirov</id>
-      <id>Europe/Simferopol</id>
-
-      <!-- 2:00 -->
-      <id>Europe/Kaliningrad</id>
-    </country>
-
-    <!-- RWANDA, 2:00 -->
-    <country code="rw">
-      <id>Africa/Kigali</id>
-    </country>
-
-    <!-- SAUDI ARABIA, 3:00 -->
-    <country code="sa">
-      <id>Asia/Riyadh</id>
-    </country>
-
-    <!-- SOLOMON ISLANDS, 11:00 -->
-    <country code="sb">
-      <id>Pacific/Guadalcanal</id>
-    </country>
-
-    <!-- SEYCHELLES, 4:00 -->
-    <country code="sc">
-      <id>Indian/Mahe</id>
-    </country>
-
-    <!-- SUDAN, 3:00 -->
-    <country code="sd">
-      <id>Africa/Khartoum</id>
-    </country>
-
-    <!-- SWEDEN, 1:00 -->
-    <country code="se">
-      <id>Europe/Stockholm</id>
-    </country>
-
-    <!-- SINGAPORE, 8:00 -->
-    <country code="sg">
-      <id>Asia/Singapore</id>
-    </country>
-
-    <!-- SAINT HELENA, 0:00 -->
-    <country code="sh">
-      <id>Atlantic/St_Helena</id>
-    </country>
-
-    <!-- SLOVENIA, 1:00 -->
-    <country code="si">
-      <id>Europe/Ljubljana</id>
-    </country>
-
-    <!-- SVALBARD AND JAN MAYEN, 1:00 -->
-    <country code="sj">
-      <id>Arctic/Longyearbyen</id>
-    </country>
-
-    <!-- SLOVAKIA, 1:00 -->
-    <country code="sk">
-      <id>Europe/Bratislava</id>
-    </country>
-
-    <!-- SIERRA LEONE, 0:00 -->
-    <country code="sl">
-      <id>Africa/Freetown</id>
-    </country>
-
-    <!-- SAN MARINO, 1:00 -->
-    <country code="sm">
-      <id>Europe/San_Marino</id>
-    </country>
-
-    <!-- SENEGAL, 0:00 -->
-    <country code="sn">
-      <id>Africa/Dakar</id>
-    </country>
-
-    <!-- SOMALIA, 3:00 -->
-    <country code="so">
-      <id>Africa/Mogadishu</id>
-    </country>
-
-    <!-- SURINAME, -3:00 -->
-    <country code="sr">
-      <id>America/Paramaribo</id>
-    </country>
-
-    <!-- South Sudan, 3:00 -->
-    <country code="ss">
-      <id>Africa/Juba</id>
-    </country>
-
-    <!-- SAO TOME AND PRINCIPE, 0:00 -->
-    <country code="st">
-      <id>Africa/Sao_Tome</id>
-    </country>
-
-    <!-- EL SALVADOR, -6:00 -->
-    <country code="sv">
-      <id>America/El_Salvador</id>
-    </country>
-
-    <!-- Sint Maarten, -4:00 -->
-    <country code="sx">
-      <id>America/Lower_Princes</id>
-    </country>
-
-    <!-- SYRIAN ARAB REPUBLIC, 2:00 -->
-    <country code="sy">
-      <id>Asia/Damascus</id>
-    </country>
-
-    <!-- SWAZILAND, 2:00 -->
-    <country code="sz">
-      <id>Africa/Mbabane</id>
-    </country>
-
-    <!-- TURKS AND CAICOS ISLANDS, -4:00 -->
-    <country code="tc">
-      <id>America/Grand_Turk</id>
-    </country>
-
-    <!-- CHAD, 1:00 -->
-    <country code="td">
-      <id>Africa/Ndjamena</id>
-    </country>
-
-    <!-- FRENCH SOUTHERN TERRITORIES -->
-    <country code="tf">
-      <!-- 5:00 -->
-      <id>Indian/Kerguelen</id>
-    </country>
-
-    <!-- TOGO, 0:00 -->
-    <country code="tg">
-      <id>Africa/Lome</id>
-    </country>
-
-    <!-- THAILAND, 7:00 -->
-    <country code="th">
-      <id>Asia/Bangkok</id>
-    </country>
-
-    <!-- TAJIKISTAN, 5:00 -->
-    <country code="tj">
-      <id>Asia/Dushanbe</id>
-    </country>
-
-    <!-- TOKELAU, +13:00 -->
-    <country code="tk">
-      <id>Pacific/Fakaofo</id>
-    </country>
-
-    <!-- TIMOR-LESTE, 9:00 -->
-    <country code="tl">
-      <id>Asia/Dili</id>
-    </country>
-
-    <!-- TURKMENISTAN, 5:00 -->
-    <country code="tm">
-      <id>Asia/Ashgabat</id>
-    </country>
-
-    <!-- TUNISIA, 1:00 -->
-    <country code="tn">
-      <id>Africa/Tunis</id>
-    </country>
-
-    <!-- TONGA, 13:00 -->
-    <country code="to">
-      <id>Pacific/Tongatapu</id>
-    </country>
-
-    <!-- TURKEY, 3:00 -->
-    <country code="tr">
-      <id>Europe/Istanbul</id>
-    </country>
-
-    <!-- TRINIDAD AND TOBAGO, -4:00 -->
-    <country code="tt">
-      <id>America/Port_of_Spain</id>
-    </country>
-
-    <!-- TUVALU, 12:00 -->
-    <country code="tv">
-      <id>Pacific/Funafuti</id>
-    </country>
-
-    <!-- TAIWAN, PROVINCE OF CHINA, 8:00 -->
-    <country code="tw">
-      <id>Asia/Taipei</id>
-    </country>
-
-    <!-- TANZANIA, UNITED REPUBLIC OF, 3:00 -->
-    <country code="tz">
-      <id>Africa/Dar_es_Salaam</id>
-    </country>
-
-    <!-- UKRAINE, 2:00 -->
-    <country code="ua">
-      <id>Europe/Kiev</id>
-      <id>Europe/Uzhgorod</id>
-      <id>Europe/Zaporozhye</id>
-    </country>
-
-    <!-- UGANDA, 3:00 -->
-    <country code="ug">
-      <id>Africa/Kampala</id>
-    </country>
-
-    <!-- UNITED STATES MINOR OUTLYING ISLANDS -->
-    <country code="um">
-      <!-- 12:00 -->
-      <id>Pacific/Wake</id>
-
-      <!-- -11:00 -->
-      <id>Pacific/Midway</id>
-    </country>
-
-    <!-- UNITED STATES -->
-    <country code="us">
-      <!-- -5:00 -->
-      <id>America/New_York</id>
-      <id>America/Detroit</id>
-      <id>America/Kentucky/Louisville</id>
-      <id>America/Kentucky/Monticello</id>
-      <id>America/Indiana/Indianapolis</id>
-      <id>America/Indiana/Vincennes</id>
-      <id>America/Indiana/Winamac</id>
-      <id>America/Indiana/Marengo</id>
-      <id>America/Indiana/Petersburg</id>
-      <id>America/Indiana/Vevay</id>
-
-      <!-- -6:00 -->
-      <id>America/Chicago</id>
-      <id>America/Indiana/Knox</id>
-      <id>America/Menominee</id>
-      <id>America/North_Dakota/Center</id>
-      <id>America/North_Dakota/New_Salem</id>
-      <id>America/Indiana/Tell_City</id>
-      <id>America/North_Dakota/Beulah</id>
-
-      <!-- -7:00 -->
-      <id>America/Denver</id>
-      <id>America/Boise</id>
-      <id>America/Phoenix</id>
-
-      <!-- -8:00 -->
-      <id>America/Los_Angeles</id>
-
-      <!-- -9:00 -->
-      <id>America/Anchorage</id>
-      <id>America/Juneau</id>
-      <id>America/Yakutat</id>
-      <id>America/Nome</id>
-      <id>America/Metlakatla</id>
-      <id>America/Sitka</id>
-
-      <!-- -10:00 -->
-      <id>Pacific/Honolulu</id>
-      <id>America/Adak</id>
-    </country>
-
-    <!-- URUGUAY, -3:00 -->
-    <country code="uy">
-      <id>America/Montevideo</id>
-    </country>
-
-    <!-- UZBEKISTAN, 5:00 -->
-    <country code="uz">
-      <id>Asia/Tashkent</id>
-      <id>Asia/Samarkand</id>
-    </country>
-
-    <!-- HOLY SEE (VATICAN CITY STATE), 1:00 -->
-    <country code="va">
-      <id>Europe/Vatican</id>
-    </country>
-
-    <!-- SAINT VINCENT AND THE GRENADINES, -4:00 -->
-    <country code="vc">
-      <id>America/St_Vincent</id>
-    </country>
-
-    <!-- VENEZUELA, -4:00 -->
-    <country code="ve">
-      <id>America/Caracas</id>
-    </country>
-
-    <!-- VIRGIN ISLANDS, BRITISH, -4:00 -->
-    <country code="vg">
-      <id>America/Tortola</id>
-    </country>
-
-    <!-- VIRGIN ISLANDS, U.S., -4:00 -->
-    <country code="vi">
-      <id>America/St_Thomas</id>
-    </country>
-
-    <!-- VIET NAM, 7:00 -->
-    <country code="vn">
-      <id>Asia/Ho_Chi_Minh</id>
-    </country>
-
-    <!-- VANUATU, 11:00 -->
-    <country code="vu">
-      <id>Pacific/Efate</id>
-    </country>
-
-    <!-- WALLIS AND FUTUNA, 12:00 -->
-    <country code="wf">
-      <id>Pacific/Wallis</id>
-    </country>
-
-    <!-- SAMOA, 13:00 -->
-    <country code="ws">
-      <id>Pacific/Apia</id>
-    </country>
-
-    <!-- YEMEN, 3:00 -->
-    <country code="ye">
-      <id>Asia/Aden</id>
-    </country>
-
-    <!-- MAYOTTE, 3:00 -->
-    <country code="yt">
-      <id>Indian/Mayotte</id>
-    </country>
-
-    <!-- SOUTH AFRICA, 2:00 -->
-    <country code="za">
-      <id>Africa/Johannesburg</id>
-    </country>
-
-    <!-- ZAMBIA, 2:00 -->
-    <country code="zm">
-      <id>Africa/Lusaka</id>
-    </country>
-
-    <!-- ZIMBABWE, 2:00 -->
-    <country code="zw">
-      <id>Africa/Harare</id>
-    </country>
-  </countryzones>
-</timezones>
diff --git a/linker/tests/linker_config_test.cpp b/linker/tests/linker_config_test.cpp
index 5e51113..c6fade9 100644
--- a/linker/tests/linker_config_test.cpp
+++ b/linker/tests/linker_config_test.cpp
@@ -33,6 +33,7 @@
 #include <gtest/gtest.h>
 
 #include "../linker_config.h"
+#include "../linker_utils.h"
 
 #include <unistd.h>
 
@@ -41,6 +42,11 @@
 #include <android-base/file.h>
 #include <android-base/test_utils.h>
 
+#if defined(__LP64__)
+#define ARCH_SUFFIX "64"
+#else
+#define ARCH_SUFFIX ""
+#endif
 
 static const char* config_str =
   "# comment \n"
@@ -70,40 +76,28 @@
   return android::base::WriteStringToFile(content, path);
 }
 
+static std::vector<std::string> resolve_paths(std::vector<std::string> paths) {
+  std::vector<std::string> resolved_paths;
+  resolve_paths(paths, &resolved_paths);
+  return resolved_paths;
+}
+
 static void run_linker_config_smoke_test(bool is_asan) {
-#if defined(__LP64__)
-  const std::vector<std::string> kExpectedDefaultSearchPath = is_asan ?
-        std::vector<std::string>({ "/data", "/vendor/lib64"}) :
-        std::vector<std::string>({ "/vendor/lib64" });
+  const std::vector<std::string> kExpectedDefaultSearchPath =
+      resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/vendor/lib" ARCH_SUFFIX }) :
+                              std::vector<std::string>({ "/vendor/lib" ARCH_SUFFIX }));
 
-  const std::vector<std::string> kExpectedDefaultPermittedPath = is_asan ?
-        std::vector<std::string>({ "/data", "/vendor" }) :
-        std::vector<std::string>({ "/vendor/lib64" });
+  const std::vector<std::string> kExpectedDefaultPermittedPath =
+      resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/vendor" }) :
+                              std::vector<std::string>({ "/vendor/lib" ARCH_SUFFIX }));
 
-  const std::vector<std::string> kExpectedSystemSearchPath = is_asan ?
-        std::vector<std::string>({ "/data", "/system/lib64" }) :
-        std::vector<std::string>({ "/system/lib64" });
+  const std::vector<std::string> kExpectedSystemSearchPath =
+      resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/system/lib" ARCH_SUFFIX }) :
+                              std::vector<std::string>({ "/system/lib" ARCH_SUFFIX }));
 
-  const std::vector<std::string> kExpectedSystemPermittedPath = is_asan ?
-        std::vector<std::string>({ "/data", "/system" }) :
-        std::vector<std::string>({ "/system/lib64" });
-#else
-  const std::vector<std::string> kExpectedDefaultSearchPath = is_asan ?
-        std::vector<std::string>({ "/data", "/vendor/lib"}) :
-        std::vector<std::string>({ "/vendor/lib" });
-
-  const std::vector<std::string> kExpectedDefaultPermittedPath = is_asan ?
-        std::vector<std::string>({ "/data", "/vendor" }) :
-        std::vector<std::string>({ "/vendor/lib" });
-
-  const std::vector<std::string> kExpectedSystemSearchPath = is_asan ?
-        std::vector<std::string>({ "/data", "/system/lib" }) :
-        std::vector<std::string>({ "/system/lib" });
-
-  const std::vector<std::string> kExpectedSystemPermittedPath = is_asan ?
-        std::vector<std::string>({ "/data", "/system" }) :
-        std::vector<std::string>({ "/system/lib" });
-#endif
+  const std::vector<std::string> kExpectedSystemPermittedPath =
+      resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/system" }) :
+                              std::vector<std::string>({ "/system/lib" ARCH_SUFFIX }));
 
   TemporaryFile tmp_file;
   close(tmp_file.fd);
diff --git a/tests/Android.bp b/tests/Android.bp
index a03f1a6..2a5b47e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -61,6 +61,7 @@
         "dirent_test.cpp",
         "elf_test.cpp",
         "endian_test.cpp",
+        "errno_test.cpp",
         "error_test.cpp",
         "eventfd_test.cpp",
         "fcntl_test.cpp",
@@ -88,6 +89,7 @@
         "nl_types_test.cpp",
         "pthread_test.cpp",
         "pty_test.cpp",
+        "qsort_test.cpp",
         "regex_test.cpp",
         "resolv_test.cpp",
         "sched_test.cpp",
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index e3ee7d7..b264e53 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -30,6 +30,7 @@
 
 #include <linux/memfd.h>
 #include <sys/mman.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/vfs.h>
 #include <sys/wait.h>
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 4901d50..5d3985f 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1271,6 +1271,22 @@
   dlclose(handle);
 }
 
+TEST(dlfcn, RTLD_macros) {
+#if !defined(RTLD_LOCAL)
+#error no RTLD_LOCAL
+#elif !defined(RTLD_LAZY)
+#error no RTLD_LAZY
+#elif !defined(RTLD_NOW)
+#error no RTLD_NOW
+#elif !defined(RTLD_NOLOAD)
+#error no RTLD_NOLOAD
+#elif !defined(RTLD_GLOBAL)
+#error no RTLD_GLOBAL
+#elif !defined(RTLD_NODELETE)
+#error no RTLD_NODELETE
+#endif
+}
+
 // Bionic specific tests
 #if defined(__BIONIC__)
 
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/tests/errno_test.cpp
similarity index 62%
rename from libc/arch-arm/include/machine/cpu-features.h
rename to tests/errno_test.cpp
index fc8c80d..ae4ce08 100644
--- a/libc/arch-arm/include/machine/cpu-features.h
+++ b/tests/errno_test.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,24 +25,10 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef _ARM_MACHINE_CPU_FEATURES_H
-#define _ARM_MACHINE_CPU_FEATURES_H
 
-/* __ARM_ARCH__ is a number corresponding to the ARM revision
- * we're going to support. Our toolchain doesn't define __ARM_ARCH__
- * so try to guess it.
- */
-#ifndef __ARM_ARCH__
-#  if defined __ARM_ARCH_7__   || defined __ARM_ARCH_7A__ || \
-        defined __ARM_ARCH_7R__  || defined __ARM_ARCH_7M__
-#    define __ARM_ARCH__ 7
-#  elif defined __ARM_ARCH_6__   || defined __ARM_ARCH_6J__ || \
-        defined __ARM_ARCH_6K__  || defined __ARM_ARCH_6Z__ || \
-        defined __ARM_ARCH_6KZ__ || defined __ARM_ARCH_6T2__
-#    define __ARM_ARCH__ 6
-#  else
-#    error Unknown or unsupported ARM architecture
-#  endif
-#endif
+#include <gtest/gtest.h>
 
-#endif /* _ARM_MACHINE_CPU_FEATURES_H */
+#include <errno.h>
+
+// Some GNU source likes to declare errno itself for some reason.
+extern "C" int errno;
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index a7b9d52..ddd78b0 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -100,16 +100,6 @@
   }
 }
 
-TEST(malloc, posix_memalign_non_power2) {
-  void* ptr;
-  ASSERT_EQ(EINVAL, posix_memalign(&ptr, 17, 1024));
-}
-
-TEST(malloc, posix_memalign_overflow) {
-  void* ptr;
-  ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
-}
-
 TEST(malloc, memalign_realloc) {
   // Memalign and then realloc the pointer a couple of times.
   for (size_t alignment = 1; alignment <= 4096; alignment <<= 1) {
diff --git a/tests/qsort_test.cpp b/tests/qsort_test.cpp
new file mode 100644
index 0000000..95b4789
--- /dev/null
+++ b/tests/qsort_test.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 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 <sys/types.h>
+
+#include <gtest/gtest.h>
+
+#include "gtest_globals.h"
+
+#define BUFFER_SIZE 1024
+
+static int cmp_long(const void *l, const void *r)
+{
+
+  return (*(long *)l - *(long *)r);
+}
+
+static int cmp_int(const void *l, const void *r)
+{
+
+  return (*(int *)l - *(int *)r);
+}
+
+#ifndef arc4random_uniform
+static bool seeded;
+
+u_int32_t arc4random_uniform(uint32_t upper_bound)
+{
+  if (!seeded) {
+    srandom((int)time(NULL));
+    seeded = true;
+  }
+
+  return (random() % upper_bound);
+}
+#endif
+
+TEST(qsort_test, long_test) {
+  long buf[BUFFER_SIZE];
+  long i;
+
+  /* Initialize buffer with known numbers */
+  for (i=0; i<BUFFER_SIZE; i++)
+    buf[i] = i;
+
+  /* Stir 1/4 pairs in the buffer */
+  for (i=0; i<BUFFER_SIZE/4; i++) {
+    u_int32_t pos1, pos2;
+    long t;
+
+    pos1 = arc4random_uniform(BUFFER_SIZE);
+    pos2 = arc4random_uniform(BUFFER_SIZE);
+
+    t = buf[pos1];
+    buf[pos1] = buf[pos2];
+    buf[pos2] = t;
+  }
+
+  /* Sort */
+  qsort(buf, BUFFER_SIZE, sizeof(buf[0]), &cmp_long);
+
+  for (i=0; i<BUFFER_SIZE; i++)
+    EXPECT_EQ(i, buf[i]);
+}
+
+TEST(qsort_test, int_test) {
+  int buf[BUFFER_SIZE];
+  int i;
+
+  /* Initialize buffer with known numbers */
+  for (i=0; i<BUFFER_SIZE; i++)
+    buf[i] = i;
+
+  /* Stir 1/4 pairs in the buffer */
+  for (i=0; i<BUFFER_SIZE/4; i++) {
+    u_int32_t pos1, pos2;
+    int t;
+
+    pos1 = arc4random_uniform(BUFFER_SIZE);
+    pos2 = arc4random_uniform(BUFFER_SIZE);
+
+    t = buf[pos1];
+    buf[pos1] = buf[pos2];
+    buf[pos2] = t;
+  }
+
+  /* Sort */
+  qsort(buf, BUFFER_SIZE, sizeof(buf[0]), &cmp_int);
+
+  for (i=0; i<BUFFER_SIZE; i++)
+    EXPECT_EQ(i, buf[i]);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index fc17cde..4c4c102 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -138,15 +138,48 @@
   EXPECT_EQ(795539493, mrand48());
 }
 
-TEST(stdlib, posix_memalign) {
-  void* p;
+TEST(stdlib, posix_memalign_sweep) {
+  void* ptr;
 
-  ASSERT_EQ(0, posix_memalign(&p, 512, 128));
-  ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(p) % 512);
-  free(p);
+  // These should all fail.
+  for (size_t align = 0; align < sizeof(long); align++) {
+    ASSERT_EQ(EINVAL, posix_memalign(&ptr, align, 256))
+        << "Unexpected value at align " << align;
+  }
 
-  // Can't align to a non-power of 2.
-  ASSERT_EQ(EINVAL, posix_memalign(&p, 81, 128));
+  // Verify powers of 2 up to 2048 allocate, and verify that all other
+  // alignment values between the powers of 2 fail.
+  size_t last_align = sizeof(long);
+  for (size_t align = sizeof(long); align <= 2048; align <<= 1) {
+    // Try all of the non power of 2 values from the last until this value.
+    for (size_t fail_align = last_align + 1; fail_align < align; fail_align++) {
+      ASSERT_EQ(EINVAL, posix_memalign(&ptr, fail_align, 256))
+          << "Unexpected success at align " << fail_align;
+    }
+    ASSERT_EQ(0, posix_memalign(&ptr, align, 256))
+        << "Unexpected failure at align " << align;
+    ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
+        << "Did not return a valid aligned ptr " << ptr << " expected alignment " << align;
+    free(ptr);
+    last_align = align;
+  }
+}
+
+TEST(stdlib, posix_memalign_various_sizes) {
+  std::vector<size_t> sizes{1, 4, 8, 256, 1024, 65000, 128000, 256000, 1000000};
+  for (auto size : sizes) {
+    void* ptr;
+    ASSERT_EQ(0, posix_memalign(&ptr, 16, 1))
+        << "posix_memalign failed at size " << size;
+    ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) & 0xf)
+        << "Pointer not aligned at size " << size << " ptr " << ptr;
+    free(ptr);
+  }
+}
+
+TEST(stdlib, posix_memalign_overflow) {
+  void* ptr;
+  ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
 }
 
 TEST(stdlib, realpath__NULL_filename) {