Remove a check for AIDs in the OEM range. am: c2c36b661c
am: fe1dc33b28

Change-Id: Ic2107c9550f368db0ada5cc3f680bf289734a812
diff --git a/README.md b/README.md
index 61314b6..ee83b08 100644
--- a/README.md
+++ b/README.md
@@ -327,19 +327,54 @@
 32-bit ABI bugs
 ---------------
 
-This probably belongs in the NDK documentation rather than here, but these
-are the known ABI bugs in the 32-bit ABI:
+### `off_t` is 32-bit.
 
- * `time_t` is 32-bit. <http://b/5819737>. In the 64-bit ABI, time_t is
-   64-bit.
+On 32-bit Android, `off_t` is a signed 32-bit integer. This limits functions
+that use `off_t` to working on files no larger than 2GiB.
 
- * `off_t` is 32-bit. There is `off64_t`, and in newer releases there is
-   almost-complete support for `_FILE_OFFSET_BITS`. Unfortunately our stdio
-   implementation uses 32-bit offsets and -- worse -- function pointers to
-   functions that use 32-bit offsets, so there's no good way to implement
-   the last few pieces <http://b/24807045>. In the 64-bit ABI, off_t is
-   off64_t.
+Android does not require the `_LARGEFILE_SOURCE` macro to be used to make
+`fseeko` and `ftello` available. Instead they're always available from API
+level 24 where they were introduced, and never available before then.
 
- * `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support
-   for real-time signals is broken. <http://b/5828899> In the 64-bit ABI,
-   `sigset_t` is the correct size for every architecture.
+Android also does not require the `_LARGEFILE64_SOURCE` macro to be used
+to make `off64_t` and corresponding functions such as `ftruncate64` available.
+Instead, whatever subset of those functions was available at your target API
+level will be visible.
+
+There are a couple of exceptions to note. Firstly, `off64_t` and the single
+function `lseek64` were available right from the beginning in API 3. Secondly,
+Android has always silently inserted `O_LARGEFILE` into any open call, so if
+all you need are functions like `read` that don't take/return `off_t`, large
+files have always worked.
+
+Android support for `_FILE_OFFSET_BITS=64` (which turns `off_t` into `off64_t`
+and replaces each `off_t` function with its `off64_t` counterpart, such as
+`lseek` in the source becoming `lseek64` at runtime) was added late. Even when
+it became available for the platform, it wasn't available from the NDK until
+r15. Before NDK r15, `_FILE_OFFSET_BITS=64` silently did nothing: all code
+compiled with that was actually using a 32-bit `off_t`. With a new enough NDK,
+the situation becomes complicated. If you're targeting an API before 21, almost
+all functions that take an `off_t` become unavailable. You've asked for their
+64-bit equivalents, and none of them (except `lseek`/`lseek64`) exist. As you
+increase your target API level, you'll have more and more of the functions
+available. API 12 adds some of the `<unistd.h>` functions, API 21 adds `mmap`,
+and by API 24 you have everything including `<stdio.h>`. See the
+[linker map](libc/libc.map.txt) for full details.
+
+In the 64-bit ABI, `off_t` is always 64-bit.
+
+### `sigset_t` is too small for real-time signals.
+
+On 32-bit Android, `sigset_t` is too small for ARM and x86 (but correct for
+MIPS). This means that there is no support for real-time signals in 32-bit
+code.
+
+In the 64-bit ABI, `sigset_t` is the correct size for every architecture.
+
+### `time_t` is 32-bit.
+
+On 32-bit Android, `time_t` is 32-bit. The header `<time64.h>` and type
+`time64_t` exist as a workaround, but the kernel interfaces exposed on 32-bit
+Android all use the 32-bit `time_t`.
+
+In the 64-bit ABI, `time_t` is 64-bit.
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index 3f95aa1..0edba65 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -35,6 +35,17 @@
         "time_benchmark.cpp",
         "unistd_benchmark.cpp",
     ],
+    static_libs: ["libBionicBenchmarksUtils"],
+}
+
+cc_defaults {
+    name: "bionic-benchmarks-extras-defaults",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wunused",
+    ],
 }
 
 // Build benchmarks for the device (with bionic's .so). Run with:
@@ -63,3 +74,19 @@
         },
     },
 }
+
+cc_library_static {
+    name: "libBionicBenchmarksUtils",
+    defaults: ["bionic-benchmarks-extras-defaults"],
+    srcs: ["util.cpp"],
+    host_supported: true,
+}
+
+cc_test {
+    name: "bionic-benchmarks-tests",
+    defaults: ["bionic-benchmarks-extras-defaults"],
+    srcs: [
+        "tests/benchmark_test.cpp",
+    ],
+    static_libs: ["libBionicBenchmarksUtils"],
+}
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index bf4d6cb..d3c2de8 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -56,7 +56,7 @@
 }
 
 static void BM_pthread_once(benchmark::State& state) {
-  pthread_once_t once = PTHREAD_ONCE_INIT;
+  static pthread_once_t once = PTHREAD_ONCE_INIT;
   pthread_once(&once, DummyPthreadOnceInitFunction);
 
   while (state.KeepRunning()) {
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index 41306db..2ab65a8 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -18,85 +18,246 @@
 #include <string.h>
 
 #include <benchmark/benchmark.h>
+#include "util.h"
 
 constexpr auto KB = 1024;
 
-#define AT_COMMON_SIZES \
-    Arg(8)->Arg(64)->Arg(512)->Arg(1*KB)->Arg(8*KB)->Arg(16*KB)->Arg(32*KB)->Arg(64*KB)
+// NOTE: these constants are temporary replacements for AT_COMMON_SIZES until
+// the new interface for Bionic benchmarks is implemented.
 
-// TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.)
+// Set all four to 0 to test normal alignment.
+#define AT_SRC_ALIGN 0
+#define AT_DST_ALIGN 0
+
+#define AT_ALIGNED_TWOBUF \
+    Args({(8), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
+    Args({(512), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(1*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
+    Args({(8*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(16*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
+    Args({(32*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64*KB), AT_SRC_ALIGN, AT_DST_ALIGN})
+
+#define AT_ALIGNED_ONEBUF \
+    Args({(8), AT_SRC_ALIGN})->Args({(64), AT_SRC_ALIGN})->Args({(512), AT_SRC_ALIGN})-> \
+    Args({(1*KB), AT_SRC_ALIGN})->Args({(8*KB), AT_SRC_ALIGN})->Args({(16*KB), AT_SRC_ALIGN})-> \
+    Args({(32*KB), AT_SRC_ALIGN})->Args({(64*KB), AT_SRC_ALIGN})
 
 static void BM_string_memcmp(benchmark::State& state) {
   const size_t nbytes = state.range(0);
-  char* src = new char[nbytes]; char* dst = new char[nbytes];
-  memset(src, 'x', nbytes);
-  memset(dst, 'x', nbytes);
+  const size_t src_alignment = state.range(1);
+  const size_t dst_alignment = state.range(2);
+
+  std::vector<char> src;
+  std::vector<char> dst;
+  char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
+  char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'x');
 
   volatile int c __attribute__((unused)) = 0;
   while (state.KeepRunning()) {
-    c += memcmp(dst, src, nbytes);
+    c += memcmp(dst_aligned, src_aligned, nbytes);
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
-  delete[] src;
-  delete[] dst;
 }
-BENCHMARK(BM_string_memcmp)->AT_COMMON_SIZES;
+BENCHMARK(BM_string_memcmp)->AT_ALIGNED_TWOBUF;
 
 static void BM_string_memcpy(benchmark::State& state) {
   const size_t nbytes = state.range(0);
-  char* src = new char[nbytes]; char* dst = new char[nbytes];
-  memset(src, 'x', nbytes);
+  const size_t src_alignment = state.range(1);
+  const size_t dst_alignment = state.range(2);
+
+  std::vector<char> src;
+  std::vector<char> dst;
+  char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
+  char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
 
   while (state.KeepRunning()) {
-    memcpy(dst, src, nbytes);
+    memcpy(dst_aligned, src_aligned, nbytes);
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
-  delete[] src;
-  delete[] dst;
 }
-BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES;
+BENCHMARK(BM_string_memcpy)->AT_ALIGNED_TWOBUF;
 
-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);
+  const size_t src_alignment = state.range(1);
+  const size_t dst_alignment = state.range(2);
+
+  std::vector<char> src;
+  std::vector<char> dst;
+  char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
+  char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
 
   while (state.KeepRunning()) {
-    memmove(buf, buf + 1, nbytes); // Worst-case overlap.
+    memmove(dst_aligned, src_aligned, 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_ALIGNED_TWOBUF;
+
+static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t alignment = state.range(1);
+
+  std::vector<char> buf(3 * alignment + nbytes + 1, 'x');
+  char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
+
+  while (state.KeepRunning()) {
+    memmove(buf_aligned, buf_aligned + 1, nbytes);  // Worst-case overlap.
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_memmove_overlap_dst_before_src)->AT_ALIGNED_ONEBUF;
+
+static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t alignment = state.range(1);
+
+  std::vector<char> buf;
+  char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
+
+  while (state.KeepRunning()) {
+    memmove(buf_aligned + 1, buf_aligned, nbytes);  // Worst-case overlap.
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_memmove_overlap_src_before_dst)->AT_ALIGNED_ONEBUF;
 
 static void BM_string_memset(benchmark::State& state) {
   const size_t nbytes = state.range(0);
-  char* dst = new char[nbytes];
+  const size_t alignment = state.range(1);
+
+  std::vector<char> buf;
+  char* buf_aligned = GetAlignedPtr(&buf, alignment, nbytes + 1);
 
   while (state.KeepRunning()) {
-    memset(dst, 0, nbytes);
+    memset(buf_aligned, 0, nbytes);
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
-  delete[] dst;
 }
-BENCHMARK(BM_string_memset)->AT_COMMON_SIZES;
+BENCHMARK(BM_string_memset)->AT_ALIGNED_ONEBUF;
 
 static void BM_string_strlen(benchmark::State& state) {
   const size_t nbytes = state.range(0);
-  char* s = new char[nbytes];
-  memset(s, 'x', nbytes);
-  s[nbytes - 1] = 0;
+  const size_t alignment = state.range(1);
+
+  std::vector<char> buf;
+  char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
+  buf_aligned[nbytes - 1] = '\0';
 
   volatile int c __attribute__((unused)) = 0;
   while (state.KeepRunning()) {
-    c += strlen(s);
+    c += strlen(buf_aligned);
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
-  delete[] s;
 }
-BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;
+BENCHMARK(BM_string_strlen)->AT_ALIGNED_ONEBUF;
+
+static void BM_string_strcat_copy_only(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t src_alignment = state.range(1);
+  const size_t dst_alignment = state.range(2);
+
+  std::vector<char> src;
+  std::vector<char> dst;
+  char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
+  char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes + 2);
+  src_aligned[nbytes - 1] = '\0';
+  dst_aligned[0] = 'y';
+  dst_aligned[1] = 'y';
+  dst_aligned[2] = '\0';
+
+  while (state.KeepRunning()) {
+    strcat(dst_aligned, src_aligned);
+    dst_aligned[2] = '\0';
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcat_copy_only)->AT_ALIGNED_TWOBUF;
+
+static void BM_string_strcat_seek_only(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t src_alignment = state.range(1);
+  const size_t dst_alignment = state.range(2);
+
+  std::vector<char> src;
+  std::vector<char> dst;
+  char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, 3, 'x');
+  char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes + 2, 'y');
+  src_aligned[2] = '\0';
+  dst_aligned[nbytes - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    strcat(dst_aligned, src_aligned);
+    dst_aligned[nbytes - 1] = '\0';
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcat_seek_only)->AT_ALIGNED_TWOBUF;
+
+static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t src_alignment = state.range(1);
+  const size_t dst_alignment = state.range(2);
+
+  std::vector<char> src;
+  std::vector<char> dst;
+  char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes / 2, 'x');
+  char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
+  src_aligned[nbytes / 2 - 1] = '\0';
+  dst_aligned[nbytes / 2 - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    strcat(dst_aligned, src_aligned);
+    dst_aligned[nbytes / 2 - 1] = '\0';
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcat_half_copy_half_seek)->AT_ALIGNED_TWOBUF;
+
+static void BM_string_strcpy(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t src_alignment = state.range(1);
+  const size_t dst_alignment = state.range(2);
+
+  std::vector<char> src;
+  std::vector<char> dst;
+  char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
+  char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
+  src_aligned[nbytes - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    strcpy(dst_aligned, src_aligned);
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcpy)->AT_ALIGNED_TWOBUF;
+
+static void BM_string_strcmp(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t s1_alignment = state.range(1);
+  const size_t s2_alignment = state.range(2);
+
+  std::vector<char> s1;
+  std::vector<char> s2;
+  char* s1_aligned = GetAlignedPtrFilled(&s1, s1_alignment, nbytes, 'x');
+  char* s2_aligned = GetAlignedPtrFilled(&s2, s2_alignment, nbytes, 'x');
+  s1_aligned[nbytes - 1] = '\0';
+  s2_aligned[nbytes - 1] = '\0';
+
+  volatile int c __attribute__((unused));
+  while (state.KeepRunning()) {
+    c = strcmp(s1_aligned, s2_aligned);
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BENCHMARK(BM_string_strcmp)->AT_ALIGNED_TWOBUF;
diff --git a/benchmarks/tests/benchmark_test.cpp b/benchmarks/tests/benchmark_test.cpp
new file mode 100644
index 0000000..df7b686
--- /dev/null
+++ b/benchmarks/tests/benchmark_test.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <util.h>
+
+TEST(benchmark, memory_align) {
+  std::vector<char> buf(100);
+  for (size_t alignment = 1; alignment <= 32; alignment *= 2) {
+    for (size_t or_mask = 0; or_mask < alignment; ++or_mask) {
+      uintptr_t aligned_ptr = reinterpret_cast<uintptr_t>(GetAlignedMemory(buf.data(), alignment,
+                                                                           or_mask));
+      ASSERT_EQ(aligned_ptr % alignment, or_mask);
+      ASSERT_EQ(aligned_ptr & alignment, alignment);
+    }
+  }
+}
+
+TEST(benchmark, ptr_align) {
+  std::vector<char> buf;
+  for (size_t alignment = 1; alignment <= 2048; alignment *= 2) {
+    uintptr_t aligned_ptr = reinterpret_cast<uintptr_t>(GetAlignedPtr(&buf, alignment, 100));
+    ASSERT_EQ(aligned_ptr & alignment, alignment);
+    ASSERT_EQ(aligned_ptr & (alignment - 1), 0u);
+  }
+}
diff --git a/benchmarks/util.cpp b/benchmarks/util.cpp
new file mode 100644
index 0000000..d9641cf
--- /dev/null
+++ b/benchmarks/util.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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 "util.h"
+
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <cstdlib>
+#include <vector>
+
+// This function returns a pointer less than 2 * alignment + or_mask bytes into the array.
+char *GetAlignedMemory(char *orig_ptr, size_t alignment, size_t or_mask) {
+  if ((alignment & (alignment - 1)) != 0) {
+    fprintf(stderr, "warning: alignment passed into GetAlignedMemory is not a power of two.\n");
+    std::abort();
+  }
+  if (or_mask > alignment) {
+    fprintf(stderr, "warning: or_mask passed into GetAlignedMemory is too high.\n");
+    std::abort();
+  }
+  uintptr_t ptr = reinterpret_cast<uintptr_t>(orig_ptr);
+  if (alignment > 0) {
+    // When setting the alignment, set it to exactly the alignment chosen.
+    // The pointer returned will be guaranteed not to be aligned to anything
+    // more than that.
+    ptr += alignment - (ptr & (alignment - 1));
+    ptr |= alignment | or_mask;
+  }
+
+  return reinterpret_cast<char*>(ptr);
+}
+
+char *GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes) {
+  buf->resize(nbytes + 3 * alignment);
+  return GetAlignedMemory(buf->data(), alignment, 0);
+}
+
+char *GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte) {
+  char* buf_aligned = GetAlignedPtr(buf, alignment, nbytes);
+  memset(buf_aligned, fill_byte, nbytes);
+  return buf_aligned;
+}
+
+#if defined(__APPLE__)
+
+// Darwin doesn't support this, so do nothing.
+bool LockToCPU(int) {
+  return false;
+}
+
+#else
+
+bool LockToCPU(int cpu_to_lock) {
+  cpu_set_t cpuset;
+
+  CPU_ZERO(&cpuset);
+  if (sched_getaffinity(0, sizeof(cpuset), &cpuset) != 0) {
+    perror("sched_getaffinity failed");
+    return false;
+  }
+
+  if (cpu_to_lock < 0) {
+    // Lock to the last active core we find.
+    for (int i = 0; i < CPU_SETSIZE; i++) {
+      if (CPU_ISSET(i, &cpuset)) {
+        cpu_to_lock = i;
+      }
+    }
+  } else if (!CPU_ISSET(cpu_to_lock, &cpuset)) {
+    printf("Cpu %d does not exist.\n", cpu_to_lock);
+    return false;
+  }
+
+  if (cpu_to_lock < 0) {
+    printf("Cannot find any valid cpu to lock.\n");
+    return false;
+  }
+
+  CPU_ZERO(&cpuset);
+  CPU_SET(cpu_to_lock, &cpuset);
+  if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
+    perror("sched_setaffinity failed");
+    return false;
+  }
+
+  return true;
+}
+
+#endif
diff --git a/benchmarks/util.h b/benchmarks/util.h
new file mode 100644
index 0000000..bd3d515
--- /dev/null
+++ b/benchmarks/util.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#ifndef _BIONIC_BENCHMARKS_UTIL_H_
+#define _BIONIC_BENCHMARKS_UTIL_H_
+
+#include <vector>
+
+// This function returns a pointer less than 2 * alignment + or_mask bytes into the array.
+char *GetAlignedMemory(char *orig_ptr, size_t alignment, size_t or_mask);
+
+char *GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes);
+
+char *GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte);
+
+bool LockToCPU(int cpu_to_lock);
+
+#endif // _BIONIC_BENCHMARKS_UTIL_H
diff --git a/libc/Android.bp b/libc/Android.bp
index 5a1c287..7b0ac23 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
@@ -1324,6 +1330,13 @@
 cc_library_static {
     defaults: ["libc_defaults"],
     srcs: [
+        "bionic/NetdClientDispatch.cpp",
+        "bionic/__cmsg_nxthdr.cpp",
+        "bionic/__errno.cpp",
+        "bionic/__gnu_basename.cpp",
+        "bionic/__libc_current_sigrtmax.cpp",
+        "bionic/__libc_current_sigrtmin.cpp",
+        "bionic/__set_errno.cpp",
         "bionic/abort.cpp",
         "bionic/accept.cpp",
         "bionic/accept4.cpp",
@@ -1346,15 +1359,14 @@
         "bionic/clock_nanosleep.cpp",
         "bionic/clone.cpp",
         "bionic/close.cpp",
-        "bionic/__cmsg_nxthdr.cpp",
         "bionic/connect.cpp",
         "bionic/ctype.cpp",
         "bionic/dirent.cpp",
         "bionic/dup2.cpp",
+        "bionic/environ.cpp",
         "bionic/epoll_create.cpp",
         "bionic/epoll_pwait.cpp",
         "bionic/epoll_wait.cpp",
-        "bionic/__errno.cpp",
         "bionic/error.cpp",
         "bionic/eventfd_read.cpp",
         "bionic/eventfd_write.cpp",
@@ -1380,7 +1392,6 @@
         "bionic/getpid.cpp",
         "bionic/getpriority.cpp",
         "bionic/gettid.cpp",
-        "bionic/__gnu_basename.cpp",
         "bionic/grp_pwd.cpp",
         "bionic/ifaddrs.cpp",
         "bionic/inotify_init.cpp",
@@ -1388,8 +1399,6 @@
         "bionic/langinfo.cpp",
         "bionic/lchown.cpp",
         "bionic/lfs64_support.cpp",
-        "bionic/__libc_current_sigrtmax.cpp",
-        "bionic/__libc_current_sigrtmin.cpp",
         "bionic/libc_init_common.cpp",
         "bionic/libgen.cpp",
         "bionic/link.cpp",
@@ -1400,7 +1409,6 @@
         "bionic/mblen.cpp",
         "bionic/mbrtoc16.cpp",
         "bionic/mbrtoc32.cpp",
-        "bionic/mbstate.cpp",
         "bionic/memmem.cpp",
         "bionic/mempcpy.cpp",
         "bionic/mkdir.cpp",
@@ -1408,9 +1416,8 @@
         "bionic/mknod.cpp",
         "bionic/mntent.cpp",
         "bionic/mremap.cpp",
-        "bionic/netdb.cpp",
-        "bionic/NetdClientDispatch.cpp",
         "bionic/net_if.cpp",
+        "bionic/netdb.cpp",
         "bionic/netinet_in.cpp",
         "bionic/nl_types.cpp",
         "bionic/open.cpp",
@@ -1437,7 +1444,6 @@
         "bionic/semaphore.cpp",
         "bionic/send.cpp",
         "bionic/setegid.cpp",
-        "bionic/__set_errno.cpp",
         "bionic/seteuid.cpp",
         "bionic/setpgrp.cpp",
         "bionic/sigaction.cpp",
@@ -1463,21 +1469,24 @@
         "bionic/socket.cpp",
         "bionic/stat.cpp",
         "bionic/statvfs.cpp",
+        "bionic/stdlib_l.cpp",
         "bionic/strchrnul.cpp",
         "bionic/strerror.cpp",
         "bionic/strerror_r.cpp",
+        "bionic/string_l.cpp",
+        "bionic/strings_l.cpp",
         "bionic/strsignal.cpp",
         "bionic/strtold.cpp",
         "bionic/symlink.cpp",
         "bionic/sync_file_range.cpp",
-        "bionic/sysinfo.cpp",
-        "bionic/syslog.cpp",
         "bionic/sys_msg.cpp",
         "bionic/sys_sem.cpp",
         "bionic/sys_shm.cpp",
         "bionic/sys_siglist.c",
         "bionic/sys_signame.c",
         "bionic/sys_time.cpp",
+        "bionic/sysinfo.cpp",
+        "bionic/syslog.cpp",
         "bionic/system_properties.cpp",
         "bionic/tdestroy.cpp",
         "bionic/termios.cpp",
@@ -1487,6 +1496,7 @@
         "bionic/unlink.cpp",
         "bionic/wait.cpp",
         "bionic/wchar.cpp",
+        "bionic/wchar_l.cpp",
         "bionic/wcstod.cpp",
         "bionic/wctype.cpp",
         "bionic/wmempcpy.cpp",
@@ -1757,10 +1767,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..ae98d1d 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.
 
@@ -881,22 +862,6 @@
 
      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) 2015 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.
@@ -1286,35 +1251,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 1983, 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.
-4. Neither the name of the University nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
--------------------------------------------------------------------
-
 Copyright (c) 1985
    The Regents of the University of California.  All rights reserved.
 
@@ -2955,6 +2891,25 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 1996, David Mazieres <dm@uun.org>
+Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
 Copyright (c) 1996-1998, 2008 Theo de Raadt
 Copyright (c) 1997, 2008-2009 Todd C. Miller
 
@@ -5432,32 +5387,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2013 David Chisnall
-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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
--------------------------------------------------------------------
-
 Copyright (c) 2013 The NetBSD Foundation, Inc.
 All rights reserved.
 
diff --git a/libc/SECCOMP_WHITELIST.TXT b/libc/SECCOMP_WHITELIST.TXT
index beffef9..0b9dad3 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/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/c16rtomb.cpp b/libc/bionic/c16rtomb.cpp
index 77512be..93749c6 100644
--- a/libc/bionic/c16rtomb.cpp
+++ b/libc/bionic/c16rtomb.cpp
@@ -50,18 +50,18 @@
       mbstate_set_byte(state, 2, (c32 & 0x00ff00) >> 8);
       return 0;
     } else if (is_low_surrogate(c16)) {
-      return reset_and_return_illegal(EINVAL, state);
+      return mbstate_reset_and_return_illegal(EINVAL, state);
     } else {
       return c32rtomb(s, static_cast<char32_t>(c16), state);
     }
   } else {
     if (!is_low_surrogate(c16)) {
-      return reset_and_return_illegal(EINVAL, state);
+      return mbstate_reset_and_return_illegal(EINVAL, state);
     }
 
     char32_t c32 = ((mbstate_get_byte(state, 3) << 16) |
                     (mbstate_get_byte(state, 2) << 8) |
                     (c16 & ~0xdc00)) + 0x10000;
-    return reset_and_return(c32rtomb(s, c32, NULL), state);
+    return mbstate_reset_and_return(c32rtomb(s, c32, NULL), state);
   }
 }
diff --git a/libc/bionic/c32rtomb.cpp b/libc/bionic/c32rtomb.cpp
index d3231c0..ebe9cd3 100644
--- a/libc/bionic/c32rtomb.cpp
+++ b/libc/bionic/c32rtomb.cpp
@@ -38,7 +38,7 @@
 
   if (s == NULL) {
     // Equivalent to c32rtomb(buf, U'\0', ps).
-    return reset_and_return(1, state);
+    return mbstate_reset_and_return(1, state);
   }
 
   // POSIX states that if char32_t is a null wide character, a null byte shall
@@ -47,11 +47,11 @@
   // stored.
   if (c32 == U'\0') {
     *s = '\0';
-    reset_and_return(1, state);
+    return mbstate_reset_and_return(1, state);
   }
 
   if (!mbsinit(state)) {
-    return reset_and_return_illegal(EILSEQ, state);
+    return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
 
   if ((c32 & ~0x7f) == 0) {
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/libc/bionic/environ.cpp
similarity index 64%
rename from libc/arch-arm/include/machine/cpu-features.h
rename to libc/bionic/environ.cpp
index fc8c80d..363c1fd 100644
--- a/libc/arch-arm/include/machine/cpu-features.h
+++ b/libc/bionic/environ.cpp
@@ -25,24 +25,9 @@
  * 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 <unistd.h>
 
-#endif /* _ARM_MACHINE_CPU_FEATURES_H */
+// Keep that variable in separate .o file to make sure programs which define
+// their own "environ" are compileable.
+char** environ;
diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c
index 31a4b2f..a43c8c9 100644
--- a/libc/bionic/fts.c
+++ b/libc/bionic/fts.c
@@ -32,6 +32,7 @@
 #include <sys/param.h>
 #include <sys/stat.h>
 
+#include <assert.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -719,7 +720,8 @@
 			/* Build a file name for fts_stat to stat. */
 			if (ISSET(FTS_NOCHDIR)) {
 				p->fts_accpath = p->fts_path;
-				memmove(cp, p->fts_name, p->fts_namelen + 1);
+				assert(cp && "cp should be non-null if FTS_NOCHDIR is set");
+				memmove(cp, p->fts_name, p->fts_namelen + 1); // NOLINT
 				p->fts_info = fts_stat(sp, p, 0, dirfd(dirp));
 			} else {
 				p->fts_accpath = p->fts_name;
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index e051762..48fd670 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -59,9 +59,6 @@
 // Not public, but well-known in the BSDs.
 const char* __progname;
 
-// Declared in <unistd.h>.
-char** environ;
-
 #if defined(__i386__)
 __attribute__((__naked__)) static void __libc_int0x80() {
   __asm__ volatile("int $0x80; ret");
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/locale.cpp b/libc/bionic/locale.cpp
index 38e15b7..08c9401 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -37,7 +37,15 @@
 
 #include "private/bionic_macros.h"
 
+#if defined(__BIONIC_BUILD_FOR_ANDROID_SUPPORT)
+#define USE_TLS_SLOT 0
+#else
+#define USE_TLS_SLOT 1
+#endif
+
+#if USE_TLS_SLOT
 #include "bionic/pthread_internal.h"
+#endif
 
 // We only support two locales, the "C" locale (also known as "POSIX"),
 // and the "C.UTF-8" locale (also known as "en_US.UTF-8").
@@ -70,6 +78,10 @@
   }
 }
 
+#if !USE_TLS_SLOT
+static thread_local locale_t g_current_locale;
+#endif
+
 static pthread_once_t g_locale_once = PTHREAD_ONCE_INIT;
 static lconv g_locale;
 
@@ -163,9 +175,16 @@
   return const_cast<char*>(__bionic_current_locale_is_utf8 ? "C.UTF-8" : "C");
 }
 
+static locale_t* get_current_locale_ptr() {
+#if USE_TLS_SLOT
+  return &__get_bionic_tls().locale;
+#else
+  return &g_current_locale;
+#endif
+}
+
 locale_t uselocale(locale_t new_locale) {
-  locale_t* locale_storage = &__get_bionic_tls().locale;
-  locale_t old_locale = *locale_storage;
+  locale_t old_locale = *get_current_locale_ptr();
 
   // If this is the first call to uselocale(3) on this thread, we return LC_GLOBAL_LOCALE.
   if (old_locale == NULL) {
@@ -173,64 +192,8 @@
   }
 
   if (new_locale != NULL) {
-    *locale_storage = new_locale;
+    *get_current_locale_ptr() = new_locale;
   }
 
   return old_locale;
 }
-
-int strcasecmp_l(const char* s1, const char* s2, locale_t) {
-  return strcasecmp(s1, s2);
-}
-
-int strcoll_l(const char* s1, const char* s2, locale_t) {
-  return strcoll(s1, s2);
-}
-
-char* strerror_l(int error, locale_t) {
-  return strerror(error);
-}
-
-int strncasecmp_l(const char* s1, const char* s2, size_t n, locale_t) {
-  return strncasecmp(s1, s2, n);
-}
-
-double strtod_l(const char* s, char** end_ptr, locale_t) {
-  return strtod(s, end_ptr);
-}
-
-float strtof_l(const char* s, char** end_ptr, locale_t) {
-  return strtof(s, end_ptr);
-}
-
-long strtol_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtol(s, end_ptr, base);
-}
-
-long double strtold_l(const char* s, char** end_ptr, locale_t) {
-  return strtold(s, end_ptr);
-}
-
-long long strtoll_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtoll(s, end_ptr, base);
-}
-
-unsigned long strtoul_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtoul(s, end_ptr, base);
-}
-
-unsigned long long strtoull_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtoull(s, end_ptr, base);
-}
-
-size_t strxfrm_l(char* dst, const char* src, size_t n, locale_t) {
-  return strxfrm(dst, src, n);
-}
-
-int wcscasecmp_l(const wchar_t* ws1, const wchar_t* ws2, locale_t) {
-  return wcscasecmp(ws1, ws2);
-}
-
-int wcsncasecmp_l(const wchar_t* ws1, const wchar_t* ws2, size_t n, locale_t) {
-  return wcsncasecmp(ws1, ws2, n);
-}
diff --git a/libc/bionic/mbrtoc16.cpp b/libc/bionic/mbrtoc16.cpp
index 6878a11..2180516 100644
--- a/libc/bionic/mbrtoc16.cpp
+++ b/libc/bionic/mbrtoc16.cpp
@@ -55,7 +55,7 @@
   char16_t trail = mbstate_get_byte(state, 1) << 8 |
                    mbstate_get_byte(state, 0);
   *pc16 = trail;
-  return reset_and_return(mbstate_get_byte(state, 3), state);
+  return mbstate_reset_and_return(mbstate_get_byte(state, 3), state);
 }
 
 size_t mbrtoc16(char16_t* pc16, const char* s, size_t n, mbstate_t* ps) {
@@ -76,13 +76,13 @@
   if (__MB_IS_ERR(nconv)) {
     return nconv;
   } else if (nconv == 0) {
-    return reset_and_return(nconv, state);
+    return mbstate_reset_and_return(nconv, state);
   } else if (c32 > 0x10ffff) {
     // Input cannot be encoded as UTF-16.
-    return reset_and_return_illegal(EILSEQ, state);
+    return mbstate_reset_and_return_illegal(EILSEQ, state);
   } else if (c32 < 0x10000) {
     *pc16 = static_cast<char16_t>(c32);
-    return reset_and_return(nconv, state);
+    return mbstate_reset_and_return(nconv, state);
   } else {
     return begin_surrogate(c32, pc16, nconv, state);
   }
diff --git a/libc/bionic/mbrtoc32.cpp b/libc/bionic/mbrtoc32.cpp
index bd40ecf..f004b78 100644
--- a/libc/bionic/mbrtoc32.cpp
+++ b/libc/bionic/mbrtoc32.cpp
@@ -41,7 +41,7 @@
   // Full state verification is done when decoding the sequence (after we have
   // all the bytes).
   if (mbstate_get_byte(state, 3) != 0) {
-    return reset_and_return_illegal(EINVAL, state);
+    return mbstate_reset_and_return_illegal(EINVAL, state);
   }
 
   if (s == NULL) {
@@ -98,7 +98,7 @@
     lower_bound = 0x10000;
   } else {
     // Malformed input; input is not UTF-8. See RFC 3629.
-    return reset_and_return_illegal(EILSEQ, state);
+    return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
 
   // Fill in the state.
@@ -107,7 +107,7 @@
   for (i = 0; i < MIN(bytes_wanted, n); i++) {
     if (!mbsinit(state) && ((*s & 0xc0) != 0x80)) {
       // Malformed input; bad characters in the middle of a character.
-      return reset_and_return_illegal(EILSEQ, state);
+      return mbstate_reset_and_return_illegal(EILSEQ, state);
     }
     mbstate_set_byte(state, bytes_so_far + i, *s++);
   }
@@ -125,14 +125,14 @@
 
   if (c32 < lower_bound) {
     // Malformed input; redundant encoding.
-    return reset_and_return_illegal(EILSEQ, state);
+    return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
   if ((c32 >= 0xd800 && c32 <= 0xdfff) || c32 == 0xfffe || c32 == 0xffff) {
     // Malformed input; invalid code points.
-    return reset_and_return_illegal(EILSEQ, state);
+    return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
   if (pc32 != NULL) {
     *pc32 = c32;
   }
-  return reset_and_return(c32 == U'\0' ? 0 : bytes_wanted, state);
+  return mbstate_reset_and_return(c32 == U'\0' ? 0 : bytes_wanted, state);
 }
diff --git a/libc/bionic/sched_cpualloc.c b/libc/bionic/sched_cpualloc.c
index 30964bc..345de91 100644
--- a/libc/bionic/sched_cpualloc.c
+++ b/libc/bionic/sched_cpualloc.c
@@ -31,7 +31,10 @@
 
 cpu_set_t* __sched_cpualloc(size_t count)
 {
-    return (cpu_set_t*) malloc(CPU_ALLOC_SIZE(count));
+    // The static analyzer complains that CPU_ALLOC_SIZE eventually expands to
+    // N * sizeof(unsigned long), which is incompatible with cpu_set_t. This is
+    // on purpose.
+    return (cpu_set_t*) malloc(CPU_ALLOC_SIZE(count)); // NOLINT
 }
 
 void __sched_cpufree(cpu_set_t* set)
diff --git a/libc/bionic/mbstate.cpp b/libc/bionic/stdlib_l.cpp
similarity index 62%
rename from libc/bionic/mbstate.cpp
rename to libc/bionic/stdlib_l.cpp
index cb327d8..18e9f86 100644
--- a/libc/bionic/mbstate.cpp
+++ b/libc/bionic/stdlib_l.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 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
@@ -26,32 +26,34 @@
  * SUCH DAMAGE.
  */
 
-#include "private/bionic_mbstate.h"
+#include <stdlib.h>
+#include <xlocale.h>
 
-#include <errno.h>
-
-__LIBC_HIDDEN__ size_t mbstate_bytes_so_far(const mbstate_t* ps) {
-  return
-    (ps->__seq[2] != 0) ? 3 :
-    (ps->__seq[1] != 0) ? 2 :
-    (ps->__seq[0] != 0) ? 1 : 0;
+double strtod_l(const char* s, char** end_ptr, locale_t) {
+  return strtod(s, end_ptr);
 }
 
-__LIBC_HIDDEN__ void mbstate_set_byte(mbstate_t* ps, int i, char byte) {
-  ps->__seq[i] = static_cast<uint8_t>(byte);
+float strtof_l(const char* s, char** end_ptr, locale_t) {
+  return strtof(s, end_ptr);
 }
 
-__LIBC_HIDDEN__ uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
-  return ps->__seq[n];
+long strtol_l(const char* s, char** end_ptr, int base, locale_t) {
+  return strtol(s, end_ptr, base);
 }
 
-__LIBC_HIDDEN__ size_t reset_and_return_illegal(int _errno, mbstate_t* ps) {
-  errno = _errno;
-  *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
-  return __MB_ERR_ILLEGAL_SEQUENCE;
+long double strtold_l(const char* s, char** end_ptr, locale_t) {
+  return strtold(s, end_ptr);
 }
 
-__LIBC_HIDDEN__ size_t reset_and_return(int _return, mbstate_t* ps) {
-  *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
-  return _return;
+long long strtoll_l(const char* s, char** end_ptr, int base, locale_t) {
+  return strtoll(s, end_ptr, base);
 }
+
+unsigned long strtoul_l(const char* s, char** end_ptr, int base, locale_t) {
+  return strtoul(s, end_ptr, base);
+}
+
+unsigned long long strtoull_l(const char* s, char** end_ptr, int base, locale_t) {
+  return strtoull(s, end_ptr, base);
+}
+
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/libc/bionic/string_l.cpp
similarity index 62%
copy from libc/arch-arm/include/machine/cpu-features.h
copy to libc/bionic/string_l.cpp
index fc8c80d..66bfb0e 100644
--- a/libc/arch-arm/include/machine/cpu-features.h
+++ b/libc/bionic/string_l.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,18 @@
  * 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 <string.h>
+#include <xlocale.h>
 
-#endif /* _ARM_MACHINE_CPU_FEATURES_H */
+int strcoll_l(const char* s1, const char* s2, locale_t) {
+  return strcoll(s1, s2);
+}
+
+char* strerror_l(int error, locale_t) {
+  return strerror(error);
+}
+
+size_t strxfrm_l(char* dst, const char* src, size_t n, locale_t) {
+  return strxfrm(dst, src, n);
+}
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/libc/bionic/strings_l.cpp
similarity index 62%
copy from libc/arch-arm/include/machine/cpu-features.h
copy to libc/bionic/strings_l.cpp
index fc8c80d..0983ab1 100644
--- a/libc/arch-arm/include/machine/cpu-features.h
+++ b/libc/bionic/strings_l.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,14 @@
  * 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 <strings.h>
+#include <xlocale.h>
 
-#endif /* _ARM_MACHINE_CPU_FEATURES_H */
+int strcasecmp_l(const char* s1, const char* s2, locale_t) {
+  return strcasecmp(s1, s2);
+}
+
+int strncasecmp_l(const char* s1, const char* s2, size_t n, locale_t) {
+  return strncasecmp(s1, s2, n);
+}
diff --git a/libc/bionic/termios.cpp b/libc/bionic/termios.cpp
index 44ae643..5fe8eb0 100644
--- a/libc/bionic/termios.cpp
+++ b/libc/bionic/termios.cpp
@@ -26,93 +26,21 @@
  * SUCH DAMAGE.
  */
 
-#include <errno.h>
 #include <termios.h>
 #include <unistd.h>
 
-static speed_t cfgetspeed(const termios* s) {
-  return (s->c_cflag & CBAUD);
-}
+// Most of termios was missing in the platform until L, but available as inlines in the NDK.
+// We share definitions with the NDK to avoid bugs (https://github.com/android-ndk/ndk/issues/441).
+#define __BIONIC_TERMIOS_INLINE /* Out of line. */
+#include <bits/termios_inlines.h>
 
-speed_t cfgetispeed(const termios* s) {
-  return cfgetspeed(s);
-}
-
-speed_t cfgetospeed(const termios* s) {
-  return cfgetspeed(s);
-}
-
-void cfmakeraw(termios* s) {
-  s->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
-  s->c_oflag &= ~OPOST;
-  s->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
-  s->c_cflag &= ~(CSIZE|PARENB);
-  s->c_cflag |= CS8;
-}
-
-int cfsetispeed(termios* s, speed_t speed) {
-  return cfsetspeed(s, speed);
-}
-
-int cfsetospeed(termios* s, speed_t speed) {
-  return cfsetspeed(s, speed);
-}
-
-int cfsetspeed(termios* s, speed_t speed) {
-  // TODO: check 'speed' is valid.
-  s->c_cflag = (s->c_cflag & ~CBAUD) | (speed & CBAUD);
-  return 0;
-}
-
-int tcdrain(int fd) {
-  // A non-zero argument to TCSBRK means "don't send a break".
-  // The drain is a side-effect of the ioctl!
-  return ioctl(fd, TCSBRK, static_cast<unsigned long>(1));
-}
-
-int tcflow(int fd, int action) {
-  return ioctl(fd, TCXONC, static_cast<unsigned long>(action));
-}
-
-int tcflush(int fd, int queue) {
-  return ioctl(fd, TCFLSH, static_cast<unsigned long>(queue));
-}
-
-int tcgetattr(int fd, termios* s) {
-  return ioctl(fd, TCGETS, s);
-}
-
-pid_t tcgetsid(int fd) {
-  pid_t sid;
-  if (ioctl(fd, TIOCGSID, &sid) == -1) {
-    return -1;
-  }
-  return sid;
-}
-
-int tcsendbreak(int fd, int duration) {
-  return ioctl(fd, TCSBRKP, static_cast<unsigned long>(duration));
-}
-
-int tcsetattr(int fd, int optional_actions, const termios* s) {
-  int cmd;
-  switch (optional_actions) {
-    case TCSANOW: cmd = TCSETS; break;
-    case TCSADRAIN: cmd = TCSETSW; break;
-    case TCSAFLUSH: cmd = TCSETSF; break;
-    default: errno = EINVAL; return -1;
-  }
-  return ioctl(fd, cmd, s);
-}
-
+// Actually declared in <unistd.h>, present on all API levels.
 pid_t tcgetpgrp(int fd) {
   pid_t pid;
-  if (ioctl(fd, TIOCGPGRP, &pid) == -1) {
-    return -1;
-  }
-  return pid;
+  return (ioctl(fd, TIOCGPGRP, &pid) == -1) ? -1 : pid;
 }
 
+// Actually declared in <unistd.h>, present on all API levels.
 int tcsetpgrp(int fd, pid_t pid) {
   return ioctl(fd, TIOCSPGRP, &pid);
 }
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 7717e10..62023d6 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -74,7 +74,7 @@
   // character appears as anything but the first byte of a
   // multibyte sequence. Check now to avoid doing it in the loops.
   if (nmc > 0 && mbstate_bytes_so_far(state) > 0 && static_cast<uint8_t>((*src)[0]) < 0x80) {
-    return reset_and_return_illegal(EILSEQ, state);
+    return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
 
   // Measure only?
@@ -83,23 +83,23 @@
       if (static_cast<uint8_t>((*src)[i]) < 0x80) {
         // Fast path for plain ASCII characters.
         if ((*src)[i] == '\0') {
-          return reset_and_return(o, state);
+          return mbstate_reset_and_return(o, state);
         }
         r = 1;
       } else {
         r = mbrtowc(NULL, *src + i, nmc - i, state);
         if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
-          return reset_and_return_illegal(EILSEQ, state);
+          return mbstate_reset_and_return_illegal(EILSEQ, state);
         }
         if (r == __MB_ERR_INCOMPLETE_SEQUENCE) {
-          return reset_and_return_illegal(EILSEQ, state);
+          return mbstate_reset_and_return_illegal(EILSEQ, state);
         }
         if (r == 0) {
-          return reset_and_return(o, state);
+          return mbstate_reset_and_return(o, state);
         }
       }
     }
-    return reset_and_return(o, state);
+    return mbstate_reset_and_return(o, state);
   }
 
   // Actually convert, updating `dst` and `src`.
@@ -110,26 +110,26 @@
       r = 1;
       if ((*src)[i] == '\0') {
         *src = nullptr;
-        return reset_and_return(o, state);
+        return mbstate_reset_and_return(o, state);
       }
     } else {
       r = mbrtowc(dst + o, *src + i, nmc - i, state);
       if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
         *src += i;
-        return reset_and_return_illegal(EILSEQ, state);
+        return mbstate_reset_and_return_illegal(EILSEQ, state);
       }
       if (r == __MB_ERR_INCOMPLETE_SEQUENCE) {
         *src += nmc;
-        return reset_and_return(EILSEQ, state);
+        return mbstate_reset_and_return_illegal(EILSEQ, state);
       }
       if (r == 0) {
         *src = NULL;
-        return reset_and_return(o, state);
+        return mbstate_reset_and_return(o, state);
       }
     }
   }
   *src += i;
-  return reset_and_return(o, state);
+  return mbstate_reset_and_return(o, state);
 }
 
 size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps) {
@@ -149,7 +149,7 @@
   mbstate_t* state = (ps == NULL) ? &__private_state : ps;
 
   if (!mbsinit(state)) {
-    return reset_and_return_illegal(EILSEQ, state);
+    return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
 
   char buf[MB_LEN_MAX];
@@ -210,25 +210,3 @@
 size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps) {
   return wcsnrtombs(dst, src, SIZE_MAX, len, ps);
 }
-
-int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
-  return wcscoll(ws1, ws2);
-}
-
-size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) {
-  return wcsxfrm(dest, src, n);
-}
-
-long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base,
-                    locale_t) {
-  return wcstoll(nptr, endptr, base);
-}
-
-unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
-                              int base, locale_t) {
-  return wcstoull(nptr, endptr, base);
-}
-
-long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) {
-  return wcstold(nptr, endptr);
-}
diff --git a/libc/bionic/wchar_l.cpp b/libc/bionic/wchar_l.cpp
new file mode 100644
index 0000000..6c39e8d
--- /dev/null
+++ b/libc/bionic/wchar_l.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <wchar.h>
+#include <xlocale.h>
+
+int wcscasecmp_l(const wchar_t* ws1, const wchar_t* ws2, locale_t) {
+  return wcscasecmp(ws1, ws2);
+}
+
+int wcsncasecmp_l(const wchar_t* ws1, const wchar_t* ws2, size_t n, locale_t) {
+  return wcsncasecmp(ws1, ws2, n);
+}
+
+int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
+  return wcscoll(ws1, ws2);
+}
+
+size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) {
+  return wcsxfrm(dest, src, n);
+}
+
+long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base,
+                    locale_t) {
+  return wcstoll(nptr, endptr, base);
+}
+
+unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
+                              int base, locale_t) {
+  return wcstoull(nptr, endptr, base);
+}
+
+long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) {
+  return wcstold(nptr, endptr);
+}
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index 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/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index e211de5..82186c7 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -36,6 +36,8 @@
 
 __BEGIN_DECLS
 
+__noreturn void _Exit(int) __RENAME(_exit);
+
 static __inline float strtof(const char *nptr, char **endptr) {
   return (float)strtod(nptr, endptr);
 }
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/libc/include/android/legacy_strings_inlines.h
similarity index 62%
copy from libc/arch-arm/include/machine/cpu-features.h
copy to libc/include/android/legacy_strings_inlines.h
index fc8c80d..6679c30 100644
--- a/libc/arch-arm/include/machine/cpu-features.h
+++ b/libc/include/android/legacy_strings_inlines.h
@@ -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,20 @@
  * 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
+#ifndef _ANDROID_LEGACY_STRINGS_INLINES_H_
+#define _ANDROID_LEGACY_STRINGS_INLINES_H_
+
+#include <strings.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#if defined(__i386__) && __ANDROID_API__ < __ANDROID_API_J_MR2__
+/* Everyone except x86 had ffs since the beginning. */
+static __inline int ffs(int __n) { return __builtin_ffs(__n); }
 #endif
 
-#endif /* _ARM_MACHINE_CPU_FEATURES_H */
+__END_DECLS
+
+#endif
diff --git a/libc/include/android/legacy_termios_inlines.h b/libc/include/android/legacy_termios_inlines.h
index 02e9429..4ed56f0 100644
--- a/libc/include/android/legacy_termios_inlines.h
+++ b/libc/include/android/legacy_termios_inlines.h
@@ -36,74 +36,8 @@
 #include <linux/termios.h>
 
 #if __ANDROID_API__ < __ANDROID_API_L__
-
-__BEGIN_DECLS
-
-static __inline int tcgetattr(int fd, struct termios *s) {
-  return ioctl(fd, TCGETS, s);
-}
-
-static __inline int tcsetattr(int fd, int __opt, const struct termios *s) {
-  return ioctl(fd, __opt, (void *)s);
-}
-
-static __inline int tcflow(int fd, int action) {
-  return ioctl(fd, TCXONC, (void *)(intptr_t)action);
-}
-
-static __inline int tcflush(int fd, int __queue) {
-  return ioctl(fd, TCFLSH, (void *)(intptr_t)__queue);
-}
-
-static __inline pid_t tcgetsid(int fd) {
-  pid_t _pid;
-  return ioctl(fd, TIOCGSID, &_pid) ? (pid_t)-1 : _pid;
-}
-
-static __inline int tcsendbreak(int fd, int __duration) {
-  return ioctl(fd, TCSBRKP, (void *)(uintptr_t)__duration);
-}
-
-static __inline speed_t cfgetospeed(const struct termios *s) {
-  return (speed_t)(s->c_cflag & CBAUD);
-}
-
-static __inline int cfsetospeed(struct termios *s, speed_t speed) {
-  s->c_cflag = (s->c_cflag & ~CBAUD) | (speed & CBAUD);
-  return 0;
-}
-
-static __inline speed_t cfgetispeed(const struct termios *s) {
-  return (speed_t)(s->c_cflag & CBAUD);
-}
-
-static __inline int cfsetispeed(struct termios *s, speed_t speed) {
-  s->c_cflag = (s->c_cflag & ~CBAUD) | (speed & CBAUD);
-  return 0;
-}
-
-static __inline void cfmakeraw(struct termios *s) {
-  s->c_iflag &=
-      ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
-  s->c_oflag &= ~OPOST;
-  s->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
-  s->c_cflag &= ~(CSIZE | PARENB);
-  s->c_cflag |= CS8;
-}
-
-static __inline int cfsetspeed(struct termios* s, speed_t speed) {
-  // TODO: check 'speed' is valid.
-  s->c_cflag = (s->c_cflag & ~CBAUD) | (speed & CBAUD);
-  return 0;
-}
-
-static __inline int tcdrain(int fd) {
-  // A non-zero argument to TCSBRK means "don't send a break".
-  // The drain is a side-effect of the ioctl!
-  return ioctl(fd, TCSBRK, __BIONIC_CAST(static_cast, unsigned long, 1));
-}
-
-__END_DECLS
-
+#define __BIONIC_TERMIOS_INLINE static __inline
+#include <bits/termios_inlines.h>
 #endif
+
 #endif /* _ANDROID_LEGACY_TERMIOS_INLINES_H_ */
diff --git a/libc/include/arpa/ftp.h b/libc/include/arpa/ftp.h
new file mode 100644
index 0000000..081c037
--- /dev/null
+++ b/libc/include/arpa/ftp.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1983, 1989, 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.
+ *
+ *	@(#)ftp.h	8.1 (Berkeley) 6/2/93
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _ARPA_FTP_H_
+#define	_ARPA_FTP_H_
+
+/* Definitions for FTP; see RFC-765. */
+
+/*
+ * Reply codes.
+ */
+#define PRELIM		1	/* positive preliminary */
+#define COMPLETE	2	/* positive completion */
+#define CONTINUE	3	/* positive intermediate */
+#define TRANSIENT	4	/* transient negative completion */
+#define ERROR		5	/* permanent negative completion */
+
+/*
+ * Type codes
+ */
+#define	TYPE_A		1	/* ASCII */
+#define	TYPE_E		2	/* EBCDIC */
+#define	TYPE_I		3	/* image */
+#define	TYPE_L		4	/* local byte size */
+
+#ifdef FTP_NAMES
+char *typenames[] =  {"0", "ASCII", "EBCDIC", "Image", "Local" };
+#endif
+
+/*
+ * Form codes
+ */
+#define	FORM_N		1	/* non-print */
+#define	FORM_T		2	/* telnet format effectors */
+#define	FORM_C		3	/* carriage control (ASA) */
+#ifdef FTP_NAMES
+char *formnames[] =  {"0", "Nonprint", "Telnet", "Carriage-control" };
+#endif
+
+/*
+ * Structure codes
+ */
+#define	STRU_F		1	/* file (no record structure) */
+#define	STRU_R		2	/* record structure */
+#define	STRU_P		3	/* page structure */
+#ifdef FTP_NAMES
+char *strunames[] =  {"0", "File", "Record", "Page" };
+#endif
+
+/*
+ * Mode types
+ */
+#define	MODE_S		1	/* stream */
+#define	MODE_B		2	/* block */
+#define	MODE_C		3	/* compressed */
+#ifdef FTP_NAMES
+char *modenames[] =  {"0", "Stream", "Block", "Compressed" };
+#endif
+
+/*
+ * Record Tokens
+ */
+#define	REC_ESC		'\377'	/* Record-mode Escape */
+#define	REC_EOR		'\001'	/* Record-mode End-of-Record */
+#define REC_EOF		'\002'	/* Record-mode End-of-File */
+
+/*
+ * Block Header
+ */
+#define	BLK_EOR		0x80	/* Block is End-of-Record */
+#define	BLK_EOF		0x40	/* Block is End-of-File */
+#define BLK_ERRORS	0x20	/* Block is suspected of containing errors */
+#define	BLK_RESTART	0x10	/* Block is Restart Marker */
+
+#define	BLK_BYTECOUNT	2	/* Bytes in this block */
+
+#endif /* !_FTP_H_ */
diff --git a/libc/include/arpa/telnet.h b/libc/include/arpa/telnet.h
index 594dc7a..758e9b8 100644
--- a/libc/include/arpa/telnet.h
+++ b/libc/include/arpa/telnet.h
@@ -10,7 +10,7 @@
  * 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -27,12 +27,11 @@
  * SUCH DAMAGE.
  *
  *	@(#)telnet.h	8.2 (Berkeley) 12/15/93
+ * $FreeBSD$
  */
 
-#ifndef _ARPA_TELNET_H
-#define	_ARPA_TELNET_H 1
-
-#include <sys/cdefs.h>
+#ifndef _ARPA_TELNET_H_
+#define	_ARPA_TELNET_H_
 
 /*
  * Definitions for the TELNET protocol.
@@ -61,11 +60,14 @@
 #define SYNCH	242		/* for telfunc calls */
 
 #ifdef TELCMDS
-char *telcmds[] = {
+const char *telcmds[] = {
 	"EOF", "SUSP", "ABORT", "EOR",
 	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
-	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
+	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC",
+	0
 };
+#else
+extern char *telcmds[];
 #endif
 
 #define	TELCMD_FIRST	xEOF
@@ -92,7 +94,7 @@
 #define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
 #define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
 #define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
-#define TELOPT_XASCII	17	/* extended ascii character set */
+#define TELOPT_XASCII	17	/* extended ascic character set */
 #define	TELOPT_LOGOUT	18	/* force logout */
 #define	TELOPT_BM	19	/* byte macro */
 #define	TELOPT_DET	20	/* data entry terminal */
@@ -115,10 +117,14 @@
 #define	TELOPT_AUTHENTICATION 37/* Authenticate */
 #define	TELOPT_ENCRYPT	38	/* Encryption option */
 #define TELOPT_NEW_ENVIRON 39	/* New - Environment variables */
+#define	TELOPT_TN3270E	40	/* RFC2355 - TN3270 Enhancements */
+#define	TELOPT_CHARSET	42	/* RFC2066 - Charset */
+#define	TELOPT_COMPORT	44	/* RFC2217 - Com Port Control */
+#define	TELOPT_KERMIT	47	/* RFC2840 - Kermit */
 #define	TELOPT_EXOPL	255	/* extended-options-list */
 
 
-#define	NTELOPTS	(1+TELOPT_NEW_ENVIRON)
+#define	NTELOPTS	(1+TELOPT_KERMIT)
 #ifdef TELOPTS
 const char *telopts[NTELOPTS+1] = {
 	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
@@ -130,11 +136,12 @@
 	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
 	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
 	"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
-	"ENCRYPT", "NEW-ENVIRON",
-	0,
+	"ENCRYPT", "NEW-ENVIRON", "TN3270E", "XAUTH", "CHARSET",
+	"RSP", "COM-PORT", "SLE", "STARTTLS", "KERMIT",
+	0
 };
 #define	TELOPT_FIRST	TELOPT_BINARY
-#define	TELOPT_LAST	TELOPT_NEW_ENVIRON
+#define	TELOPT_LAST	TELOPT_KERMIT
 #define	TELOPT_OK(x)	((unsigned int)(x) <= TELOPT_LAST)
 #define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
 #endif
@@ -192,20 +199,39 @@
 #define	SLC_XOFF	16
 #define	SLC_FORW1	17
 #define	SLC_FORW2	18
+#define SLC_MCL         19
+#define SLC_MCR         20
+#define SLC_MCWL        21
+#define SLC_MCWR        22
+#define SLC_MCBOL       23
+#define SLC_MCEOL       24
+#define SLC_INSRT       25
+#define SLC_OVER        26
+#define SLC_ECR         27
+#define SLC_EWR         28
+#define SLC_EBOL        29
+#define SLC_EEOL        30
 
-#define	NSLC		18
+#define	NSLC		30
 
 /*
  * For backwards compatibility, we define SLC_NAMES to be the
  * list of names if SLC_NAMES is not defined.
  */
-#define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
-			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
-			"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
+#define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR",	\
+			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP",	\
+			"LNEXT", "XON", "XOFF", "FORW1", "FORW2",	\
+			"MCL", "MCR", "MCWL", "MCWR", "MCBOL",		\
+			"MCEOL", "INSRT", "OVER", "ECR", "EWR",		\
+			"EBOL", "EEOL",					\
+			0
+
 #ifdef	SLC_NAMES
 const char *slc_names[] = {
 	SLC_NAMELIST
 };
+#else
+extern char *slc_names[];
 #define	SLC_NAMES SLC_NAMELIST
 #endif
 
@@ -256,14 +282,18 @@
 #define	AUTHTYPE_KERBEROS_V5	2
 #define	AUTHTYPE_SPX		3
 #define	AUTHTYPE_MINK		4
-#define	AUTHTYPE_CNT		5
+#define	AUTHTYPE_SRA		6
+#define	AUTHTYPE_CNT		7
 
 #define	AUTHTYPE_TEST		99
 
 #ifdef	AUTH_NAMES
 const char *authtype_names[] = {
-	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
+	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", NULL, "SRA",
+	0
 };
+#else
+extern char *authtype_names[];
 #endif
 
 #define	AUTHTYPE_NAME_OK(x)	((unsigned int)(x) < AUTHTYPE_CNT)
@@ -278,7 +308,7 @@
 #define	ENCRYPT_START		3	/* Am starting to send encrypted */
 #define	ENCRYPT_END		4	/* Am ending encrypted */
 #define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
-#define	ENCRYPT_REQEND		6	/* Request you send encrypting */
+#define	ENCRYPT_REQEND		6	/* Request you end encrypting */
 #define	ENCRYPT_ENC_KEYID	7
 #define	ENCRYPT_DEC_KEYID	8
 #define	ENCRYPT_CNT		9
@@ -292,11 +322,15 @@
 const char *encrypt_names[] = {
 	"IS", "SUPPORT", "REPLY", "START", "END",
 	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
-	0,
+	0
 };
 const char *enctype_names[] = {
-	"ANY", "DES_CFB64",  "DES_OFB64",  0,
+	"ANY", "DES_CFB64",  "DES_OFB64",
+	0
 };
+#else
+extern char *encrypt_names[];
+extern char *enctype_names[];
 #endif
 
 
@@ -306,4 +340,4 @@
 #define	ENCTYPE_NAME_OK(x)	((unsigned int)(x) < ENCTYPE_CNT)
 #define	ENCTYPE_NAME(x)		enctype_names[x]
 
-#endif /* arpa/telnet.h */
+#endif /* !_TELNET_H_ */
diff --git a/libc/include/arpa/tftp.h b/libc/include/arpa/tftp.h
new file mode 100644
index 0000000..20733ec
--- /dev/null
+++ b/libc/include/arpa/tftp.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1983, 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.
+ *
+ *	@(#)tftp.h	8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+#ifndef _ARPA_TFTP_H_
+#define	_ARPA_TFTP_H_
+
+#include <sys/cdefs.h>
+
+/*
+ * Trivial File Transfer Protocol (IEN-133)
+ */
+#define	SEGSIZE		512		/* data segment size */
+
+/*
+ * Packet types.
+ */
+#define	RRQ	01			/* read request */
+#define	WRQ	02			/* write request */
+#define	DATA	03			/* data packet */
+#define	ACK	04			/* acknowledgement */
+#define	ERROR	05			/* error code */
+#define	OACK	06			/* option acknowledgement */
+
+struct tftphdr {
+	unsigned short	th_opcode;		/* packet type */
+	union {
+		unsigned short	tu_block;	/* block # */
+		unsigned short	tu_code;	/* error code */
+		char	tu_stuff[1];	/* request packet stuff */
+	} __packed th_u;
+	char	th_data[1];		/* data or error string */
+} __packed;
+
+#define	th_block	th_u.tu_block
+#define	th_code		th_u.tu_code
+#define	th_stuff	th_u.tu_stuff
+#define	th_msg		th_data
+
+/*
+ * Error codes.
+ */
+#define	EUNDEF		0		/* not defined */
+#define	ENOTFOUND	1		/* file not found */
+#define	EACCESS		2		/* access violation */
+#define	ENOSPACE	3		/* disk full or allocation exceeded */
+#define	EBADOP		4		/* illegal TFTP operation */
+#define	EBADID		5		/* unknown transfer ID */
+#define	EEXISTS		6		/* file already exists */
+#define	ENOUSER		7		/* no such user */
+#define	EOPTNEG		8		/* option negotiation failed */
+
+#endif /* !_TFTP_H_ */
diff --git a/libc/include/bits/lockf.h b/libc/include/bits/lockf.h
index 655514d..c24f18b 100644
--- a/libc/include/bits/lockf.h
+++ b/libc/include/bits/lockf.h
@@ -40,7 +40,7 @@
 __BEGIN_DECLS
 
 #if defined(__USE_FILE_OFFSET64)
-int lockf(int, int, off_t) __RENAME(lockf64);
+int lockf(int, int, off_t) __RENAME(lockf64) __INTRODUCED_IN(24);
 #else
 int lockf(int, int, off_t) __INTRODUCED_IN(24);
 #endif
diff --git a/libc/include/bits/termios_inlines.h b/libc/include/bits/termios_inlines.h
new file mode 100644
index 0000000..d49167e
--- /dev/null
+++ b/libc/include/bits/termios_inlines.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BITS_TERMIOS_INLINES_H_
+#define _BITS_TERMIOS_INLINES_H_
+
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/termios.h>
+
+#if !defined(__BIONIC_TERMIOS_INLINE)
+#define __BIONIC_TERMIOS_INLINE static __inline
+#endif
+
+__BEGIN_DECLS
+
+static __inline speed_t cfgetspeed(const struct termios* s) {
+  return __BIONIC_CAST(static_cast, speed_t, s->c_cflag & CBAUD);
+}
+
+__BIONIC_TERMIOS_INLINE speed_t cfgetispeed(const struct termios* s) {
+  return cfgetspeed(s);
+}
+
+__BIONIC_TERMIOS_INLINE speed_t cfgetospeed(const struct termios* s) {
+  return cfgetspeed(s);
+}
+
+__BIONIC_TERMIOS_INLINE void cfmakeraw(struct termios* s) {
+  s->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+  s->c_oflag &= ~OPOST;
+  s->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+  s->c_cflag &= ~(CSIZE|PARENB);
+  s->c_cflag |= CS8;
+}
+
+__BIONIC_TERMIOS_INLINE int cfsetspeed(struct termios* s, speed_t speed) {
+  // TODO: check 'speed' is valid.
+  s->c_cflag = (s->c_cflag & ~CBAUD) | (speed & CBAUD);
+  return 0;
+}
+
+__BIONIC_TERMIOS_INLINE int cfsetispeed(struct termios* s, speed_t speed) {
+  return cfsetspeed(s, speed);
+}
+
+__BIONIC_TERMIOS_INLINE int cfsetospeed(struct termios* s, speed_t speed) {
+  return cfsetspeed(s, speed);
+}
+
+__BIONIC_TERMIOS_INLINE int tcdrain(int fd) {
+  // A non-zero argument to TCSBRK means "don't send a break".
+  // The drain is a side-effect of the ioctl!
+  return ioctl(fd, TCSBRK, __BIONIC_CAST(static_cast, unsigned long, 1));
+}
+
+__BIONIC_TERMIOS_INLINE int tcflow(int fd, int action) {
+  return ioctl(fd, TCXONC, __BIONIC_CAST(static_cast, unsigned long, action));
+}
+
+__BIONIC_TERMIOS_INLINE int tcflush(int fd, int queue) {
+  return ioctl(fd, TCFLSH, __BIONIC_CAST(static_cast, unsigned long, queue));
+}
+
+__BIONIC_TERMIOS_INLINE int tcgetattr(int fd, struct termios* s) {
+  return ioctl(fd, TCGETS, s);
+}
+
+__BIONIC_TERMIOS_INLINE pid_t tcgetsid(int fd) {
+  pid_t sid;
+  return (ioctl(fd, TIOCGSID, &sid) == -1) ? -1 : sid;
+}
+
+__BIONIC_TERMIOS_INLINE int tcsendbreak(int fd, int duration) {
+  return ioctl(fd, TCSBRKP, __BIONIC_CAST(static_cast, unsigned long, duration));
+}
+
+__BIONIC_TERMIOS_INLINE int tcsetattr(int fd, int optional_actions, const struct termios* s) {
+  int cmd;
+  switch (optional_actions) {
+    case TCSANOW: cmd = TCSETS; break;
+    case TCSADRAIN: cmd = TCSETSW; break;
+    case TCSAFLUSH: cmd = TCSETSF; break;
+    default: errno = EINVAL; return -1;
+  }
+  return ioctl(fd, cmd, s);
+}
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/dirent.h b/libc/include/dirent.h
index 3f9ad18..ebcf085 100644
--- a/libc/include/dirent.h
+++ b/libc/include/dirent.h
@@ -31,6 +31,7 @@
 
 #include <stdint.h>
 #include <sys/cdefs.h>
+#include <sys/types.h>
 
 __BEGIN_DECLS
 
@@ -46,17 +47,24 @@
 #define DT_WHT 14
 #endif
 
+#if defined(__LP64__)
+#define __DIRENT64_INO_T ino_t
+#else
+#define __DIRENT64_INO_T uint64_t /* Historical accident. */
+#endif
+
 #define __DIRENT64_BODY \
-    uint64_t         d_ino; \
-    int64_t          d_off; \
-    unsigned short   d_reclen; \
-    unsigned char    d_type; \
-    char             d_name[256]; \
+    __DIRENT64_INO_T d_ino; \
+    off64_t d_off; \
+    unsigned short d_reclen; \
+    unsigned char d_type; \
+    char d_name[256]; \
 
 struct dirent { __DIRENT64_BODY };
 struct dirent64 { __DIRENT64_BODY };
 
 #undef __DIRENT64_BODY
+#undef __DIRENT64_INO_T
 
 /* glibc compatibility. */
 #undef _DIRENT_HAVE_D_NAMLEN /* Linux doesn't have a d_namlen field. */
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/fcntl.h b/libc/include/fcntl.h
index 652430c..c98022c 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -56,14 +56,18 @@
 #define O_ASYNC FASYNC
 #define O_RSYNC O_SYNC
 
+#if __ANDROID_API__ >= __ANDROID_API_L__
 #define SPLICE_F_MOVE 1
 #define SPLICE_F_NONBLOCK 2
 #define SPLICE_F_MORE 4
 #define SPLICE_F_GIFT 8
+#endif
 
+#if __ANDROID_API__ >= __ANDROID_API_O__
 #define SYNC_FILE_RANGE_WAIT_BEFORE 1
 #define SYNC_FILE_RANGE_WRITE 2
 #define SYNC_FILE_RANGE_WAIT_AFTER 4
+#endif
 
 int creat(const char*, mode_t);
 int creat64(const char*, mode_t) __INTRODUCED_IN(21);
diff --git a/libc/include/limits.h b/libc/include/limits.h
index a25eb65..157f7a6 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -138,9 +138,9 @@
 
 #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
 
-#define  _POSIX_VERSION             200809L   /* Posix C language bindings version */
-#define  _POSIX2_VERSION            -1        /* we don't support Posix command-line tools */
-#define  _XOPEN_VERSION             700       /* by Posix definition */
+#define _POSIX_VERSION 200809L
+#define _POSIX2_VERSION _POSIX_VERSION
+#define _XOPEN_VERSION 700       /* by Posix definition */
 
 /* >= _POSIX_THREAD_DESTRUCTOR_ITERATIONS */
 #define PTHREAD_DESTRUCTOR_ITERATIONS 4
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index c34d1a3..7dec3cc 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -160,6 +160,26 @@
 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 the proper POSIX
+ * APIs for things, but instead had some locally grown, artisan equivalents.
+ * Keep exposing the old prototypes on old API levels so we don't regress
+ * functionality.
+ *
+ * See the following bugs:
+ *  * https://github.com/android-ndk/ndk/issues/420
+ *  * https://github.com/android-ndk/ndk/issues/423
+ *  * https://stackoverflow.com/q/44580542/632035
+ */
+
+int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex, unsigned msecs);
+int pthread_cond_timeout_np(pthread_cond_t* cond, pthread_mutex_t* mutex, unsigned msecs);
+int pthread_cond_timedwait_monotonic_np(pthread_cond_t*, pthread_mutex_t*, const struct timespec*);
+int pthread_cond_timedwait_relative_np(pthread_cond_t* cond, pthread_mutex_t* mutex,
+                                       const struct timespec* reltime);
+#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/stdio.h b/libc/include/stdio.h
index 24916d6..ca56437 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -176,17 +176,17 @@
 int fseek(FILE*, long, int);
 long ftell(FILE*);
 
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= __ANDROID_API_N__
-int fgetpos(FILE*, fpos_t*) __RENAME(fgetpos64);
-int fsetpos(FILE*, const fpos_t*) __RENAME(fsetpos64);
-int fseeko(FILE*, off_t, int) __RENAME(fseeko64);
-off_t ftello(FILE*) __RENAME(ftello64);
+#if defined(__USE_FILE_OFFSET64)
+int fgetpos(FILE*, fpos_t*) __RENAME(fgetpos64) __INTRODUCED_IN(24);
+int fsetpos(FILE*, const fpos_t*) __RENAME(fsetpos64) __INTRODUCED_IN(24);
+int fseeko(FILE*, off_t, int) __RENAME(fseeko64) __INTRODUCED_IN(24);
+off_t ftello(FILE*) __RENAME(ftello64) __INTRODUCED_IN(24);
 #  if defined(__USE_BSD)
 FILE* funopen(const void*,
               int (*)(void*, char*, int),
               int (*)(void*, const char*, int),
               fpos_t (*)(void*, fpos_t, int),
-              int (*)(void*)) __RENAME(funopen64);
+              int (*)(void*)) __RENAME(funopen64) __INTRODUCED_IN(24);
 #  endif
 #else
 int fgetpos(FILE*, fpos_t*);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 3cd8ad1..24ddd99 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -225,12 +225,12 @@
 // Implemented as static inlines before 21.
 #endif
 
-#if __ANDROID_API__ >= __ANDROID_API_FUTURE__
+#if __ANDROID_API__ >= __ANDROID_API_O__
 double strtod_l(const char*, char**, locale_t) __INTRODUCED_IN(26);
 float strtof_l(const char*, char**, locale_t) __INTRODUCED_IN(26);
 long strtol_l(const char*, char**, int, locale_t) __INTRODUCED_IN(26);
 #else
-// Implemented as static inlines.
+// Implemented as static inlines before 26.
 #endif
 
 __END_DECLS
diff --git a/libc/include/string.h b/libc/include/string.h
index c178a3c..c15fe4a 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -67,8 +67,8 @@
 char* __strchr_chk(const char* _Nonnull, int, size_t) __INTRODUCED_IN(18);
 #if defined(__USE_GNU)
 #if defined(__cplusplus)
-extern "C++" char* strchrnul(char* _Nonnull, int) __RENAME(strchrnul) __attribute_pure__;
-extern "C++" const char* strchrnul(const char* _Nonnull, int) __RENAME(strchrnul) __attribute_pure__;
+extern "C++" char* strchrnul(char* _Nonnull, int) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
+extern "C++" const char* strchrnul(const char* _Nonnull, int) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
 #else
 char* strchrnul(const char* _Nonnull, int) __attribute_pure__ __INTRODUCED_IN(24);
 #endif
@@ -142,8 +142,8 @@
  * It doesn't modify its argument, and in C++ it's const-correct.
  */
 #if defined(__cplusplus)
-extern "C++" char* basename(char* _Nonnull) __RENAME(__gnu_basename);
-extern "C++" const char* basename(const char* _Nonnull) __RENAME(__gnu_basename);
+extern "C++" char* basename(char* _Nonnull) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
+extern "C++" const char* basename(const char* _Nonnull) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
 #else
 char* basename(const char* _Nonnull) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
 #endif
diff --git a/libc/include/strings.h b/libc/include/strings.h
index 021e2b4..11f3213 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -54,8 +54,12 @@
 #define bzero(b, len) (void)(__builtin_memset((b), '\0', (len)))
 #endif
 
+#if !defined(__i386__) || __ANDROID_API__ >= __ANDROID_API_J_MR2__
 int ffs(int) __INTRODUCED_IN_X86(18);
+#endif
 
 __END_DECLS
 
+#include <android/legacy_strings_inlines.h>
+
 #endif /* !defined(_STRINGS_H_) */
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 004c6b5..307545c 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -235,10 +235,11 @@
 #endif
 
 /* _FILE_OFFSET_BITS 64 support. */
-#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
-#if _FILE_OFFSET_BITS == 64
+#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
 #define __USE_FILE_OFFSET64 1
-#endif
+#define __RENAME_IF_FILE_OFFSET64(func) __RENAME(func)
+#else
+#define __RENAME_IF_FILE_OFFSET64(func)
 #endif
 
 #define  __BIONIC__   1
@@ -303,13 +304,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/mman.h b/libc/include/sys/mman.h
index 9a2ec35..1440dc6 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -43,7 +43,7 @@
 #define MREMAP_MAYMOVE  1
 #define MREMAP_FIXED    2
 
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= __ANDROID_API_L__
+#if defined(__USE_FILE_OFFSET64)
 void* mmap(void*, size_t, int, int, int, off_t) __RENAME(mmap64) __INTRODUCED_IN(21);
 #else
 void* mmap(void*, size_t, int, int, int, off_t);
@@ -71,7 +71,7 @@
  * Some third-party code uses the existence of POSIX_MADV_NORMAL to detect the
  * availability of posix_madvise. This is not correct, since having up-to-date
  * UAPI headers says nothing about the C library, but for the time being we
- * don't want to harm adoption to the unified headers.
+ * don't want to harm adoption of the unified headers.
  *
  * https://github.com/android-ndk/ndk/issues/395
  */
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/procfs.h b/libc/include/sys/procfs.h
index 7ef5023..eff39e2 100644
--- a/libc/include/sys/procfs.h
+++ b/libc/include/sys/procfs.h
@@ -49,6 +49,14 @@
 typedef pid_t lwpid_t;
 typedef void* psaddr_t;
 
+struct elf_siginfo {
+  int si_signo;
+  int si_code;
+  int si_errno;
+};
+
+#define ELF_PRARGSZ 80
+
 __END_DECLS
 
 #endif /* _SYS_PROCFS_H_ */
diff --git a/libc/include/sys/sendfile.h b/libc/include/sys/sendfile.h
index dccdec5..43b334c 100644
--- a/libc/include/sys/sendfile.h
+++ b/libc/include/sys/sendfile.h
@@ -34,9 +34,8 @@
 
 __BEGIN_DECLS
 
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= __ANDROID_API_L__
-ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) __RENAME(sendfile64)
-  __INTRODUCED_IN(21);
+#if defined(__USE_FILE_OFFSET64)
+ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) __RENAME(sendfile64) __INTRODUCED_IN(21);
 #else
 ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
 #endif
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/ttydefaults.h b/libc/include/sys/ttydefaults.h
index 62af84b..4dcc649 100644
--- a/libc/include/sys/ttydefaults.h
+++ b/libc/include/sys/ttydefaults.h
@@ -48,7 +48,7 @@
  * Defaults on "first" open.
  */
 #define	TTYDEF_IFLAG	(BRKINT | ICRNL | IMAXBEL | IXON | IXANY)
-#define TTYDEF_OFLAG	(OPOST | ONLCR | OXTABS)
+#define TTYDEF_OFLAG	(OPOST | ONLCR | XTABS)
 #define TTYDEF_LFLAG	(ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
 #define TTYDEF_CFLAG	(CREAD | CS8 | HUPCL)
 #define TTYDEF_SPEED	(B9600)
@@ -58,7 +58,7 @@
  */
 #define CTRL(x)	(x&037)
 #define	CEOF		CTRL('d')
-#define	CEOL		((unsigned char)'\377')	/* XXX avoid _POSIX_VDISABLE */
+#define	CEOL		'\0'	/* XXX avoid _POSIX_VDISABLE */
 #define	CERASE		0177
 #define	CINTR		CTRL('c')
 #define	CSTATUS		CTRL('t')
@@ -80,34 +80,4 @@
 #define CRPRNT		CREPRINT
 #define	CFLUSH		CDISCARD
 
-/* PROTECTED INCLUSION ENDS HERE */
 #endif /* !_SYS_TTYDEFAULTS_H_ */
-
-/*
- * #define TTYDEFCHARS to include an array of default control characters.
- */
-#ifdef TTYDEFCHARS
-const cc_t ttydefchars[NCCS] = {
-	[VEOF] = CEOF,
-	[VEOL] = CEOL,
-	[VEOL2] = CEOL,
-	[VERASE] = CERASE,
-	[VWERASE] = CWERASE,
-	[VKILL] = CKILL,
-	[VREPRINT] = CREPRINT,
-	[7] = _POSIX_VDISABLE,	/* spare */
-	[VINTR] = CINTR,
-	[VQUIT] = CQUIT,
-	[VSUSP] = CSUSP,
-	[VDSUSP] = CDSUSP,
-	[VSTART] = CSTART,
-	[VSTOP] = CSTOP,
-	[VLNEXT] = CLNEXT,
-	[VDISCARD] = CDISCARD,
-	[VMIN] = CMIN,
-	[VTIME] = CTIME,
-	[VSTATUS] = CSTATUS,
-	[19] = _POSIX_VDISABLE,	/* spare */
-};
-#undef TTYDEFCHARS
-#endif
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/sys/uio.h b/libc/include/sys/uio.h
index 0e56d7d..2611774 100644
--- a/libc/include/sys/uio.h
+++ b/libc/include/sys/uio.h
@@ -39,8 +39,8 @@
 
 #if defined(__USE_GNU)
 #if defined(__USE_FILE_OFFSET64)
-ssize_t preadv(int, const struct iovec*, int, off_t) __RENAME(preadv64);
-ssize_t pwritev(int, const struct iovec*, int, off_t) __RENAME(pwritev64);
+ssize_t preadv(int, const struct iovec*, int, off_t) __RENAME(preadv64) __INTRODUCED_IN(24);
+ssize_t pwritev(int, const struct iovec*, int, off_t) __RENAME(pwritev64) __INTRODUCED_IN(24);
 #else
 ssize_t preadv(int, const struct iovec*, int, off_t) __INTRODUCED_IN(24);
 ssize_t pwritev(int, const struct iovec*, int, off_t) __INTRODUCED_IN(24);
diff --git a/libc/include/sys/user.h b/libc/include/sys/user.h
index f9ad956..ed3e10a 100644
--- a/libc/include/sys/user.h
+++ b/libc/include/sys/user.h
@@ -102,6 +102,10 @@
   int u_debugreg[8];
 };
 
+#define UPAGES 1
+#define HOST_TEXT_START_ADDR (u.start_code)
+#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * PAGE_SIZE)
+
 #elif defined(__x86_64__)
 
 struct user_fpregs_struct {
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index ff2e9f6..e024527 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -173,7 +173,7 @@
 
 off64_t lseek64(int __fd, off64_t __offset, int __whence);
 
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= __ANDROID_API_L__
+#if defined(__USE_FILE_OFFSET64)
 int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
 ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset)
   __overloadable __RENAME(pread64) __INTRODUCED_IN(12);
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/private/bionic_mbstate.h b/libc/private/bionic_mbstate.h
index 018b47c..292959a 100644
--- a/libc/private/bionic_mbstate.h
+++ b/libc/private/bionic_mbstate.h
@@ -43,11 +43,31 @@
 #define __MB_IS_ERR(rv) (rv == __MB_ERR_ILLEGAL_SEQUENCE || \
                          rv == __MB_ERR_INCOMPLETE_SEQUENCE)
 
-size_t mbstate_bytes_so_far(const mbstate_t* ps);
-void mbstate_set_byte(mbstate_t* ps, int i, char byte);
-uint8_t mbstate_get_byte(const mbstate_t* ps, int n);
-size_t reset_and_return_illegal(int _errno, mbstate_t* ps);
-size_t reset_and_return(int _return, mbstate_t* ps);
+static inline __wur size_t mbstate_bytes_so_far(const mbstate_t* ps) {
+  return
+      (ps->__seq[2] != 0) ? 3 :
+      (ps->__seq[1] != 0) ? 2 :
+      (ps->__seq[0] != 0) ? 1 : 0;
+}
+
+static inline void mbstate_set_byte(mbstate_t* ps, int i, char byte) {
+  ps->__seq[i] = static_cast<uint8_t>(byte);
+}
+
+static inline __wur uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
+  return ps->__seq[n];
+}
+
+static inline __wur size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
+  errno = _errno;
+  *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
+  return __MB_ERR_ILLEGAL_SEQUENCE;
+}
+
+static inline __wur size_t mbstate_reset_and_return(int _return, mbstate_t* ps) {
+  *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
+  return _return;
+}
 
 __END_DECLS
 
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate-NOTICE.py
index 6573644..d40891c 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate-NOTICE.py
@@ -14,17 +14,33 @@
 import tarfile
 import tempfile
 
-def IsUninteresting(path):
-    path = path.lower()
-    if path.endswith(".mk") or path.endswith(".py") or path.endswith(".pyc") or path.endswith(".txt") or path.endswith(".3") or path.endswith(".swp"):
-        return True
-    if path.endswith("/notice") or path.endswith("/readme") or path.endswith("/caveats"):
-        return True
-    if path.endswith("/tzdata") or path.endswith("/zoneinfo/generate"):
-        return True
-    return False
+VERBOSE = False
 
-def IsAutoGenerated(content):
+def warn(s):
+    sys.stderr.write("warning: %s\n" % s)
+
+def warn_verbose(s):
+    if VERBOSE:
+        warn(s)
+
+def is_interesting(path):
+    path = path.lower()
+    uninteresting_extensions = [
+        ".bp",
+        ".map",
+        ".mk",
+        ".py",
+        ".pyc",
+        ".swp",
+        ".txt",
+    ]
+    if os.path.splitext(path)[1] in uninteresting_extensions:
+        return False
+    if path.endswith("/notice") or path.endswith("/readme"):
+        return False
+    return True
+
+def is_auto_generated(content):
     if "Generated by gensyscalls.py" in content or "generated by genserv.py" in content:
         return True
     if "This header was automatically generated from a Linux kernel header" in content:
@@ -33,7 +49,7 @@
 
 copyrights = set()
 
-def ExtractCopyrightAt(lines, i):
+def extract_copyright_at(lines, i):
     hash = lines[i].startswith("#")
 
     # Do we need to back up to find the start of the copyright header?
@@ -100,13 +116,42 @@
 
     return i
 
-args = sys.argv[1:]
-if len(args) == 0:
-    args = [ "." ]
 
-for arg in args:
-    sys.stderr.write('Searching for source files in "%s"...\n' % arg)
+def do_file(path):
+    with open(path, "r") as the_file:
+        try:
+            content = open(path, "r").read().decode("utf-8")
+        except UnicodeDecodeError:
+            warn("bad UTF-8 in %s" % path)
+            content = open(path, "r").read().decode("iso-8859-1")
 
+    lines = content.split("\n")
+
+    if len(lines) <= 4:
+        warn_verbose("ignoring short file %s" % path)
+        return
+
+    if is_auto_generated(content):
+        warn_verbose("ignoring auto-generated file %s" % path)
+        return
+
+    if not "Copyright" in content:
+        if "public domain" in content.lower():
+            warn("ignoring public domain file %s" % path)
+            return
+        warn('no copyright notice found in "%s" (%d lines)' % (path, len(lines)))
+        return
+
+    # Manually iterate because extract_copyright_at tells us how many lines to skip.
+    i = 0
+    while i < len(lines):
+        if "Copyright" in lines[i] and not "@(#) Copyright" in lines[i]:
+            i = extract_copyright_at(lines, i)
+        else:
+            i += 1
+
+
+def do_dir(path):
     for directory, sub_directories, filenames in os.walk(arg):
         if ".git" in sub_directories:
             sub_directories.remove(".git")
@@ -114,45 +159,24 @@
 
         for filename in sorted(filenames):
             path = os.path.join(directory, filename)
-            if IsUninteresting(path):
-                #print "ignoring uninteresting file %s" % path
-                continue
+            if is_interesting(path):
+                do_file(path)
 
-            try:
-                content = open(path, 'r').read().decode('utf-8')
-            except:
-                sys.stderr.write('warning: bad UTF-8 in %s\n' % path)
-                content = open(path, 'r').read().decode('iso-8859-1')
 
-            lines = content.split("\n")
+args = sys.argv[1:]
+if len(args) == 0:
+    args = [ "." ]
 
-            if len(lines) <= 4:
-                #print "ignoring short file %s" % path
-                continue
-
-            if IsAutoGenerated(content):
-                #print "ignoring auto-generated file %s" % path
-                continue
-
-            if not "Copyright" in content:
-                if "public domain" in content.lower():
-                    #print "ignoring public domain file %s" % path
-                    continue
-                sys.stderr.write('warning: no copyright notice found in "%s" (%d lines)\n' % (path, len(lines)))
-                continue
-
-            i = 0
-            while i < len(lines):
-                if "Copyright" in lines[i] and not "@(#) Copyright" in lines[i]:
-                    i = ExtractCopyrightAt(lines, i)
-                i += 1
-
-            #print path
+for arg in args:
+    if os.path.isdir(arg):
+        do_dir(arg)
+    else:
+        do_file(arg)
 
 for copyright in sorted(copyrights):
-    print copyright.encode('utf-8')
+    print copyright.encode("utf-8")
     print
-    print '-------------------------------------------------------------------'
+    print "-------------------------------------------------------------------"
     print
 
 sys.exit(0)
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/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index bec860b..9b16da7 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -22,6 +22,11 @@
 #include <sys/cdefs.h>
 #include <stddef.h> // For size_t.
 
+#define __BEGIN_HIDDEN_DECLS _Pragma("GCC visibility push(hidden)")
+#define __END_HIDDEN_DECLS _Pragma("GCC visibility pop")
+
+extern const char* __progname;
+
 /* Redirect internal C library calls to the public function. */
 #define _err err
 #define _errx errx
diff --git a/libc/upstream-openbsd/lib/libc/crypt/arc4random.c b/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
index 64248b6..8a4ecc9 100644
--- a/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
+++ b/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
@@ -1,9 +1,10 @@
-/*	$OpenBSD: arc4random.c,v 1.50 2014/07/21 18:13:12 deraadt Exp $	*/
+/*	$OpenBSD: arc4random.c,v 1.54 2015/09/13 08:31:47 guenther Exp $	*/
 
 /*
  * Copyright (c) 1996, David Mazieres <dm@uun.org>
  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
  * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+ * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -30,18 +31,18 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
-#include <sys/param.h>
 #include <sys/time.h>
 
 #define KEYSTREAM_ONLY
 #include "chacha_private.h"
 
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#ifdef __GNUC__
+#define minimum(a, b) ((a) < (b) ? (a) : (b))
+
+#if defined(__GNUC__) || defined(_MSC_VER)
 #define inline __inline
-#else				/* !__GNUC__ */
+#else				/* __GNUC__ || _MSC_VER */
 #define inline
-#endif				/* !__GNUC__ */
+#endif				/* !__GNUC__ && !_MSC_VER */
 
 #define KEYSZ	32
 #define IVSZ	8
@@ -127,7 +128,7 @@
 	if (dat) {
 		size_t i, m;
 
-		m = min(datlen, KEYSZ + IVSZ);
+		m = minimum(datlen, KEYSZ + IVSZ);
 		for (i = 0; i < m; i++)
 			rsx->rs_buf[i] ^= dat[i];
 	}
@@ -147,7 +148,7 @@
 	_rs_stir_if_needed(n);
 	while (n > 0) {
 		if (rs->rs_have > 0) {
-			m = min(n, rs->rs_have);
+			m = minimum(n, rs->rs_have);
 			keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
 			    - rs->rs_have;
 			memcpy(buf, keystream, m);
@@ -185,6 +186,7 @@
 	_ARC4_UNLOCK();
 	return val;
 }
+DEF_WEAK(arc4random);
 
 void
 arc4random_buf(void *buf, size_t n)
@@ -193,3 +195,4 @@
 	_rs_random_buf(buf, n);
 	_ARC4_UNLOCK();
 }
+DEF_WEAK(arc4random_buf);
diff --git a/libc/upstream-openbsd/lib/libc/crypt/arc4random_uniform.c b/libc/upstream-openbsd/lib/libc/crypt/arc4random_uniform.c
index 1aa9a62..23a15e3 100644
--- a/libc/upstream-openbsd/lib/libc/crypt/arc4random_uniform.c
+++ b/libc/upstream-openbsd/lib/libc/crypt/arc4random_uniform.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $	*/
+/*	$OpenBSD: arc4random_uniform.c,v 1.2 2015/09/13 08:31:47 guenther Exp $	*/
 
 /*
  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
@@ -54,3 +54,4 @@
 
 	return r % upper_bound;
 }
+DEF_WEAK(arc4random_uniform);
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/dmisc.c b/libc/upstream-openbsd/lib/libc/gdtoa/dmisc.c
index a5795cf..f3d8ea7 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/dmisc.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/dmisc.c
@@ -104,6 +104,7 @@
 		dtoa_result = 0;
 #endif
 	}
+DEF_STRONG(freedtoa);
 
  int
 quorem
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/dtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/dtoa.c
index 668f7b5..c1c8724 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/dtoa.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/dtoa.c
@@ -837,3 +837,4 @@
 		*rve = s;
 	return s0;
 	}
+DEF_STRONG(dtoa);
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.c
index fd11de5..feae5af 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.c
@@ -827,3 +827,4 @@
 	*kindp |= inex;
 	return s0;
 	}
+DEF_STRONG(gdtoa);
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
index 7a36967..0f3de12 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
@@ -590,7 +590,7 @@
 			int *decpt, int *sign, char **rve));
  extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
  extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
- extern void hexdig_init_D2A(Void);
+ extern void __hexdig_init_D2A(Void);
  extern int hexnan ANSI((CONST char**, FPI*, ULong*));
  extern int hi0bits_D2A ANSI((ULong));
  extern Bigint *i2b ANSI((int));
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c b/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
index 7ace0fa..f521f15 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
@@ -67,7 +67,7 @@
 #endif
 
 	if (!hexdig['0'])
-		hexdig_init_D2A();
+		__hexdig_init_D2A();
 	*bp = 0;
 	havedig = 0;
 	s0 = *(CONST unsigned char **)sp + 2;
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/hd_init.c b/libc/upstream-openbsd/lib/libc/gdtoa/hd_init.c
index fa6e18d..2227640 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/hd_init.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/hd_init.c
@@ -46,7 +46,7 @@
 	}
 
  void
-hexdig_init_D2A(Void)
+__hexdig_init_D2A(Void)
 {
 #define USC (unsigned char *)
 	htinit(hexdig, USC "0123456789", 0x10);
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
index c62f6d5..45caef4 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: hdtoa.c,v 1.2 2009/10/16 12:15:03 martynas Exp $	*/
+/*	$OpenBSD: hdtoa.c,v 1.3 2015/09/14 12:49:33 guenther Exp $	*/
 /*-
  * Copyright (c) 2004, 2005 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
@@ -210,6 +210,7 @@
 
 	return (s0);
 }
+DEF_STRONG(__hdtoa);
 
 #if (LDBL_MANT_DIG > DBL_MANT_DIG)
 
@@ -319,6 +320,7 @@
 
 	return (s0);
 }
+DEF_STRONG(__hldtoa);
 
 #else	/* (LDBL_MANT_DIG == DBL_MANT_DIG) */
 
@@ -328,5 +330,6 @@
 {
 	return (__hdtoa((double)e, xdigs, ndigits, decpt, sign, rve));
 }
+DEF_STRONG(__hldtoa);
 
 #endif	/* (LDBL_MANT_DIG == DBL_MANT_DIG) */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/hexnan.c b/libc/upstream-openbsd/lib/libc/gdtoa/hexnan.c
index a443721..b47d499 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/hexnan.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/hexnan.c
@@ -62,7 +62,7 @@
 	int havedig, hd0, i, nbits;
 
 	if (!hexdig['0'])
-		hexdig_init_D2A();
+		__hexdig_init_D2A();
 	nbits = fpi->nbits;
 	x = x0 + (nbits >> kshift);
 	if (nbits & kmask)
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
index 16f6f9c..7282e7a 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ldtoa.c,v 1.2 2014/08/10 02:15:18 guenther Exp $	*/
+/*	$OpenBSD: ldtoa.c,v 1.4 2016/03/09 16:28:47 deraadt Exp $	*/
 /*-
  * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
@@ -26,9 +26,7 @@
  */
 
 #include <sys/types.h>
-#ifndef __vax__
 #include <machine/ieee.h>
-#endif /* !__vax__ */
 #include <float.h>
 #include <stdint.h>
 #include <limits.h>
@@ -106,6 +104,7 @@
 		*decpt = INT_MAX;
 	return ret;
 }
+DEF_STRONG(__ldtoa);
 
 #else   /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
 
@@ -120,5 +119,6 @@
 		*decpt = INT_MAX;
 	return ret;
 }
+DEF_STRONG(__ldtoa);
 
 #endif  /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
index 6ad706b..b149f07 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
@@ -98,9 +98,9 @@
 	if (v) {
 		if (v->k > Kmax)
 #ifdef FREE
-			FREE((void*)v);
+			FREE(v);
 #else
-			free((void*)v);
+			free(v);
 #endif
 		else {
 			ACQUIRE_DTOA_LOCK(0);
@@ -876,6 +876,8 @@
 #endif
 		};
 
+#ifdef NO_STRING_H
+
  char *
 #ifdef KR_headers
 strcp_D2A(a, b) char *a; char *b;
@@ -888,8 +890,6 @@
 	return a;
 	}
 
-#ifdef NO_STRING_H
-
  Char *
 #ifdef KR_headers
 memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
index ded47d8..ac2283c 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
@@ -1102,4 +1102,4 @@
 		*se = (char *)s;
 	return sign ? -dval(&rv) : dval(&rv);
 	}
-
+DEF_STRONG(strtod);
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtof.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtof.c
index 224491b..914e218 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/strtof.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtof.c
@@ -79,3 +79,4 @@
 		u.L[0] |= 0x80000000L;
 	return u.f;
 	}
+DEF_STRONG(strtof);
diff --git a/libc/upstream-openbsd/lib/libc/gen/alarm.c b/libc/upstream-openbsd/lib/libc/gen/alarm.c
index 2af847a..8bca23a 100644
--- a/libc/upstream-openbsd/lib/libc/gen/alarm.c
+++ b/libc/upstream-openbsd/lib/libc/gen/alarm.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: alarm.c,v 1.7 2005/08/08 08:05:33 espie Exp $ */
+/*	$OpenBSD: alarm.c,v 1.8 2016/01/28 16:40:54 schwarze Exp $ */
 /*
  * Copyright (c) 1983, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -28,9 +28,6 @@
  * SUCH DAMAGE.
  */
 
-/*
- * Backwards compatible alarm.
- */
 #include <sys/time.h>
 #include <unistd.h>
 
diff --git a/libc/upstream-openbsd/lib/libc/gen/ctype_.c b/libc/upstream-openbsd/lib/libc/gen/ctype_.c
index 89c8257..8972244 100644
--- a/libc/upstream-openbsd/lib/libc/gen/ctype_.c
+++ b/libc/upstream-openbsd/lib/libc/gen/ctype_.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ctype_.c,v 1.10 2011/09/22 09:06:10 stsp Exp $ */
+/*	$OpenBSD: ctype_.c,v 1.12 2015/09/19 04:02:21 guenther Exp $ */
 /*
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
@@ -74,3 +74,6 @@
 };
 
 const char *_ctype_ = _C_ctype_;
+#if 0
+DEF_STRONG(_ctype_);
+#endif
diff --git a/libc/upstream-openbsd/lib/libc/gen/ftok.c b/libc/upstream-openbsd/lib/libc/gen/ftok.c
index f9d6621..387b80f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/ftok.c
+++ b/libc/upstream-openbsd/lib/libc/gen/ftok.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ftok.c,v 1.7 2005/08/08 08:05:34 espie Exp $ */
+/*	$OpenBSD: ftok.c,v 1.8 2014/11/15 22:38:47 guenther Exp $ */
 /*
  * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
  * All rights reserved.
@@ -26,7 +26,6 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ipc.h>
 
diff --git a/libc/upstream-openbsd/lib/libc/gen/getprogname.c b/libc/upstream-openbsd/lib/libc/gen/getprogname.c
index 17046ab..a020830 100644
--- a/libc/upstream-openbsd/lib/libc/gen/getprogname.c
+++ b/libc/upstream-openbsd/lib/libc/gen/getprogname.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getprogname.c,v 1.3 2013/11/12 06:09:48 deraadt Exp $ */
+/* $OpenBSD: getprogname.c,v 1.4 2016/03/13 18:34:20 guenther Exp $ */
 /*
  * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
  *
@@ -17,8 +17,6 @@
 
 #include <stdlib.h>
 
-extern const char *__progname;
-
 const char *
 getprogname(void)
 {
diff --git a/libc/upstream-openbsd/lib/libc/gen/isctype.c b/libc/upstream-openbsd/lib/libc/gen/isctype.c
index 970b5e2..a4e944c 100644
--- a/libc/upstream-openbsd/lib/libc/gen/isctype.c
+++ b/libc/upstream-openbsd/lib/libc/gen/isctype.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: isctype.c,v 1.11 2005/08/08 08:05:34 espie Exp $ */
+/*	$OpenBSD: isctype.c,v 1.12 2015/09/13 11:38:08 guenther Exp $ */
 /*
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
@@ -43,6 +43,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L|_N)));
 }
+DEF_STRONG(isalnum);
 
 #undef isalpha
 int
@@ -50,6 +51,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L)));
 }
+DEF_STRONG(isalpha);
 
 #undef isblank
 int
@@ -57,6 +59,7 @@
 {
 	return (c == ' ' || c == '\t');
 }
+DEF_STRONG(isblank);
 
 #undef iscntrl
 int
@@ -64,6 +67,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _C));
 }
+DEF_STRONG(iscntrl);
 
 #undef isdigit
 int
@@ -71,6 +75,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _N));
 }
+DEF_STRONG(isdigit);
 
 #undef isgraph
 int
@@ -78,6 +83,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N)));
 }
+DEF_STRONG(isgraph);
 
 #undef islower
 int
@@ -85,6 +91,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _L));
 }
+DEF_STRONG(islower);
 
 #undef isprint
 int
@@ -92,6 +99,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N|_B)));
 }
+DEF_STRONG(isprint);
 
 #undef ispunct
 int
@@ -99,6 +107,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _P));
 }
+DEF_STRONG(ispunct);
 
 #undef isspace
 int
@@ -106,6 +115,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _S));
 }
+DEF_STRONG(isspace);
 
 #undef isupper
 int
@@ -113,6 +123,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _U));
 }
+DEF_STRONG(isupper);
 
 #undef isxdigit
 int
@@ -120,6 +131,7 @@
 {
 	return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_N|_X)));
 }
+DEF_STRONG(isxdigit);
 
 #undef isascii
 int
@@ -127,6 +139,7 @@
 {
 	return ((unsigned int)c <= 0177);
 }
+DEF_WEAK(isascii);
 
 #undef toascii
 int
diff --git a/libc/upstream-openbsd/lib/libc/gen/setprogname.c b/libc/upstream-openbsd/lib/libc/gen/setprogname.c
index 089a15a..ec3189f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/setprogname.c
+++ b/libc/upstream-openbsd/lib/libc/gen/setprogname.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: setprogname.c,v 1.4 2013/11/12 06:09:48 deraadt Exp $ */
+/* $OpenBSD: setprogname.c,v 1.5 2016/03/13 18:34:20 guenther Exp $ */
 /*
  * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
  *
@@ -18,8 +18,6 @@
 #include <string.h>
 #include <stdlib.h>
 
-extern const char *__progname;
-
 void
 setprogname(const char *progname)
 {
diff --git a/libc/upstream-openbsd/lib/libc/gen/tolower_.c b/libc/upstream-openbsd/lib/libc/gen/tolower_.c
index 50dcc7b..2402c42 100644
--- a/libc/upstream-openbsd/lib/libc/gen/tolower_.c
+++ b/libc/upstream-openbsd/lib/libc/gen/tolower_.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: tolower_.c,v 1.9 2005/08/08 08:05:34 espie Exp $ */
+/*	$OpenBSD: tolower_.c,v 1.11 2015/09/19 04:02:21 guenther Exp $ */
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
@@ -46,6 +46,9 @@
 };
 
 const short *_tolower_tab_ = _C_tolower_;
+#if 0
+DEF_STRONG(_tolower_tab_);
+#endif
 
 #undef tolower
 int
@@ -55,3 +58,4 @@
 		return(c);
 	return((_tolower_tab_ + 1)[c]);
 }
+DEF_STRONG(tolower);
diff --git a/libc/upstream-openbsd/lib/libc/gen/toupper_.c b/libc/upstream-openbsd/lib/libc/gen/toupper_.c
index 4093199..8408f9e 100644
--- a/libc/upstream-openbsd/lib/libc/gen/toupper_.c
+++ b/libc/upstream-openbsd/lib/libc/gen/toupper_.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: toupper_.c,v 1.10 2005/08/09 08:36:48 kevlo Exp $ */
+/*	$OpenBSD: toupper_.c,v 1.12 2015/09/19 04:02:21 guenther Exp $ */
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
@@ -47,6 +47,9 @@
 };
 
 const short *_toupper_tab_ = _C_toupper_;
+#if 0
+DEF_STRONG(_toupper_tab_);
+#endif
 
 #undef toupper
 int
@@ -56,3 +59,4 @@
 		return(c);
 	return((_toupper_tab_ + 1)[c]);
 }
+DEF_STRONG(toupper);
diff --git a/libc/upstream-openbsd/lib/libc/gen/verr.c b/libc/upstream-openbsd/lib/libc/gen/verr.c
index 8f4722b..b27b9ca 100644
--- a/libc/upstream-openbsd/lib/libc/gen/verr.c
+++ b/libc/upstream-openbsd/lib/libc/gen/verr.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: verr.c,v 1.10 2015/08/31 02:53:57 guenther Exp $ */
+/*	$OpenBSD: verr.c,v 1.11 2016/03/13 18:34:20 guenther Exp $ */
 /*-
  * Copyright (c) 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -35,8 +35,6 @@
 #include <string.h>
 #include <stdarg.h>
 
-extern char *__progname;		/* Program name, from crt0. */
-
 __dead void
 verr(int eval, const char *fmt, va_list ap)
 {
diff --git a/libc/upstream-openbsd/lib/libc/gen/verrx.c b/libc/upstream-openbsd/lib/libc/gen/verrx.c
index f0186b6..0c9308f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/verrx.c
+++ b/libc/upstream-openbsd/lib/libc/gen/verrx.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: verrx.c,v 1.10 2015/08/31 02:53:57 guenther Exp $ */
+/*	$OpenBSD: verrx.c,v 1.11 2016/03/13 18:34:20 guenther Exp $ */
 /*-
  * Copyright (c) 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -33,8 +33,6 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
-extern char *__progname;		/* Program name, from crt0. */
-
 __dead void
 verrx(int eval, const char *fmt, va_list ap)
 {
diff --git a/libc/upstream-openbsd/lib/libc/gen/vwarn.c b/libc/upstream-openbsd/lib/libc/gen/vwarn.c
index 44d8be4..457d619 100644
--- a/libc/upstream-openbsd/lib/libc/gen/vwarn.c
+++ b/libc/upstream-openbsd/lib/libc/gen/vwarn.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vwarn.c,v 1.10 2015/08/31 02:53:57 guenther Exp $ */
+/*	$OpenBSD: vwarn.c,v 1.11 2016/03/13 18:34:20 guenther Exp $ */
 /*-
  * Copyright (c) 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -31,11 +31,10 @@
 #include <err.h>
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
 
-extern char *__progname;		/* Program name, from crt0. */
-
 void
 vwarn(const char *fmt, va_list ap)
 {
diff --git a/libc/upstream-openbsd/lib/libc/gen/vwarnx.c b/libc/upstream-openbsd/lib/libc/gen/vwarnx.c
index 67d8f5b..146e267 100644
--- a/libc/upstream-openbsd/lib/libc/gen/vwarnx.c
+++ b/libc/upstream-openbsd/lib/libc/gen/vwarnx.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vwarnx.c,v 1.10 2015/08/31 02:53:57 guenther Exp $ */
+/*	$OpenBSD: vwarnx.c,v 1.11 2016/03/13 18:34:20 guenther Exp $ */
 /*-
  * Copyright (c) 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,10 +30,9 @@
 
 #include <err.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <stdarg.h>
 
-extern char *__progname;		/* Program name, from crt0. */
-
 void
 vwarnx(const char *fmt, va_list ap)
 {
diff --git a/libc/upstream-openbsd/lib/libc/include/ctype_private.h b/libc/upstream-openbsd/lib/libc/include/ctype_private.h
index 39cc792..cbe1b20 100644
--- a/libc/upstream-openbsd/lib/libc/include/ctype_private.h
+++ b/libc/upstream-openbsd/lib/libc/include/ctype_private.h
@@ -1,7 +1,9 @@
-/* $OpenBSD: ctype_private.h,v 1.1 2005/08/08 05:53:00 espie Exp $ */
+/* $OpenBSD: ctype_private.h,v 1.2 2015/08/27 04:37:09 guenther Exp $ */
 /* Written by Marc Espie, public domain */
 #define CTYPE_NUM_CHARS       256
+
+__BEGIN_HIDDEN_DECLS
 extern const char _C_ctype_[];
 extern const short _C_toupper_[];
 extern const short _C_tolower_[];
-
+__END_HIDDEN_DECLS
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
index 7b49bbf..1b60a3a 100644
--- a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: _wcstol.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/*	$OpenBSD: _wcstol.h,v 1.3 2015/10/01 02:32:07 guenther Exp $	*/
 /* $NetBSD: _wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
 
 /*-
@@ -130,7 +130,7 @@
 		}
 	}
 	if (endptr != 0)
-		/* LINTED interface specification */
 		*endptr = (wchar_t *)(any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(FUNCNAME);
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
index 736b38f..159b22b 100644
--- a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: _wcstoul.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/*	$OpenBSD: _wcstoul.h,v 1.3 2015/10/01 02:32:07 guenther Exp $	*/
 /* $NetBSD: _wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
 
 /*
@@ -110,7 +110,7 @@
 	if (neg && any > 0)
 		acc = -acc;
 	if (endptr != 0)
-		/* LINTED interface specification */
 		*endptr = (wchar_t *)(any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(FUNCNAME);
diff --git a/libc/upstream-openbsd/lib/libc/locale/btowc.c b/libc/upstream-openbsd/lib/libc/locale/btowc.c
index 9627340..455b346 100644
--- a/libc/upstream-openbsd/lib/libc/locale/btowc.c
+++ b/libc/upstream-openbsd/lib/libc/locale/btowc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: btowc.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+/*	$OpenBSD: btowc.c,v 1.3 2015/09/12 16:23:14 guenther Exp $ */
 
 /*-
  * Copyright (c) 2002, 2003 Tim J. Robbins.
@@ -50,3 +50,4 @@
 		return (WEOF);
 	return (wc);
 }
+DEF_STRONG(btowc);
diff --git a/libc/upstream-openbsd/lib/libc/locale/mbrlen.c b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c
index 0f05bd0..52df61a 100644
--- a/libc/upstream-openbsd/lib/libc/locale/mbrlen.c
+++ b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: mbrlen.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+/*	$OpenBSD: mbrlen.c,v 1.3 2015/09/12 16:23:14 guenther Exp $ */
 
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
@@ -37,3 +37,4 @@
 		ps = &mbs;
 	return (mbrtowc(NULL, s, n, ps));
 }
+DEF_STRONG(mbrlen);
diff --git a/libc/upstream-openbsd/lib/libc/locale/wctob.c b/libc/upstream-openbsd/lib/libc/locale/wctob.c
index ea1f40c..51ac355 100644
--- a/libc/upstream-openbsd/lib/libc/locale/wctob.c
+++ b/libc/upstream-openbsd/lib/libc/locale/wctob.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: wctob.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+/*	$OpenBSD: wctob.c,v 1.3 2015/09/12 16:23:14 guenther Exp $ */
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
  * All rights reserved.
@@ -41,3 +41,4 @@
 		return (EOF);
 	return ((unsigned char)*buf);
 }
+DEF_STRONG(wctob);
diff --git a/libc/upstream-openbsd/lib/libc/locale/wctoint.h b/libc/upstream-openbsd/lib/libc/locale/wctoint.h
index c9bf084..ea50c5a 100644
--- a/libc/upstream-openbsd/lib/libc/locale/wctoint.h
+++ b/libc/upstream-openbsd/lib/libc/locale/wctoint.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: wctoint.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/*	$OpenBSD: wctoint.h,v 1.2 2015/09/13 11:38:08 guenther Exp $	*/
 /* $NetBSD: __wctoint.h,v 1.1 2001/09/28 11:25:37 yamt Exp $ */
 
 /*-
@@ -30,7 +30,7 @@
  */
 
 
-__inline static int
+inline static int
 wctoint(wchar_t wc)
 {
 	int n;
diff --git a/libc/upstream-openbsd/lib/libc/net/inet_lnaof.c b/libc/upstream-openbsd/lib/libc/net/inet_lnaof.c
index b1a58cd..9284538 100644
--- a/libc/upstream-openbsd/lib/libc/net/inet_lnaof.c
+++ b/libc/upstream-openbsd/lib/libc/net/inet_lnaof.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: inet_lnaof.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
+/*	$OpenBSD: inet_lnaof.c,v 1.7 2015/01/16 16:48:51 deraadt Exp $ */
 /*
  * Copyright (c) 1983, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -28,7 +28,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
diff --git a/libc/upstream-openbsd/lib/libc/net/inet_makeaddr.c b/libc/upstream-openbsd/lib/libc/net/inet_makeaddr.c
index 87d9325..88ddd28 100644
--- a/libc/upstream-openbsd/lib/libc/net/inet_makeaddr.c
+++ b/libc/upstream-openbsd/lib/libc/net/inet_makeaddr.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: inet_makeaddr.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
+/*	$OpenBSD: inet_makeaddr.c,v 1.7 2015/01/16 16:48:51 deraadt Exp $ */
 /*
  * Copyright (c) 1983, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -28,7 +28,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
diff --git a/libc/upstream-openbsd/lib/libc/net/inet_netof.c b/libc/upstream-openbsd/lib/libc/net/inet_netof.c
index 2f468c3..4efceed 100644
--- a/libc/upstream-openbsd/lib/libc/net/inet_netof.c
+++ b/libc/upstream-openbsd/lib/libc/net/inet_netof.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: inet_netof.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
+/*	$OpenBSD: inet_netof.c,v 1.7 2015/01/16 16:48:51 deraadt Exp $ */
 /*
  * Copyright (c) 1983, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -28,7 +28,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
diff --git a/libc/upstream-openbsd/lib/libc/net/inet_ntop.c b/libc/upstream-openbsd/lib/libc/net/inet_ntop.c
index f991a07..2bb11c2 100644
--- a/libc/upstream-openbsd/lib/libc/net/inet_ntop.c
+++ b/libc/upstream-openbsd/lib/libc/net/inet_ntop.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: inet_ntop.c,v 1.10 2014/05/17 18:16:14 tedu Exp $	*/
+/*	$OpenBSD: inet_ntop.c,v 1.13 2016/09/21 04:38:56 guenther Exp $	*/
 
 /* Copyright (c) 1996 by Internet Software Consortium.
  *
@@ -16,7 +16,6 @@
  * SOFTWARE.
  */
 
-#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -47,15 +46,16 @@
 {
 	switch (af) {
 	case AF_INET:
-		return (inet_ntop4(src, dst, (size_t)size));
+		return (inet_ntop4(src, dst, size));
 	case AF_INET6:
-		return (inet_ntop6(src, dst, (size_t)size));
+		return (inet_ntop6(src, dst, size));
 	default:
 		errno = EAFNOSUPPORT;
 		return (NULL);
 	}
 	/* NOTREACHED */
 }
+DEF_WEAK(inet_ntop);
 
 /* const char *
  * inet_ntop4(src, dst, size)
@@ -167,7 +167,7 @@
 		/* Is this address an encapsulated IPv4? */
 		if (i == 6 && best.base == 0 &&
 		    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
-			if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
+			if (!inet_ntop4(src+12, tp, ep - tp))
 				return (NULL);
 			tp += strlen(tp);
 			break;
diff --git a/libc/upstream-openbsd/lib/libc/net/inet_pton.c b/libc/upstream-openbsd/lib/libc/net/inet_pton.c
index 7e521c3..5d7148e 100644
--- a/libc/upstream-openbsd/lib/libc/net/inet_pton.c
+++ b/libc/upstream-openbsd/lib/libc/net/inet_pton.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: inet_pton.c,v 1.8 2010/05/06 15:47:14 claudio Exp $	*/
+/*	$OpenBSD: inet_pton.c,v 1.10 2015/09/13 21:36:08 guenther Exp $	*/
 
 /* Copyright (c) 1996 by Internet Software Consortium.
  *
@@ -16,7 +16,6 @@
  * SOFTWARE.
  */
 
-#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -58,6 +57,7 @@
 	}
 	/* NOTREACHED */
 }
+DEF_WEAK(inet_pton);
 
 /* int
  * inet_pton4(src, dst)
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fflush.c b/libc/upstream-openbsd/lib/libc/stdio/fflush.c
index 3e30f10..fd1a4b3 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fflush.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fflush.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fflush.c,v 1.8 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: fflush.c,v 1.9 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -52,6 +52,7 @@
 	FUNLOCKFILE(fp);
 	return (r);
 }
+DEF_STRONG(fflush);
 
 int
 __sflush(FILE *fp)
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fgets.c b/libc/upstream-openbsd/lib/libc/stdio/fgets.c
index 345884a..3cea8f7 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fgets.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgets.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fgets.c,v 1.14 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: fgets.c,v 1.16 2016/09/21 04:38:56 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -83,19 +83,19 @@
 		 */
 		if (len > n)
 			len = n;
-		t = memchr((void *)p, '\n', len);
+		t = memchr(p, '\n', len);
 		if (t != NULL) {
 			len = ++t - p;
 			fp->_r -= len;
 			fp->_p = t;
-			(void)memcpy((void *)s, (void *)p, len);
+			(void)memcpy(s, p, len);
 			s[len] = '\0';
 			FUNLOCKFILE(fp);
 			return (buf);
 		}
 		fp->_r -= len;
 		fp->_p += len;
-		(void)memcpy((void *)s, (void *)p, len);
+		(void)memcpy(s, p, len);
 		s += len;
 		n -= len;
 	}
@@ -103,3 +103,4 @@
 	FUNLOCKFILE(fp);
 	return (buf);
 }
+DEF_STRONG(fgets);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c b/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c
index 8cda047..00c2764 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fmemopen.c,v 1.2 2013/03/27 15:06:25 mpi Exp $	*/
+/*	$OpenBSD: fmemopen.c,v 1.3 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*
  * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
@@ -181,3 +181,4 @@
 
 	return (fp);
 }
+DEF_WEAK(fmemopen);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fpurge.c b/libc/upstream-openbsd/lib/libc/stdio/fpurge.c
index 65bd749..8dd8a91 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fpurge.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fpurge.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fpurge.c,v 1.9 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: fpurge.c,v 1.10 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -59,3 +59,4 @@
 	FUNLOCKFILE(fp);
 	return (0);
 }
+DEF_WEAK(fpurge);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputs.c b/libc/upstream-openbsd/lib/libc/stdio/fputs.c
index ea8556a..05ead5c 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fputs.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fputs.c,v 1.10 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: fputs.c,v 1.11 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -56,3 +56,4 @@
 	FUNLOCKFILE(fp);
 	return (ret);
 }
+DEF_STRONG(fputs);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputws.c b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
index 108846e..8961571 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fputws.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fputws.c,v 1.7 2013/11/12 07:04:35 deraadt Exp $	*/
+/*	$OpenBSD: fputws.c,v 1.8 2015/08/31 02:53:57 guenther Exp $	*/
 /* $NetBSD: fputws.c,v 1.1 2003/03/07 07:11:37 tshiozak Exp $ */
 
 /*-
@@ -55,3 +55,4 @@
 
 	return (0);
 }
+DEF_STRONG(fputws);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
index d3a309b..f04565b 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fvwrite.h,v 1.6 2013/11/12 07:04:35 deraadt Exp $	*/
+/*	$OpenBSD: fvwrite.h,v 1.7 2015/08/27 04:37:09 guenther Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -45,5 +45,7 @@
 	int	uio_resid;
 };
 
+__BEGIN_HIDDEN_DECLS
 extern int __sfvwrite(FILE *, struct __suio *);
 wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
+__END_HIDDEN_DECLS
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwalk.c b/libc/upstream-openbsd/lib/libc/stdio/fwalk.c
index 8ac6628..4b1aa43 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fwalk.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwalk.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fwalk.c,v 1.10 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: fwalk.c,v 1.12 2016/05/23 00:21:48 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwide.c b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
index 93cddc6..27ca0f8 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fwide.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fwide.c,v 1.4 2009/11/09 00:18:27 kurt Exp $	*/
+/*	$OpenBSD: fwide.c,v 1.5 2015/08/31 02:53:57 guenther Exp $	*/
 /* $NetBSD: fwide.c,v 1.2 2003/01/18 11:29:54 thorpej Exp $ */
 
 /*-
@@ -62,3 +62,4 @@
 
 	return mode;
 }
+DEF_STRONG(fwide);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
index c72d968..f829398 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fwrite.c,v 1.11 2014/05/01 16:40:36 deraadt Exp $ */
+/*	$OpenBSD: fwrite.c,v 1.12 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -86,3 +86,4 @@
 		return (count);
 	return ((n - uio.uio_resid) / size);
 }
+DEF_STRONG(fwrite);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
index 956608c..4b81d5d 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: mktemp.c,v 1.35 2014/10/31 15:54:14 millert Exp $ */
+/*	$OpenBSD: mktemp.c,v 1.38 2015/09/13 08:31:47 guenther Exp $ */
 /*
  * Copyright (c) 1996-1998, 2008 Theo de Raadt
  * Copyright (c) 1997, 2008-2009 Todd C. Miller
@@ -110,8 +110,6 @@
 	return(-1);
 }
 
-char *_mktemp(char *);
-
 char *
 _mktemp(char *path)
 {
@@ -140,12 +138,14 @@
 {
 	return(mktemp_internal(path, 0, MKTEMP_FILE, 0));
 }
+DEF_WEAK(mkstemp);
 
 int
 mkostemp(char *path, int flags)
 {
 	return(mktemp_internal(path, 0, MKTEMP_FILE, flags));
 }
+DEF_WEAK(mkostemp);
 
 int
 mkstemps(char *path, int slen)
diff --git a/libc/upstream-openbsd/lib/libc/stdio/perror.c b/libc/upstream-openbsd/lib/libc/stdio/perror.c
index 8728718..fdd6120 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/perror.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/perror.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: perror.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
+/*	$OpenBSD: perror.c,v 1.9 2015/08/31 02:53:57 guenther Exp $ */
 /*
  * Copyright (c) 1988, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -60,3 +60,4 @@
 	v->iov_len = 1;
 	(void)writev(STDERR_FILENO, iov, (v - iov) + 1);
 }
+DEF_STRONG(perror);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/puts.c b/libc/upstream-openbsd/lib/libc/stdio/puts.c
index 655aed7..57d4b78 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/puts.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/puts.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: puts.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
+/*	$OpenBSD: puts.c,v 1.12 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -60,3 +60,4 @@
 	FUNLOCKFILE(stdout);
 	return (ret ? EOF : '\n');
 }
+DEF_STRONG(puts);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/rget.c b/libc/upstream-openbsd/lib/libc/stdio/rget.c
index 4cd97cb..368815b 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/rget.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/rget.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: rget.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*	$OpenBSD: rget.c,v 1.8 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -49,3 +49,4 @@
 	}
 	return (EOF);
 }
+DEF_STRONG(__srget);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
index 9b2ab57..da68b90 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: setvbuf.c,v 1.12 2015/01/13 07:18:21 guenther Exp $ */
+/*	$OpenBSD: setvbuf.c,v 1.14 2016/09/21 04:38:56 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -70,7 +70,7 @@
 	fp->_r = fp->_lbfsize = 0;
 	flags = fp->_flags;
 	if (flags & __SMBF)
-		free((void *)fp->_bf._base);
+		free(fp->_bf._base);
 	flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT | __SEOF);
 
 	/* If setting unbuffered mode, skip all the hard work. */
@@ -157,3 +157,4 @@
 
 	return (ret);
 }
+DEF_STRONG(setvbuf);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c b/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c
index 32e0a22..d6dc10e 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: tmpnam.c,v 1.10 2005/08/08 08:05:36 espie Exp $ */
+/*	$OpenBSD: tmpnam.c,v 1.11 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -39,8 +39,6 @@
 __warn_references(tmpnam,
     "warning: tmpnam() possibly used unsafely; consider using mkstemp()");
 
-extern char *_mktemp(char *);
-
 char *
 tmpnam(char *s)
 {
diff --git a/libc/upstream-openbsd/lib/libc/stdio/ungetc.c b/libc/upstream-openbsd/lib/libc/stdio/ungetc.c
index ec98f26..4cd638b 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/ungetc.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/ungetc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ungetc.c,v 1.13 2014/10/11 04:05:10 deraadt Exp $ */
+/*	$OpenBSD: ungetc.c,v 1.15 2016/09/21 04:38:56 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -53,7 +53,7 @@
 		/*
 		 * Get a new buffer (rather than expanding the old one).
 		 */
-		if ((p = malloc((size_t)BUFSIZ)) == NULL)
+		if ((p = malloc(BUFSIZ)) == NULL)
 			return (EOF);
 		_UB(fp)._base = p;
 		_UB(fp)._size = BUFSIZ;
@@ -68,7 +68,7 @@
 	if (p == NULL)
 		return (EOF);
 	/* no overlap (hence can use memcpy) because we doubled the size */
-	(void)memcpy((void *)(p + i), (void *)p, (size_t)i);
+	(void)memcpy(p + i, p, i);
 	fp->_p = p + i;
 	_UB(fp)._base = p;
 	_UB(fp)._size = i * 2;
@@ -143,3 +143,4 @@
 	FUNLOCKFILE(fp);
 	return (c);
 }
+DEF_STRONG(ungetc);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c b/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c
index c0321e9..9b312df 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ungetwc.c,v 1.5 2011/10/16 13:20:51 stsp Exp $	*/
+/*	$OpenBSD: ungetwc.c,v 1.6 2015/08/31 02:53:57 guenther Exp $	*/
 /* $NetBSD: ungetwc.c,v 1.2 2003/01/18 11:29:59 thorpej Exp $ */
 
 /*-
@@ -75,3 +75,4 @@
 	FUNLOCKFILE(fp);
 	return (r);
 }
+DEF_STRONG(ungetwc);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
index 49c1969..e76fcd4 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vdprintf.c,v 1.1 2013/01/30 00:08:13 brad Exp $	*/
+/*	$OpenBSD: vdprintf.c,v 1.2 2015/08/31 02:53:57 guenther Exp $	*/
 /*	$FreeBSD: src/lib/libc/stdio/vdprintf.c,v 1.4 2012/11/17 01:49:40 svnexp Exp $ */
 
 /*-
@@ -71,3 +71,4 @@
 
 	return fflush(&f) ? EOF : ret;
 }
+DEF_WEAK(vdprintf);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vsscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vsscanf.c
index 71eb752..86e0b4c 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vsscanf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vsscanf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vsscanf.c,v 1.12 2011/11/08 18:30:42 guenther Exp $ */
+/*	$OpenBSD: vsscanf.c,v 1.13 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -35,7 +35,6 @@
 #include <string.h>
 #include "local.h"
 
-/* ARGSUSED */
 static int
 eofread(void *cookie, char *buf, int len)
 {
@@ -57,3 +56,4 @@
 	f._lb._base = NULL;
 	return (__svfscanf(&f, fmt, ap));
 }
+DEF_STRONG(vsscanf);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c
index cbaa250..e87dfeb 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vswscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+/* $OpenBSD: vswscanf.c,v 1.3 2015/08/31 02:53:57 guenther Exp $ */
 
 /*-
  * Copyright (c) 1990, 1993
@@ -86,3 +86,4 @@
 
 	return (r);
 }
+DEF_STRONG(vswscanf);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/wbuf.c b/libc/upstream-openbsd/lib/libc/stdio/wbuf.c
index 6aa00e1..2d07750 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/wbuf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/wbuf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: wbuf.c,v 1.12 2009/11/09 00:18:28 kurt Exp $ */
+/*	$OpenBSD: wbuf.c,v 1.13 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -82,3 +82,4 @@
 			return (EOF);
 	return (c);
 }
+DEF_STRONG(__swbuf);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/abs.c b/libc/upstream-openbsd/lib/libc/stdlib/abs.c
index 5d2fbae..0e39cc5 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/abs.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/abs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: abs.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*	$OpenBSD: abs.c,v 1.6 2015/09/13 08:31:47 guenther Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -35,3 +35,4 @@
 {
 	return(j < 0 ? -j : j);
 }
+DEF_STRONG(abs);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/atoi.c b/libc/upstream-openbsd/lib/libc/stdlib/atoi.c
index b084267..7c9eb13 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/atoi.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/atoi.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: atoi.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*	$OpenBSD: atoi.c,v 1.6 2015/09/13 08:31:47 guenther Exp $ */
 /*
  * Copyright (c) 1988 Regents of the University of California.
  * All rights reserved.
@@ -35,3 +35,4 @@
 {
 	return((int)strtol(str, (char **)NULL, 10));
 }
+DEF_STRONG(atoi);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/tfind.c b/libc/upstream-openbsd/lib/libc/stdlib/tfind.c
index 0d1d519..49f9dbc 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/tfind.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/tfind.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: tfind.c,v 1.6 2014/03/16 18:38:30 guenther Exp $	*/
+/*	$OpenBSD: tfind.c,v 1.7 2015/09/26 16:03:48 guenther Exp $	*/
 
 /*
  * Tree search generalized from Knuth (6.2.2) Algorithm T just like
@@ -10,7 +10,6 @@
  *
  * Totally public domain.
  */
-/*LINTLIBRARY*/
 #include <search.h>
 
 typedef struct node_t
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c b/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
index a141085..1dd3145 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: tsearch.c,v 1.8 2014/03/16 18:38:30 guenther Exp $	*/
+/*	$OpenBSD: tsearch.c,v 1.10 2015/09/26 16:03:48 guenther Exp $	*/
 
 /*
  * Tree search generalized from Knuth (6.2.2) Algorithm T just like
@@ -10,7 +10,6 @@
  *
  * Totally public domain.
  */
-/*LINTLIBRARY*/
 
 #include <search.h>
 #include <stdlib.h>
@@ -40,7 +39,7 @@
 	    &(*rootp)->left :		/* T3: follow left branch */
 	    &(*rootp)->right;		/* T4: follow right branch */
     }
-    q = (node *) malloc(sizeof(node));	/* T5: key not found */
+    q = malloc(sizeof(node));	/* T5: key not found */
     if (q != (struct node_t *)0) {	/* make new node */
 	*rootp = q;			/* link new node to old */
 	q->key = key;			/* initialize new node */
diff --git a/libc/upstream-openbsd/lib/libc/string/memchr.c b/libc/upstream-openbsd/lib/libc/string/memchr.c
index 05a1197..976ed21 100644
--- a/libc/upstream-openbsd/lib/libc/string/memchr.c
+++ b/libc/upstream-openbsd/lib/libc/string/memchr.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: memchr.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
+/*	$OpenBSD: memchr.c,v 1.8 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -34,7 +34,8 @@
 #include <string.h>
 
 void *
-memchr(const void *s, int c, size_t n) __overloadable {
+memchr(const void *s, int c, size_t n) __overloadable
+{
 	if (n != 0) {
 		const unsigned char *p = s;
 
@@ -45,3 +46,4 @@
 	}
 	return (NULL);
 }
+DEF_STRONG(memchr);
diff --git a/libc/upstream-openbsd/lib/libc/string/memmove.c b/libc/upstream-openbsd/lib/libc/string/memmove.c
index 910f48c..6b5db47 100644
--- a/libc/upstream-openbsd/lib/libc/string/memmove.c
+++ b/libc/upstream-openbsd/lib/libc/string/memmove.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: memmove.c,v 1.1 2014/11/30 19:43:56 deraadt Exp $ */
+/*	$OpenBSD: memmove.c,v 1.2 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -110,3 +110,4 @@
 done:
 	return (dst0);
 }
+DEF_STRONG(memmove);
diff --git a/libc/upstream-openbsd/lib/libc/string/memrchr.c b/libc/upstream-openbsd/lib/libc/string/memrchr.c
index 1cce809..4b67503 100644
--- a/libc/upstream-openbsd/lib/libc/string/memrchr.c
+++ b/libc/upstream-openbsd/lib/libc/string/memrchr.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: memrchr.c,v 1.2 2007/11/27 16:22:12 martynas Exp $	*/
+/*	$OpenBSD: memrchr.c,v 1.3 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*
  * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -36,3 +36,4 @@
 	}
 	return(NULL);
 }
+DEF_WEAK(memrchr);
diff --git a/libc/upstream-openbsd/lib/libc/string/stpncpy.c b/libc/upstream-openbsd/lib/libc/string/stpncpy.c
index 661a4fd..f30bf15 100644
--- a/libc/upstream-openbsd/lib/libc/string/stpncpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/stpncpy.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: stpncpy.c,v 1.2 2012/07/11 10:44:59 naddy Exp $	*/
+/*	$OpenBSD: stpncpy.c,v 1.3 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -54,3 +54,4 @@
 	}
 	return (dst);
 }
+DEF_WEAK(stpncpy);
diff --git a/libc/upstream-openbsd/lib/libc/string/strcasecmp.c b/libc/upstream-openbsd/lib/libc/string/strcasecmp.c
index 2be0913..edbd638 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcasecmp.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcasecmp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strcasecmp.c,v 1.6 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strcasecmp.c,v 1.7 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*
  * Copyright (c) 1987, 1993
@@ -85,6 +85,7 @@
 			return (0);
 	return (cm[*us1] - cm[*--us2]);
 }
+DEF_WEAK(strcasecmp);
 
 int
 strncasecmp(const char *s1, const char *s2, size_t n)
@@ -103,3 +104,4 @@
 	}
 	return (0);
 }
+DEF_WEAK(strncasecmp);
diff --git a/libc/upstream-openbsd/lib/libc/string/strcmp.c b/libc/upstream-openbsd/lib/libc/string/strcmp.c
index d1b6c50..be17556 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.8 2014/06/10 04:17:37 deraadt Exp $	*/
+/*	$OpenBSD: strcmp.c,v 1.9 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -45,3 +45,4 @@
 			return (0);
 	return (*(unsigned char *)s1 - *(unsigned char *)--s2);
 }
+DEF_STRONG(strcmp);
diff --git a/libc/upstream-openbsd/lib/libc/string/strcspn.c b/libc/upstream-openbsd/lib/libc/string/strcspn.c
index 1eb2336..3c1f5a4 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcspn.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcspn.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strcspn.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
+/*	$OpenBSD: strcspn.c,v 1.6 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -56,3 +56,4 @@
 	}
 	/* NOTREACHED */
 }
+DEF_STRONG(strcspn);
diff --git a/libc/upstream-openbsd/lib/libc/string/strdup.c b/libc/upstream-openbsd/lib/libc/string/strdup.c
index a6aa1e0..9aebf39 100644
--- a/libc/upstream-openbsd/lib/libc/string/strdup.c
+++ b/libc/upstream-openbsd/lib/libc/string/strdup.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strdup.c,v 1.6 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strdup.c,v 1.7 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*
  * Copyright (c) 1988, 1993
@@ -47,3 +47,4 @@
 	(void)memcpy(copy, str, siz);
 	return(copy);
 }
+DEF_WEAK(strdup);
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcat.c b/libc/upstream-openbsd/lib/libc/string/strlcat.c
index 7bf98aa..8a950f5 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlcat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlcat.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strlcat.c,v 1.16 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: strlcat.c,v 1.18 2016/10/16 17:37:39 dtucker Exp $	*/
 
 /*
  * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcpy.c b/libc/upstream-openbsd/lib/libc/string/strlcpy.c
index a5343b8..647b18b 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlcpy.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strlcpy.c,v 1.13 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: strlcpy.c,v 1.15 2016/10/16 17:37:39 dtucker Exp $	*/
 
 /*
  * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
diff --git a/libc/upstream-openbsd/lib/libc/string/strncat.c b/libc/upstream-openbsd/lib/libc/string/strncat.c
index 32334b3..5b07749 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncat.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strncat.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
+/*	$OpenBSD: strncat.c,v 1.6 2015/08/31 02:53:57 guenther Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -55,3 +55,4 @@
 	}
 	return (dst);
 }
+DEF_STRONG(strncat);
diff --git a/libc/upstream-openbsd/lib/libc/string/strncmp.c b/libc/upstream-openbsd/lib/libc/string/strncmp.c
index 0a4ddc1..535d2a6 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.8 2014/06/10 04:17:37 deraadt Exp $	*/
+/*	$OpenBSD: strncmp.c,v 1.9 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*
  * Copyright (c) 1989 The Regents of the University of California.
@@ -45,3 +45,4 @@
 	} while (--n != 0);
 	return (0);
 }
+DEF_STRONG(strncmp);
diff --git a/libc/upstream-openbsd/lib/libc/string/strncpy.c b/libc/upstream-openbsd/lib/libc/string/strncpy.c
index e83c7e5..ad9dc84 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.7 2014/06/10 04:17:37 deraadt Exp $	*/
+/*	$OpenBSD: strncpy.c,v 1.8 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -56,3 +56,4 @@
 	}
 	return (dst);
 }
+DEF_STRONG(strncpy);
diff --git a/libc/upstream-openbsd/lib/libc/string/strndup.c b/libc/upstream-openbsd/lib/libc/string/strndup.c
index 27701ac..a6e5bff 100644
--- a/libc/upstream-openbsd/lib/libc/string/strndup.c
+++ b/libc/upstream-openbsd/lib/libc/string/strndup.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strndup.c,v 1.1 2010/05/18 22:24:55 tedu Exp $	*/
+/*	$OpenBSD: strndup.c,v 1.2 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*
  * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -37,3 +37,4 @@
 
 	return copy;
 }
+DEF_WEAK(strndup);
diff --git a/libc/upstream-openbsd/lib/libc/string/strpbrk.c b/libc/upstream-openbsd/lib/libc/string/strpbrk.c
index cd3b71c..336c22d 100644
--- a/libc/upstream-openbsd/lib/libc/string/strpbrk.c
+++ b/libc/upstream-openbsd/lib/libc/string/strpbrk.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strpbrk.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
+/*	$OpenBSD: strpbrk.c,v 1.6 2015/08/31 02:53:57 guenther Exp $ */
 /*
  * Copyright (c) 1985 Regents of the University of California.
  * All rights reserved.
@@ -46,3 +46,4 @@
 	}
 	return (NULL);
 }
+DEF_STRONG(strpbrk);
diff --git a/libc/upstream-openbsd/lib/libc/string/strsep.c b/libc/upstream-openbsd/lib/libc/string/strsep.c
index 2ffc4b4..97c3cbf 100644
--- a/libc/upstream-openbsd/lib/libc/string/strsep.c
+++ b/libc/upstream-openbsd/lib/libc/string/strsep.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strsep.c,v 1.7 2014/02/05 20:42:32 stsp Exp $	*/
+/*	$OpenBSD: strsep.c,v 1.8 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -68,3 +68,4 @@
 	}
 	/* NOTREACHED */
 }
+DEF_WEAK(strsep);
diff --git a/libc/upstream-openbsd/lib/libc/string/strspn.c b/libc/upstream-openbsd/lib/libc/string/strspn.c
index 385649c..0ce41cb 100644
--- a/libc/upstream-openbsd/lib/libc/string/strspn.c
+++ b/libc/upstream-openbsd/lib/libc/string/strspn.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strspn.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
+/*	$OpenBSD: strspn.c,v 1.6 2015/08/31 02:53:57 guenther Exp $ */
 /*
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
@@ -49,3 +49,4 @@
 			goto cont;
 	return (p - 1 - s1);
 }
+DEF_STRONG(strspn);
diff --git a/libc/upstream-openbsd/lib/libc/string/wcsstr.c b/libc/upstream-openbsd/lib/libc/string/wcsstr.c
index 669e340..6a7b0da 100644
--- a/libc/upstream-openbsd/lib/libc/string/wcsstr.c
+++ b/libc/upstream-openbsd/lib/libc/string/wcsstr.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: wcsstr.c,v 1.3 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: wcsstr.c,v 1.5 2015/10/01 02:32:07 guenther Exp $	*/
 /*	$NetBSD: wcsstr.c,v 1.3 2003/03/05 20:18:17 tshiozak Exp $	*/
 
 /*-
@@ -43,7 +43,6 @@
 	const wchar_t *r;
 
 	if (!*little) {
-		/* LINTED interface specification */
 		return (wchar_t *)big;
 	}
 	if (wcslen(big) < wcslen(little))
@@ -61,10 +60,12 @@
 			r++;
 		}
 		if (!*q) {
-			/* LINTED interface specification */
 			return (wchar_t *)p;
 		}
 		p++;
 	}
 	return NULL;
 }
+#ifndef WCSWCS
+DEF_STRONG(wcsstr);
+#endif
diff --git a/libc/upstream-openbsd/lib/libc/string/wcswidth.c b/libc/upstream-openbsd/lib/libc/string/wcswidth.c
index 8ea1bdf..9f003f9 100644
--- a/libc/upstream-openbsd/lib/libc/string/wcswidth.c
+++ b/libc/upstream-openbsd/lib/libc/string/wcswidth.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: wcswidth.c,v 1.4 2011/04/04 18:16:24 stsp Exp $	*/
+/*	$OpenBSD: wcswidth.c,v 1.5 2015/09/12 16:23:14 guenther Exp $	*/
 /*	$NetBSD: wcswidth.c,v 1.2 2001/01/03 14:29:37 lukem Exp $	*/
 
 /*-
@@ -48,3 +48,4 @@
 
 	return w;
 }
+DEF_WEAK(wcswidth);
diff --git a/libc/upstream-openbsd/lib/libc/string/wmemcpy.c b/libc/upstream-openbsd/lib/libc/string/wmemcpy.c
index 9bbd836..cf02ab9 100644
--- a/libc/upstream-openbsd/lib/libc/string/wmemcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/wmemcpy.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: wmemcpy.c,v 1.3 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: wmemcpy.c,v 1.4 2015/09/12 16:23:14 guenther Exp $	*/
 /*	$NetBSD: wmemcpy.c,v 1.2 2001/01/03 14:29:37 lukem Exp $	*/
 
 /*-
@@ -38,3 +38,4 @@
 
 	return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t));
 }
+DEF_STRONG(wmemcpy);
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/libdl/libdl.arm.map b/libdl/libdl.arm.map
index 668f008..292bd97 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -34,11 +34,15 @@
     dlvsym; # introduced=24
 } LIBC;
 
+LIBC_OMR1 { # future
+  global:
+    __cfi_slowpath; # future
+    __cfi_slowpath_diag; # future
+} LIBC_N;
+
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    __cfi_slowpath;
-    __cfi_slowpath_diag;
     android_dlwarning;
     android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
@@ -48,4 +52,4 @@
     android_create_namespace;
     android_link_namespaces;
     android_get_exported_namespace;
-} LIBC_N;
+} LIBC_OMR1;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index 8270fe9..2fe2c7b 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -33,11 +33,15 @@
     dlvsym; # introduced=24
 } LIBC;
 
+LIBC_OMR1 { # future
+  global:
+    __cfi_slowpath; # future
+    __cfi_slowpath_diag; # future
+} LIBC_N;
+
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    __cfi_slowpath;
-    __cfi_slowpath_diag;
     android_dlwarning;
     android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
@@ -47,4 +51,4 @@
     android_create_namespace;
     android_link_namespaces;
     android_get_exported_namespace;
-} LIBC_N;
+} LIBC_OMR1;
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index a4c6483..408d4dc 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -33,11 +33,15 @@
     dlvsym; # introduced=24
 } LIBC;
 
+LIBC_OMR1 { # future
+  global:
+    __cfi_slowpath; # future
+    __cfi_slowpath_diag; # future
+} LIBC_N;
+
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    __cfi_slowpath;
-    __cfi_slowpath_diag;
     android_dlwarning;
     android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
@@ -47,4 +51,4 @@
     android_create_namespace;
     android_link_namespaces;
     android_get_exported_namespace;
-} LIBC_N;
+} LIBC_OMR1;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index 8270fe9..2fe2c7b 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -33,11 +33,15 @@
     dlvsym; # introduced=24
 } LIBC;
 
+LIBC_OMR1 { # future
+  global:
+    __cfi_slowpath; # future
+    __cfi_slowpath_diag; # future
+} LIBC_N;
+
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    __cfi_slowpath;
-    __cfi_slowpath_diag;
     android_dlwarning;
     android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
@@ -47,4 +51,4 @@
     android_create_namespace;
     android_link_namespaces;
     android_get_exported_namespace;
-} LIBC_N;
+} LIBC_OMR1;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index 8270fe9..2fe2c7b 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -33,11 +33,15 @@
     dlvsym; # introduced=24
 } LIBC;
 
+LIBC_OMR1 { # future
+  global:
+    __cfi_slowpath; # future
+    __cfi_slowpath_diag; # future
+} LIBC_N;
+
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    __cfi_slowpath;
-    __cfi_slowpath_diag;
     android_dlwarning;
     android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
@@ -47,4 +51,4 @@
     android_create_namespace;
     android_link_namespaces;
     android_get_exported_namespace;
-} LIBC_N;
+} LIBC_OMR1;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index 8270fe9..2fe2c7b 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -33,11 +33,15 @@
     dlvsym; # introduced=24
 } LIBC;
 
+LIBC_OMR1 { # future
+  global:
+    __cfi_slowpath; # future
+    __cfi_slowpath_diag; # future
+} LIBC_N;
+
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    __cfi_slowpath;
-    __cfi_slowpath_diag;
     android_dlwarning;
     android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
@@ -47,4 +51,4 @@
     android_create_namespace;
     android_link_namespaces;
     android_get_exported_namespace;
-} LIBC_N;
+} LIBC_OMR1;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index 8270fe9..2fe2c7b 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -33,11 +33,15 @@
     dlvsym; # introduced=24
 } LIBC;
 
+LIBC_OMR1 { # future
+  global:
+    __cfi_slowpath; # future
+    __cfi_slowpath_diag; # future
+} LIBC_N;
+
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    __cfi_slowpath;
-    __cfi_slowpath_diag;
     android_dlwarning;
     android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
@@ -47,4 +51,4 @@
     android_create_namespace;
     android_link_namespaces;
     android_get_exported_namespace;
-} LIBC_N;
+} LIBC_OMR1;
diff --git a/libm/Android.bp b/libm/Android.bp
index 07d4261..75e8957 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -63,7 +63,6 @@
         "upstream-freebsd/lib/msun/src/e_sinhf.c",
         "upstream-freebsd/lib/msun/src/e_sqrt.c",
         "upstream-freebsd/lib/msun/src/e_sqrtf.c",
-        "upstream-freebsd/lib/msun/src/imprecise.c",
         "upstream-freebsd/lib/msun/src/k_cos.c",
         "upstream-freebsd/lib/msun/src/k_cosf.c",
         "upstream-freebsd/lib/msun/src/k_exp.c",
@@ -209,6 +208,7 @@
         // Functionality not in the BSDs.
         "significandl.c",
         "sincos.c",
+        "fake_long_double.c",
 
         // Modified versions of BSD code.
         "signbit.c",
@@ -218,10 +218,6 @@
     ],
 
     multilib: {
-        lib32: {
-            srcs: ["fake_long_double.c"],
-        },
-
         lib64: {
             srcs: [
                 "upstream-freebsd/lib/msun/src/e_acosl.c",
@@ -529,6 +525,7 @@
     sanitize: {
         address: false,
         coverage: false,
+        integer_overflow: false,
     },
     stl: "none",
 }
diff --git a/libm/fake_long_double.c b/libm/fake_long_double.c
index 20148a3..fd983ed 100644
--- a/libm/fake_long_double.c
+++ b/libm/fake_long_double.c
@@ -17,12 +17,11 @@
 #include <float.h>
 #include <math.h>
 
-#ifndef __LP64__
-/*
- * The BSD "long double" functions are broken when sizeof(long double) == sizeof(double).
- * Android works around those cases by replacing the broken functions with our own trivial stubs
- * that call the regular "double" function.
- */
+#if !defined(__LP64__)
+
+// The BSD "long double" functions are broken when sizeof(long double) == sizeof(double).
+// Android works around those cases by replacing the broken functions with our own trivial stubs
+// that call the regular "double" function.
 
 long double copysignl(long double a1, long double a2) { return copysign(a1, a2); }
 long double fmaxl(long double a1, long double a2) { return fmax(a1, a2); }
@@ -40,3 +39,7 @@
 long double roundl(long double a1) { return round(a1); }
 
 #endif // __LP64__
+
+// FreeBSD doesn't have ld128 implementations of powl or tgammal, so both LP32 and LP64 need these.
+long double powl(long double x, long double y) { return pow(x, y); }
+long double tgammal(long double x) { return tgamma(x); }
diff --git a/libm/freebsd-compat.h b/libm/freebsd-compat.h
index a4dd6c2..ee41e45 100644
--- a/libm/freebsd-compat.h
+++ b/libm/freebsd-compat.h
@@ -28,7 +28,15 @@
 
 #define __warn_references(sym,msg) /* ignored */
 
-/* digittoint is in BSD's <ctype.h>. */
+// digittoint is in BSD's <ctype.h>, but not ours, so we have a secret
+// implementation in libm. We reuse parts of libm in the NDK's
+// libandroid_support, where it's a static library, so we want all our
+// "hidden" functions start with a double underscore --- being HIDDEN
+// in the ELF sense is not sufficient.
+#define digittoint __libm_digittoint
 int digittoint(char ch);
 
+// Similarly rename _scan_nan.
+#define _scan_nan __libm_scan_nan
+
 #endif
diff --git a/libm/upstream-freebsd/lib/msun/src/imprecise.c b/libm/upstream-freebsd/lib/msun/src/imprecise.c
deleted file mode 100644
index 08cd239..0000000
--- a/libm/upstream-freebsd/lib/msun/src/imprecise.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*-
- * Copyright (c) 2013 David Chisnall
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#include <float.h>
-#include <math.h>
-
-/*
- * If long double is not the same size as double, then these will lose
- * precision and we should emit a warning whenever something links against
- * them.
- */
-#if (LDBL_MANT_DIG > 53)
-#define WARN_IMPRECISE(x) \
-	__warn_references(x, # x " has lower than advertised precision");
-#else
-#define WARN_IMPRECISE(x)
-#endif
-/*
- * Declare the functions as weak variants so that other libraries providing
- * real versions can override them.
- */
-#define	DECLARE_WEAK(x)\
-	__weak_reference(imprecise_## x, x);\
-	WARN_IMPRECISE(x)
-
-long double
-imprecise_powl(long double x, long double y)
-{
-
-	return pow(x, y);
-}
-DECLARE_WEAK(powl);
-
-#define DECLARE_IMPRECISE(f) \
-	long double imprecise_ ## f ## l(long double v) { return f(v); }\
-	DECLARE_WEAK(f ## l)
-
-DECLARE_IMPRECISE(tgamma);
diff --git a/linker/Android.bp b/linker/Android.bp
index efd91ac..fda7eb5 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -101,6 +101,12 @@
         "-Werror",
     ],
 
+    product_variables: {
+        debuggable: {
+            cppflags: ["-DUSE_LD_CONFIG_FILE"],
+        },
+    },
+
     cppflags: ["-Wold-style-cast"],
 
     // we are going to link libc++_static manually because
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 8e7a141..4397551 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -558,9 +558,10 @@
 
   static LoadTask* create(const char* name,
                           soinfo* needed_by,
+                          android_namespace_t* start_from,
                           std::unordered_map<const soinfo*, ElfReader>* readers_map) {
     LoadTask* ptr = TypeBasedAllocator<LoadTask>::alloc();
-    return new (ptr) LoadTask(name, needed_by, readers_map);
+    return new (ptr) LoadTask(name, needed_by, start_from, readers_map);
   }
 
   const char* get_name() const {
@@ -612,6 +613,11 @@
     is_dt_needed_ = is_dt_needed;
   }
 
+  // returns the namespace from where we need to start loading this.
+  const android_namespace_t* get_start_from() const {
+    return start_from_;
+  }
+
   const ElfReader& get_elf_reader() const {
     CHECK(si_ != nullptr);
     return (*elf_readers_map_)[si_];
@@ -650,10 +656,11 @@
  private:
   LoadTask(const char* name,
            soinfo* needed_by,
+           android_namespace_t* start_from,
            std::unordered_map<const soinfo*, ElfReader>* readers_map)
     : name_(name), needed_by_(needed_by), si_(nullptr),
       fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map),
-      is_dt_needed_(false) {}
+      is_dt_needed_(false), start_from_(start_from) {}
 
   ~LoadTask() {
     if (fd_ != -1 && close_fd_) {
@@ -672,6 +679,7 @@
   // TODO(dimitry): needed by workaround for http://b/26394120 (the grey-list)
   bool is_dt_needed_;
   // END OF WORKAROUND
+  const android_namespace_t* const start_from_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask);
 };
@@ -1041,7 +1049,7 @@
                         ZipArchiveCache* zip_archive_cache,
                         const char* name, soinfo *needed_by,
                         off64_t* file_offset, std::string* realpath) {
-  TRACE("[ opening %s ]", name);
+  TRACE("[ opening %s at namespace %s]", name, ns->get_name());
 
   // If the name contains a slash, we should attempt to open it directly and not search the paths.
   if (strchr(name, '/') != nullptr) {
@@ -1146,6 +1154,27 @@
   return *candidate != nullptr;
 }
 
+static bool find_loaded_library_by_realpath(android_namespace_t* ns, const char* realpath,
+                                            bool search_linked_namespaces, soinfo** candidate) {
+  auto predicate = [&](soinfo* si) { return strcmp(realpath, si->get_realpath()) == 0; };
+
+  *candidate = ns->soinfo_list().find_if(predicate);
+
+  if (*candidate == nullptr && search_linked_namespaces) {
+    for (auto& link : ns->linked_namespaces()) {
+      android_namespace_t* linked_ns = link.linked_namespace();
+      soinfo* si = linked_ns->soinfo_list().find_if(predicate);
+
+      if (si != nullptr && link.is_accessible(si->get_soname())) {
+        *candidate = si;
+        return true;
+      }
+    }
+  }
+
+  return *candidate != nullptr;
+}
+
 static bool load_library(android_namespace_t* ns,
                          LoadTask* task,
                          LoadTaskList* load_tasks,
@@ -1273,7 +1302,7 @@
   }
 
   for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
-    load_tasks->push_back(LoadTask::create(name, si, task->get_readers_map()));
+    load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
   });
 
   return true;
@@ -1368,8 +1397,7 @@
 }
 
 static bool find_library_in_linked_namespace(const android_namespace_link_t& namespace_link,
-                                             LoadTask* task,
-                                             int rtld_flags) {
+                                             LoadTask* task) {
   android_namespace_t* ns = namespace_link.linked_namespace();
 
   soinfo* candidate;
@@ -1394,29 +1422,10 @@
     return true;
   }
 
-  // try to load the library - once namespace boundary is crossed
-  // we need to load a library within separate load_group
-  // to avoid using symbols from foreign namespace while.
-  //
-  // All symbols during relocation should be resolved within a
-  // namespace to preserve library locality to a namespace.
-  const char* name = task->get_name();
-  if (find_libraries(ns,
-                     task->get_needed_by(),
-                     &name,
-                     1,
-                     &candidate,
-                     nullptr /* ld_preloads */,
-                     0 /* ld_preload_count*/,
-                     rtld_flags,
-                     nullptr /* extinfo*/,
-                     false /* add_as_children */,
-                     false /* search_linked_namespaces */)) {
-    task->set_soinfo(candidate);
-    return true;
-  }
-
-  return false;
+  // returning true with empty soinfo means that the library is okay to be
+  // loaded in the namespace buy has not yet been loaded there before.
+  task->set_soinfo(nullptr);
+  return true;
 }
 
 static bool find_library_internal(android_namespace_t* ns,
@@ -1445,9 +1454,24 @@
     // if a library was not found - look into linked namespaces
     for (auto& linked_namespace : ns->linked_namespaces()) {
       if (find_library_in_linked_namespace(linked_namespace,
-                                           task,
-                                           rtld_flags)) {
-        return true;
+                                           task)) {
+        if (task->get_soinfo() == nullptr) {
+          // try to load the library - once namespace boundary is crossed
+          // we need to load a library within separate load_group
+          // to avoid using symbols from foreign namespace while.
+          //
+          // However, actual linking is deferred until when the global group
+          // is fully identified and is applied to all namespaces.
+          // Otherwise, the libs in the linked namespace won't get symbols from
+          // the global group.
+          if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) {
+            return true;
+          }
+          // lib was not found in the namespace. Try next linked namespace.
+        } else {
+          // lib is already loaded
+          return true;
+        }
       }
     }
   }
@@ -1458,44 +1482,6 @@
 static void soinfo_unload(soinfo* si);
 static void soinfo_unload(soinfo* soinfos[], size_t count);
 
-// TODO: this is slightly unusual way to construct
-// the global group for relocation. Not every RTLD_GLOBAL
-// library is included in this group for backwards-compatibility
-// reasons.
-//
-// This group consists of the main executable, LD_PRELOADs
-// and libraries with the DF_1_GLOBAL flag set.
-static soinfo_list_t make_global_group(android_namespace_t* ns) {
-  soinfo_list_t global_group;
-  ns->soinfo_list().for_each([&](soinfo* si) {
-    if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
-      global_group.push_back(si);
-    }
-  });
-
-  return global_group;
-}
-
-// This function provides a list of libraries to be shared
-// by the namespace. For the default namespace this is the global
-// group (see make_global_group). For all others this is a group
-// of RTLD_GLOBAL libraries (which includes the global group from
-// the default namespace).
-static soinfo_list_t get_shared_group(android_namespace_t* ns) {
-  if (ns == &g_default_namespace) {
-    return make_global_group(ns);
-  }
-
-  soinfo_list_t shared_group;
-  ns->soinfo_list().for_each([&](soinfo* si) {
-    if ((si->get_rtld_flags() & RTLD_GLOBAL) != 0) {
-      shared_group.push_back(si);
-    }
-  });
-
-  return shared_group;
-}
-
 static void shuffle(std::vector<LoadTask*>* v) {
   for (size_t i = 0, size = v->size(); i < size; ++i) {
     size_t n = size - i;
@@ -1518,19 +1504,17 @@
                     int rtld_flags,
                     const android_dlextinfo* extinfo,
                     bool add_as_children,
-                    bool search_linked_namespaces) {
+                    bool search_linked_namespaces,
+                    std::unordered_map<const soinfo*, ElfReader>& readers_map,
+                    std::vector<android_namespace_t*>* namespaces) {
   // Step 0: prepare.
   LoadTaskList load_tasks;
-  std::unordered_map<const soinfo*, ElfReader> readers_map;
 
   for (size_t i = 0; i < library_names_count; ++i) {
     const char* name = library_names[i];
-    load_tasks.push_back(LoadTask::create(name, start_with, &readers_map));
+    load_tasks.push_back(LoadTask::create(name, start_with, ns, &readers_map));
   }
 
-  // Construct global_group.
-  soinfo_list_t global_group = make_global_group(ns);
-
   // If soinfos array is null allocate one on stack.
   // The array is needed in case of failure; for example
   // when library_names[] = {libone.so, libtwo.so} and libone.so
@@ -1570,7 +1554,12 @@
     task->set_extinfo(is_dt_needed ? nullptr : extinfo);
     task->set_dt_needed(is_dt_needed);
 
-    if (!find_library_internal(ns,
+    // try to find the load.
+    // Note: start from the namespace that is stored in the LoadTask. This namespace
+    // is different from the current namespace when the LoadTask is for a transitive
+    // dependency and the lib that created the LoadTask is not found in the
+    // current namespace but in one of the linked namespace.
+    if (!find_library_internal(const_cast<android_namespace_t*>(task->get_start_from()),
                                task,
                                &zip_archive_cache,
                                &load_tasks,
@@ -1629,18 +1618,61 @@
     }
   }
 
-  // Step 4: Add LD_PRELOADed libraries to the global group for
-  // future runs. There is no need to explicitly add them to
-  // the global group for this run because they are going to
-  // appear in the local group in the correct order.
+  // Step 4: Construct the global group. Note: DF_1_GLOBAL bit of a library is
+  // determined at step 3.
+
+  // Step 4-1: DF_1_GLOBAL bit is force set for LD_PRELOADed libs because they
+  // must be added to the global group
   if (ld_preloads != nullptr) {
     for (auto&& si : *ld_preloads) {
       si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
     }
   }
 
+  // Step 4-2: Gather all DF_1_GLOBAL libs which were newly loaded during this
+  // run. These will be the new member of the global group
+  soinfo_list_t new_global_group_members;
+  for (auto&& task : load_tasks) {
+    soinfo* si = task->get_soinfo();
+    if (!si->is_linked() && (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
+      new_global_group_members.push_back(si);
+    }
+  }
 
-  // Step 5: link libraries.
+  // Step 4-3: Add the new global group members to all the linked namespaces
+  for (auto si : new_global_group_members) {
+    for (auto linked_ns : *namespaces) {
+      if (si->get_primary_namespace() != linked_ns) {
+        linked_ns->add_soinfo(si);
+        si->add_secondary_namespace(linked_ns);
+      }
+    }
+  }
+
+  // Step 5: link libraries that are not destined to this namespace.
+  // Do this by recursively calling find_libraries on the namespace where the lib
+  // was found during Step 1.
+  for (auto&& task : load_tasks) {
+    soinfo* si = task->get_soinfo();
+    if (si->get_primary_namespace() != ns) {
+      const char* name = task->get_name();
+      if (find_libraries(si->get_primary_namespace(), task->get_needed_by(), &name, 1,
+                         nullptr /* soinfos */, nullptr /* ld_preloads */, 0 /* ld_preload_count */,
+                         rtld_flags, nullptr /* extinfo */, false /* add_as_children */,
+                         false /* search_linked_namespaces */, readers_map, namespaces)) {
+        // If this lib is directly needed by one of the libs in this namespace,
+        // then increment the count
+        soinfo* needed_by = task->get_needed_by();
+        if (needed_by != nullptr && needed_by->get_primary_namespace() == ns && si->is_linked()) {
+          si->increment_ref_count();
+        }
+      } else {
+        return false;
+      }
+    }
+  }
+
+  // Step 6: link libraries in this namespace
   soinfo_list_t local_group;
   walk_dependencies_tree(
       (start_with != nullptr && add_as_children) ? &start_with : soinfos,
@@ -1654,6 +1686,7 @@
     }
   });
 
+  soinfo_list_t global_group = ns->get_global_group();
   bool linked = local_group.visit([&](soinfo* si) {
     if (!si->is_linked()) {
       if (!si->link_image(global_group, local_group, extinfo) ||
@@ -1684,6 +1717,9 @@
                             soinfo* needed_by) {
   soinfo* si;
 
+  // readers_map is shared across recursive calls to find_libraries.
+  // However, the map is not shared across different threads.
+  std::unordered_map<const soinfo*, ElfReader> readers_map;
   if (name == nullptr) {
     si = solist_get_somain();
   } else if (!find_libraries(ns,
@@ -1696,7 +1732,8 @@
                              rtld_flags,
                              extinfo,
                              false /* add_as_children */,
-                             true /* search_linked_namespaces */)) {
+                             true /* search_linked_namespaces */,
+                             readers_map)) {
     return nullptr;
   }
 
@@ -1956,12 +1993,18 @@
 
   const char* translated_name = name;
   if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
-    char translated_path[PATH_MAX];
-    if (realpath(translated_name, translated_path) != nullptr) {
-      asan_name_holder = std::string(kAsanLibDirPrefix) + translated_path;
+    char original_path[PATH_MAX];
+    if (realpath(name, original_path) != nullptr) {
+      asan_name_holder = std::string(kAsanLibDirPrefix) + original_path;
       if (file_exists(asan_name_holder.c_str())) {
-        translated_name = asan_name_holder.c_str();
-        PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+        soinfo* si = nullptr;
+        if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
+          PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
+                asan_name_holder.c_str());
+        } else {
+          PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+          translated_name = asan_name_holder.c_str();
+        }
       }
     }
   }
@@ -2208,7 +2251,7 @@
     }
   } else {
     // If not shared - copy only the shared group
-    add_soinfos_to_namespace(get_shared_group(parent_namespace), ns);
+    add_soinfos_to_namespace(parent_namespace->get_shared_group(), ns);
   }
 
   ns->set_ld_library_paths(std::move(ld_library_paths));
@@ -3413,7 +3456,7 @@
   return true;
 }
 
-static void init_default_namespace_no_config(bool is_asan) {
+static std::vector<android_namespace_t*> init_default_namespace_no_config(bool is_asan) {
   g_default_namespace.set_isolated(false);
   auto default_ld_paths = is_asan ? kAsanDefaultLdPaths : kDefaultLdPaths;
 
@@ -3428,9 +3471,13 @@
   }
 
   g_default_namespace.set_default_library_paths(std::move(ld_default_paths));
+
+  std::vector<android_namespace_t*> namespaces;
+  namespaces.push_back(&g_default_namespace);
+  return namespaces;
 }
 
-void init_default_namespace(const char* executable_path) {
+std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path) {
   g_default_namespace.set_name("(default)");
 
   soinfo* somain = solist_get_somain();
@@ -3447,14 +3494,24 @@
 
   std::string error_msg;
 
-  if (!Config::read_binary_config(kLdConfigFilePath,
+  const char* config_file = kLdConfigFilePath;
+#ifdef USE_LD_CONFIG_FILE
+  // This is a debugging/testing only feature. Must not be available on
+  // production builds.
+  const char* ld_config_file = getenv("LD_CONFIG_FILE");
+  if (ld_config_file != nullptr && file_exists(ld_config_file)) {
+    config_file = ld_config_file;
+  }
+#endif
+
+  if (!Config::read_binary_config(config_file,
                                   executable_path,
                                   g_is_asan,
                                   &config,
                                   &error_msg)) {
     if (!error_msg.empty()) {
       DL_WARN("error reading config file \"%s\" for \"%s\" (will use default configuration): %s",
-              kLdConfigFilePath,
+              config_file,
               executable_path,
               error_msg.c_str());
     }
@@ -3462,8 +3519,7 @@
   }
 
   if (config == nullptr) {
-    init_default_namespace_no_config(g_is_asan);
-    return;
+    return init_default_namespace_no_config(g_is_asan);
   }
 
   const auto& namespace_configs = config->namespace_configs();
@@ -3514,10 +3570,17 @@
   soinfo* ld_android_so = solist_get_head();
   for (auto it : namespaces) {
     it.second->add_soinfo(ld_android_so);
-    // TODO (dimitry): somain and ld_preloads should probably be added to all of these namespaces too?
+    // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
   }
 
   set_application_target_sdk_version(config->target_sdk_version());
+
+  std::vector<android_namespace_t*> created_namespaces;
+  created_namespaces.reserve(namespaces.size());
+  for (auto kv : namespaces) {
+    created_namespaces.push_back(kv.second);
+  }
+  return created_namespaces;
 }
 
 // This function finds a namespace exported in ld.config.txt by its name.
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index 2bdde1e..0a9aeab 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -371,15 +371,6 @@
                                       bool is_asan,
                                       const Config** config,
                                       std::string* error_msg) {
-  // TODO(b/38114603) Currently, multiple namespaces does not support ASAN mode
-  // where some symbols should be intercepted via LD_PRELOAD; LD_PRELOADed libs
-  // are not being preloaded into the linked namespaces other than the default
-  // namespace. Until we fix the problem, we temporarily disable ld.config.txt
-  // in ASAN mode.
-  if (is_asan) {
-    return false;
-  }
-
   g_config.clear();
 
   std::unordered_map<std::string, PropertyValue> property_map;
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 5dc215f..0f691c3 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -87,6 +87,7 @@
 
   // prev will never be null, because the first entry in solist is
   // always the static libdl_info.
+  CHECK(prev != nullptr);
   prev->next = si->next;
   if (si == sonext) {
     sonext = prev;
@@ -137,8 +138,7 @@
 // An empty list of soinfos
 static soinfo_list_t g_empty_list;
 
-static void add_vdso(KernelArgumentBlock& args __unused) {
-#if defined(AT_SYSINFO_EHDR)
+static void add_vdso(KernelArgumentBlock& args) {
   ElfW(Ehdr)* ehdr_vdso = reinterpret_cast<ElfW(Ehdr)*>(args.getauxval(AT_SYSINFO_EHDR));
   if (ehdr_vdso == nullptr) {
     return;
@@ -154,7 +154,6 @@
 
   si->prelink_image();
   si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr);
-#endif
 }
 
 /* gdb expects the linker to be in the debug shared object list.
@@ -307,6 +306,11 @@
       break;
     }
   }
+
+  if (si->base == 0) {
+    async_safe_fatal("Could not find a PHDR: broken executable?");
+  }
+
   si->dynamic = nullptr;
 
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
@@ -333,7 +337,7 @@
 
   somain = si;
 
-  init_default_namespace(executable_path);
+  std::vector<android_namespace_t*> namespaces = init_default_namespaces(executable_path);
 
   if (!si->prelink_image()) {
     async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
@@ -341,6 +345,13 @@
 
   // add somain to global group
   si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
+  // ... and add it to all other linked namespaces
+  for (auto linked_ns : namespaces) {
+    if (linked_ns != &g_default_namespace) {
+      linked_ns->add_soinfo(somain);
+      somain->add_secondary_namespace(linked_ns);
+    }
+  }
 
   // Load ld_preloads and dependencies.
   std::vector<const char*> needed_library_name_list;
@@ -358,6 +369,9 @@
   const char** needed_library_names = &needed_library_name_list[0];
   size_t needed_libraries_count = needed_library_name_list.size();
 
+  // readers_map is shared across recursive calls to find_libraries so that we
+  // don't need to re-load elf headers.
+  std::unordered_map<const soinfo*, ElfReader> readers_map;
   if (needed_libraries_count > 0 &&
       !find_libraries(&g_default_namespace,
                       si,
@@ -369,7 +383,9 @@
                       RTLD_GLOBAL,
                       nullptr,
                       true /* add_as_children */,
-                      true /* search_linked_namespaces */)) {
+                      true /* search_linked_namespaces */,
+                      readers_map,
+                      &namespaces)) {
     async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
   } else if (needed_libraries_count == 0) {
     if (!si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr)) {
@@ -488,6 +504,15 @@
   static uintptr_t linktime_addr = reinterpret_cast<uintptr_t>(&linktime_addr);
   ElfW(Addr) linker_addr = reinterpret_cast<uintptr_t>(&linktime_addr) - linktime_addr;
 
+#if defined(__clang_analyzer__)
+  // The analyzer assumes that linker_addr will always be null. Make it an
+  // unknown value so we don't have to mark N places with NOLINTs.
+  //
+  // (`+=`, rather than `=`, allows us to sidestep a potential "unused store"
+  // complaint)
+  linker_addr += reinterpret_cast<uintptr_t>(raw_args);
+#endif
+
   ElfW(Addr) entry_point = args.getauxval(AT_ENTRY);
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
   ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
diff --git a/linker/linker_main.h b/linker/linker_main.h
index 8f3f07c..2cf30c2 100644
--- a/linker/linker_main.h
+++ b/linker/linker_main.h
@@ -31,6 +31,9 @@
 
 #include <android/dlext.h>
 
+#include <unordered_map>
+#include <vector>
+
 #include "linker_namespaces.h"
 #include "linker_soinfo.h"
 
@@ -44,7 +47,9 @@
   static size_t ref_count_;
 };
 
-void init_default_namespace(const char* executable_path);
+class ElfReader;
+
+std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path);
 soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
                      struct stat* file_stat, off64_t file_offset,
                      uint32_t rtld_flags);
@@ -59,7 +64,9 @@
                     int rtld_flags,
                     const android_dlextinfo* extinfo,
                     bool add_as_children,
-                    bool search_linked_namespaces);
+                    bool search_linked_namespaces,
+                    std::unordered_map<const soinfo*, ElfReader>& readers_map,
+                    std::vector<android_namespace_t*>* namespaces = nullptr);
 
 void solist_add_soinfo(soinfo* si);
 bool solist_remove_soinfo(soinfo* si);
diff --git a/linker/linker_namespaces.cpp b/linker/linker_namespaces.cpp
index 3c86f99..9fdf0b5 100644
--- a/linker/linker_namespaces.cpp
+++ b/linker/linker_namespaces.cpp
@@ -31,6 +31,8 @@
 #include "linker_soinfo.h"
 #include "linker_utils.h"
 
+#include <dlfcn.h>
+
 bool android_namespace_t::is_accessible(const std::string& file) {
   if (!is_isolated_) {
     return true;
@@ -86,3 +88,41 @@
     return !is_accessible_ftor(si);
   });
 }
+
+// TODO: this is slightly unusual way to construct
+// the global group for relocation. Not every RTLD_GLOBAL
+// library is included in this group for backwards-compatibility
+// reasons.
+//
+// This group consists of the main executable, LD_PRELOADs
+// and libraries with the DF_1_GLOBAL flag set.
+soinfo_list_t android_namespace_t::get_global_group() {
+  soinfo_list_t global_group;
+  soinfo_list().for_each([&](soinfo* si) {
+    if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
+      global_group.push_back(si);
+    }
+  });
+
+  return global_group;
+}
+
+// This function provides a list of libraries to be shared
+// by the namespace. For the default namespace this is the global
+// group (see get_global_group). For all others this is a group
+// of RTLD_GLOBAL libraries (which includes the global group from
+// the default namespace).
+soinfo_list_t android_namespace_t::get_shared_group() {
+  if (this == &g_default_namespace) {
+    return get_global_group();
+  }
+
+  soinfo_list_t shared_group;
+  soinfo_list().for_each([&](soinfo* si) {
+    if ((si->get_rtld_flags() & RTLD_GLOBAL) != 0) {
+      shared_group.push_back(si);
+    }
+  });
+
+  return shared_group;
+}
diff --git a/linker/linker_namespaces.h b/linker/linker_namespaces.h
index 1099b6b..16906d6 100644
--- a/linker/linker_namespaces.h
+++ b/linker/linker_namespaces.h
@@ -136,6 +136,9 @@
   // or one of it's parent soinfos belongs to this namespace.
   bool is_accessible(soinfo* si);
 
+  soinfo_list_t get_global_group();
+  soinfo_list_t get_shared_group();
+
  private:
   const char* name_;
   bool is_isolated_;
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 42c29c8..a9873c4 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -147,8 +147,9 @@
 }
 
 bool ElfReader::Read(const char* name, int fd, off64_t file_offset, off64_t file_size) {
-  CHECK(!did_read_);
-  CHECK(!did_load_);
+  if (did_read_) {
+    return true;
+  }
   name_ = name;
   fd_ = fd;
   file_offset_ = file_offset;
@@ -167,7 +168,9 @@
 
 bool ElfReader::Load(const android_dlextinfo* extinfo) {
   CHECK(did_read_);
-  CHECK(!did_load_);
+  if (did_load_) {
+    return true;
+  }
   if (ReserveAddressSpace(extinfo) &&
       LoadSegments() &&
       FindPhdr()) {
diff --git a/linker/tests/linker_config_test.cpp b/linker/tests/linker_config_test.cpp
index b024011..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);
@@ -174,7 +168,6 @@
   run_linker_config_smoke_test(false);
 }
 
-// TODO(b/38114603) revive this test when ld.config.txt is enabled for ASAN mode
-//TEST(linker_config, asan_smoke) {
-//  run_linker_config_smoke_test(true);
-//}
+TEST(linker_config, asan_smoke) {
+  run_linker_config_smoke_test(true);
+}
diff --git a/tests/Android.bp b/tests/Android.bp
index a03f1a6..e8fa5bd 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",
@@ -132,6 +134,7 @@
         "sys_sysmacros_test.cpp",
         "sys_time_test.cpp",
         "sys_timex_test.cpp",
+        "sys_ttydefaults_test.cpp",
         "sys_types_test.cpp",
         "sys_uio_test.cpp",
         "sys_vfs_test.cpp",
@@ -286,6 +289,7 @@
             ],
             static_libs: [
                 "libpagemap",
+                "libziparchive",
                 "libLLVMObject",
                 "libLLVMBitReader",
                 "libLLVMMC",
@@ -294,7 +298,13 @@
                 "libLLVMSupport",
             ],
         }
-    }
+    },
+
+    product_variables: {
+        debuggable: {
+            cppflags: ["-DUSE_LD_CONFIG_FILE"],
+        },
+    },
 }
 
 // -----------------------------------------------------------------------------
@@ -595,6 +605,12 @@
     sanitize: {
         never: false,
     },
+
+    product_variables: {
+        debuggable: {
+            cppflags: ["-DUSE_LD_CONFIG_FILE"],
+        },
+    },
 }
 
 subdirs = ["libs"]
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index aa8bd57..857640a 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -23,6 +23,8 @@
 #include <stdint.h>
 
 #include <string>
+#include <iostream>
+#include <fstream>
 
 #include "gtest_globals.h"
 #include "utils.h"
@@ -109,4 +111,131 @@
 #endif
 }
 
-// TODO: Add tests for LD_PRELOADs
+
+TEST(dl, exec_without_ld_preload) {
+#if defined(__BIONIC__)
+  std::string helper = get_testlib_root() +
+      "/ld_preload_test_helper/ld_preload_test_helper";
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345");
+#endif
+}
+
+TEST(dl, exec_with_ld_preload) {
+#if defined(__BIONIC__)
+  std::string helper = get_testlib_root() +
+      "/ld_preload_test_helper/ld_preload_test_helper";
+  std::string env = std::string("LD_PRELOAD=") + get_testlib_root() + "/ld_preload_test_helper_lib2.so";
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.SetEnv({ env.c_str(), nullptr });
+  // ld_preload_test_helper calls get_value_from_lib() and returns the value.
+  // The symbol is defined by two libs: ld_preload_test_helper_lib.so and
+  // ld_preloaded_lib.so. The former is DT_NEEDED and the latter is LD_PRELOADED
+  // via this execution. The main executable is linked to the LD_PRELOADED lib
+  // and the value given from the lib is returned.
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321");
+#endif
+}
+
+
+// ld_config_test_helper must fail because it is depending on a lib which is not
+// in the search path
+//
+// Call sequence is...
+// _helper -- (get_value_from_lib()) -->
+//     _lib1.so -- (get_value_from_another_lib()) -->
+//       _lib2.so (returns 12345)
+// The two libs are in ns2/ subdir.
+TEST(dl, exec_without_ld_config_file) {
+#if defined(__BIONIC__)
+  std::string error_message = "CANNOT LINK EXECUTABLE \"" + get_testlib_root() + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" not found\n";
+  std::string helper = get_testlib_root() +
+      "/ld_config_test_helper/ld_config_test_helper";
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, -6, error_message.c_str());
+#endif
+}
+
+#if defined(__BIONIC__)
+static void create_ld_config_file(std::string& config_file) {
+  std::ofstream fout(config_file.c_str(), std::ios::out);
+  fout << "dir.test = " << get_testlib_root() << "/ld_config_test_helper/" << std::endl
+       << "[test]" << std::endl
+       << "additional.namespaces = ns2" << std::endl
+       << "namespace.default.search.paths = " << get_testlib_root() << std::endl
+       << "namespace.default.links = ns2" << std::endl
+       << "namespace.default.link.ns2.shared_libs = libc.so:libm.so:libdl.so:ld_config_test_helper_lib1.so" << std::endl
+       << "namespace.ns2.search.paths = /system/${LIB}:" << get_testlib_root() << "/ns2" << std::endl;
+  fout.close();
+}
+#endif
+
+#ifdef USE_LD_CONFIG_FILE
+
+// _lib1.so and _lib2.so are now searchable by having another namespace 'ns2'
+// whose search paths include the 'ns2/' subdir.
+TEST(dl, exec_with_ld_config_file) {
+#if defined(__BIONIC__)
+  std::string helper = get_testlib_root() +
+      "/ld_config_test_helper/ld_config_test_helper";
+  std::string config_file = get_testlib_root() + "/ld.config.txt";
+  create_ld_config_file(config_file);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file;
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.SetEnv({ env.c_str(), nullptr });
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345");
+#endif
+}
+
+// _lib3.so has same symbol as lib2.so but returns 54321. _lib3.so is
+// LD_PRELOADed. This test is to ensure LD_PRELOADed libs are available to
+// additional namespaces other than the default namespace.
+TEST(dl, exec_with_ld_config_file_with_ld_preload) {
+#if defined(__BIONIC__)
+  std::string helper = get_testlib_root() +
+      "/ld_config_test_helper/ld_config_test_helper";
+  std::string config_file = get_testlib_root() + "/ld.config.txt";
+  create_ld_config_file(config_file);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file;
+  std::string env2 = std::string("LD_PRELOAD=") + get_testlib_root() + "/ld_config_test_helper_lib3.so";
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.SetEnv({ env.c_str(), env2.c_str(), nullptr });
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321");
+#endif
+}
+
+#endif // USE_LD_CONFIG_FILE
+
+// ensures that LD_CONFIG_FILE env var does not work for production builds.
+// The test input is the same as exec_with_ld_config_file, but it must fail in
+// this case.
+TEST(dl, disable_ld_config_file) {
+#if defined(__BIONIC__)
+  if (getuid() == 0) {
+    // when executed from the shell (e.g. not as part of CTS), skip the test.
+    // This test is only for CTS.
+    return;
+  }
+  std::string error_message = "CANNOT LINK EXECUTABLE \"" + get_testlib_root() + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" not found\n";
+  std::string helper = get_testlib_root() +
+      "/ld_config_test_helper/ld_config_test_helper";
+  std::string config_file = get_testlib_root() + "/ld.config.txt";
+  create_ld_config_file(config_file);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file;
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.SetEnv({ env.c_str(), nullptr });
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, -6, error_message.c_str());
+#endif
+}
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 4901d50..1e2b6c9 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1271,6 +1271,37 @@
   dlclose(handle);
 }
 
+TEST(dlfcn, dt_runpath_absolute_path) {
+  std::string libpath = get_testlib_root() + "/libtest_dt_runpath_d.so";
+  void* handle = dlopen(libpath.c_str(), RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+
+  typedef void *(* dlopen_b_fn)();
+  dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
+  ASSERT_TRUE(fn != nullptr) << dlerror();
+
+  void *p = fn();
+  ASSERT_TRUE(p != nullptr);
+
+  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__)
 
@@ -1352,21 +1383,6 @@
 
 #endif //  defined(__arm__)
 
-TEST(dlfcn, dt_runpath_absolute_path) {
-  std::string libpath = get_testlib_root() + "/libtest_dt_runpath_d.so";
-  void* handle = dlopen(libpath.c_str(), RTLD_NOW);
-  ASSERT_TRUE(handle != nullptr) << dlerror();
-
-  typedef void *(* dlopen_b_fn)();
-  dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
-  ASSERT_TRUE(fn != nullptr) << dlerror();
-
-  void *p = fn();
-  ASSERT_TRUE(p != nullptr);
-
-  dlclose(handle);
-}
-
 TEST(dlfcn, dlopen_invalid_rw_load_segment) {
   const std::string libpath = get_testlib_root() +
                               "/" + kPrebuiltElfDir +
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/tests/errno_test.cpp
similarity index 62%
copy from libc/arch-arm/include/machine/cpu-features.h
copy 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/fcntl_test.cpp b/tests/fcntl_test.cpp
index 74d3675..f385311 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -279,9 +279,10 @@
 }
 
 /*
- * Kernels less than 4.1 are affected.
- * Devices that fail this test should include change id from Nexus:
- * Commit: 9b431291a1fadbdbcca1485711b5bab145112293
+ * b/28760453:
+ * Kernels older than 4.1 should have ext4 FALLOC_FL_PUNCH_HOLE disabled due to CVE-2015-8839.
+ * Devices that fail this test should cherry-pick the following commit:
+ * https://android.googlesource.com/kernel/msm/+/bdba352e898cbf57c8620ad68c8abf749c784d1f
  */
 TEST(fcntl, falloc_punch) {
   long major = 0, minor = 0;
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 973a8d2..c1600cc 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -617,3 +617,59 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["preinit_syscall_test_helper.cpp"],
 }
+
+cc_test {
+    name: "ld_preload_test_helper",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["ld_preload_test_helper.cpp"],
+    shared_libs: ["ld_preload_test_helper_lib1"],
+    ldflags: ["-Wl,--rpath,${ORIGIN}/.."],
+}
+
+cc_test_library {
+    name: "ld_preload_test_helper_lib1",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["ld_preload_test_helper_lib1.cpp"],
+}
+
+cc_test_library {
+    name: "ld_preload_test_helper_lib2",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["ld_preload_test_helper_lib2.cpp"],
+}
+
+cc_test {
+    name: "ld_config_test_helper",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["ld_config_test_helper.cpp"],
+    shared_libs: ["ld_config_test_helper_lib1"],
+    ldflags: ["-Wl,--rpath,${ORIGIN}/.."],
+}
+
+cc_test_library {
+    name: "ld_config_test_helper_lib1",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["ld_config_test_helper_lib1.cpp"],
+    shared_libs: ["ld_config_test_helper_lib2"],
+    relative_install_path: "/ns2",
+}
+
+cc_test_library {
+    name: "ld_config_test_helper_lib2",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["ld_config_test_helper_lib2.cpp"],
+    relative_install_path: "/ns2",
+}
+
+cc_test_library {
+    name: "ld_config_test_helper_lib3",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["ld_config_test_helper_lib3.cpp"],
+}
diff --git a/tests/libs/ld_config_test_helper.cpp b/tests/libs/ld_config_test_helper.cpp
new file mode 100644
index 0000000..592e8c0
--- /dev/null
+++ b/tests/libs/ld_config_test_helper.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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 <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern int get_value_from_lib();
+
+int main() {
+  printf("%d", get_value_from_lib());
+  return 0;
+}
diff --git a/tests/libs/ld_config_test_helper_lib1.cpp b/tests/libs/ld_config_test_helper_lib1.cpp
new file mode 100644
index 0000000..fc5401a
--- /dev/null
+++ b/tests/libs/ld_config_test_helper_lib1.cpp
@@ -0,0 +1,4 @@
+extern int get_value_from_another_lib();
+int get_value_from_lib() {
+  return get_value_from_another_lib();
+}
diff --git a/tests/libs/ld_config_test_helper_lib2.cpp b/tests/libs/ld_config_test_helper_lib2.cpp
new file mode 100644
index 0000000..a620a6c
--- /dev/null
+++ b/tests/libs/ld_config_test_helper_lib2.cpp
@@ -0,0 +1,3 @@
+int get_value_from_another_lib() {
+  return 12345;
+}
diff --git a/tests/libs/ld_config_test_helper_lib3.cpp b/tests/libs/ld_config_test_helper_lib3.cpp
new file mode 100644
index 0000000..93d1cd8
--- /dev/null
+++ b/tests/libs/ld_config_test_helper_lib3.cpp
@@ -0,0 +1,3 @@
+int get_value_from_another_lib() {
+  return 54321;
+}
diff --git a/tests/libs/ld_preload_test_helper.cpp b/tests/libs/ld_preload_test_helper.cpp
new file mode 100644
index 0000000..592e8c0
--- /dev/null
+++ b/tests/libs/ld_preload_test_helper.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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 <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern int get_value_from_lib();
+
+int main() {
+  printf("%d", get_value_from_lib());
+  return 0;
+}
diff --git a/tests/libs/ld_preload_test_helper_lib1.cpp b/tests/libs/ld_preload_test_helper_lib1.cpp
new file mode 100644
index 0000000..74e89db
--- /dev/null
+++ b/tests/libs/ld_preload_test_helper_lib1.cpp
@@ -0,0 +1,3 @@
+int get_value_from_lib() {
+  return 12345;
+}
diff --git a/tests/libs/ld_preload_test_helper_lib2.cpp b/tests/libs/ld_preload_test_helper_lib2.cpp
new file mode 100644
index 0000000..9239891
--- /dev/null
+++ b/tests/libs/ld_preload_test_helper_lib2.cpp
@@ -0,0 +1,3 @@
+int get_value_from_lib() {
+  return 54321;
+}
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) {
diff --git a/tests/sys_ptrace_test.cpp b/tests/sys_ptrace_test.cpp
index 00322ec..78fcf2b 100644
--- a/tests/sys_ptrace_test.cpp
+++ b/tests/sys_ptrace_test.cpp
@@ -66,14 +66,28 @@
   long result = ptrace(PTRACE_GETHBPREGS, child, 0, &capabilities);
   if (result == -1) {
     EXPECT_EQ(EIO, errno);
+    GTEST_LOG_(INFO) << "Hardware debug support disabled at kernel configuration time.";
     return false;
   }
-  switch (feature) {
-    case HwFeature::Watchpoint:
-      return ((capabilities >> 8) & 0xff) > 0;
-    case HwFeature::Breakpoint:
-      return (capabilities & 0xff) > 0;
+  uint8_t hb_count = capabilities & 0xff;
+  capabilities >>= 8;
+  uint8_t wp_count = capabilities & 0xff;
+  capabilities >>= 8;
+  uint8_t max_wp_size = capabilities & 0xff;
+  if (max_wp_size == 0) {
+    GTEST_LOG_(INFO)
+        << "Kernel reports zero maximum watchpoint size. Hardware debug support missing.";
+    return false;
   }
+  if (feature == HwFeature::Watchpoint && wp_count == 0) {
+    GTEST_LOG_(INFO) << "Kernel reports zero hardware watchpoints";
+    return false;
+  }
+  if (feature == HwFeature::Breakpoint && hb_count == 0) {
+    GTEST_LOG_(INFO) << "Kernel reports zero hardware breakpoints";
+    return false;
+  }
+  return true;
 #elif defined(__aarch64__)
   user_hwdebug_state dreg_state;
   iovec iov;
diff --git a/tests/sys_ttydefaults_test.cpp b/tests/sys_ttydefaults_test.cpp
new file mode 100644
index 0000000..fa4f7c7
--- /dev/null
+++ b/tests/sys_ttydefaults_test.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <sys/ttydefaults.h>
+#include <termios.h>
+
+TEST(sys_ttydefaults, flags) {
+  int i;
+  i = TTYDEF_IFLAG;
+  i = TTYDEF_OFLAG;
+  i = TTYDEF_LFLAG;
+  i = TTYDEF_CFLAG;
+  i = TTYDEF_SPEED;
+}
+
+TEST(sys_ttydefaults, correct_CEOL) {
+  ASSERT_EQ(_POSIX_VDISABLE, CEOL);
+}
diff --git a/tests/uchar_test.cpp b/tests/uchar_test.cpp
index c887f8a..8b29667 100644
--- a/tests/uchar_test.cpp
+++ b/tests/uchar_test.cpp
@@ -280,7 +280,10 @@
 
   char bytes[MB_LEN_MAX];
 
+  memset(bytes, 1, sizeof(bytes));
   EXPECT_EQ(1U, c32rtomb(bytes, L'\0', NULL));
+  EXPECT_EQ('\0', bytes[0]);
+  EXPECT_EQ('\x01', bytes[1]);
 
   memset(bytes, 0, sizeof(bytes));
   EXPECT_EQ(1U, c32rtomb(bytes, L'h', NULL));
@@ -408,4 +411,3 @@
   GTEST_LOG_(INFO) << "uchar.h is unavailable.\n";
 #endif
 }
-
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 9a80409..a81f112 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -759,6 +759,7 @@
   EXPECT_GT(_POSIX_TZNAME_MAX, 0);
   EXPECT_NE(-1, _POSIX_VDISABLE);
 
+  EXPECT_EQ(_POSIX_VERSION, _POSIX2_VERSION);
   EXPECT_GT(_POSIX2_BC_BASE_MAX, 0);
   EXPECT_GT(_POSIX2_BC_DIM_MAX, 0);
   EXPECT_GT(_POSIX2_BC_SCALE_MAX, 0);
@@ -774,12 +775,6 @@
   EXPECT_GT(_XOPEN_IOV_MAX, 0);
   EXPECT_GT(_XOPEN_UNIX, 0);
 
-  // In O, the headers still have -1 (even though all the functionality has
-  // been there for a long time). This was fixed in O-DR, but there isn't a
-  // separate CTS for O-DR, so we'll accept both.
-  EXPECT_TRUE(_POSIX_THREAD_PROCESS_SHARED == -1 ||
-              _POSIX_THREAD_PROCESS_SHARED == _POSIX_VERSION);
-
 #if defined(__BIONIC__)
   // These tests only pass on bionic, as bionic and glibc has different support on these macros.
   // Macros like _POSIX_ASYNCHRONOUS_IO are not supported on bionic yet.
@@ -790,7 +785,6 @@
   EXPECT_EQ(-1, _POSIX_SPAWN);
   EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_INHERIT);
 
-  EXPECT_EQ(-1, _POSIX2_VERSION);
   EXPECT_EQ(-1, _POSIX2_CHAR_TERM);
   EXPECT_EQ(-1, _POSIX2_C_DEV);
   EXPECT_EQ(-1, _POSIX2_LOCALEDEF);
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 830eb70..097647f 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -445,6 +445,18 @@
   ASSERT_EQ(L'e', dst[1]);
   ASSERT_EQ(L'l', dst[2]);
   ASSERT_EQ(&s[3], src);
+
+  memset(dst, 0, sizeof(dst));
+  const char* incomplete = "\xc2"; // Incomplete UTF-8 sequence.
+  src = incomplete;
+  errno = 0;
+  ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(dst, &src, SIZE_MAX, 3, nullptr));
+  ASSERT_EQ(EILSEQ, errno);
+
+  src = incomplete;
+  errno = 0;
+  ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(nullptr, &src, SIZE_MAX, 3, nullptr));
+  ASSERT_EQ(EILSEQ, errno);
 }
 
 TEST(wchar, wcsftime) {
diff --git a/tools/relocation_packer/src/elf_file.cc b/tools/relocation_packer/src/elf_file.cc
index 96e6efd..275e486 100644
--- a/tools/relocation_packer/src/elf_file.cc
+++ b/tools/relocation_packer/src/elf_file.cc
@@ -234,24 +234,22 @@
   }
 
   // Loading failed if we did not find the required special sections.
-  if (!found_relocations_section) {
-    LOG(ERROR) << "Missing or empty .rel.dyn or .rela.dyn section";
-    return false;
-  }
   if (!found_dynamic_section) {
     LOG(ERROR) << "Missing .dynamic section";
     return false;
   }
 
-  // Loading failed if we could not identify the relocations type.
-  if (!has_rel_relocations && !has_rela_relocations) {
-    LOG(ERROR) << "No relocations sections found";
-    return false;
-  }
-  if (has_rel_relocations && has_rela_relocations) {
-    LOG(ERROR) << "Multiple relocations sections with different types found, "
-               << "not currently supported";
-    return false;
+  if (found_relocations_section != nullptr) {
+    // Loading failed if we could not identify the relocations type.
+    if (!has_rel_relocations && !has_rela_relocations) {
+      LOG(ERROR) << "No relocations sections found";
+      return false;
+    }
+    if (has_rel_relocations && has_rela_relocations) {
+      LOG(ERROR) << "Multiple relocations sections with different types found, "
+                 << "not currently supported";
+      return false;
+    }
   }
 
   elf_ = elf;
@@ -682,6 +680,11 @@
     return false;
   }
 
+  if (relocations_section_ == nullptr) {
+    // There is nothing to do
+    return true;
+  }
+
   // Retrieve the current dynamic relocations section data.
   Elf_Data* data = GetSectionData(relocations_section_);
   // we always pack rela, because packed format is pretty much the same
@@ -831,6 +834,11 @@
     return false;
   }
 
+  if (relocations_section_ == nullptr) {
+    // There is nothing to do
+    return true;
+  }
+
   typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
   // Retrieve the current packed android relocations section data.
   Elf_Data* data = GetSectionData(relocations_section_);