Merge "Support larger guard regions."
diff --git a/README.md b/README.md
index cd409d9..7114015 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+Using bionic
+============
+
+See the [additional documentation](docs/).
+
 Working on bionic
 =================
 
@@ -43,7 +48,7 @@
 
 #### benchmarks/ --- benchmarks
 
-The `benchmarks/` directory contains benchmarks.
+The `benchmarks/` directory contains benchmarks, with its own [documentation](benchmarks/README.md).
 
 
 What's in libc/?
@@ -298,35 +303,6 @@
 The coverage report is now available at `covreport/index.html`.
 
 
-Running the benchmarks
-----------------------
-
-### Device benchmarks
-
-    $ mma
-    $ adb remount
-    $ adb sync
-    $ adb shell /data/nativetest/bionic-benchmarks/bionic-benchmarks
-    $ adb shell /data/nativetest64/bionic-benchmarks/bionic-benchmarks
-
-When operated without specifying an xml file, the default is to use the xml
-file called full.xml found in the directory `suites/` bound in the same directory
-as the bionic-benchmarks executable.
-
-To use a different xml file, use the `--bionic_xml=FILE.XML` option. By default, this
-option searches for the xml file in the `suites/` directory. If it doesn't exist
-in that directory then the file will be found as relative to the current
-directory. If the option specifies the full path to an xml file such as
-`/data/nativetest/suites/example.xml`, it will be used as is.
-
-You can use `--benchmark_filter=getpid` to just run benchmarks with "getpid"
-in their name.
-
-### Host benchmarks
-
-See the "Host tests" section of "Running the tests" above. The default for
-host tests is to use the `host.xml` file in the suites directory instead of `full.xml`.
-
 Attaching GDB to the tests
 --------------------------
 
@@ -341,54 +317,4 @@
 32-bit ABI bugs
 ---------------
 
-### `off_t` is 32-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.
-
-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.
-
-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.
+See [32-bit ABI bugs](docs/32-bit-abi.md).
diff --git a/benchmarks/README.md b/benchmarks/README.md
index 6501839..9cb130d 100644
--- a/benchmarks/README.md
+++ b/benchmarks/README.md
@@ -1,10 +1,41 @@
 Bionic Benchmarks
 =================
+
 Bionic benchmarks is a command line tool for measuring the runtimes of libc functions. It is built
 on top of [Google benchmarks](https://github.com/google/benchmark) with some additions to organize
 tests into suites.
 
-Instructions for running these can be found in the platform_bionic README.
+Running the benchmarks
+----------------------
+
+### Device benchmarks
+
+    $ mma
+    $ adb remount
+    $ adb sync
+    $ adb shell /data/nativetest/bionic-benchmarks/bionic-benchmarks
+    $ adb shell /data/nativetest64/bionic-benchmarks/bionic-benchmarks
+
+When operated without specifying an xml file, the default is to use the
+xml file called full.xml found in the directory `suites/` bound in the
+same directory as the bionic-benchmarks executable.
+
+To use a different xml file, use the `--bionic_xml=FILE.XML` option. By
+default, this option searches for the xml file in the `suites/`
+directory. If it doesn't exist in that directory then the file will be
+found as relative to the current directory. If the option specifies the
+full path to an xml file such as `/data/nativetest/suites/example.xml`,
+it will be used as is.
+
+You can use `--benchmark_filter=getpid` to just run benchmarks with "getpid"
+in their name.
+
+### Host benchmarks
+
+See the benchmarks/run-on-host.sh script. The default for host tests is
+to use the `host.xml` file in the suites directory instead of `full.xml`.
+The host benchmarks can be run with 32- or 64-bit bionic, or the host glibc.
+
 
 ## Suites
 
diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md
new file mode 100644
index 0000000..eecbe6d
--- /dev/null
+++ b/docs/32-bit-abi.md
@@ -0,0 +1,59 @@
+32-bit ABI bugs
+===============
+
+`off_t` is 32-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.
+
+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.
+
+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/docs/status.md b/docs/status.md
new file mode 100644
index 0000000..25f5663
--- /dev/null
+++ b/docs/status.md
@@ -0,0 +1,142 @@
+Android bionic status
+=====================
+
+libc
+----
+
+Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/libc/libc.map.txt
+
+New libc functions in P:
+  * `__freading`/`__fwriting` (completing <stdio_ext.h>)
+  * `getlogin_r`
+  * `iconv`/`iconv_close`/`iconv_open` (adding <iconv.h>)
+  * `syncfs`
+
+New libc functions in O:
+  * `sendto` FORTIFY support
+  * `__system_property_read_callback`/`__system_property_wait`
+  * legacy `bsd_signal`
+  * `catclose`/`catgets`/`catopen` (adding <nl_types.h>)
+  * `ctermid`
+  * all 6 <grp.h>/<pwd.h> (get|set|end)(gr|pw)ent functions
+  * `futimes`/`futimesat`/`lutimes`
+  * `getdomainname`/`setdomainname`
+  * `getsubopt`
+  * `hasmntopt`
+  * `mallopt`
+  * `mblen`
+  * 4 <sys/msg.h> `msg*` functions
+  * <langinfo.h> `nl_langinfo`/`nl_langinfo_l`
+  * `pthread_getname_np`
+  * 2 new Linux system calls `quotactl` and `sync_file_range`
+  * 4 <sys/sem.h> `sem*` functions
+  * 4 <sys/shm.h> `shm*` functions
+  * 5 legacy <signal.h> functions: `sighold`/`sigignore`/`sigpause`/`sigrelse`/`sigset`
+  * `strtod_l`/`strtof_l`/`strtol_l`/`strtoul_l`
+  * <wctype.h> `towctrans`/`towctrans_l`/`wctrans`/`wctrans_l`
+
+New libc functions in N:
+  * more FORTIFY support functions (`fread`/`fwrite`/`getcwd`/`pwrite`/`write`)
+  * all remaining `_FILE_OFFSET_BITS=64` functions, completing `_FILE_OFFSET_BITS=64` support in bionic (8)
+  * all 7 `pthread_barrier*` functions
+  * all 5 `pthread_spin*` functions
+  * `lockf`/`preadv`/`pwritev`/`scandirat` and `off64_t` variants
+  * `adjtimex`/`clock_adjtime`
+  * `getifaddrs`/`freeifaddrs`/`if_freenameindex`/`if_nameindex`
+  * `getgrgid_r`/`getgrnam_r`
+  * GNU extensions `fileno_unlocked`/`strchrnul`
+  * 32-bit `prlimit`
+
+libc function count over time:
+  G 803, H 825, I 826, J 846, J-MR1 873, J-MR2 881, K 896, L 1116, M 1181, N 1226, O 1278
+
+```
+ndk-r17$ for i in `ls -1v platforms/android-*/arch-arm/usr/lib/libc.so` ; do echo $i; nm $i | grep -vw [AbdNnt] | grep -vw B | wc -l ; done
+```
+
+Run `./libc/tools/check-symbols-glibc.py` in bionic/ for the current
+list of POSIX functions implemented by glibc but not by bionic. Currently
+(2017-09):
+```
+aio_cancel
+aio_error
+aio_fsync
+aio_read
+aio_return
+aio_suspend
+aio_write
+endhostent
+endnetent
+endprotoent
+endutxent
+fexecve
+fmtmsg
+getdate
+getdate_err
+getnetent
+getprotoent
+glob
+globfree
+hcreate
+hdestroy
+hsearch
+lio_listio
+posix_spawn
+posix_spawn_file_actions_addclose
+posix_spawn_file_actions_adddup2
+posix_spawn_file_actions_addopen
+posix_spawn_file_actions_destroy
+posix_spawn_file_actions_init
+posix_spawnattr_destroy
+posix_spawnattr_getflags
+posix_spawnattr_getpgroup
+posix_spawnattr_getschedparam
+posix_spawnattr_getschedpolicy
+posix_spawnattr_getsigdefault
+posix_spawnattr_getsigmask
+posix_spawnattr_init
+posix_spawnattr_setflags
+posix_spawnattr_setpgroup
+posix_spawnattr_setschedparam
+posix_spawnattr_setschedpolicy
+posix_spawnattr_setsigdefault
+posix_spawnattr_setsigmask
+posix_spawnp
+pthread_attr_getinheritsched
+pthread_attr_setinheritsched
+pthread_cancel
+pthread_getconcurrency
+pthread_mutex_consistent
+pthread_mutex_getprioceiling
+pthread_mutex_setprioceiling
+pthread_mutexattr_getprioceiling
+pthread_mutexattr_getprotocol
+pthread_mutexattr_getrobust
+pthread_mutexattr_setprioceiling
+pthread_mutexattr_setprotocol
+pthread_mutexattr_setrobust
+pthread_setcancelstate
+pthread_setcanceltype
+pthread_setconcurrency
+pthread_setschedprio
+pthread_testcancel
+sethostent
+setnetent
+setprotoent
+sockatmark
+swab
+wordexp
+wordfree
+```
+
+libm
+----
+
+Current libm symbols: https://android.googlesource.com/platform/bionic/+/master/libm/libm.map.txt
+
+0 remaining missing POSIX libm functions.
+
+19 new libm functions in O: complex trig/exp/log functions.
+
+libm function count over time:
+  G 158, J-MR2 164, L 220, M 265, O 284
diff --git a/libc/Android.bp b/libc/Android.bp
index 204ad19..8932be6 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -72,7 +72,6 @@
         never: true,
     },
     native_coverage: false,
-    clang: true,
 }
 
 // ANDROIDMK TRANSLATION ERROR: unsupported directive
@@ -218,6 +217,10 @@
         "upstream-freebsd/lib/libc/gen/sleep.c",
         "upstream-freebsd/lib/libc/gen/usleep.c",
         "upstream-freebsd/lib/libc/stdlib/getopt_long.c",
+        "upstream-freebsd/lib/libc/stdlib/hcreate.c",
+        "upstream-freebsd/lib/libc/stdlib/hcreate_r.c",
+        "upstream-freebsd/lib/libc/stdlib/hdestroy_r.c",
+        "upstream-freebsd/lib/libc/stdlib/hsearch_r.c",
         "upstream-freebsd/lib/libc/stdlib/qsort.c",
         "upstream-freebsd/lib/libc/stdlib/quick_exit.c",
         "upstream-freebsd/lib/libc/string/wcpcpy.c",
@@ -282,6 +285,7 @@
     cflags: [
         "-Wno-sign-compare",
         "-Wno-uninitialized",
+        "-Wno-unused-parameter",
         "-include freebsd-compat.h",
     ],
 
@@ -1567,7 +1571,11 @@
             srcs: ["bionic/mmap.cpp"],
         },
     },
-
+    product_variables: {
+        treble: {
+            cflags: ["-D__ANDROID_TREBLE__"],
+        },
+    },
     cppflags: ["-Wold-style-cast"],
     local_include_dirs: ["stdio"],
     include_dirs: ["bionic/libstdc++/include"],
@@ -1975,7 +1983,6 @@
             local_include_dirs: ["arch-x86_64/include"],
         },
     },
-    clang: true,
 }
 
 cc_defaults {
diff --git a/libc/NOTICE b/libc/NOTICE
index 90de7ef..feea29d 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -5644,6 +5644,31 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2015 Nuxi, https://nuxi.nl/
+
+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) 2017 Imagination Technologies.
 
 All rights reserved.
diff --git a/libc/arch-x86/bionic/__set_tls.cpp b/libc/arch-x86/bionic/__set_tls.cpp
index 241d94a..3f58bc5 100644
--- a/libc/arch-x86/bionic/__set_tls.cpp
+++ b/libc/arch-x86/bionic/__set_tls.cpp
@@ -28,7 +28,6 @@
 
 #include <limits.h>
 #include <pthread.h>
-#include <stdbool.h>
 
 #include <asm/ldt.h>
 
diff --git a/libc/bionic/__bionic_get_shell_path.cpp b/libc/bionic/__bionic_get_shell_path.cpp
index 477fa4a..41162e9 100644
--- a/libc/bionic/__bionic_get_shell_path.cpp
+++ b/libc/bionic/__bionic_get_shell_path.cpp
@@ -31,18 +31,24 @@
 #include <sys/cdefs.h>
 #include <unistd.h>
 
-__LIBC_HIDDEN__ static const char* __libc_system_sh = "/system/bin/sh";
-__LIBC_HIDDEN__ static const char* __libc_vendor_sh = "/vendor/bin/sh";
+#define VENDOR_PREFIX "/vendor/"
 
 static const char* init_sh_path() {
-  /* look for /system or /vendor prefix */
-  char exe_path[7];
-  ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
-  if (len != -1 && !strncmp(exe_path, __libc_vendor_sh, sizeof(exe_path))) {
-    return __libc_vendor_sh;
-  }
+  /* If the device is not treble enabled, return the path to the system shell.
+   * Vendor code, on non-treble enabled devices could use system() / popen()
+   * with relative paths for executables on /system. Since /system will not be
+   * in $PATH for the vendor shell, simply return the system shell.
+   */
 
-  return __libc_system_sh;
+#ifdef __ANDROID_TREBLE__
+  /* look for /system or /vendor prefix */
+  char exe_path[strlen(VENDOR_PREFIX)];
+  ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
+  if (len != -1 && !strncmp(exe_path, VENDOR_PREFIX, strlen(VENDOR_PREFIX))) {
+    return "/vendor/bin/sh";
+  }
+#endif
+  return "/system/bin/sh";
 }
 
 __LIBC_HIDDEN__ extern "C" const char* __bionic_get_shell_path() {
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index 39d6e09..fc9e74a 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -164,7 +164,7 @@
   // Hunt for the region that contains that address.
   FILE* fp = fopen("/proc/self/maps", "re");
   if (fp == nullptr) {
-    async_safe_fatal("couldn't open /proc/self/maps");
+    async_safe_fatal("couldn't open /proc/self/maps: %s", strerror(errno));
   }
   char line[BUFSIZ];
   while (fgets(line, sizeof(line), fp) != NULL) {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index dc1b984..09ae16c 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -59,14 +59,14 @@
   size_t allocation_size = BIONIC_TLS_SIZE + (2 * PTHREAD_GUARD_SIZE);
   void* allocation = mmap(nullptr, allocation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   if (allocation == MAP_FAILED) {
-    async_safe_fatal("failed to allocate TLS");
+    async_safe_fatal("failed to allocate TLS: %s", strerror(errno));
   }
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard");
 
   thread->bionic_tls = reinterpret_cast<bionic_tls*>(static_cast<char*>(allocation) +
                                                      PTHREAD_GUARD_SIZE);
   if (mprotect(thread->bionic_tls, BIONIC_TLS_SIZE, PROT_READ | PROT_WRITE) != 0) {
-    async_safe_fatal("failed to mprotect TLS");
+    async_safe_fatal("failed to mprotect TLS: %s", strerror(errno));
   }
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->bionic_tls, BIONIC_TLS_SIZE, "bionic TLS");
 }
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index abd403b..829194c 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -104,9 +104,13 @@
   // Check if we're looking for ourselves before acquiring the lock.
   if (thread == __get_thread()) return thread;
 
-  ScopedReadLock locker(&g_thread_list_lock);
-  for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
-    if (t == thread) return thread;
+  {
+    // Make sure to release the lock before the abort below. Otherwise,
+    // some apps might deadlock in their own crash handlers (see b/6565627).
+    ScopedReadLock locker(&g_thread_list_lock);
+    for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
+      if (t == thread) return thread;
+    }
   }
 
   // Historically we'd return null, but
diff --git a/libc/bionic/strtold.cpp b/libc/bionic/strtold.cpp
index c55dd61..6b673e6 100644
--- a/libc/bionic/strtold.cpp
+++ b/libc/bionic/strtold.cpp
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+
 #include <float.h>
 #include <stdlib.h>
 
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 6906ecd..c57cd9c 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -31,7 +31,6 @@
 #include <fcntl.h>
 #include <poll.h>
 #include <stdatomic.h>
-#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/libc/bionic/tdestroy.cpp b/libc/bionic/tdestroy.cpp
index 95c3e64..2968ff9 100644
--- a/libc/bionic/tdestroy.cpp
+++ b/libc/bionic/tdestroy.cpp
@@ -14,10 +14,15 @@
  * limitations under the License.
  */
 
-#define _SEARCH_PRIVATE
 #include <search.h>
 #include <stdlib.h>
 
+struct node_t {
+  char* key;
+  struct node* llink;
+  struct node* rlink;
+};
+
 // Destroy a tree and free all allocated resources.
 // This is a GNU extension, not available from BSD.
 void tdestroy(void* root, void (*destroy_func)(void*)) {
diff --git a/libc/bionic/wcstod.cpp b/libc/bionic/wcstod.cpp
index f7bd433..41df854 100644
--- a/libc/bionic/wcstod.cpp
+++ b/libc/bionic/wcstod.cpp
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+
 #include <wchar.h>
 
 #include <stdlib.h>
diff --git a/libc/include/complex.h b/libc/include/complex.h
index 79fe07c..3fe8f35 100644
--- a/libc/include/complex.h
+++ b/libc/include/complex.h
@@ -61,99 +61,99 @@
 /* 7.3.5.1 The cacos functions */
 double complex cacos(double complex __z) __INTRODUCED_IN(23);
 float complex cacosf(float complex __z) __INTRODUCED_IN(23);
-long double complex cacosl(long double complex __z) __INTRODUCED_IN(26);
+long double complex cacosl(long double complex __z) __RENAME_LDBL(cacos, 23, 26);
 /* 7.3.5.2 The casin functions */
 double complex casin(double complex __z) __INTRODUCED_IN(23);
 float complex casinf(float complex __z) __INTRODUCED_IN(23);
-long double complex casinl(long double complex __z) __INTRODUCED_IN(26);
+long double complex casinl(long double complex __z) __RENAME_LDBL(casin, 23, 26);
 /* 7.3.5.1 The catan functions */
 double complex catan(double complex __z) __INTRODUCED_IN(23);
 float complex catanf(float complex __z) __INTRODUCED_IN(23);
-long double complex catanl(long double complex __z) __INTRODUCED_IN(26);
+long double complex catanl(long double complex __z) __RENAME_LDBL(catan, 23, 26);
 /* 7.3.5.1 The ccos functions */
 double complex ccos(double complex __z) __INTRODUCED_IN(23);
 float complex ccosf(float complex __z) __INTRODUCED_IN(23);
-long double complex ccosl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ccosl(long double complex __z) __RENAME_LDBL(ccos, 23, 26);
 /* 7.3.5.1 The csin functions */
 double complex csin(double complex __z) __INTRODUCED_IN(23);
 float complex csinf(float complex __z) __INTRODUCED_IN(23);
-long double complex csinl(long double complex __z) __INTRODUCED_IN(26);
+long double complex csinl(long double complex __z) __RENAME_LDBL(csin, 23, 26);
 /* 7.3.5.1 The ctan functions */
 double complex ctan(double complex __z) __INTRODUCED_IN(23);
 float complex ctanf(float complex __z) __INTRODUCED_IN(23);
-long double complex ctanl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ctanl(long double complex __z) __RENAME_LDBL(ctan, 23, 26);
 
 /* 7.3.6 Hyperbolic functions */
 /* 7.3.6.1 The cacosh functions */
 double complex cacosh(double complex __z) __INTRODUCED_IN(23);
 float complex cacoshf(float complex __z) __INTRODUCED_IN(23);
-long double complex cacoshl(long double complex __z) __INTRODUCED_IN(26);
+long double complex cacoshl(long double complex __z) __RENAME_LDBL(cacosh, 23, 26);
 /* 7.3.6.2 The casinh functions */
 double complex casinh(double complex __z) __INTRODUCED_IN(23);
 float complex casinhf(float complex __z) __INTRODUCED_IN(23);
-long double complex casinhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex casinhl(long double complex __z) __RENAME_LDBL(casinh, 23, 26);
 /* 7.3.6.3 The catanh functions */
 double complex catanh(double complex __z) __INTRODUCED_IN(23);
 float complex catanhf(float complex __z) __INTRODUCED_IN(23);
-long double complex catanhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex catanhl(long double complex __z) __RENAME_LDBL(catanh, 23, 26);
 /* 7.3.6.4 The ccosh functions */
 double complex ccosh(double complex __z) __INTRODUCED_IN(23);
 float complex ccoshf(float complex __z) __INTRODUCED_IN(23);
-long double complex ccoshl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ccoshl(long double complex __z) __RENAME_LDBL(ccosh, 23, 26);
 /* 7.3.6.5 The csinh functions */
 double complex csinh(double complex __z) __INTRODUCED_IN(23);
 float complex csinhf(float complex __z) __INTRODUCED_IN(23);
-long double complex csinhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex csinhl(long double complex __z) __RENAME_LDBL(csinh, 23, 26);
 /* 7.3.6.6 The ctanh functions */
 double complex ctanh(double complex __z) __INTRODUCED_IN(23);
 float complex ctanhf(float complex __z) __INTRODUCED_IN(23);
-long double complex ctanhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ctanhl(long double complex __z) __RENAME_LDBL(ctanh, 23, 26);
 
 /* 7.3.7 Exponential and logarithmic functions */
 /* 7.3.7.1 The cexp functions */
 double complex cexp(double complex __z) __INTRODUCED_IN(23);
 float complex cexpf(float complex __z) __INTRODUCED_IN(23);
-long double complex cexpl(long double complex __z) __INTRODUCED_IN(26);
+long double complex cexpl(long double complex __z) __RENAME_LDBL(cexp, 23, 26);
 /* 7.3.7.2 The clog functions */
 double complex clog(double complex __z) __INTRODUCED_IN(26);
 float complex clogf(float complex __z) __INTRODUCED_IN(26);
-long double complex clogl(long double complex __z) __INTRODUCED_IN(26);
+long double complex clogl(long double complex __z) __RENAME_LDBL(clog, 26, 26);
 
 /* 7.3.8 Power and absolute-value functions */
 /* 7.3.8.1 The cabs functions */
 double cabs(double complex __z) __INTRODUCED_IN(23);
 float cabsf(float complex __z) __INTRODUCED_IN(23);
-long double cabsl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23);
+long double cabsl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(cabs)*/;
 /* 7.3.8.2 The cpow functions */
 double complex cpow(double complex __x, double complex __z) __INTRODUCED_IN(26);
 float complex cpowf(float complex __x, float complex __z) __INTRODUCED_IN(26);
-long double complex cpowl(long double complex __x, long double complex __z) __INTRODUCED_IN(26);
+long double complex cpowl(long double complex __x, long double complex __z) __RENAME_LDBL(cpow, 26, 26);
 /* 7.3.8.3 The csqrt functions */
 double complex csqrt(double complex __z) __INTRODUCED_IN(23);
 float complex csqrtf(float complex __z) __INTRODUCED_IN(23);
-long double complex csqrtl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23);
+long double complex csqrtl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(csqrt)*/;
 
 /* 7.3.9 Manipulation functions */
 /* 7.3.9.1 The carg functions */
 double carg(double complex __z) __INTRODUCED_IN(23);
 float cargf(float complex __z) __INTRODUCED_IN(23);
-long double cargl(long double complex __z) __INTRODUCED_IN(23);
+long double cargl(long double complex __z) __RENAME_LDBL(carg, 23, 23);
 /* 7.3.9.2 The cimag functions */
 double cimag(double complex __z) __INTRODUCED_IN(23);
 float cimagf(float complex __z) __INTRODUCED_IN(23);
-long double cimagl(long double complex __z) __INTRODUCED_IN(23);
+long double cimagl(long double complex __z) __RENAME_LDBL(cimag, 23, 23);
 /* 7.3.9.3 The conj functions */
 double complex conj(double complex __z) __INTRODUCED_IN(23);
 float complex conjf(float complex __z) __INTRODUCED_IN(23);
-long double complex conjl(long double complex __z) __INTRODUCED_IN(23);
+long double complex conjl(long double complex __z) __RENAME_LDBL(conj, 23, 23);
 /* 7.3.9.4 The cproj functions */
 double complex cproj(double complex __z) __INTRODUCED_IN(23);
 float complex cprojf(float complex __z) __INTRODUCED_IN(23);
-long double complex cprojl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23);
+long double complex cprojl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(cproj)*/;
 /* 7.3.9.5 The creal functions */
 double creal(double complex __z) __INTRODUCED_IN(23);
 float crealf(float complex __z) __INTRODUCED_IN(23);
-long double creall(long double complex __z) __INTRODUCED_IN(23);
+long double creall(long double complex __z) __RENAME_LDBL(creal, 23, 23);
 
 __END_DECLS
 
diff --git a/libc/include/math.h b/libc/include/math.h
index 248ed3c..3d0ec49 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -22,19 +22,26 @@
 
 __BEGIN_DECLS
 
-#define HUGE_VAL	__builtin_huge_val()
+/* C11. */
 
-#define FP_ILOGB0	(-INT_MAX)
-#define FP_ILOGBNAN	INT_MAX
+typedef double __double_t;
+typedef __double_t double_t;
+typedef float __float_t;
+typedef __float_t float_t;
 
-#define HUGE_VALF	__builtin_huge_valf()
-#define HUGE_VALL	__builtin_huge_vall()
-#define INFINITY	__builtin_inff()
-#define NAN		__builtin_nanf("")
+#define HUGE_VAL __builtin_huge_val()
+#define HUGE_VALF __builtin_huge_valf()
+#define HUGE_VALL __builtin_huge_vall()
 
-#define MATH_ERRNO	1
-#define MATH_ERREXCEPT	2
-#define math_errhandling	MATH_ERREXCEPT
+#define INFINITY __builtin_inff()
+
+#define NAN __builtin_nanf("")
+
+#define FP_INFINITE 0x01
+#define FP_NAN 0x02
+#define FP_NORMAL 0x04
+#define FP_SUBNORMAL 0x08
+#define FP_ZERO 0x10
 
 #if defined(__FP_FAST_FMA)
 #define FP_FAST_FMA 1
@@ -46,20 +53,257 @@
 #define FP_FAST_FMAL 1
 #endif
 
-/* Symbolic constants to classify floating point numbers. */
-#define FP_INFINITE	0x01
-#define FP_NAN		0x02
-#define FP_NORMAL	0x04
-#define FP_SUBNORMAL	0x08
-#define FP_ZERO		0x10
-#define fpclassify(x) \
-    __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
+#define FP_ILOGB0 (-INT_MAX)
+#define FP_ILOGBNAN INT_MAX
+
+#define MATH_ERRNO 1
+#define MATH_ERREXCEPT 2
+#define math_errhandling MATH_ERREXCEPT
+
+#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
 
 #define isfinite(x) __builtin_isfinite(x)
+
 #define isinf(x) __builtin_isinf(x)
+
 #define isnan(x) __builtin_isnan(x)
+
 #define isnormal(x) __builtin_isnormal(x)
 
+#define signbit(x) \
+    ((sizeof(x) == sizeof(float)) ? __builtin_signbitf(x) \
+    : (sizeof(x) == sizeof(double)) ? __builtin_signbit(x) \
+    : __builtin_signbitl(x))
+
+double acos(double __x);
+float acosf(float __x);
+long double acosl(long double __x) __RENAME_LDBL(acos, 3, 21);
+
+double asin(double __x);
+float asinf(float __x);
+long double asinl(long double __x) __RENAME_LDBL(asin, 3, 21);
+
+double atan(double __x);
+float atanf(float __x);
+long double atanl(long double __x) __RENAME_LDBL(atan, 3, 21);
+
+double atan2(double __y, double __x);
+float atan2f(float __y, float __x);
+long double atan2l(long double __y, long double __x) __RENAME_LDBL(atan2, 3, 21);
+
+double cos(double __x);
+float cosf(float __x);
+long double cosl(long double __x) __RENAME_LDBL(cos, 3, 21);
+
+double sin(double __x);
+float sinf(float __x);
+long double sinl(long double __x) __RENAME_LDBL(sin, 3, 21);
+
+double tan(double __x);
+float tanf(float __x);
+long double tanl(long double __x) __RENAME_LDBL(tan, 3, 21);
+
+double acosh(double __x);
+float acoshf(float __x);
+long double acoshl(long double __x) __RENAME_LDBL(acosh, 3, 21);
+
+double asinh(double __x);
+float asinhf(float __x);
+long double asinhl(long double __x) __RENAME_LDBL(asinh, 3, 21);
+
+double atanh(double __x);
+float atanhf(float __x);
+long double atanhl(long double __x) __RENAME_LDBL(atanh, 3, 21);
+
+double cosh(double __x);
+float coshf(float __x);
+long double coshl(long double __x) __RENAME_LDBL(cosh, 3, 21);
+
+double sinh(double __x);
+float sinhf(float __x);
+long double sinhl(long double __x) __RENAME_LDBL(sinh, 3, 21);
+
+double tanh(double __x);
+float tanhf(float __x);
+long double tanhl(long double __x) __RENAME_LDBL(tanh, 3, 21);
+
+double exp(double __x);
+float expf(float __x);
+long double expl(long double __x) __RENAME_LDBL(exp, 3, 21);
+
+double exp2(double __x);
+float exp2f(float __x);
+long double exp2l(long double __x) __RENAME_LDBL(exp2, 3, 21);
+
+double expm1(double __x);
+float expm1f(float __x);
+long double expm1l(long double __x) __RENAME_LDBL(expm1, 3, 21);
+
+double frexp(double __x, int* __exponent);
+float frexpf(float __x, int* __exponent);
+long double frexpl(long double __x, int* __exponent) __RENAME_LDBL(frexp, 3, 21);
+
+int ilogb(double __x) __attribute_const__;
+int ilogbf(float __x) __attribute_const__;
+int ilogbl(long double __x) __attribute_const__ __RENAME_LDBL(ilogb, 3, 3);
+
+double ldexp(double __x, int __exponent);
+float ldexpf(float __x, int __exponent);
+long double ldexpl(long double __x, int __exponent) __RENAME_LDBL(ldexp, 3, 3);
+
+double log(double __x);
+float logf(float __x);
+long double logl(long double __x) __RENAME_LDBL(log, 3, 21);
+
+double log10(double __x);
+float log10f(float __x);
+long double log10l(long double __x) __RENAME_LDBL(log10, 3, 21);
+
+double log1p(double __x);
+float log1pf(float __x);
+long double log1pl(long double __x) __RENAME_LDBL(log1p, 3, 21);
+
+double log2(double __x) __INTRODUCED_IN(18);
+float log2f(float __x) __INTRODUCED_IN(18);
+long double log2l(long double __x) __RENAME_LDBL(log2, 18, 18);
+
+double logb(double __x);
+float logbf(float __x);
+long double logbl(long double __x) __RENAME_LDBL(logb, 3, 18);
+
+double modf(double __x, double* __integral_part);
+float modff(float __x, float* __integral_part);
+long double modfl(long double __x, long double* __integral_part) __RENAME_LDBL(modf, 3, 21);
+
+double scalbn(double __x, int __exponent);
+float scalbnf(float __x, int __exponent);
+long double scalbnl(long double __x, int __exponent) __RENAME_LDBL(scalbn, 3, 3);
+
+/* TODO: once the NDK only supports >= 18, use __RENAME_LDBL here too. */
+double scalbln(double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
+float scalblnf(float __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
+long double scalblnl(long double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
+
+double cbrt(double __x);
+float cbrtf(float __x);
+long double cbrtl(long double __x) __RENAME_LDBL(cbrt, 3, 21);
+
+double fabs(double __x) __attribute_const__;
+float fabsf(float __x) __attribute_const__;
+long double fabsl(long double __x) __attribute_const__ __RENAME_LDBL(fabs, 3, 3);
+
+double hypot(double __x, double __y);
+float hypotf(float __x, float __y);
+long double hypotl(long double __x, long double __y) __RENAME_LDBL(hypot, 3, 21);
+
+double pow(double __x, double __y);
+float powf(float __x, float __y);
+long double powl(long double __x, long double __y) __RENAME_LDBL(pow, 3, 21);
+
+double sqrt(double __x);
+float sqrtf(float __x);
+long double sqrtl(long double __x) __RENAME_LDBL(sqrt, 3, 21);
+
+double erf(double __x);
+float erff(float __x);
+long double erfl(long double __x) __RENAME_LDBL(erf, 3, 21);
+
+double erfc(double __x);
+float erfcf(float __x);
+long double erfcl(long double __x) __RENAME_LDBL(erfc, 3, 21);
+
+double lgamma(double __x);
+float lgammaf(float __x);
+long double lgammal(long double __x) __RENAME_LDBL(lgamma, 3, 21);
+
+double tgamma(double __x);
+float tgammaf(float __x) __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
+long double tgammal(long double __x) __RENAME_LDBL(tgamma, 3, 21);
+
+double ceil(double __x);
+float ceilf(float __x);
+long double ceill(long double __x) __RENAME_LDBL(ceil, 3, 3);
+
+double floor(double __x);
+float floorf(float __x);
+long double floorl(long double __x) __RENAME_LDBL(floor, 3, 3);
+
+double nearbyint(double __x);
+float nearbyintf(float __x);
+long double nearbyintl(long double __x) __RENAME_LDBL(nearbyint, 3, 21);
+
+double rint(double __x);
+float rintf(float __x);
+long double rintl(long double __x) __RENAME_LDBL(rint, 3, 21);
+
+long lrint(double __x);
+long lrintf(float __x);
+long lrintl(long double __x) __RENAME_LDBL(lrint, 3, 21);
+
+long long llrint(double __x);
+long long llrintf(float __x);
+long long llrintl(long double __x) __RENAME_LDBL(llrint, 3, 21);
+
+double round(double __x);
+float roundf(float __x);
+long double roundl(long double __x) __RENAME_LDBL(roundl, 3, 3);
+
+long lround(double __x);
+long lroundf(float __x);
+long lroundl(long double __x) __RENAME_LDBL(lround, 3, 3);
+
+long long llround(double __x);
+long long llroundf(float __x);
+long long llroundl(long double __x) __RENAME_LDBL(llround, 3, 3);
+
+double trunc(double __x);
+float truncf(float __x);
+long double truncl(long double __x) __RENAME_LDBL(trunc, 3, 3);
+
+double fmod(double __x, double __y);
+float fmodf(float __x, float __y);
+long double fmodl(long double __x, long double __y) __RENAME_LDBL(fmod, 3, 21);
+
+double remainder(double __x, double __y);
+float remainderf(float __x, float __y);
+long double remainderl(long double __x, long double __y) __RENAME_LDBL(remainder, 3, 21);
+
+double remquo(double __x, double __y, int* __quotient_bits);
+float remquof(float __x, float __y, int* __quotient_bits);
+long double remquol(long double __x, long double __y, int* __quotient_bits) __RENAME_LDBL(remquo, 3, 21);
+
+double copysign(double __value, double __sign) __attribute_const__;
+float copysignf(float __value, float __sign) __attribute_const__;
+long double copysignl(long double __value, long double __sign) __attribute_const__ __RENAME_LDBL(copysign, 3, 3);
+
+double nan(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
+float nanf(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
+long double nanl(const char* __kind) __attribute_const__ __RENAME_LDBL(nan, 13, 13);
+
+double nextafter(double __x, double __y);
+float nextafterf(float __x, float __y);
+long double nextafterl(long double __x, long double __y) __RENAME_LDBL(nextafter, 3, 21) __VERSIONER_NO_GUARD;
+
+double nexttoward(double __x, long double __y) __INTRODUCED_IN(18) __VERSIONER_NO_GUARD;
+float nexttowardf(float __x, long double __y);
+long double nexttowardl(long double __x, long double __y) __RENAME_LDBL(nexttoward, 18, 18) __VERSIONER_NO_GUARD;
+
+double fdim(double __x, double __y);
+float fdimf(float __x, float __y);
+long double fdiml(long double __x, long double __y) __RENAME_LDBL(fdim, 3, 3);
+
+double fmax(double __x, double __y) __attribute_const__;
+float fmaxf(float __x, float __y) __attribute_const__;
+long double fmaxl(long double __x, long double __y) __attribute_const__ __RENAME_LDBL(fmax, 3, 3);
+
+double fmin(double __x, double __y) __attribute_const__;
+float fminf(float __x, float __y) __attribute_const__;
+long double fminl(long double __x, long double __y) __attribute_const__ __RENAME_LDBL(fmin, 3, 3);
+
+double fma(double __x, double __y, double __z);
+float fmaf(float __x, float __y, float __z);
+long double fmal(long double __x, long double __y, long double __z) __RENAME_LDBL(fma, 3, 21) __VERSIONER_NO_GUARD;
+
 #define isgreater(x, y) __builtin_isgreater((x), (y))
 #define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y))
 #define isless(x, y) __builtin_isless((x), (y))
@@ -67,92 +311,6 @@
 #define islessgreater(x, y) __builtin_islessgreater((x), (y))
 #define isunordered(x, y) __builtin_isunordered((x), (y))
 
-#define signbit(x) \
-    ((sizeof(x) == sizeof(float)) ? __builtin_signbitf(x) \
-    : (sizeof(x) == sizeof(double)) ? __builtin_signbit(x) \
-    : __builtin_signbitl(x))
-
-typedef double __double_t;
-typedef __double_t double_t;
-typedef float __float_t;
-typedef __float_t float_t;
-
-#if defined(__USE_BSD)
-#define HUGE MAXFLOAT
-#endif
-
-extern int signgam;
-
-/*
- * Most of these functions depend on the rounding mode and have the side
- * effect of raising floating-point exceptions, so they are not declared
- * as __attribute_const__. In C99, FENV_ACCESS affects the purity of these functions.
- */
-
-int __fpclassifyd(double __x) __attribute_const__;
-int __fpclassifyf(float __x) __attribute_const__;
-int __fpclassifyl(long double __x) __attribute_const__;
-int __isfinitef(float __x) __attribute_const__;
-int __isfinite(double __x) __attribute_const__;
-int __isfinitel(long double __x) __attribute_const__;
-int __isinff(float __x) __attribute_const__;
-int __isinfl(long double __x) __attribute_const__;
-int __isnanf(float __x) __attribute_const__ __INTRODUCED_IN(21);
-int __isnanl(long double __x) __attribute_const__;
-int __isnormalf(float __x) __attribute_const__;
-int __isnormal(double __x) __attribute_const__;
-int __isnormall(long double __x) __attribute_const__;
-int __signbit(double __x) __attribute_const__;
-int __signbitf(float __x) __attribute_const__;
-int __signbitl(long double __x) __attribute_const__;
-
-double acos(double __x);
-double asin(double __x);
-double atan(double __x);
-double atan2(double __y, double __x);
-double cos(double __x);
-double sin(double __x);
-double tan(double __x);
-
-double cosh(double __x);
-double sinh(double __x);
-double tanh(double __x);
-
-double exp(double __x);
-double frexp(double __x, int* __exponent); /* fundamentally !__attribute_const__ */
-double ldexp(double __x, int __exponent);
-double log(double __x);
-double log10(double __x);
-double modf(double __x, double* __integral_part); /* fundamentally !__attribute_const__ */
-
-double pow(double __x, double __y);
-double sqrt(double __x);
-
-double ceil(double __x);
-double fabs(double __x) __attribute_const__;
-double floor(double __x);
-double fmod(double __x, double __y);
-
-double acosh(double __x);
-double asinh(double __x);
-double atanh(double __x);
-double cbrt(double __x);
-double erf(double __x);
-double erfc(double __x);
-double exp2(double __x);
-double expm1(double __x);
-double fma(double __x, double __y, double __z);
-double hypot(double __x, double __y);
-int ilogb(double __x) __attribute_const__;
-double lgamma(double __x);
-long long llrint(double __x);
-long long llround(double __x);
-double log1p(double __x);
-double log2(double __x) __INTRODUCED_IN(18);
-double logb(double __x);
-long lrint(double __x);
-long lround(double __x);
-
 /*
  * https://code.google.com/p/android/issues/detail?id=271629
  * To be fully compliant with C++, we need to not define these (C doesn't
@@ -167,150 +325,9 @@
 int (isinf)(double __x) __attribute_const__ __INTRODUCED_IN(21);
 int (isnan)(double __x) __attribute_const__;
 
-double nan(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13)
-    __INTRODUCED_IN_X86(9);
+/* POSIX extensions. */
 
-double nextafter(double __x, double __y);
-double remainder(double __x, double __y);
-double remquo(double __x, double __y, int* __quotient_bits);
-double rint(double __x);
-
-double copysign(double __value, double __sign) __attribute_const__;
-double fdim(double __x, double __y);
-double fmax(double __x, double __y) __attribute_const__;
-double fmin(double __x, double __y) __attribute_const__;
-double nearbyint(double __x);
-double round(double __x);
-double scalbln(double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-double scalbn(double __x, int __exponent);
-double tgamma(double __x);
-double trunc(double __x);
-
-float acosf(float __x);
-float asinf(float __x);
-float atanf(float __x);
-float atan2f(float __y, float __x);
-float cosf(float __x);
-float sinf(float __x);
-float tanf(float __x);
-
-float coshf(float __x);
-float sinhf(float __x);
-float tanhf(float __x);
-
-float exp2f(float __x);
-float expf(float __x);
-float expm1f(float __x);
-float frexpf(float __x, int* __exponent); /* fundamentally !__attribute_const__ */
-int ilogbf(float __x) __attribute_const__;
-float ldexpf(float __x, int __exponent);
-float log10f(float __x);
-float log1pf(float __x);
-float log2f(float __x) __INTRODUCED_IN(18);
-float logf(float __x);
-float modff(float __x, float* __integral_part); /* fundamentally !__attribute_const__ */
-
-float powf(float __x, float __y);
-float sqrtf(float __x);
-
-float ceilf(float __x);
-float fabsf(float __x) __attribute_const__;
-float floorf(float __x);
-float fmodf(float __x, float __y);
-float roundf(float __x);
-
-float erff(float __x);
-float erfcf(float __x);
-float hypotf(float __x, float __y);
-float lgammaf(float __x);
-float tgammaf(float __x) __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
-
-float acoshf(float __x);
-float asinhf(float __x);
-float atanhf(float __x);
-float cbrtf(float __x);
-float logbf(float __x);
-float copysignf(float __value, float __sign) __attribute_const__;
-long long llrintf(float __x);
-long long llroundf(float __x);
-long lrintf(float __x);
-long lroundf(float __x);
-float nanf(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13)
-    __INTRODUCED_IN_X86(9);
-float nearbyintf(float __x);
-float nextafterf(float __x, float __y);
-float remainderf(float __x, float __y);
-float remquof(float __x, float __y, int* __quotient_bits);
-float rintf(float __x);
-float scalblnf(float __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-float scalbnf(float __x, int __exponent);
-float truncf(float __x);
-
-float fdimf(float __x, float __y);
-float fmaf(float __x, float __y, float __z);
-float fmaxf(float __x, float __y) __attribute_const__;
-float fminf(float __x, float __y) __attribute_const__;
-
-long double acoshl(long double __x) __INTRODUCED_IN(21);
-long double acosl(long double __x) __INTRODUCED_IN(21);
-long double asinhl(long double __x) __INTRODUCED_IN(21);
-long double asinl(long double __x) __INTRODUCED_IN(21);
-long double atan2l(long double __y, long double __x) __INTRODUCED_IN(21);
-long double atanhl(long double __x) __INTRODUCED_IN(21);
-long double atanl(long double __x) __INTRODUCED_IN(21);
-long double cbrtl(long double __x) __INTRODUCED_IN(21);
-long double ceill(long double __x);
-long double copysignl(long double __value, long double __sign) __attribute_const__;
-long double coshl(long double __x) __INTRODUCED_IN(21);
-long double cosl(long double __x) __INTRODUCED_IN(21);
-long double erfcl(long double __x) __INTRODUCED_IN(21);
-long double erfl(long double __x) __INTRODUCED_IN(21);
-long double exp2l(long double __x) __INTRODUCED_IN(21);
-long double expl(long double __x) __INTRODUCED_IN(21);
-long double expm1l(long double __x) __INTRODUCED_IN(21);
-long double fabsl(long double __x) __attribute_const__;
-long double fdiml(long double __x, long double __y);
-long double floorl(long double __x);
-long double fmal(long double __x, long double __y, long double __z) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
-long double fmaxl(long double __x, long double __y) __attribute_const__;
-long double fminl(long double __x, long double __y) __attribute_const__;
-long double fmodl(long double __x, long double __y) __INTRODUCED_IN(21);
-long double frexpl(long double __x, int* __exponent)
-    __INTRODUCED_IN(21) __VERSIONER_NO_GUARD; /* fundamentally !__attribute_const__ */
-long double hypotl(long double __x, long double __y) __INTRODUCED_IN(21);
-int ilogbl(long double __x) __attribute_const__;
-long double ldexpl(long double __x, int __exponent);
-long double lgammal(long double __x) __INTRODUCED_IN(21);
-long long llrintl(long double __x) __INTRODUCED_IN(21);
-long long llroundl(long double __x);
-long double log10l(long double __x) __INTRODUCED_IN(21);
-long double log1pl(long double __x) __INTRODUCED_IN(21);
-long double log2l(long double __x) __INTRODUCED_IN(18);
-long double logbl(long double __x) __INTRODUCED_IN(18);
-long double logl(long double __x) __INTRODUCED_IN(21);
-long lrintl(long double __x) __INTRODUCED_IN(21);
-long lroundl(long double __x);
-long double modfl(long double __x, long double* __integral_part) __INTRODUCED_IN(21); /* fundamentally !__attribute_const__ */
-long double nanl(const char* __kind) __attribute_const__ __INTRODUCED_IN(13);
-long double nearbyintl(long double __x) __INTRODUCED_IN(21);
-long double nextafterl(long double __x, long double __y) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
-double nexttoward(double __x, long double __y) __INTRODUCED_IN(18) __VERSIONER_NO_GUARD;
-float nexttowardf(float __x, long double __y);
-long double nexttowardl(long double __x, long double __y) __INTRODUCED_IN(18) __VERSIONER_NO_GUARD;
-long double powl(long double __x, long double __y) __INTRODUCED_IN(21);
-long double remainderl(long double __x, long double __y) __INTRODUCED_IN(21);
-long double remquol(long double __x, long double __y, int* __quotient_bits) __INTRODUCED_IN(21);
-long double rintl(long double __x) __INTRODUCED_IN(21);
-long double roundl(long double __x);
-long double scalblnl(long double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-long double scalbnl(long double __x, int __exponent);
-long double sinhl(long double __x) __INTRODUCED_IN(21);
-long double sinl(long double __x) __INTRODUCED_IN(21);
-long double sqrtl(long double __x) __INTRODUCED_IN(21);
-long double tanhl(long double __x) __INTRODUCED_IN(21);
-long double tanl(long double __x) __INTRODUCED_IN(21);
-long double tgammal(long double __x) __INTRODUCED_IN(21);
-long double truncl(long double __x);
+extern int signgam;
 
 double j0(double __x);
 double j1(double __x);
@@ -335,6 +352,38 @@
 
 #define MAXFLOAT	((float)3.40282346638528860e+38)
 
+/* Legacy cruft from before we had builtin implementations of the standard macros. */
+
+int __fpclassifyd(double __x) __attribute_const__;
+int __fpclassifyf(float __x) __attribute_const__;
+int __fpclassifyl(long double __x) __attribute_const__;
+
+int __isfinitef(float __x) __attribute_const__;
+int __isfinite(double __x) __attribute_const__;
+int __isfinitel(long double __x) __attribute_const__;
+
+int __isinff(float __x) __attribute_const__;
+int __isinfl(long double __x) __attribute_const__;
+
+int __isnanf(float __x) __attribute_const__ __INTRODUCED_IN(21);
+int __isnanl(long double __x) __attribute_const__;
+
+int __isnormal(double __x) __attribute_const__;
+int __isnormalf(float __x) __attribute_const__;
+int __isnormall(long double __x) __attribute_const__;
+
+int __signbit(double __x) __attribute_const__;
+int __signbitf(float __x) __attribute_const__;
+int __signbitl(long double __x) __attribute_const__;
+
+/* BSD extensions. */
+
+#if defined(__USE_BSD)
+#define HUGE MAXFLOAT
+#endif
+
+/* Extensions in both BSD and GNU. */
+
 #if defined(__USE_BSD) || defined(__USE_GNU)
 double gamma(double __x);
 double scalb(double __x, double __exponent);
@@ -361,6 +410,8 @@
 float significandf(float __x);
 #endif
 
+/* GNU extensions. */
+
 #if defined(__USE_GNU)
 #define M_El            2.718281828459045235360287471352662498L /* e */
 #define M_LOG2El        1.442695040888963407359924681001892137L /* log 2e */
diff --git a/libc/include/search.h b/libc/include/search.h
index 0015699..5930bcd 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -13,18 +13,26 @@
 #include <sys/types.h>
 
 typedef enum {
+  FIND,
+  ENTER
+} ACTION;
+
+typedef struct entry {
+  char* key;
+  void* data;
+} ENTRY;
+
+typedef enum {
   preorder,
   postorder,
   endorder,
   leaf
 } VISIT;
 
-#ifdef _SEARCH_PRIVATE
-typedef struct node {
-  char* key;
-  struct node* llink;
-  struct node* rlink;
-} node_t;
+#if defined(__USE_BSD) || defined(__USE_GNU)
+struct hsearch_data {
+  struct __hsearch* __hsearch;
+};
 #endif
 
 __BEGIN_DECLS
@@ -32,6 +40,16 @@
 void insque(void* __element, void* __previous) __INTRODUCED_IN(21);
 void remque(void* __element) __INTRODUCED_IN(21);
 
+int hcreate(size_t) __INTRODUCED_IN_FUTURE;
+void hdestroy(void) __INTRODUCED_IN_FUTURE;
+ENTRY* hsearch(ENTRY, ACTION) __INTRODUCED_IN_FUTURE;
+
+#if defined(__USE_BSD) || defined(__USE_GNU)
+int hcreate_r(size_t, struct hsearch_data*) __INTRODUCED_IN_FUTURE;
+void hdestroy_r(struct hsearch_data*) __INTRODUCED_IN_FUTURE;
+int hsearch_r(ENTRY, ACTION, ENTRY**, struct hsearch_data*) __INTRODUCED_IN_FUTURE;
+#endif
+
 void* lfind(const void* __key, const void* __base, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*))
   __INTRODUCED_IN(21);
 void* lsearch(const void* __key, void* __base, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*))
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 4182f2d..86336a0 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -75,7 +75,7 @@
 int posix_memalign(void** __memptr, size_t __alignment, size_t __size) __INTRODUCED_IN(16);
 
 double strtod(const char* __s, char** __end_ptr);
-long double strtold(const char* __s, char** __end_ptr) __INTRODUCED_IN(21);
+long double strtold(const char* __s, char** __end_ptr) __RENAME_LDBL(strtod, 3, 21);
 
 unsigned long strtoul_l(const char* __s, char** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(26);
 
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 58eebc5..063b51d 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -37,6 +37,11 @@
 #ifndef	_SYS_CDEFS_H_
 #define	_SYS_CDEFS_H_
 
+#include <android/api-level.h>
+#include <android/versioning.h>
+
+#define __BIONIC__ 1
+
 /*
  * Testing against Clang-specific extensions.
  */
@@ -219,8 +224,21 @@
 #define __RENAME_IF_FILE_OFFSET64(func)
 #endif
 
-#define  __BIONIC__   1
-#include <android/api-level.h>
+/*
+ * For LP32, `long double` == `double`. Historically many `long double` functions were incorrect
+ * on x86, missing on most architectures, and even if they are present and correct, linking to
+ * them just bloats your ELF file by adding extra relocations. The __BIONIC_LP32_USE_LONG_DOUBLE
+ * macro lets us test the headers both ways (and adds an escape valve).
+ *
+ * Note that some functions have their __RENAME_LDBL commented out as a sign that although we could
+ * use __RENAME_LDBL it would actually cause the function to be introduced later because the
+ * `long double` variant appeared before the `double` variant.
+ */
+#if defined(__LP64__) || defined(__BIONIC_LP32_USE_LONG_DOUBLE)
+#define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN(regular_api_level)
+#else
+#define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN(rewrite_api_level)
+#endif
 
 /* glibc compatibility. */
 #if defined(__LP64__)
@@ -334,8 +352,6 @@
 /* Used to rename functions so that the compiler emits a call to 'x' rather than the function this was applied to. */
 #define __RENAME(x) __asm__(#x)
 
-#include <android/versioning.h>
-
 #if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
 #if defined(__LP64__)
 #define __size_mul_overflow(a, b, result) __builtin_umull_overflow(a, b, result)
diff --git a/libc/include/sys/endian.h b/libc/include/sys/endian.h
index 799a6f2..9155b4c 100644
--- a/libc/include/sys/endian.h
+++ b/libc/include/sys/endian.h
@@ -45,7 +45,7 @@
 
 #define __swap16 __builtin_bswap16
 #define __swap32 __builtin_bswap32
-#define __swap64 __builtin_bswap64
+#define __swap64(x) __BIONIC_CAST(static_cast,uint64_t,__builtin_bswap64(x))
 
 /* glibc compatibility. */
 __BEGIN_DECLS
@@ -70,17 +70,17 @@
 #define PDP_ENDIAN _PDP_ENDIAN
 #define BYTE_ORDER _BYTE_ORDER
 
-#define	NTOHL(x) (x) = ntohl((u_int32_t)(x))
-#define	NTOHS(x) (x) = ntohs((u_int16_t)(x))
-#define	HTONL(x) (x) = htonl((u_int32_t)(x))
-#define	HTONS(x) (x) = htons((u_int16_t)(x))
+#define	NTOHL(x) (x) = ntohl(__BIONIC_CAST(static_cast,u_int32_t,(x)))
+#define	NTOHS(x) (x) = ntohs(__BIONIC_CAST(static_cast,u_int16_t,(x)))
+#define	HTONL(x) (x) = htonl(__BIONIC_CAST(static_cast,u_int32_t,(x)))
+#define	HTONS(x) (x) = htons(__BIONIC_CAST(static_cast,u_int16_t,(x)))
 
-#define htobe16 __swap16
-#define htobe32 __swap32
-#define htobe64 __swap64
-#define betoh16 __swap16
-#define betoh32 __swap32
-#define betoh64 __swap64
+#define htobe16(x) __swap16(x)
+#define htobe32(x) __swap32(x)
+#define htobe64(x) __swap64(x)
+#define betoh16(x) __swap16(x)
+#define betoh32(x) __swap32(x)
+#define betoh64(x) __swap64(x)
 
 #define htole16(x) (x)
 #define htole32(x) (x)
@@ -101,6 +101,7 @@
 #define le16toh(x) htole16(x)
 #define le32toh(x) htole32(x)
 #define le64toh(x) htole64(x)
-#endif /* __USE_BSD */
+
+#endif
 
 #endif
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 1dda4bd..1cf498c83 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -98,7 +98,7 @@
 wchar_t* wcstok(wchar_t* __s, const wchar_t* __delimiter, wchar_t** __ptr);
 long wcstol(const wchar_t* __s, wchar_t** __end_ptr, int __base);
 long long wcstoll(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
-long double wcstold(const wchar_t* __s, wchar_t** __end_ptr) __INTRODUCED_IN(21);
+long double wcstold(const wchar_t* __s, wchar_t** __end_ptr) __RENAME_LDBL(wcstod, 3, 21);
 unsigned long wcstoul(const wchar_t* __s, wchar_t** __end_ptr, int __base);
 unsigned long long wcstoull(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
 int wcswidth(const wchar_t* __s, size_t __n);
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index bca491b..fff80f6 100644
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 """A glorified C pre-processor parser."""
 
 import ctypes
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 31c2a53..5018951 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1323,6 +1323,12 @@
     __freading; # future
     __fwriting; # future
     getlogin_r; # future
+    hcreate; # future
+    hcreate_r; # future
+    hdestroy; # future
+    hdestroy_r; # future
+    hsearch; # future
+    hsearch_r; # future
     iconv; # future
     iconv_close; # future
     iconv_open; # future
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 6cc6d64..4ea5896 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1243,6 +1243,12 @@
     __freading; # future
     __fwriting; # future
     getlogin_r; # future
+    hcreate; # future
+    hcreate_r; # future
+    hdestroy; # future
+    hdestroy_r; # future
+    hsearch; # future
+    hsearch_r; # future
     iconv; # future
     iconv_close; # future
     iconv_open; # future
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 5cbfaeb..a0ac50a 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1348,6 +1348,12 @@
     __freading; # future
     __fwriting; # future
     getlogin_r; # future
+    hcreate; # future
+    hcreate_r; # future
+    hdestroy; # future
+    hdestroy_r; # future
+    hsearch; # future
+    hsearch_r; # future
     iconv; # future
     iconv_close; # future
     iconv_open; # future
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 34369ba..8970549 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1307,6 +1307,12 @@
     __freading; # future
     __fwriting; # future
     getlogin_r; # future
+    hcreate; # future
+    hcreate_r; # future
+    hdestroy; # future
+    hdestroy_r; # future
+    hsearch; # future
+    hsearch_r; # future
     iconv; # future
     iconv_close; # future
     iconv_open; # future
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 6cc6d64..4ea5896 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1243,6 +1243,12 @@
     __freading; # future
     __fwriting; # future
     getlogin_r; # future
+    hcreate; # future
+    hcreate_r; # future
+    hdestroy; # future
+    hdestroy_r; # future
+    hsearch; # future
+    hsearch_r; # future
     iconv; # future
     iconv_close; # future
     iconv_open; # future
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 76dffa5..5439852 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1305,6 +1305,12 @@
     __freading; # future
     __fwriting; # future
     getlogin_r; # future
+    hcreate; # future
+    hcreate_r; # future
+    hdestroy; # future
+    hdestroy_r; # future
+    hsearch; # future
+    hsearch_r; # future
     iconv; # future
     iconv_close; # future
     iconv_open; # future
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 6cc6d64..4ea5896 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1243,6 +1243,12 @@
     __freading; # future
     __fwriting; # future
     getlogin_r; # future
+    hcreate; # future
+    hcreate_r; # future
+    hdestroy; # future
+    hdestroy_r; # future
+    hsearch; # future
+    hsearch_r; # future
     iconv; # future
     iconv_close; # future
     iconv_open; # future
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 752d507..65ae6fa 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -41,12 +41,12 @@
 #include "debug_log.h"
 #include "malloc_debug.h"
 
-static void EnableToggle(int, siginfo_t*, void*) {
-  if (g_debug->backtrace->enabled()) {
-    g_debug->backtrace->set_enabled(false);
-  } else {
-    g_debug->backtrace->set_enabled(true);
-  }
+static void ToggleBacktraceEnable(int, siginfo_t*, void*) {
+  g_debug->backtrace->ToggleBacktraceEnabled();
+}
+
+static void EnableDump(int, siginfo_t*, void*) {
+  g_debug->backtrace->EnableDumping();
 }
 
 BacktraceData::BacktraceData(DebugData* debug_data, const Config& config, size_t* offset)
@@ -62,7 +62,7 @@
     struct sigaction enable_act;
     memset(&enable_act, 0, sizeof(enable_act));
 
-    enable_act.sa_sigaction = EnableToggle;
+    enable_act.sa_sigaction = ToggleBacktraceEnable;
     enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
     sigemptyset(&enable_act.sa_mask);
     if (sigaction(config.backtrace_signal(), &enable_act, nullptr) != 0) {
@@ -72,5 +72,20 @@
     info_log("%s: Run: 'kill -%d %d' to enable backtracing.", getprogname(),
              config.backtrace_signal(), getpid());
   }
+
+  struct sigaction act;
+  memset(&act, 0, sizeof(act));
+
+  act.sa_sigaction = EnableDump;
+  act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+  sigemptyset(&act.sa_mask);
+  if (sigaction(config.backtrace_dump_signal(), &act, nullptr) != 0) {
+    error_log("Unable to set up backtrace dump signal function: %s", strerror(errno));
+    return false;
+  }
+  info_log("%s: Run: 'kill -%d %d' to dump the backtrace.", getprogname(),
+           config.backtrace_dump_signal(), getpid());
+
+  dump_ = false;
   return true;
 }
diff --git a/libc/malloc_debug/BacktraceData.h b/libc/malloc_debug/BacktraceData.h
index 6dee505..c8234dc 100644
--- a/libc/malloc_debug/BacktraceData.h
+++ b/libc/malloc_debug/BacktraceData.h
@@ -31,6 +31,8 @@
 
 #include <stdint.h>
 
+#include <atomic>
+
 #include <private/bionic_macros.h>
 
 #include "OptionData.h"
@@ -47,13 +49,21 @@
 
   inline size_t alloc_offset() { return alloc_offset_; }
 
-  bool enabled() { return enabled_; }
-  void set_enabled(bool enabled) { enabled_ = enabled; }
+  bool ShouldBacktrace() { return enabled_ == 1; }
+  void ToggleBacktraceEnabled() { enabled_.fetch_xor(1); }
+
+  void EnableDumping() { dump_ = true; }
+  bool ShouldDumpAndReset() {
+    bool expected = true;
+    return dump_.compare_exchange_strong(expected, false);
+  }
 
  private:
   size_t alloc_offset_ = 0;
 
-  volatile bool enabled_ = false;
+  std::atomic_uint8_t enabled_;
+
+  std::atomic_bool dump_;
 
   DISALLOW_COPY_AND_ASSIGN(BacktraceData);
 };
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index df453a9..e3798ab 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -56,6 +56,7 @@
 
 static constexpr size_t DEFAULT_BACKTRACE_FRAMES = 16;
 static constexpr size_t MAX_BACKTRACE_FRAMES = 256;
+static constexpr const char DEFAULT_BACKTRACE_DUMP_PREFIX[] = "/data/local/tmp/backtrace_heap";
 
 static constexpr size_t DEFAULT_EXPAND_BYTES = 16;
 static constexpr size_t MAX_EXPAND_BYTES = 16384;
@@ -85,6 +86,13 @@
       {BACKTRACE | TRACK_ALLOCS, &Config::SetBacktraceEnableOnSignal},
     },
 
+    {"backtrace_dump_on_exit",
+      {0, &Config::SetBacktraceDumpOnExit},
+    },
+    {"backtrace_dump_prefix",
+      {0, &Config::SetBacktraceDumpPrefix},
+    },
+
     {"fill",
       {FILL_ON_ALLOC | FILL_ON_FREE, &Config::SetFill},
     },
@@ -236,6 +244,24 @@
                     &backtrace_frames_);
 }
 
+bool Config::SetBacktraceDumpOnExit(const std::string& option, const std::string& value) {
+  if (Config::VerifyValueEmpty(option, value)) {
+    backtrace_dump_on_exit_ = true;
+    return true;
+  }
+  return false;
+}
+
+bool Config::SetBacktraceDumpPrefix(const std::string&, const std::string& value) {
+  if (value.empty()) {
+    backtrace_dump_prefix_ = DEFAULT_BACKTRACE_DUMP_PREFIX;
+  } else {
+    backtrace_dump_prefix_ = value;
+  }
+  return true;
+}
+
+
 bool Config::SetExpandAlloc(const std::string& option, const std::string& value) {
   return ParseValue(option, value, DEFAULT_EXPAND_BYTES, 1, MAX_EXPAND_BYTES, &expand_alloc_bytes_);
 }
@@ -309,6 +335,9 @@
   error_log("  backtrace[=XX]");
   error_log("    Enable capturing the backtrace at the point of allocation.");
   error_log("    If XX is set it sets the number of backtrace frames.");
+  error_log("    This option also enables dumping the backtrace heap data");
+  error_log("    when a signal is received. The data is dumped to the file");
+  error_log("    backtrace_dump_prefix.<PID>.txt.");
   error_log("    The default is %zu frames, the max number of frames is %zu.",
             DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
   error_log("");
@@ -319,6 +348,19 @@
   error_log("    frames. The default is %zu frames, the max number of frames is %zu.",
             DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
   error_log("");
+  error_log("  backtrace_dump_prefix[=FILE]");
+  error_log("    This option only has meaning if the backtrace option has been specified.");
+  error_log("    This is the prefix of the name of the file to which backtrace heap");
+  error_log("    data will be dumped. The file will be named backtrace_dump_prefix.<PID>.txt.");
+  error_log("    The default is %s.", DEFAULT_BACKTRACE_DUMP_PREFIX);
+
+  error_log("");
+  error_log("  backtrace_dump_on_exit");
+  error_log("    This option only has meaning if the backtrace option has been specified.");
+  error_log("    This will cause all live allocations to be dumped to the file");
+  error_log("    backtrace_dump_prefix.<PID>.final.txt.");
+  error_log("    The default is false.");
+  error_log("");
   error_log("  fill_on_alloc[=XX]");
   error_log("    On first allocation, fill with the value 0x%02x.", DEFAULT_FILL_ALLOC_VALUE);
   error_log("    If XX is set it will only fill up to XX bytes of the");
@@ -426,12 +468,15 @@
   front_guard_value_ = DEFAULT_FRONT_GUARD_VALUE;
   rear_guard_value_ = DEFAULT_REAR_GUARD_VALUE;
   backtrace_signal_ = SIGRTMAX - 19;
+  backtrace_dump_signal_ = SIGRTMAX - 17;
   record_allocs_signal_ = SIGRTMAX - 18;
   free_track_backtrace_num_frames_ = 0;
   record_allocs_file_.clear();
   fill_on_free_bytes_ = 0;
   backtrace_enable_on_signal_ = false;
   backtrace_enabled_ = false;
+  backtrace_dump_on_exit_ = false;
+  backtrace_dump_prefix_ = DEFAULT_BACKTRACE_DUMP_PREFIX;
 
   // Process each option name we can find.
   std::string option;
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index d8a7069..349ad77 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -65,9 +65,12 @@
   uint64_t options() const { return options_; }
 
   int backtrace_signal() const { return backtrace_signal_; }
+  int backtrace_dump_signal() const { return backtrace_dump_signal_; }
   size_t backtrace_frames() const { return backtrace_frames_; }
   size_t backtrace_enabled() const { return backtrace_enabled_; }
   size_t backtrace_enable_on_signal() const { return backtrace_enable_on_signal_; }
+  bool backtrace_dump_on_exit() const { return backtrace_dump_on_exit_; }
+  const std::string& backtrace_dump_prefix() const { return backtrace_dump_prefix_; }
 
   size_t front_guard_bytes() const { return front_guard_bytes_; }
   size_t rear_guard_bytes() const { return rear_guard_bytes_; }
@@ -110,6 +113,8 @@
 
   bool SetBacktrace(const std::string& option, const std::string& value);
   bool SetBacktraceEnableOnSignal(const std::string& option, const std::string& value);
+  bool SetBacktraceDumpOnExit(const std::string& option, const std::string& value);
+  bool SetBacktraceDumpPrefix(const std::string& option, const std::string& value);
 
   bool SetExpandAlloc(const std::string& option, const std::string& value);
 
@@ -130,8 +135,11 @@
 
   bool backtrace_enable_on_signal_ = false;
   int backtrace_signal_ = 0;
+  int backtrace_dump_signal_ = 0;
   bool backtrace_enabled_ = false;
   size_t backtrace_frames_ = 0;
+  bool backtrace_dump_on_exit_ = false;
+  std::string backtrace_dump_prefix_;
 
   size_t fill_on_alloc_bytes_ = 0;
   size_t fill_on_free_bytes_ = 0;
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index 03a8a73..bb56cb8 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -108,6 +108,17 @@
 This option adds a special header to all allocations that contains the
 backtrace and information about the original allocation.
 
+As of P, this option will also enable dumping backtrace heap data to a
+file when the process receives the signal SIGRTMAX - 17 ( which is 47 on most
+Android devices). The format of this dumped data is the same format as
+that dumped when running am dumpheap -n. The default is to dump this data
+to the file /data/local/tmp/backtrace\_heap.**PID**.txt. This is useful when
+used with native only executables that run for a while since these processes
+are not spawned from a zygote process.
+
+Note that when the signal is received, the heap is not dumped until the next
+malloc/free occurs.
+
 ### backtrace\_enable\_on\_signal[=MAX\_FRAMES]
 Enable capturing the backtrace of each allocation site. If the
 backtrace capture is toggled when the process receives the signal
@@ -123,6 +134,26 @@
 This option adds a special header to all allocations that contains the
 backtrace and information about the original allocation.
 
+### backtrace\_dump\_on\_exit
+As of P, when the backtrace option has been enabled, this causes the backtrace
+dump heap data to be dumped to a file when the program exits. If the backtrace
+option has not been enabled, this does nothing. The default is to dump this
+to the file named /data/local/tmp/backtrace\_heap.**PID**.exit.txt.
+
+The file location can be changed by setting the backtrace\_dump\_prefix
+option.
+
+### backtrace\_dump\_prefix
+As of P, when the backtrace options has been enabled, this sets the prefix
+used for dumping files when the signal SIGRTMAX - 17 is received or when
+the program exits and backtrace\_dump\_on\_exit is set.
+
+The default is /data/local/tmp/backtrace\_heap.
+
+When this value is changed from the default, then the filename chosen
+on the signal will be backtrace\_dump\_prefix.**PID**.txt. The filename chosen
+when the program exits will be backtrace\_dump\_prefix.**PID**.exit.txt.
+
 ### fill\_on\_alloc[=MAX\_FILLED\_BYTES]
 Any allocation routine, other than calloc, will result in the allocation being
 filled with the value 0xeb. When doing a realloc to a larger size, the bytes
@@ -369,6 +400,66 @@
 As with the other error message, the function in parenthesis is the
 function that was called with the bad pointer.
 
+Backtrace Heap Dump Format
+==========================
+
+This section describes the format of the backtrace heap dump. This data is
+generated by am dumpheap -n or, as of P, by the signal or on exit.
+
+The data has this header:
+
+    Android Native Heap Dump v1.0
+
+    Total memory: XXXX
+    Allocation records: YYYY
+    Backtrace size: ZZZZ
+
+Total memory is the total of all of the currently live allocations.
+Allocation records is the total number of allocation records.
+Backtrace size is the maximum number of backtrace frames that can be present.
+
+Following this header are two different sections, the first section is the
+allocation records, the second section is the map data.
+
+The allocation record data has this format:
+
+    z ZYGOTE_CHILD_ALLOC  sz    ALLOCATION_SIZE  num  NUM_ALLOCATIONS bt FRAMES
+
+ZYGOTE\_CHILD\_ALLOC is either 0 or 1. 0 means this was allocated by the
+zygote process or in a process not spawned from the zygote. 1 means this
+was allocated by an application after it forked off from the zygote process.
+
+ALLOCATION\_SIZE is the size of the allocation.
+NUM\_ALLOCATIONS is the number of allocations that have this size and have the
+same backtrace.
+FRAMES is a list of instruction pointers that represent the backtrace of the
+allocation.
+
+Example:
+
+    z 0  sz      400  num    1  bt 0000a230 0000b500
+    z 1  sz      500  num    3  bt 0000b000 0000c000
+
+The first allocation record was created by the zygote of size 400 only one
+with this backtrace/size and a backtrace of 0xa230, 0xb500.
+The second allocation record was create by an application spawned from the
+zygote of size 500, where there are three of these allocation with the same
+backtrace/size and a backtrace of 0xb000, 0xc000.
+
+The final section is the map data for the process:
+
+    MAPS
+    7fe9181000-7fe91a2000 rw-p 00000000 00:00 0                              /system/lib/libc.so
+    .
+    .
+    .
+    END
+
+The map data is simply the output of /proc/PID/maps. This data can be used to
+decode the frames in the backtraces.
+
+There is a tool to visualize this data, development/scripts/native\_heapdump\_viewer.py.
+
 Examples
 ========
 
diff --git a/libc/malloc_debug/TrackData.cpp b/libc/malloc_debug/TrackData.cpp
index 7ce477c..4266aa2 100644
--- a/libc/malloc_debug/TrackData.cpp
+++ b/libc/malloc_debug/TrackData.cpp
@@ -59,6 +59,49 @@
   });
 }
 
+void TrackData::GetListBySizeThenBacktrace(std::vector<const Header*>* list, size_t* total_memory) {
+  if (!(debug_->config().options() & BACKTRACE)) {
+    return;
+  }
+
+  *total_memory = 0;
+  for (const auto& header : headers_) {
+    list->push_back(header);
+    *total_memory += header->real_size();
+  }
+
+  // Put all zygote allocations first by size and backtrace.
+  // Then all zygote child allocation by size and backtrace.
+  std::sort(list->begin(), list->end(), [&](const Header* a, const Header* b) {
+    if (a->zygote_child_alloc() && !b->zygote_child_alloc()) {
+      return false;
+    } else if (!a->zygote_child_alloc() && b->zygote_child_alloc()) {
+      return true;
+    }
+    if (a->real_size() != b->real_size()) return a->real_size() < b->real_size();
+    // If the size is the same, compare backtrace elements.
+    BacktraceHeader* a_back = debug_->GetAllocBacktrace(a);
+    BacktraceHeader* b_back = debug_->GetAllocBacktrace(b);
+    for (size_t i = 0; i < a_back->num_frames; i++) {
+      if (i > b_back->num_frames) {
+        // All frames equal up to this point, but a has more frames available.
+        return false;
+      }
+      if (a_back->frames[i] < b_back->frames[i]) {
+        return false;
+      } else if (a_back->frames[i] > b_back->frames[i]) {
+        return true;
+      }
+    }
+    if (a_back->num_frames < b_back->num_frames) {
+      // All frames equal up to this point, but b has more frames available.
+      return true;
+    }
+    return false;
+  });
+
+}
+
 void TrackData::Add(const Header* header, bool backtrace_found) {
   pthread_mutex_lock(&mutex_);
   if (backtrace_found) {
diff --git a/libc/malloc_debug/TrackData.h b/libc/malloc_debug/TrackData.h
index e4c8951..f7486e9 100644
--- a/libc/malloc_debug/TrackData.h
+++ b/libc/malloc_debug/TrackData.h
@@ -51,6 +51,8 @@
 
   void GetList(std::vector<const Header*>* list);
 
+  void GetListBySizeThenBacktrace(std::vector<const Header*>* list, size_t* total_memory);
+
   void Add(const Header* header, bool backtrace_found);
 
   void Remove(const Header* header, bool backtrace_found);
diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map
index 59bb102..e92a7cf 100644
--- a/libc/malloc_debug/exported32.map
+++ b/libc/malloc_debug/exported32.map
@@ -1,6 +1,7 @@
 LIBC_MALLOC_DEBUG {
   global:
     debug_calloc;
+    debug_dump_heap;
     debug_finalize;
     debug_free;
     debug_free_malloc_leak_info;
diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map
index ec9d840..94104b0 100644
--- a/libc/malloc_debug/exported64.map
+++ b/libc/malloc_debug/exported64.map
@@ -1,6 +1,7 @@
 LIBC_MALLOC_DEBUG {
   global:
     debug_calloc;
+    debug_dump_heap;
     debug_finalize;
     debug_free;
     debug_free_malloc_leak_info;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 014d385..d890a1c 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -34,8 +34,11 @@
 #include <sys/param.h>
 #include <unistd.h>
 
+#include <mutex>
 #include <vector>
 
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <private/bionic_malloc_dispatch.h>
 
 #include "backtrace.h"
@@ -65,6 +68,7 @@
 bool debug_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_child,
     const char* options);
 void debug_finalize();
+bool debug_dump_heap(const char* file_name);
 void debug_get_malloc_leak_info(
     uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory,
     size_t* backtrace_size);
@@ -138,7 +142,7 @@
   header->orig_pointer = orig_pointer;
   header->size = size;
   if (*g_malloc_zygote_child) {
-    header->set_zygote();
+    header->set_zygote_child_alloc();
   }
   header->usable_size = g_dispatch->malloc_usable_size(orig_pointer);
   if (header->usable_size == 0) {
@@ -164,7 +168,7 @@
   bool backtrace_found = false;
   if (g_debug->config().options() & BACKTRACE) {
     BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
-    if (g_debug->backtrace->enabled()) {
+    if (g_debug->backtrace->ShouldBacktrace()) {
       back_header->num_frames = backtrace_get(
           &back_header->frames[0], g_debug->config().backtrace_frames());
       backtrace_found = back_header->num_frames > 0;
@@ -224,6 +228,13 @@
     g_debug->track->DisplayLeaks();
   }
 
+  if ((g_debug->config().options() & BACKTRACE) && g_debug->config().backtrace_dump_on_exit()) {
+    ScopedDisableDebugCalls disable;
+    debug_dump_heap(
+        android::base::StringPrintf("%s.%d.exit.txt",
+                                    g_debug->config().backtrace_dump_prefix().c_str(),                              getpid()).c_str());
+  }
+
   DebugDisableSet(true);
 
   backtrace_shutdown();
@@ -288,6 +299,13 @@
 }
 
 static void *internal_malloc(size_t size) {
+  if ((g_debug->config().options() & BACKTRACE) && g_debug->backtrace->ShouldDumpAndReset()) {
+    debug_dump_heap(
+        android::base::StringPrintf("%s.%d.txt",
+                                    g_debug->config().backtrace_dump_prefix().c_str(),
+                                    getpid()).c_str());
+  }
+
   if (size == 0) {
     size = 1;
   }
@@ -341,6 +359,13 @@
 }
 
 static void internal_free(void* pointer) {
+  if ((g_debug->config().options() & BACKTRACE) && g_debug->backtrace->ShouldDumpAndReset()) {
+    debug_dump_heap(
+        android::base::StringPrintf("%s.%d.txt",
+                                    g_debug->config().backtrace_dump_prefix().c_str(),
+                                    getpid()).c_str());
+  }
+
   void* free_pointer = pointer;
   size_t bytes;
   Header* header;
@@ -538,7 +563,7 @@
     if (real_size < header->usable_size) {
       header->size = real_size;
       if (*g_malloc_zygote_child) {
-        header->set_zygote();
+        header->set_zygote_child_alloc();
       }
       if (g_debug->config().options() & REAR_GUARD) {
         // Don't bother allocating a smaller pointer in this case, simply
@@ -758,3 +783,65 @@
   return debug_memalign(getpagesize(), size);
 }
 #endif
+
+static std::mutex g_dump_lock;
+
+bool debug_dump_heap(const char* file_name) {
+  ScopedDisableDebugCalls disable;
+
+  std::lock_guard<std::mutex> guard(g_dump_lock);
+
+  FILE* fp = fopen(file_name, "w+e");
+  if (fp == nullptr) {
+    error_log("Unable to create file: %s", file_name);
+    return false;
+  }
+  error_log("Dumping to file: %s\n", file_name);
+
+  if (!(g_debug->config().options() & BACKTRACE)) {
+    fprintf(fp, "Native heap dump not available. To enable, run these commands (requires root):\n");
+    fprintf(fp, "# adb shell stop\n");
+    fprintf(fp, "# adb shell setprop libc.debug.malloc.options backtrace\n");
+    fprintf(fp, "# adb shell start\n");
+    fclose(fp);
+    return false;
+  }
+
+  fprintf(fp, "Android Native Heap Dump v1.0\n\n");
+
+  std::vector<const Header*> list;
+  size_t total_memory;
+  g_debug->track->GetListBySizeThenBacktrace(&list, &total_memory);
+  fprintf(fp, "Total memory: %zu\n", total_memory);
+  fprintf(fp, "Allocation records: %zd\n", list.size());
+  fprintf(fp, "Backtrace size: %zu\n", g_debug->config().backtrace_frames());
+  fprintf(fp, "\n");
+
+  for (const auto& header : list) {
+    const BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
+    fprintf(fp, "z %d  sz %8zu  num    1  bt", (header->zygote_child_alloc()) ? 1 : 0,
+            header->real_size());
+    for (size_t i = 0; i < back_header->num_frames; i++) {
+      if (back_header->frames[i] == 0) {
+        break;
+      }
+#ifdef __LP64__
+      fprintf(fp, " %016" PRIxPTR, back_header->frames[i]);
+#else
+      fprintf(fp, " %08" PRIxPTR, back_header->frames[i]);
+#endif
+    }
+    fprintf(fp, "\n");
+  }
+
+  fprintf(fp, "MAPS\n");
+  std::string content;
+  if (!android::base::ReadFileToString("/proc/self/maps", &content)) {
+    fprintf(fp, "Could not open /proc/self/maps\n");
+  } else {
+    fprintf(fp, "%s", content.c_str());
+  }
+  fprintf(fp, "END\n");
+  fclose(fp);
+  return true;
+}
diff --git a/libc/malloc_debug/malloc_debug.h b/libc/malloc_debug/malloc_debug.h
index 347fae2..4a1e8da 100644
--- a/libc/malloc_debug/malloc_debug.h
+++ b/libc/malloc_debug/malloc_debug.h
@@ -54,7 +54,8 @@
   size_t size;
   size_t usable_size;
   size_t real_size() const { return size & ~(1U << 31); }
-  void set_zygote() { size |= 1U << 31; }
+  void set_zygote_child_alloc() { size |= 1U << 31; }
+  bool zygote_child_alloc() const { return size & (1U << 31); }
   static size_t max_size() { return (1U << 31) - 1; }
 } __attribute__((packed));
 
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index 77dc848..ee8fe06 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -60,6 +60,9 @@
   "6 malloc_debug   backtrace[=XX]\n"
   "6 malloc_debug     Enable capturing the backtrace at the point of allocation.\n"
   "6 malloc_debug     If XX is set it sets the number of backtrace frames.\n"
+  "6 malloc_debug     This option also enables dumping the backtrace heap data\n"
+  "6 malloc_debug     when a signal is received. The data is dumped to the file\n"
+  "6 malloc_debug     backtrace_dump_prefix.<PID>.txt.\n"
   "6 malloc_debug     The default is 16 frames, the max number of frames is 256.\n"
   "6 malloc_debug \n"
   "6 malloc_debug   backtrace_enable_on_signal[=XX]\n"
@@ -68,6 +71,18 @@
   "6 malloc_debug     receives a signal. If XX is set it sets the number of backtrace\n"
   "6 malloc_debug     frames. The default is 16 frames, the max number of frames is 256.\n"
   "6 malloc_debug \n"
+  "6 malloc_debug   backtrace_dump_prefix[=FILE]\n"
+  "6 malloc_debug     This option only has meaning if the backtrace option has been specified.\n"
+  "6 malloc_debug     This is the prefix of the name of the file to which backtrace heap\n"
+  "6 malloc_debug     data will be dumped. The file will be named backtrace_dump_prefix.<PID>.txt.\n"
+  "6 malloc_debug     The default is /data/local/tmp/backtrace_heap.\n"
+  "6 malloc_debug \n"
+  "6 malloc_debug   backtrace_dump_on_exit\n"
+  "6 malloc_debug     This option only has meaning if the backtrace option has been specified.\n"
+  "6 malloc_debug     This will cause all live allocations to be dumped to the file\n"
+  "6 malloc_debug     backtrace_dump_prefix.<PID>.final.txt.\n"
+  "6 malloc_debug     The default is false.\n"
+  "6 malloc_debug \n"
   "6 malloc_debug   fill_on_alloc[=XX]\n"
   "6 malloc_debug     On first allocation, fill with the value 0xeb.\n"
   "6 malloc_debug     If XX is set it will only fill up to XX bytes of the\n"
@@ -292,12 +307,14 @@
   ASSERT_EQ(64U, config->backtrace_frames());
   ASSERT_TRUE(config->backtrace_enabled());
   ASSERT_FALSE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
 
   ASSERT_TRUE(InitConfig("backtrace")) << getFakeLogPrint();
   ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
   ASSERT_EQ(16U, config->backtrace_frames());
   ASSERT_TRUE(config->backtrace_enabled());
   ASSERT_FALSE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -309,12 +326,14 @@
   ASSERT_EQ(64U, config->backtrace_frames());
   ASSERT_FALSE(config->backtrace_enabled());
   ASSERT_TRUE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
 
   ASSERT_TRUE(InitConfig("backtrace_enable_on_signal")) << getFakeLogPrint();
   ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
   ASSERT_EQ(16U, config->backtrace_frames());
   ASSERT_FALSE(config->backtrace_enabled());
   ASSERT_TRUE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -326,12 +345,14 @@
   ASSERT_EQ(64U, config->backtrace_frames());
   ASSERT_FALSE(config->backtrace_enabled());
   ASSERT_TRUE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
 
   ASSERT_TRUE(InitConfig("backtrace")) << getFakeLogPrint();
   ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
   ASSERT_EQ(16U, config->backtrace_frames());
   ASSERT_TRUE(config->backtrace_enabled());
   ASSERT_FALSE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -343,12 +364,46 @@
   ASSERT_EQ(16U, config->backtrace_frames());
   ASSERT_TRUE(config->backtrace_enabled());
   ASSERT_TRUE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
 
   ASSERT_TRUE(InitConfig("backtrace backtrace_enable_on_signal")) << getFakeLogPrint();
   ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
   ASSERT_EQ(16U, config->backtrace_frames());
   ASSERT_TRUE(config->backtrace_enabled());
   ASSERT_TRUE(config->backtrace_enable_on_signal());
+  ASSERT_FALSE(config->backtrace_dump_on_exit());
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_dump_on_exit) {
+  ASSERT_TRUE(InitConfig("backtrace_dump_on_exit")) << getFakeLogPrint();
+  ASSERT_EQ(0U, config->options());
+  ASSERT_TRUE(config->backtrace_dump_on_exit());
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_dump_on_exit_error) {
+  ASSERT_FALSE(InitConfig("backtrace_dump_on_exit=something")) << getFakeLogPrint();
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string log_msg(
+      "6 malloc_debug malloc_testing: value set for option 'backtrace_dump_on_exit' "
+      "which does not take a value\n");
+  ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_dump_prefix) {
+  ASSERT_TRUE(InitConfig("backtrace_dump_prefix")) << getFakeLogPrint();
+  ASSERT_EQ(0U, config->options());
+  ASSERT_EQ("/data/local/tmp/backtrace_heap", config->backtrace_dump_prefix());
+
+  ASSERT_TRUE(InitConfig("backtrace_dump_prefix=/fake/location")) << getFakeLogPrint();
+  ASSERT_EQ(0U, config->options());
+  ASSERT_EQ("/fake/location", config->backtrace_dump_prefix());
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 4fdba2e..37d8057 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -32,6 +32,7 @@
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 
 #include <private/bionic_macros.h>
 #include <private/bionic_malloc_dispatch.h>
@@ -82,6 +83,8 @@
 
 static constexpr const char RECORD_ALLOCS_FILE[] = "/data/local/tmp/record_allocs.txt";
 
+static constexpr const char BACKTRACE_DUMP_PREFIX[] = "/data/local/tmp/backtrace_heap";
+
 class MallocDebugTest : public ::testing::Test {
  protected:
   void SetUp() override {
@@ -104,6 +107,8 @@
     initialized = true;
   }
 
+  void BacktraceDumpOnSignal(bool trigger_with_alloc);
+
   bool initialized;
 
   int zygote;
@@ -132,7 +137,7 @@
   mallopt,
 };
 
-void VerifyAllocCalls() {
+void VerifyAllocCalls(bool backtrace_enabled) {
   size_t alloc_size = 1024;
 
   // Verify debug_malloc.
@@ -186,17 +191,23 @@
   ASSERT_TRUE(pointer == nullptr);
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
-  ASSERT_STREQ("", getFakeLogPrint().c_str());
+  std::string expected_log;
+  if (backtrace_enabled) {
+    expected_log += android::base::StringPrintf(
+        "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+        SIGRTMAX - 17, getpid());
+  }
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
 TEST_F(MallocDebugTest, fill_generic) {
   Init("fill");
-  VerifyAllocCalls();
+  VerifyAllocCalls(false);
 }
 
 TEST_F(MallocDebugTest, fill_on_alloc_generic) {
   Init("fill_on_alloc");
-  VerifyAllocCalls();
+  VerifyAllocCalls(false);
 }
 
 TEST_F(MallocDebugTest, fill_on_alloc_partial) {
@@ -275,7 +286,7 @@
 
 TEST_F(MallocDebugTest, all_options) {
   Init("guard backtrace fill expand_alloc free_track leak_track");
-  VerifyAllocCalls();
+  VerifyAllocCalls(true);
 }
 
 TEST_F(MallocDebugTest, expand_alloc) {
@@ -624,6 +635,9 @@
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  expected_log += android::base::StringPrintf(
       "6 malloc_debug +++ malloc_testing leaked block of size 1024 at %p (leak 1 of 3)\n",
       pointer3);
   expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
@@ -649,7 +663,6 @@
   expected_log += "6 malloc_debug   #00 pc 0x1000\n";
   expected_log += "6 malloc_debug   #01 pc 0x2000\n";
   expected_log += "6 malloc_debug   #02 pc 0x3000\n";
-
   ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
@@ -1022,7 +1035,10 @@
   ASSERT_EQ(0U, backtrace_size);
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
-  ASSERT_STREQ("", getFakeLogPrint().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
 TEST_F(MallocDebugTest, get_malloc_leak_info_single) {
@@ -1065,7 +1081,10 @@
   debug_free(pointer);
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
-  ASSERT_STREQ("", getFakeLogPrint().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
 TEST_F(MallocDebugTest, get_malloc_leak_info_multi) {
@@ -1144,7 +1163,10 @@
   debug_free(pointers[2]);
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
-  ASSERT_STREQ("", getFakeLogPrint().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
 TEST_F(MallocDebugTest, get_malloc_leak_info_multi_skip_empty_backtrace) {
@@ -1215,6 +1237,185 @@
   debug_free(pointers[2]);
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+static std::string SanitizeHeapData(const std::string& data) {
+  // Remove the map data since it's not consistent.
+  std::string sanitized;
+  bool skip_map_data = false;
+  bool map_data_found = false;
+  for (auto& line : android::base::Split(data, "\n")) {
+    if (skip_map_data) {
+      if (line == "END") {
+        if (map_data_found) {
+          sanitized += "MAP_DATA\n";
+          map_data_found = false;
+        }
+        skip_map_data = false;
+      } else {
+        map_data_found = true;
+        continue;
+      }
+    }
+    if (line == "MAPS") {
+      skip_map_data = true;
+    }
+    sanitized += line + '\n';
+  }
+  return sanitized;
+}
+
+void MallocDebugTest::BacktraceDumpOnSignal(bool trigger_with_alloc) {
+  Init("backtrace=4");
+
+  backtrace_fake_add(std::vector<uintptr_t> {0x100, 0x200});
+  backtrace_fake_add(std::vector<uintptr_t> {0x300, 0x400});
+  backtrace_fake_add(std::vector<uintptr_t> {0x500, 0x600});
+
+  backtrace_fake_add(std::vector<uintptr_t> {0xa000, 0xb000});
+  backtrace_fake_add(std::vector<uintptr_t> {0xa100, 0xb200});
+  backtrace_fake_add(std::vector<uintptr_t> {0xa300, 0xb300});
+
+  std::vector<void*> pointers;
+  zygote = 1;
+  pointers.push_back(debug_malloc(100));
+  ASSERT_TRUE(pointers.back() != nullptr);
+  pointers.push_back(debug_malloc(40));
+  ASSERT_TRUE(pointers.back() != nullptr);
+  pointers.push_back(debug_malloc(200));
+  ASSERT_TRUE(pointers.back() != nullptr);
+
+  zygote = 0;
+  pointers.push_back(debug_malloc(10));
+  ASSERT_TRUE(pointers.back() != nullptr);
+  pointers.push_back(debug_malloc(50));
+  ASSERT_TRUE(pointers.back() != nullptr);
+  pointers.push_back(debug_malloc(5));
+  ASSERT_TRUE(pointers.back() != nullptr);
+
+  // Dump all of the data accumulated so far.
+  ASSERT_TRUE(kill(getpid(), SIGRTMAX - 17) == 0);
+  sleep(1);
+
+  // This triggers the dumping.
+  if (trigger_with_alloc) {
+    pointers.push_back(debug_malloc(23));
+    ASSERT_TRUE(pointers.back() != nullptr);
+  } else {
+    debug_free(pointers.back());
+    pointers.pop_back();
+  }
+
+  for (auto* pointer : pointers) {
+    debug_free(pointer);
+  }
+
+  // Read all of the contents.
+  std::string actual;
+  std::string name = android::base::StringPrintf("%s.%d.txt", BACKTRACE_DUMP_PREFIX, getpid());
+  ASSERT_TRUE(android::base::ReadFileToString(name, &actual));
+  ASSERT_EQ(0, unlink(name.c_str()));
+
+  std::string sanitized(SanitizeHeapData(actual));
+
+  std::string expected =
+      "Android Native Heap Dump v1.0\n"
+      "\n"
+      "Total memory: 405\n"
+      "Allocation records: 6\n"
+      "Backtrace size: 4\n"
+      "\n"
+#if defined(__LP64__)
+      "z 0  sz        5  num    1  bt 000000000000a300 000000000000b300\n"
+      "z 0  sz       10  num    1  bt 000000000000a000 000000000000b000\n"
+      "z 0  sz       50  num    1  bt 000000000000a100 000000000000b200\n"
+      "z 1  sz       40  num    1  bt 0000000000000300 0000000000000400\n"
+      "z 1  sz      100  num    1  bt 0000000000000100 0000000000000200\n"
+      "z 1  sz      200  num    1  bt 0000000000000500 0000000000000600\n"
+#else
+      "z 0  sz        5  num    1  bt 0000a300 0000b300\n"
+      "z 0  sz       10  num    1  bt 0000a000 0000b000\n"
+      "z 0  sz       50  num    1  bt 0000a100 0000b200\n"
+      "z 1  sz       40  num    1  bt 00000300 00000400\n"
+      "z 1  sz      100  num    1  bt 00000100 00000200\n"
+      "z 1  sz      200  num    1  bt 00000500 00000600\n"
+#endif
+      "MAPS\n"
+      "MAP_DATA\n"
+      "END\n\n";
+  ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug Dumping to file: /data/local/tmp/backtrace_heap.%d.txt\n\n", getpid());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_dump_on_signal_by_malloc) {
+  BacktraceDumpOnSignal(true);
+}
+
+TEST_F(MallocDebugTest, backtrace_dump_on_signal_by_free) {
+  BacktraceDumpOnSignal(false);
+}
+
+TEST_F(MallocDebugTest, backtrace_dump_on_exit) {
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    Init("backtrace=4 backtrace_dump_on_exit");
+    backtrace_fake_add(std::vector<uintptr_t> {0x100, 0x200});
+    backtrace_fake_add(std::vector<uintptr_t> {0xa000, 0xb000});
+    backtrace_fake_add(std::vector<uintptr_t> {0xa000, 0xb000, 0xc000});
+
+    std::vector<void*> pointers;
+    pointers.push_back(debug_malloc(300));
+    pointers.push_back(debug_malloc(400));
+    pointers.push_back(debug_malloc(500));
+
+    // Call the exit function manually.
+    debug_finalize();
+    exit(0);
+  }
+  ASSERT_NE(-1, pid);
+  ASSERT_EQ(pid, waitpid(pid, nullptr, 0));
+
+  // Read all of the contents.
+  std::string actual;
+  std::string name = android::base::StringPrintf("%s.%d.exit.txt", BACKTRACE_DUMP_PREFIX, pid);
+  ASSERT_TRUE(android::base::ReadFileToString(name, &actual));
+  ASSERT_EQ(0, unlink(name.c_str()));
+
+  std::string sanitized(SanitizeHeapData(actual));
+
+  std::string expected =
+      "Android Native Heap Dump v1.0\n"
+      "\n"
+      "Total memory: 1200\n"
+      "Allocation records: 3\n"
+      "Backtrace size: 4\n"
+      "\n"
+#if defined(__LP64__)
+      "z 0  sz      300  num    1  bt 0000000000000100 0000000000000200\n"
+      "z 0  sz      400  num    1  bt 000000000000a000 000000000000b000\n"
+      "z 0  sz      500  num    1  bt 000000000000a000 000000000000b000 000000000000c000\n"
+#else
+      "z 0  sz      300  num    1  bt 00000100 00000200\n"
+      "z 0  sz      400  num    1  bt 0000a000 0000b000\n"
+      "z 0  sz      500  num    1  bt 0000a000 0000b000 0000c000\n"
+#endif
+      "MAPS\n"
+      "MAP_DATA\n"
+      "END\n\n";
+  ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
@@ -1317,6 +1518,9 @@
   std::string expected_log = android::base::StringPrintf(
       "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to enable backtracing.\n",
       SIGRTMAX - 19, getpid());
+  expected_log += android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
   ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
@@ -1439,7 +1643,10 @@
   debug_free(pointer);
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
-  ASSERT_STREQ("", getFakeLogPrint().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
 TEST_F(MallocDebugTest, max_size) {
@@ -1596,6 +1803,7 @@
   // Read all of the contents.
   std::string actual;
   ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
 
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
@@ -1653,6 +1861,7 @@
   // Read all of the contents.
   std::string actual;
   ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
 
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
@@ -1694,6 +1903,7 @@
   // Read all of the contents.
   std::string actual;
   ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
 
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
@@ -1748,6 +1958,7 @@
   expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
 
   ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+  ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
   ASSERT_STREQ(expected.c_str(), actual.c_str());
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index e40f3e3..9aba2e2 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -100,6 +100,7 @@
   '__memrchr_chk',
   '__pwrite64_chk',
   '__pwrite_chk',
+  '__sendto_chk',
   '__stack_chk_guard',
   '__stpncpy_chk2',
   '__strchr_chk',
@@ -184,23 +185,42 @@
 # POSIX has some stuff that's too stupid for words (a64l) or not actually
 # implemented in glibc unless you count always failing with ENOSYS as
 # being implemented (fattach).
-in_posix_and_glibc_but_actually_dead = set([
-  'a64l',
-  'confstr',
-  'fattach',
-  'fdetach',
-  'gethostid',
-  'getmsg',
-  'getpmsg',
-  'isastream',
-  'l64a',
-  'putmsg',
-  'putpmsg',
-  'ulimit',
+in_posix_and_glibc_but_dead_or_useless = set([
+  'a64l', # obsolete
+  'confstr', # obsolete
+  'fattach', # obsolete
+  'fdetach', # obsolete
+  'gethostid', # obsolete
+  'getmsg', # obsolete
+  'getpmsg', # obsolete
+  'getutxent', # no utmp on Android
+  'getutxid', # no utmp on Android
+  'getutxline', # no utmp on Android
+  'isastream', # obsolete
+  'l64a', # obsolete
+  'mq_close', # disallowed by SELinux
+  'mq_getattr', # disallowed by SELinux
+  'mq_notify', # disallowed by SELinux
+  'mq_open', # disallowed by SELinux
+  'mq_receive', # disallowed by SELinux
+  'mq_send', # disallowed by SELinux
+  'mq_setattr', # disallowed by SELinux
+  'mq_timedreceive', # disallowed by SELinux
+  'mq_timedsend', # disallowed by SELinux
+  'mq_unlink', # disallowed by SELinux
+  'putmsg', # obsolete
+  'putpmsg', # obsolete
+  'pututxline', # no utmp on Android
+  'shm_open', # disallowed by SELinux
+  'shm_unlink', # disallowed by SELinux
+  'setutxent', # no utmp on Android
+  'strfmon', # icu4c
+  'strfmon_l', # icu4c
+  'ulimit', # obsolete
 ])
 
-posix = posix - in_posix_and_glibc_but_actually_dead
-glibc = glibc - in_posix_and_glibc_but_actually_dead
+posix = posix - in_posix_and_glibc_but_dead_or_useless
+glibc = glibc - in_posix_and_glibc_but_dead_or_useless
 
 if not only_unwanted:
   #print 'glibc:'
diff --git a/libc/tools/check-symbols.py b/libc/tools/check-symbols.py
index a6cf50c..6568917 100755
--- a/libc/tools/check-symbols.py
+++ b/libc/tools/check-symbols.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 import glob
 import os
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate-NOTICE.py
index d40891c..e59fc7a 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate-NOTICE.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # Run with directory arguments from any directory, with no special setup required.
 # Or:
 # for i in libc libdl libm linker libstdc++ ; do ./libc/tools/generate-NOTICE.py $i > $i/NOTICE ; done
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index e6240a1..46affb7 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 # This tool is used to generate the assembler system call stubs,
 # the header files listing all available system calls, and the
diff --git a/libc/tools/genversion-scripts.py b/libc/tools/genversion-scripts.py
index 0a98994..5410580 100755
--- a/libc/tools/genversion-scripts.py
+++ b/libc/tools/genversion-scripts.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 # This tool is used to generate the version scripts for libc and libm
 # for every architecture.
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c b/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000..d512857
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <search.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+/*
+ * Thread unsafe interface: use a single process-wide hash table and
+ * forward calls to *_r() functions.
+ */
+
+static struct hsearch_data global_hashtable;
+static bool global_hashtable_initialized = false;
+
+int
+hcreate(size_t nel)
+{
+
+	return (1);
+}
+
+void
+hdestroy(void)
+{
+
+	/* Destroy global hash table if present. */
+	if (global_hashtable_initialized) {
+		hdestroy_r(&global_hashtable);
+		global_hashtable_initialized = false;
+	}
+}
+
+ENTRY *
+hsearch(ENTRY item, ACTION action)
+{
+	ENTRY *retval;
+
+	/* Create global hash table if needed. */
+	if (!global_hashtable_initialized) {
+		if (hcreate_r(0, &global_hashtable) == 0)
+			return (NULL);
+		global_hashtable_initialized = true;
+	}
+	if (hsearch_r(item, action, &retval, &global_hashtable) == 0)
+		return (NULL);
+	return (retval);
+}
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hcreate_r.c b/libc/upstream-freebsd/lib/libc/stdlib/hcreate_r.c
new file mode 100644
index 0000000..34db88e
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hcreate_r.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate_r.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <search.h>
+#include <stdlib.h>
+
+#include "hsearch.h"
+
+int
+hcreate_r(size_t nel, struct hsearch_data *htab)
+{
+	struct __hsearch *hsearch;
+
+	/*
+	 * Allocate a hash table object. Ignore the provided hint and start
+	 * off with a table of sixteen entries. In most cases this hint is
+	 * just a wild guess. Resizing the table dynamically if the use
+	 * increases a threshold does not affect the worst-case running time.
+	 */
+	hsearch = malloc(sizeof(*hsearch));
+	if (hsearch == NULL)
+		return 0;
+	hsearch->entries = calloc(16, sizeof(ENTRY));
+	if (hsearch->entries == NULL) {
+		free(hsearch);
+		return 0;
+	}
+
+	/*
+	 * Pick a random initialization for the FNV-1a hashing. This makes it
+	 * hard to come up with a fixed set of keys to force hash collisions.
+	 */
+	arc4random_buf(&hsearch->offset_basis, sizeof(hsearch->offset_basis));
+	hsearch->index_mask = 0xf;
+	hsearch->entries_used = 0;
+	htab->__hsearch = hsearch;
+	return 1;
+}
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hdestroy_r.c b/libc/upstream-freebsd/lib/libc/stdlib/hdestroy_r.c
new file mode 100644
index 0000000..76d8a42
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hdestroy_r.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hdestroy_r.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <search.h>
+#include <stdlib.h>
+
+#include "hsearch.h"
+
+void
+hdestroy_r(struct hsearch_data *htab)
+{
+	struct __hsearch *hsearch;
+
+	/* Free hash table object and its entries. */
+	hsearch = htab->__hsearch;
+	free(hsearch->entries);
+	free(hsearch);
+}
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hsearch.h b/libc/upstream-freebsd/lib/libc/stdlib/hsearch.h
new file mode 100644
index 0000000..a0542b5
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hsearch.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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: head/lib/libc/stdlib/hsearch.h 292767 2015-12-27 07:50:11Z ed $
+ */
+
+#ifndef HSEARCH_H
+#define HSEARCH_H
+
+#include <search.h>
+
+struct __hsearch {
+	size_t offset_basis;	/* Initial value for FNV-1a hashing. */
+	size_t index_mask;	/* Bitmask for indexing the table. */
+	size_t entries_used;	/* Number of entries currently used. */
+	ENTRY *entries;		/* Hash table entries. */
+};
+
+#endif
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hsearch_r.c b/libc/upstream-freebsd/lib/libc/stdlib/hsearch_r.c
new file mode 100644
index 0000000..9a859d3
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hsearch_r.c
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hsearch_r.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <errno.h>
+#include <limits.h>
+#include <search.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "hsearch.h"
+
+/*
+ * Look up an unused entry in the hash table for a given hash. For this
+ * implementation we use quadratic probing. Quadratic probing has the
+ * advantage of preventing primary clustering.
+ */
+static ENTRY *
+hsearch_lookup_free(struct __hsearch *hsearch, size_t hash)
+{
+	size_t index, i;
+
+	for (index = hash, i = 0;; index += ++i) {
+		ENTRY *entry = &hsearch->entries[index & hsearch->index_mask];
+		if (entry->key == NULL)
+			return (entry);
+	}
+}
+
+/*
+ * Computes an FNV-1a hash of the key. Depending on the pointer size, this
+ * either uses the 32- or 64-bit FNV prime.
+ */
+static size_t
+hsearch_hash(size_t offset_basis, const char *str)
+{
+	size_t hash;
+
+	hash = offset_basis;
+	while (*str != '\0') {
+		hash ^= (uint8_t)*str++;
+		if (sizeof(size_t) * CHAR_BIT <= 32)
+			hash *= UINT32_C(16777619);
+		else
+			hash *= UINT64_C(1099511628211);
+	}
+	return (hash);
+}
+
+int
+hsearch_r(ENTRY item, ACTION action, ENTRY **retval, struct hsearch_data *htab)
+{
+	struct __hsearch *hsearch;
+	ENTRY *entry, *old_entries, *new_entries;
+	size_t hash, index, i, old_hash, old_count, new_count;
+
+	hsearch = htab->__hsearch;
+	hash = hsearch_hash(hsearch->offset_basis, item.key);
+
+	/*
+	 * Search the hash table for an existing entry for this key.
+	 * Stop searching if we run into an unused hash table entry.
+	 */
+	for (index = hash, i = 0;; index += ++i) {
+		entry = &hsearch->entries[index & hsearch->index_mask];
+		if (entry->key == NULL)
+			break;
+		if (strcmp(entry->key, item.key) == 0) {
+			*retval = entry;
+			return (1);
+		}
+	}
+
+	/* Only perform the insertion if action is set to ENTER. */
+	if (action == FIND) {
+		errno = ESRCH;
+		return (0);
+	}
+
+	if (hsearch->entries_used * 2 >= hsearch->index_mask) {
+		/* Preserve the old hash table entries. */
+		old_count = hsearch->index_mask + 1;
+		old_entries = hsearch->entries;
+
+		/*
+		 * Allocate and install a new table if insertion would
+		 * yield a hash table that is more than 50% used. By
+		 * using 50% as a threshold, a lookup will only take up
+		 * to two steps on average.
+		 */
+		new_count = (hsearch->index_mask + 1) * 2;
+		new_entries = calloc(new_count, sizeof(ENTRY));
+		if (new_entries == NULL)
+			return (0);
+		hsearch->entries = new_entries;
+		hsearch->index_mask = new_count - 1;
+
+		/* Copy over the entries from the old table to the new table. */
+		for (i = 0; i < old_count; ++i) {
+			entry = &old_entries[i];
+			if (entry->key != NULL) {
+				old_hash = hsearch_hash(hsearch->offset_basis,
+				    entry->key);
+				*hsearch_lookup_free(hsearch, old_hash) =
+				    *entry;
+			}
+		}
+
+		/* Destroy the old hash table entries. */
+		free(old_entries);
+
+		/*
+		 * Perform a new lookup for a free table entry, so that
+		 * we insert the entry into the new hash table.
+		 */
+		hsearch = htab->__hsearch;
+		entry = hsearch_lookup_free(hsearch, hash);
+	}
+
+	/* Insert the new entry into the hash table. */
+	*entry = item;
+	++hsearch->entries_used;
+	*retval = entry;
+	return (1);
+}
diff --git a/libc/upstream-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
index d006045..4c4be0e 100644
--- a/libc/upstream-openbsd/android/include/arc4random.h
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -45,10 +45,8 @@
 #define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
 #endif
 
-static inline void
-_getentropy_fail(void)
-{
-	async_safe_fatal("getentropy failed");
+static inline void _getentropy_fail(void) {
+    async_safe_fatal("getentropy failed: %s", strerror(errno));
 }
 
 volatile sig_atomic_t _rs_forked;
diff --git a/libdl/Android.bp b/libdl/Android.bp
index ffdf7f7..9f67ee8 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -44,7 +44,12 @@
             version_script: "libdl.x86_64.map",
         },
     },
-    srcs: ["libdl.c", "libdl_cfi.cpp"],
+    shared: {
+        srcs: ["libdl.c", "libdl_cfi.cpp"],
+    },
+    static: {
+        srcs: [ "libdl_static.c" ],
+    },
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/libdl/libdl_cfi.cpp b/libdl/libdl_cfi.cpp
index 483364f..1dd5b21 100644
--- a/libdl/libdl_cfi.cpp
+++ b/libdl/libdl_cfi.cpp
@@ -52,7 +52,10 @@
 
 static uintptr_t cfi_check_addr(uint16_t v, void* Ptr) {
   uintptr_t addr = reinterpret_cast<uintptr_t>(Ptr);
-  uintptr_t aligned_addr = align_up(addr, CFIShadow::kShadowAlign);
+  // The aligned range of [0, kShadowAlign) uses a single shadow element, therefore all pointers in
+  // this range must get the same aligned_addr below. This matches CFIShadowWriter::Add; not the
+  // same as align_up().
+  uintptr_t aligned_addr = align_down(addr, CFIShadow::kShadowAlign) + CFIShadow::kShadowAlign;
   uintptr_t p = aligned_addr - (static_cast<uintptr_t>(v - CFIShadow::kRegularShadowMin)
                                 << CFIShadow::kCfiCheckGranularity);
 #ifdef __arm__
diff --git a/libdl/libdl_static.c b/libdl/libdl_static.c
new file mode 100644
index 0000000..0dbd73f
--- /dev/null
+++ b/libdl/libdl_static.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 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 <dlfcn.h>
+#include <link.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+// Proxy calls to bionic loader
+void* dlopen(const char* filename __unused, int flag __unused) {
+  return NULL;
+}
+
+char* dlerror() {
+  return NULL;
+}
+
+void* dlsym(void* handle __unused, const char* symbol __unused) {
+  return NULL;
+}
+
+void* dlvsym(void* handle __unused,
+             const char* symbol __unused,
+             const char* version __unused) {
+  return NULL;
+}
+
+int dladdr(const void* addr __unused, Dl_info* info __unused) {
+  return 0;
+}
+
+int dlclose(void* handle __unused) {
+  return -1;
+}
+
+#if defined(__arm__)
+_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __unused, int* pcount __unused) {
+  return 0;
+}
+#endif
+
+void android_set_application_target_sdk_version(uint32_t target __unused) {
+}
+
diff --git a/libm/Android.bp b/libm/Android.bp
index 75e8957..bf86264 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -283,7 +283,7 @@
             srcs: [
                 "arm/fenv.c",
             ],
-            armv7_a_neon: {
+            neon: {
                 srcs: [
                     "arm/sqrt.S",
                     "arm/floor.S",
@@ -506,6 +506,7 @@
     ],
 
     cflags: [
+        "-D__BIONIC_LP32_USE_LONG_DOUBLE",
         "-D__BIONIC_NO_MATH_INLINES",
         "-D_BSD_SOURCE",
         "-DFLT_EVAL_METHOD=0",
diff --git a/libm/libm.map.txt b/libm/libm.map.txt
index 1fb16b7..1f9a3f9 100644
--- a/libm/libm.map.txt
+++ b/libm/libm.map.txt
@@ -271,7 +271,7 @@
     *;
 };
 
-LIBC_O {
+LIBC_O { # introduced=O
   global:
     cacoshl;
     cacosl;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 59e4bac..a843b7b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -286,8 +286,7 @@
                      struct stat* file_stat, off64_t file_offset,
                      uint32_t rtld_flags) {
   if (strlen(name) >= PATH_MAX) {
-    DL_ERR("library name \"%s\" too long", name);
-    return nullptr;
+    async_safe_fatal("library name \"%s\" too long", name);
   }
 
   TRACE("name %s: allocating soinfo for ns=%p", name, ns);
@@ -3211,8 +3210,23 @@
 
       default:
         if (!relocating_linker) {
-          DL_WARN("\"%s\" unused DT entry: type %p arg %p", get_realpath(),
-              reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+          const char* tag_name;
+          if (d->d_tag == DT_RPATH) {
+            tag_name = "DT_RPATH";
+          } else if (d->d_tag == DT_ENCODING) {
+            tag_name = "DT_ENCODING";
+          } else if (d->d_tag >= DT_LOOS && d->d_tag <= DT_HIOS) {
+            tag_name = "unknown OS-specific";
+          } else if (d->d_tag >= DT_LOPROC && d->d_tag <= DT_HIPROC) {
+            tag_name = "unknown processor-specific";
+          } else {
+            tag_name = "unknown";
+          }
+          DL_WARN("\"%s\" unused DT entry: %s (type %p arg %p)",
+                  get_realpath(),
+                  tag_name,
+                  reinterpret_cast<void*>(d->d_tag),
+                  reinterpret_cast<void*>(d->d_un.d_val));
         }
         break;
     }
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index fd6f496..a37e910 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -200,12 +200,10 @@
 }
 
 void LinkerSmallObjectAllocator::alloc_page() {
-  static_assert(sizeof(page_info) % 16 == 0,
-                "sizeof(page_info) is not multiple of 16");
-  void* map_ptr = mmap(nullptr, PAGE_SIZE,
-      PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+  static_assert(sizeof(page_info) % 16 == 0, "sizeof(page_info) is not multiple of 16");
+  void* map_ptr = mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
   if (map_ptr == MAP_FAILED) {
-    async_safe_fatal("mmap failed");
+    async_safe_fatal("mmap failed: %s", strerror(errno));
   }
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, "linker_alloc_small_objects");
@@ -246,11 +244,11 @@
 
 void* LinkerMemoryAllocator::alloc_mmap(size_t size) {
   size_t allocated_size = PAGE_END(size + sizeof(page_info));
-  void* map_ptr = mmap(nullptr, allocated_size,
-      PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+  void* map_ptr = mmap(nullptr, allocated_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
+                       -1, 0);
 
   if (map_ptr == MAP_FAILED) {
-    async_safe_fatal("mmap failed");
+    async_safe_fatal("mmap failed: %s", strerror(errno));
   }
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob");
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index 80ae508..9c16828 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -88,12 +88,12 @@
 
   T* allocate(size_t n, const T* hint = nullptr) {
     size_t size = n * sizeof(T);
-    void* ptr = mmap(const_cast<T*>(hint), size,
-        PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+    void* ptr = mmap(const_cast<T*>(hint), size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
+                     -1, 0);
     if (ptr == MAP_FAILED) {
       // Spec says we need to throw std::bad_alloc here but because our
       // code does not support exception handling anyways - we are going to abort.
-      async_safe_fatal("mmap failed");
+      async_safe_fatal("mmap failed: %s", strerror(errno));
     }
 
     prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "linker_alloc_vector");
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index 605e185..abb1ebd 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -117,7 +117,7 @@
                 "Invalid sizeof(LinkerBlockAllocatorPage)");
 
   LinkerBlockAllocatorPage* page = reinterpret_cast<LinkerBlockAllocatorPage*>(
-      mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0));
+      mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
 
   if (page == MAP_FAILED) {
     abort(); // oom
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index e8b02d6..3862d8c 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -276,11 +276,8 @@
 
   const char* executable_path = get_executable_path();
   soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL);
-  if (si == nullptr) {
-    async_safe_fatal("Couldn't allocate soinfo: out of memory?");
-  }
 
-  /* bootstrap the link map, the main exe always needs to be first */
+  // Bootstrap the link map, the main exe always needs to be first.
   si->set_main_executable();
   link_map* map = &(si->link_map_head);
 
diff --git a/tests/Android.bp b/tests/Android.bp
index b5f8dc8..3731156 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -57,6 +57,7 @@
         "buffer_tests.cpp",
         "bug_26110743_test.cpp",
         "complex_test.cpp",
+        "complex_force_long_double_test.cpp",
         "ctype_test.cpp",
         "dirent_test.cpp",
         "elf_test.cpp",
@@ -66,6 +67,7 @@
         "eventfd_test.cpp",
         "fcntl_test.cpp",
         "fenv_test.cpp",
+        "float_test.cpp",
         "ftw_test.cpp",
         "getauxval_test.cpp",
         "getcwd_test.cpp",
@@ -73,14 +75,17 @@
         "iconv_test.cpp",
         "ifaddrs_test.cpp",
         "inttypes_test.cpp",
+        "iso646_test.c",
         "langinfo_test.cpp",
         "leak_test.cpp",
         "libgen_basename_test.cpp",
         "libgen_test.cpp",
+        "limits_test.cpp",
         "linux_swab_test.cpp",
         "locale_test.cpp",
         "malloc_test.cpp",
         "math_test.cpp",
+        "math_force_long_double_test.cpp",
         "mntent_test.cpp",
         "netdb_test.cpp",
         "net_if_test.cpp",
@@ -102,12 +107,16 @@
         "stack_protector_test.cpp",
         "stack_protector_test_helper.cpp",
         "stack_unwinding_test.cpp",
+        "stdalign_test.cpp",
+        "stdarg_test.cpp",
         "stdatomic_test.cpp",
+        "stdbool_test.c",
         "stdint_test.cpp",
         "stdio_nofortify_test.cpp",
         "stdio_test.cpp",
         "stdio_ext_test.cpp",
         "stdlib_test.cpp",
+        "stdnoreturn_test.cpp",
         "string_nofortify_test.cpp",
         "string_test.cpp",
         "string_posix_strerror_r_test.cpp",
@@ -142,6 +151,7 @@
         "sys_xattr_test.cpp",
         "system_properties_test.cpp",
         "system_properties_test2.cpp",
+        "tgmath_test.c",
         "time_test.cpp",
         "uchar_test.cpp",
         "unistd_nofortify_test.cpp",
@@ -210,13 +220,11 @@
     // Ignore that we don't have ASAN symbols linked in.
     allow_undefined_symbols: true,
     srcs: ["fortify_compilation_test.cpp"],
-    clang: true,
 }
 
 cc_test_library {
     name: "libfortify1-tests-clang",
     defaults: ["bionic_fortify_tests_defaults", "bionic_tests_defaults"],
-    clang: true,
     cflags: [
         "-D_FORTIFY_SOURCE=1",
         "-DTEST_NAME=Fortify1_clang"
@@ -229,7 +237,6 @@
 cc_test_library {
     name: "libfortify2-tests-clang",
     defaults: ["bionic_fortify_tests_defaults", "bionic_tests_defaults"],
-    clang: true,
     cflags: [
         "-D_FORTIFY_SOURCE=2",
         "-DTEST_NAME=Fortify2_clang"
@@ -418,7 +425,6 @@
 cc_test {
     name: "bionic-unit-tests",
     defaults: ["bionic_unit_tests_defaults", "bionic_tests_defaults"],
-    clang: true,
 
     target: {
         android: {
diff --git a/tests/complex_force_long_double_test.cpp b/tests/complex_force_long_double_test.cpp
new file mode 100644
index 0000000..2ea7bd4
--- /dev/null
+++ b/tests/complex_force_long_double_test.cpp
@@ -0,0 +1,2 @@
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+#include "complex_test.cpp"
diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp
index 3a5ef74..85b20de 100644
--- a/tests/complex_test.cpp
+++ b/tests/complex_test.cpp
@@ -16,6 +16,12 @@
 
 #include <gtest/gtest.h>
 
+#if defined(__BIONIC_LP32_USE_LONG_DOUBLE)
+#define COMPLEX_TEST complex_h_force_long_double
+#else
+#define COMPLEX_TEST complex_h
+#endif
+
 // This file is compiled against both glibc and bionic, and our complex.h
 // depends on bionic-specific macros, so hack around that.
 #include <sys/cdefs.h>
@@ -24,6 +30,7 @@
 #define __INTRODUCED_IN_32(x)
 #define __INTRODUCED_IN_64(x)
 #define __INTRODUCED_IN_FUTURE
+#define __RENAME_LDBL(a,b,c)
 #endif
 
 // libc++ actively gets in the way of including <complex.h> from C++, so we
@@ -36,6 +43,7 @@
 
 #include <math.h> // For M_PI_2/M_PI_2l.
 
+#if 0
 // Note that gtest doesn't support complex numbers, so the output from
 // assertion failures is misleading/useless (at best you'll only see the real
 // part).
@@ -54,267 +62,268 @@
   os << "(" << creall(c) << "," << cimagl(c) << "i)";
   return os;
 }
+#endif
 
-TEST(complex, cabs) {
+TEST(COMPLEX_TEST, cabs) {
   ASSERT_EQ(0.0, cabs(0));
 }
 
-TEST(complex, cabsf) {
+TEST(COMPLEX_TEST, cabsf) {
   ASSERT_EQ(0.0, cabsf(0));
 }
 
-TEST(complex, cabsl) {
+TEST(COMPLEX_TEST, cabsl) {
   ASSERT_EQ(0.0, cabsl(0));
 }
 
-TEST(complex, cacos) {
+TEST(COMPLEX_TEST, cacos) {
   ASSERT_EQ(M_PI_2, cacos(0.0));
 }
 
-TEST(complex, cacosf) {
+TEST(COMPLEX_TEST, cacosf) {
   ASSERT_EQ(static_cast<float>(M_PI_2), cacosf(0.0));
 }
 
-TEST(complex, cacosl) {
+TEST(COMPLEX_TEST, cacosl) {
   ASSERT_EQ(M_PI_2l, cacosl(0.0));
 }
 
-TEST(complex, cacosh) {
+TEST(COMPLEX_TEST, cacosh) {
   ASSERT_EQ(0.0, cacosh(1.0));
 }
 
-TEST(complex, cacoshl) {
+TEST(COMPLEX_TEST, cacoshl) {
   ASSERT_EQ(0.0, cacoshl(1.0));
 }
 
-TEST(complex, cacoshf) {
+TEST(COMPLEX_TEST, cacoshf) {
   ASSERT_EQ(0.0, cacoshf(1.0));
 }
 
-TEST(complex, carg) {
+TEST(COMPLEX_TEST, carg) {
   ASSERT_EQ(0.0, carg(0));
 }
 
-TEST(complex, cargf) {
+TEST(COMPLEX_TEST, cargf) {
   ASSERT_EQ(0.0, cargf(0));
 }
 
-TEST(complex, cargl) {
+TEST(COMPLEX_TEST, cargl) {
   ASSERT_EQ(0.0, cargl(0));
 }
 
-TEST(complex, casin) {
+TEST(COMPLEX_TEST, casin) {
   ASSERT_EQ(0.0, casin(0));
 }
 
-TEST(complex, casinf) {
+TEST(COMPLEX_TEST, casinf) {
   ASSERT_EQ(0.0, casinf(0));
 }
 
-TEST(complex, casinl) {
+TEST(COMPLEX_TEST, casinl) {
   ASSERT_EQ(0.0, casinl(0));
 }
 
-TEST(complex, casinh) {
+TEST(COMPLEX_TEST, casinh) {
   ASSERT_EQ(0.0, casinh(0));
 }
 
-TEST(complex, casinhf) {
+TEST(COMPLEX_TEST, casinhf) {
   ASSERT_EQ(0.0, casinhf(0));
 }
 
-TEST(complex, casinhl) {
+TEST(COMPLEX_TEST, casinhl) {
   ASSERT_EQ(0.0, casinhl(0));
 }
 
-TEST(complex, catan) {
+TEST(COMPLEX_TEST, catan) {
   ASSERT_EQ(0.0, catan(0));
 }
 
-TEST(complex, catanf) {
+TEST(COMPLEX_TEST, catanf) {
   ASSERT_EQ(0.0, catanf(0));
 }
 
-TEST(complex, catanl) {
+TEST(COMPLEX_TEST, catanl) {
   ASSERT_EQ(0.0, catanl(0));
 }
 
-TEST(complex, catanh) {
+TEST(COMPLEX_TEST, catanh) {
   ASSERT_EQ(0.0, catanh(0));
 }
 
-TEST(complex, catanhf) {
+TEST(COMPLEX_TEST, catanhf) {
   ASSERT_EQ(0.0, catanhf(0));
 }
 
-TEST(complex, catanhl) {
+TEST(COMPLEX_TEST, catanhl) {
   ASSERT_EQ(0.0, catanhl(0));
 }
 
-TEST(complex, ccos) {
+TEST(COMPLEX_TEST, ccos) {
   ASSERT_EQ(1.0, ccos(0));
 }
 
-TEST(complex, ccosf) {
+TEST(COMPLEX_TEST, ccosf) {
   ASSERT_EQ(1.0, ccosf(0));
 }
 
-TEST(complex, ccosl) {
+TEST(COMPLEX_TEST, ccosl) {
   ASSERT_EQ(1.0, ccosl(0));
 }
 
-TEST(complex, ccosh) {
+TEST(COMPLEX_TEST, ccosh) {
   ASSERT_EQ(1.0, ccosh(0));
 }
 
-TEST(complex, ccoshf) {
+TEST(COMPLEX_TEST, ccoshf) {
   ASSERT_EQ(1.0, ccoshf(0));
 }
 
-TEST(complex, ccoshl) {
+TEST(COMPLEX_TEST, ccoshl) {
   ASSERT_EQ(1.0, ccoshl(0));
 }
 
-TEST(complex, cexp) {
+TEST(COMPLEX_TEST, cexp) {
   ASSERT_EQ(1.0, cexp(0));
 }
 
-TEST(complex, cexpf) {
+TEST(COMPLEX_TEST, cexpf) {
   ASSERT_EQ(1.0, cexpf(0));
 }
 
-TEST(complex, cexpl) {
+TEST(COMPLEX_TEST, cexpl) {
   ASSERT_EQ(1.0, cexpl(0));
 }
 
-TEST(complex, cimag) {
+TEST(COMPLEX_TEST, cimag) {
   ASSERT_EQ(0.0, cimag(0));
 }
 
-TEST(complex, cimagf) {
+TEST(COMPLEX_TEST, cimagf) {
   ASSERT_EQ(0.0f, cimagf(0));
 }
 
-TEST(complex, cimagl) {
+TEST(COMPLEX_TEST, cimagl) {
   ASSERT_EQ(0.0, cimagl(0));
 }
 
-TEST(complex, clog) {
+TEST(COMPLEX_TEST, clog) {
   ASSERT_EQ(0.0, clog(1.0));
 }
 
-TEST(complex, clogf) {
+TEST(COMPLEX_TEST, clogf) {
   ASSERT_EQ(0.0f, clogf(1.0f));
 }
 
-TEST(complex, clogl) {
+TEST(COMPLEX_TEST, clogl) {
   ASSERT_EQ(0.0L, clogl(1.0L));
 }
 
-TEST(complex, conj) {
+TEST(COMPLEX_TEST, conj) {
   ASSERT_EQ(0.0, conj(0));
 }
 
-TEST(complex, conjf) {
+TEST(COMPLEX_TEST, conjf) {
   ASSERT_EQ(0.0f, conjf(0));
 }
 
-TEST(complex, conjl) {
+TEST(COMPLEX_TEST, conjl) {
   ASSERT_EQ(0.0, conjl(0));
 }
 
-TEST(complex, cpow) {
+TEST(COMPLEX_TEST, cpow) {
   ASSERT_EQ(8.0, cpow(2.0, 3.0));
 }
 
-TEST(complex, cpowf) {
+TEST(COMPLEX_TEST, cpowf) {
   ASSERT_EQ(8.0f, cpowf(2.0f, 3.0f));
 }
 
-TEST(complex, cpowl) {
+TEST(COMPLEX_TEST, cpowl) {
   ASSERT_EQ(8.0L, cpowl(2.0L, 3.0L));
 }
 
-TEST(complex, cproj) {
+TEST(COMPLEX_TEST, cproj) {
   ASSERT_EQ(0.0, cproj(0));
 }
 
-TEST(complex, cprojf) {
+TEST(COMPLEX_TEST, cprojf) {
   ASSERT_EQ(0.0f, cprojf(0));
 }
 
-TEST(complex, cprojl) {
+TEST(COMPLEX_TEST, cprojl) {
   ASSERT_EQ(0.0, cprojl(0));
 }
 
-TEST(complex, creal) {
+TEST(COMPLEX_TEST, creal) {
   ASSERT_EQ(2.0, creal(2.0 + 3.0I));
 }
 
-TEST(complex, crealf) {
+TEST(COMPLEX_TEST, crealf) {
   ASSERT_EQ(2.0f, crealf(2.0f + 3.0fI));
 }
 
-TEST(complex, creall) {
+TEST(COMPLEX_TEST, creall) {
   ASSERT_EQ(2.0, creall(2.0L + 3.0LI));
 }
 
-TEST(complex, csin) {
+TEST(COMPLEX_TEST, csin) {
   ASSERT_EQ(0.0, csin(0));
 }
 
-TEST(complex, csinf) {
+TEST(COMPLEX_TEST, csinf) {
   ASSERT_EQ(0.0, csinf(0));
 }
 
-TEST(complex, csinl) {
+TEST(COMPLEX_TEST, csinl) {
   ASSERT_EQ(0.0, csinl(0));
 }
 
-TEST(complex, csinh) {
+TEST(COMPLEX_TEST, csinh) {
   ASSERT_EQ(0.0, csinh(0));
 }
 
-TEST(complex, csinhf) {
+TEST(COMPLEX_TEST, csinhf) {
   ASSERT_EQ(0.0, csinhf(0));
 }
 
-TEST(complex, csinhl) {
+TEST(COMPLEX_TEST, csinhl) {
   ASSERT_EQ(0.0, csinhl(0));
 }
 
-TEST(complex, csqrt) {
+TEST(COMPLEX_TEST, csqrt) {
   ASSERT_EQ(0.0, csqrt(0));
 }
 
-TEST(complex, csqrtf) {
+TEST(COMPLEX_TEST, csqrtf) {
   ASSERT_EQ(0.0f, csqrtf(0));
 }
 
-TEST(complex, csqrtl) {
+TEST(COMPLEX_TEST, csqrtl) {
   ASSERT_EQ(0.0, csqrtl(0));
 }
 
-TEST(complex, ctan) {
+TEST(COMPLEX_TEST, ctan) {
   ASSERT_EQ(0.0, ctan(0));
 }
 
-TEST(complex, ctanf) {
+TEST(COMPLEX_TEST, ctanf) {
   ASSERT_EQ(0.0, ctanf(0));
 }
 
-TEST(complex, ctanl) {
+TEST(COMPLEX_TEST, ctanl) {
   ASSERT_EQ(0.0, ctanl(0));
 }
 
-TEST(complex, ctanh) {
+TEST(COMPLEX_TEST, ctanh) {
   ASSERT_EQ(0.0, ctanh(0));
 }
 
-TEST(complex, ctanhf) {
+TEST(COMPLEX_TEST, ctanhf) {
   ASSERT_EQ(0.0, ctanhf(0));
 }
 
-TEST(complex, ctanhl) {
+TEST(COMPLEX_TEST, ctanhl) {
   ASSERT_EQ(0.0, ctanhl(0));
 }
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 857640a..aaf2c37 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -16,6 +16,10 @@
 
 #include <gtest/gtest.h>
 
+#if defined(__BIONIC__)
+#include <android-base/properties.h>
+#endif
+
 #include <dlfcn.h>
 #include <libgen.h>
 #include <limits.h>
@@ -226,6 +230,12 @@
     // This test is only for CTS.
     return;
   }
+  std::string build_type = android::base::GetProperty("ro.build.type", "user");
+  if (build_type == "userdebug" || build_type == "eng") {
+    // Skip the test for non production devices
+    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";
diff --git a/tests/float_test.cpp b/tests/float_test.cpp
new file mode 100644
index 0000000..a75214e
--- /dev/null
+++ b/tests/float_test.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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 <float.h>
+
+TEST(float_h, macros) {
+#if !defined(FLT_RADIX)
+#error FLT_RADIX
+#endif
+#if !defined(DECIMAL_DIG)
+#error DECIMAL_DIG
+#endif
+#if !defined(FLT_DECIMAL_DIG)
+#error FLT_DECIMAL_DIG
+#endif
+#if !defined(DBL_DECIMAL_DIG)
+#error DBL_DECIMAL_DIG
+#endif
+#if !defined(LDBL_DECIMAL_DIG)
+#error LDBL_DECIMAL_DIG
+#endif
+#if !defined(FLT_MIN)
+#error FLT_MIN
+#endif
+#if !defined(DBL_MIN)
+#error DBL_MIN
+#endif
+#if !defined(LDBL_MIN)
+#error LDBL_MIN
+#endif
+#if !defined(FLT_EPSILON)
+#error FLT_EPSILON
+#endif
+#if !defined(DBL_EPSILON)
+#error DBL_EPSILON
+#endif
+#if !defined(LDBL_EPSILON)
+#error LDBL_EPSILON
+#endif
+#if !defined(FLT_DIG)
+#error FLT_DIG
+#endif
+#if !defined(DBL_DIG)
+#error DBL_DIG
+#endif
+#if !defined(LDBL_DIG)
+#error LDBL_DIG
+#endif
+#if !defined(FLT_MANT_DIG)
+#error FLT_MANT_DIG
+#endif
+#if !defined(DBL_MANT_DIG)
+#error DBL_MANT_DIG
+#endif
+#if !defined(LDBL_MANT_DIG)
+#error LDBL_MANT_DIG
+#endif
+#if !defined(FLT_MIN_EXP)
+#error FLT_MIN_EXP
+#endif
+#if !defined(DBL_MIN_EXP)
+#error DBL_MIN_EXP
+#endif
+#if !defined(LDBL_MIN_EXP)
+#error LDBL_MIN_EXP
+#endif
+#if !defined(FLT_MIN_10_EXP)
+#error FLT_MIN_10_EXP
+#endif
+#if !defined(DBL_MIN_10_EXP)
+#error DBL_MIN_10_EXP
+#endif
+#if !defined(LDBL_MIN_10_EXP)
+#error LDBL_MIN_10_EXP
+#endif
+#if !defined(FLT_MAX_EXP)
+#error FLT_MAX_EXP
+#endif
+#if !defined(DBL_MAX_EXP)
+#error DBL_MAX_EXP
+#endif
+#if !defined(LDBL_MAX_EXP)
+#error LDBL_MAX_EXP
+#endif
+#if !defined(FLT_MAX_10_EXP)
+#error FLT_MAX_10_EXP
+#endif
+#if !defined(DBL_MAX_10_EXP)
+#error DBL_MAX_10_EXP
+#endif
+#if !defined(LDBL_MAX_10_EXP)
+#error LDBL_MAX_10_EXP
+#endif
+#if !defined(FLT_ROUNDS)
+#error FLT_ROUNDS
+#endif
+#if !defined(FLT_EVAL_METHOD)
+#error FLT_EVAL_METHOD
+#endif
+// TODO: FLT_HAS_SUBNORM currently missing from clang. Negate this test when fixed.
+#if defined(FLT_HAS_SUBNORM)
+#error FLT_HAS_SUBNORM
+#endif
+// TODO: DBL_HAS_SUBNORM currently missing from clang. Negate this test when fixed.
+#if defined(DBL_HAS_SUBNORM)
+#error DBL_HAS_SUBNORM
+#endif
+// TODO: LDBL_HAS_SUBNORM currently missing from clang. Negate this test when fixed.
+#if defined(LDBL_HAS_SUBNORM)
+#error LDBL_HAS_SUBNORM
+#endif
+}
diff --git a/tests/iconv_test.cpp b/tests/iconv_test.cpp
index b197152..768b4fd 100644
--- a/tests/iconv_test.cpp
+++ b/tests/iconv_test.cpp
@@ -427,3 +427,29 @@
 TEST(iconv, iconv_EINVAL_utf32le_short) {
   Check(EINVAL, "utf32le", "\x24\x00\x00", 3); // Missing final byte.
 }
+
+TEST(iconv, iconv_initial_shift_state) {
+  // POSIX: "For state-dependent encodings, the conversion descriptor
+  // cd is placed into its initial shift state by a call for which inbuf
+  // is a null pointer, or for which inbuf points to a null pointer."
+  iconv_t c = iconv_open("utf8", "utf8");
+  char* in = nullptr;
+  size_t in_bytes = 0;
+  wchar_t out_buf[16];
+  size_t out_bytes = sizeof(out_buf);
+  char* out = reinterpret_cast<char*>(out_buf);
+
+  // Points to a null pointer...
+  errno = 0;
+  ASSERT_EQ(static_cast<size_t>(0), iconv(c, &in, &in_bytes, &out, &out_bytes));
+  EXPECT_EQ(0, errno);
+  EXPECT_EQ(sizeof(out_buf), out_bytes);
+
+  // Is a null pointer...
+  errno = 0;
+  ASSERT_EQ(static_cast<size_t>(0), iconv(c, nullptr, &in_bytes, &out, &out_bytes));
+  EXPECT_EQ(0, errno);
+  EXPECT_EQ(sizeof(out_buf), out_bytes);
+
+  EXPECT_EQ(0, iconv_close(c));
+}
diff --git a/tests/inttypes_test.cpp b/tests/inttypes_test.cpp
index 01d6b82..da12ec4 100644
--- a/tests/inttypes_test.cpp
+++ b/tests/inttypes_test.cpp
@@ -156,3 +156,32 @@
   wcstoumax(L"123", NULL, 37);
   ASSERT_EQ(EINVAL, errno);
 }
+
+TEST(inttypes, div) {
+  div_t r = div(-5, 3);
+  ASSERT_EQ(-1, r.quot);
+  ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, ldiv) {
+  ldiv_t r = ldiv(-5, 3);
+  ASSERT_EQ(-1, r.quot);
+  ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, lldiv) {
+  lldiv_t r = lldiv(-5, 3);
+  ASSERT_EQ(-1, r.quot);
+  ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, imaxdiv) {
+  imaxdiv_t r = imaxdiv(-5, 3);
+  ASSERT_EQ(-1, r.quot);
+  ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, imaxabs) {
+  ASSERT_EQ(INTMAX_MAX, imaxabs(-INTMAX_MAX));
+  ASSERT_EQ(INTMAX_MAX, imaxabs(INTMAX_MAX));
+}
diff --git a/tests/iso646_test.c b/tests/iso646_test.c
new file mode 100644
index 0000000..618f027
--- /dev/null
+++ b/tests/iso646_test.c
@@ -0,0 +1,51 @@
+/*
+ * 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 <iso646.h>
+
+#if !defined(and)
+#error and
+#endif
+#if !defined(and_eq)
+#error and_eq
+#endif
+#if !defined(bitand)
+#error bitand
+#endif
+#if !defined(bitor)
+#error bitor
+#endif
+#if !defined(compl)
+#error compl
+#endif
+#if !defined(not)
+#error not
+#endif
+#if !defined(not_eq)
+#error not_eq
+#endif
+#if !defined(or)
+#error or
+#endif
+#if !defined(or_eq)
+#error or_eq
+#endif
+#if !defined(xor)
+#error xor
+#endif
+#if !defined(xor_eq)
+#error xor_eq
+#endif
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
new file mode 100644
index 0000000..1d48ffe
--- /dev/null
+++ b/tests/limits_test.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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 <limits.h>
+
+TEST(limits, macros) {
+#if CHAR_BIT != 8
+#error Insane CHAR_BIT
+#endif
+#if !defined(MB_LEN_MAX)
+#error MB_LEN_MAX
+#endif
+#if !defined(CHAR_MIN)
+#error CHAR_MIN
+#endif
+#if !defined(CHAR_MAX)
+#error CHAR_MAX
+#endif
+#if !defined(SCHAR_MIN)
+#error SCHAR_MIN
+#endif
+#if !defined(SCHAR_MAX)
+#error SCHAR_MAX
+#endif
+#if !defined(SHRT_MIN)
+#error SHRT_MIN
+#endif
+#if !defined(SHRT_MAX)
+#error SHRT_MAX
+#endif
+#if !defined(INT_MIN)
+#error INT_MIN
+#endif
+#if !defined(INT_MAX)
+#error INT_MAX
+#endif
+#if !defined(LONG_MIN)
+#error LONG_MIN
+#endif
+#if !defined(LONG_MAX)
+#error LONG_MAX
+#endif
+#if !defined(LLONG_MIN)
+#error LLONG_MIN
+#endif
+#if !defined(LLONG_MAX)
+#error LLONG_MAX
+#endif
+#if !defined(UCHAR_MAX)
+#error UCHAR_MAX
+#endif
+#if !defined(USHRT_MAX)
+#error USHRT_MAX
+#endif
+#if !defined(UINT_MAX)
+#error UINT_MAX
+#endif
+#if !defined(ULONG_MAX)
+#error ULONG_MAX
+#endif
+#if !defined(ULLONG_MAX)
+#error ULLONG_MAX
+#endif
+}
diff --git a/tests/math_force_long_double_test.cpp b/tests/math_force_long_double_test.cpp
new file mode 100644
index 0000000..432182b
--- /dev/null
+++ b/tests/math_force_long_double_test.cpp
@@ -0,0 +1,2 @@
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+#include "math_test.cpp"
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index b960944..0fc4e50 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -48,6 +48,12 @@
 }
 }
 
+#if defined(__BIONIC_LP32_USE_LONG_DOUBLE)
+#define MATH_TEST math_h_force_long_double
+#else
+#define MATH_TEST math_h
+#endif
+
 #include "math_data_test.h"
 
 #include <gtest/gtest.h>
@@ -59,7 +65,7 @@
 
 #include <android-base/scopeguard.h>
 
-float float_subnormal() {
+static float float_subnormal() {
   union {
     float f;
     uint32_t i;
@@ -68,7 +74,7 @@
   return u.f;
 }
 
-double double_subnormal() {
+static double double_subnormal() {
   union {
     double d;
     uint64_t i;
@@ -77,7 +83,7 @@
   return u.d;
 }
 
-long double ldouble_subnormal() {
+static long double ldouble_subnormal() {
   union {
     long double e;
     unsigned char c[sizeof(long double)];
@@ -96,7 +102,7 @@
   return u.e;
 }
 
-TEST(math, fpclassify) {
+TEST(MATH_TEST, fpclassify) {
   ASSERT_EQ(FP_INFINITE, fpclassify(INFINITY));
   ASSERT_EQ(FP_INFINITE, fpclassify(HUGE_VALF));
   ASSERT_EQ(FP_INFINITE, fpclassify(HUGE_VAL));
@@ -119,7 +125,7 @@
   ASSERT_EQ(FP_ZERO, fpclassify(0.0L));
 }
 
-TEST(math, isfinite) {
+TEST(MATH_TEST, isfinite) {
   ASSERT_TRUE(test_capture_isfinite(123.0f));
   ASSERT_TRUE(test_capture_isfinite(123.0));
   ASSERT_TRUE(test_capture_isfinite(123.0L));
@@ -128,7 +134,7 @@
   ASSERT_FALSE(test_capture_isfinite(HUGE_VALL));
 }
 
-TEST(math, isinf) {
+TEST(MATH_TEST, isinf) {
   ASSERT_FALSE(test_capture_isinf(123.0f));
   ASSERT_FALSE(test_capture_isinf(123.0));
   ASSERT_FALSE(test_capture_isinf(123.0L));
@@ -137,7 +143,7 @@
   ASSERT_TRUE(test_capture_isinf(HUGE_VALL));
 }
 
-TEST(math, isnan) {
+TEST(MATH_TEST, isnan) {
   ASSERT_FALSE(test_capture_isnan(123.0f));
   ASSERT_FALSE(test_capture_isnan(123.0));
   ASSERT_FALSE(test_capture_isnan(123.0L));
@@ -146,7 +152,7 @@
   ASSERT_TRUE(test_capture_isnan(nanl("")));
 }
 
-TEST(math, isnormal) {
+TEST(MATH_TEST, isnormal) {
   ASSERT_TRUE(isnormal(123.0f));
   ASSERT_TRUE(isnormal(123.0));
   ASSERT_TRUE(isnormal(123.0L));
@@ -156,7 +162,7 @@
 }
 
 // TODO: isgreater, isgreaterequals, isless, islessequal, islessgreater, isunordered
-TEST(math, signbit) {
+TEST(MATH_TEST, signbit) {
   ASSERT_EQ(0, test_capture_signbit(0.0f));
   ASSERT_EQ(0, test_capture_signbit(0.0));
   ASSERT_EQ(0, test_capture_signbit(0.0L));
@@ -170,7 +176,7 @@
   ASSERT_NE(0, test_capture_signbit(-1.0L));
 }
 
-TEST(math, __fpclassifyd) {
+TEST(MATH_TEST, __fpclassifyd) {
 #if defined(__GLIBC__)
 #define __fpclassifyd __fpclassify
 #endif
@@ -181,7 +187,7 @@
   ASSERT_EQ(FP_ZERO, __fpclassifyd(0.0));
 }
 
-TEST(math, __fpclassifyf) {
+TEST(MATH_TEST, __fpclassifyf) {
   ASSERT_EQ(FP_INFINITE, __fpclassifyf(HUGE_VALF));
   ASSERT_EQ(FP_NAN, __fpclassifyf(nanf("")));
   ASSERT_EQ(FP_NORMAL, __fpclassifyf(1.0f));
@@ -189,7 +195,7 @@
   ASSERT_EQ(FP_ZERO, __fpclassifyf(0.0f));
 }
 
-TEST(math, __fpclassifyl) {
+TEST(MATH_TEST, __fpclassifyl) {
   EXPECT_EQ(FP_INFINITE, __fpclassifyl(HUGE_VALL));
   EXPECT_EQ(FP_NAN, __fpclassifyl(nanl("")));
   EXPECT_EQ(FP_NORMAL, __fpclassifyl(1.0L));
@@ -197,12 +203,12 @@
   EXPECT_EQ(FP_ZERO, __fpclassifyl(0.0L));
 }
 
-TEST(math, finitef) {
+TEST(MATH_TEST, finitef) {
   ASSERT_TRUE(finitef(123.0f));
   ASSERT_FALSE(finitef(HUGE_VALF));
 }
 
-TEST(math, __isfinite) {
+TEST(MATH_TEST, __isfinite) {
 #if defined(__GLIBC__)
 #define __isfinite __finite
 #endif
@@ -210,7 +216,7 @@
   ASSERT_FALSE(__isfinite(HUGE_VAL));
 }
 
-TEST(math, __isfinitef) {
+TEST(MATH_TEST, __isfinitef) {
 #if defined(__GLIBC__)
 #define __isfinitef __finitef
 #endif
@@ -218,7 +224,7 @@
   ASSERT_FALSE(__isfinitef(HUGE_VALF));
 }
 
-TEST(math, __isfinitel) {
+TEST(MATH_TEST, __isfinitel) {
 #if defined(__GLIBC__)
 #define __isfinitel __finitel
 #endif
@@ -226,49 +232,49 @@
   ASSERT_FALSE(__isfinitel(HUGE_VALL));
 }
 
-TEST(math, finite) {
+TEST(MATH_TEST, finite) {
   ASSERT_TRUE(finite(123.0));
   ASSERT_FALSE(finite(HUGE_VAL));
 }
 
-TEST(math, isinf_function) {
+TEST(MATH_TEST, isinf_function) {
   // The isinf macro deals with all three types; the isinf function is for doubles.
   ASSERT_FALSE((isinf)(123.0));
   ASSERT_TRUE((isinf)(HUGE_VAL));
 }
 
-TEST(math, __isinff) {
+TEST(MATH_TEST, __isinff) {
   ASSERT_FALSE(__isinff(123.0f));
   ASSERT_TRUE(__isinff(HUGE_VALF));
 }
 
-TEST(math, __isinfl) {
+TEST(MATH_TEST, __isinfl) {
   ASSERT_FALSE(__isinfl(123.0L));
   ASSERT_TRUE(__isinfl(HUGE_VALL));
 }
 
-TEST(math, isnan_function) {
+TEST(MATH_TEST, isnan_function) {
   // The isnan macro deals with all three types; the isnan function is for doubles.
   ASSERT_FALSE((isnan)(123.0));
   ASSERT_TRUE((isnan)(nan("")));
 }
 
-TEST(math, __isnanf) {
+TEST(MATH_TEST, __isnanf) {
   ASSERT_FALSE(__isnanf(123.0f));
   ASSERT_TRUE(__isnanf(nanf("")));
 }
 
-TEST(math, __isnanl) {
+TEST(MATH_TEST, __isnanl) {
   ASSERT_FALSE(__isnanl(123.0L));
   ASSERT_TRUE(__isnanl(nanl("")));
 }
 
-TEST(math, isnanf) {
+TEST(MATH_TEST, isnanf) {
   ASSERT_FALSE(isnanf(123.0f));
   ASSERT_TRUE(isnanf(nanf("")));
 }
 
-TEST(math, __isnormal) {
+TEST(MATH_TEST, __isnormal) {
 #if defined(__BIONIC__)
   ASSERT_TRUE(__isnormal(123.0));
   ASSERT_FALSE(__isnormal(double_subnormal()));
@@ -277,7 +283,7 @@
 #endif // __BIONIC__
 }
 
-TEST(math, __isnormalf) {
+TEST(MATH_TEST, __isnormalf) {
 #if defined(__BIONIC__)
   ASSERT_TRUE(__isnormalf(123.0f));
   ASSERT_FALSE(__isnormalf(float_subnormal()));
@@ -286,7 +292,7 @@
 #endif // __BIONIC__
 }
 
-TEST(math, __isnormall) {
+TEST(MATH_TEST, __isnormall) {
 #if defined(__BIONIC__)
   ASSERT_TRUE(__isnormall(123.0L));
   ASSERT_FALSE(__isnormall(ldouble_subnormal()));
@@ -295,486 +301,486 @@
 #endif // __BIONIC__
 }
 
-TEST(math, __signbit) {
+TEST(MATH_TEST, __signbit) {
   ASSERT_EQ(0, __signbit(0.0));
   ASSERT_EQ(0, __signbit(1.0));
   ASSERT_NE(0, __signbit(-1.0));
 }
 
-TEST(math, __signbitf) {
+TEST(MATH_TEST, __signbitf) {
   ASSERT_EQ(0, __signbitf(0.0f));
   ASSERT_EQ(0, __signbitf(1.0f));
   ASSERT_NE(0, __signbitf(-1.0f));
 }
 
-TEST(math, __signbitl) {
+TEST(MATH_TEST, __signbitl) {
   ASSERT_EQ(0L, __signbitl(0.0L));
   ASSERT_EQ(0L, __signbitl(1.0L));
   ASSERT_NE(0L, __signbitl(-1.0L));
 }
 
-TEST(math, acos) {
+TEST(MATH_TEST, acos) {
   ASSERT_DOUBLE_EQ(M_PI/2.0, acos(0.0));
 }
 
-TEST(math, acosf) {
+TEST(MATH_TEST, acosf) {
   ASSERT_FLOAT_EQ(static_cast<float>(M_PI)/2.0f, acosf(0.0f));
 }
 
-TEST(math, acosl) {
+TEST(MATH_TEST, acosl) {
   ASSERT_DOUBLE_EQ(M_PI/2.0L, acosl(0.0L));
 }
 
-TEST(math, asin) {
+TEST(MATH_TEST, asin) {
   ASSERT_DOUBLE_EQ(0.0, asin(0.0));
 }
 
-TEST(math, asinf) {
+TEST(MATH_TEST, asinf) {
   ASSERT_FLOAT_EQ(0.0f, asinf(0.0f));
 }
 
-TEST(math, asinl) {
+TEST(MATH_TEST, asinl) {
   ASSERT_DOUBLE_EQ(0.0L, asinl(0.0L));
 }
 
-TEST(math, atan) {
+TEST(MATH_TEST, atan) {
   ASSERT_DOUBLE_EQ(0.0, atan(0.0));
 }
 
-TEST(math, atanf) {
+TEST(MATH_TEST, atanf) {
   ASSERT_FLOAT_EQ(0.0f, atanf(0.0f));
 }
 
-TEST(math, atanl) {
+TEST(MATH_TEST, atanl) {
   ASSERT_DOUBLE_EQ(0.0L, atanl(0.0L));
 }
 
-TEST(math, atan2) {
+TEST(MATH_TEST, atan2) {
   ASSERT_DOUBLE_EQ(0.0, atan2(0.0, 0.0));
 }
 
-TEST(math, atan2f) {
+TEST(MATH_TEST, atan2f) {
   ASSERT_FLOAT_EQ(0.0f, atan2f(0.0f, 0.0f));
 }
 
-TEST(math, atan2l) {
+TEST(MATH_TEST, atan2l) {
   ASSERT_DOUBLE_EQ(0.0L, atan2l(0.0L, 0.0L));
 }
 
-TEST(math, cos) {
+TEST(MATH_TEST, cos) {
   ASSERT_DOUBLE_EQ(1.0, cos(0.0));
 }
 
-TEST(math, cosf) {
+TEST(MATH_TEST, cosf) {
   ASSERT_FLOAT_EQ(1.0f, cosf(0.0f));
 }
 
-TEST(math, cosl) {
+TEST(MATH_TEST, cosl) {
   ASSERT_DOUBLE_EQ(1.0L, cosl(0.0L));
 }
 
-TEST(math, sin) {
+TEST(MATH_TEST, sin) {
   ASSERT_DOUBLE_EQ(0.0, sin(0.0));
 }
 
-TEST(math, sinf) {
+TEST(MATH_TEST, sinf) {
   ASSERT_FLOAT_EQ(0.0f, sinf(0.0f));
 }
 
-TEST(math, sinl) {
+TEST(MATH_TEST, sinl) {
   ASSERT_DOUBLE_EQ(0.0L, sinl(0.0L));
 }
 
-TEST(math, sincos) {
+TEST(MATH_TEST, sincos) {
   double s, c;
   sincos(0.0, &s, &c);
   ASSERT_DOUBLE_EQ(0.0, s);
   ASSERT_DOUBLE_EQ(1.0, c);
 }
 
-TEST(math, sincosf) {
+TEST(MATH_TEST, sincosf) {
   float s, c;
   sincosf(0.0f, &s, &c);
   ASSERT_FLOAT_EQ(0.0f, s);
   ASSERT_FLOAT_EQ(1.0f, c);
 }
 
-TEST(math, sincosl) {
+TEST(MATH_TEST, sincosl) {
   long double s, c;
   sincosl(0.0L, &s, &c);
   ASSERT_DOUBLE_EQ(0.0L, s);
   ASSERT_DOUBLE_EQ(1.0L, c);
 }
 
-TEST(math, tan) {
+TEST(MATH_TEST, tan) {
   ASSERT_DOUBLE_EQ(0.0, tan(0.0));
 }
 
-TEST(math, tanf) {
+TEST(MATH_TEST, tanf) {
   ASSERT_FLOAT_EQ(0.0f, tanf(0.0f));
 }
 
-TEST(math, tanl) {
+TEST(MATH_TEST, tanl) {
   ASSERT_DOUBLE_EQ(0.0L, tanl(0.0L));
 }
 
-TEST(math, acosh) {
+TEST(MATH_TEST, acosh) {
   ASSERT_DOUBLE_EQ(0.0, acosh(1.0));
 }
 
-TEST(math, acoshf) {
+TEST(MATH_TEST, acoshf) {
   ASSERT_FLOAT_EQ(0.0f, acoshf(1.0f));
 }
 
-TEST(math, acoshl) {
+TEST(MATH_TEST, acoshl) {
   ASSERT_DOUBLE_EQ(0.0L, acoshl(1.0L));
 }
 
-TEST(math, asinh) {
+TEST(MATH_TEST, asinh) {
   ASSERT_DOUBLE_EQ(0.0, asinh(0.0));
 }
 
-TEST(math, asinhf) {
+TEST(MATH_TEST, asinhf) {
   ASSERT_FLOAT_EQ(0.0f, asinhf(0.0f));
 }
 
-TEST(math, asinhl) {
+TEST(MATH_TEST, asinhl) {
   ASSERT_DOUBLE_EQ(0.0L, asinhl(0.0L));
 }
 
-TEST(math, atanh) {
+TEST(MATH_TEST, atanh) {
   ASSERT_DOUBLE_EQ(0.0, atanh(0.0));
 }
 
-TEST(math, atanhf) {
+TEST(MATH_TEST, atanhf) {
   ASSERT_FLOAT_EQ(0.0f, atanhf(0.0f));
 }
 
-TEST(math, atanhl) {
+TEST(MATH_TEST, atanhl) {
   ASSERT_DOUBLE_EQ(0.0L, atanhl(0.0L));
 }
 
-TEST(math, cosh) {
+TEST(MATH_TEST, cosh) {
   ASSERT_DOUBLE_EQ(1.0, cosh(0.0));
 }
 
-TEST(math, coshf) {
+TEST(MATH_TEST, coshf) {
   ASSERT_FLOAT_EQ(1.0f, coshf(0.0f));
 }
 
-TEST(math, coshl) {
+TEST(MATH_TEST, coshl) {
   ASSERT_DOUBLE_EQ(1.0L, coshl(0.0L));
 }
 
-TEST(math, sinh) {
+TEST(MATH_TEST, sinh) {
   ASSERT_DOUBLE_EQ(0.0, sinh(0.0));
 }
 
-TEST(math, sinhf) {
+TEST(MATH_TEST, sinhf) {
   ASSERT_FLOAT_EQ(0.0f, sinhf(0.0f));
 }
 
-TEST(math, sinhl) {
+TEST(MATH_TEST, sinhl) {
   ASSERT_DOUBLE_EQ(0.0L, sinhl(0.0L));
 }
 
-TEST(math, tanh) {
+TEST(MATH_TEST, tanh) {
   ASSERT_DOUBLE_EQ(0.0, tanh(0.0));
 }
 
-TEST(math, tanhf) {
+TEST(MATH_TEST, tanhf) {
   ASSERT_FLOAT_EQ(0.0f, tanhf(0.0f));
 }
 
-TEST(math, tanhl) {
+TEST(MATH_TEST, tanhl) {
   ASSERT_DOUBLE_EQ(0.0L, tanhl(0.0L));
 }
 
-TEST(math, log) {
+TEST(MATH_TEST, log) {
   ASSERT_DOUBLE_EQ(1.0, log(M_E));
 }
 
-TEST(math, logf) {
+TEST(MATH_TEST, logf) {
   ASSERT_FLOAT_EQ(1.0f, logf(static_cast<float>(M_E)));
 }
 
-TEST(math, logl) {
+TEST(MATH_TEST, logl) {
   ASSERT_DOUBLE_EQ(1.0L, logl(M_E));
 }
 
-TEST(math, log2) {
+TEST(MATH_TEST, log2) {
   ASSERT_DOUBLE_EQ(12.0, log2(4096.0));
 }
 
-TEST(math, log2f) {
+TEST(MATH_TEST, log2f) {
   ASSERT_FLOAT_EQ(12.0f, log2f(4096.0f));
 }
 
-TEST(math, log2l) {
+TEST(MATH_TEST, log2l) {
   ASSERT_DOUBLE_EQ(12.0L, log2l(4096.0L));
 }
 
-TEST(math, log10) {
+TEST(MATH_TEST, log10) {
   ASSERT_DOUBLE_EQ(3.0, log10(1000.0));
 }
 
-TEST(math, log10f) {
+TEST(MATH_TEST, log10f) {
   ASSERT_FLOAT_EQ(3.0f, log10f(1000.0f));
 }
 
-TEST(math, log10l) {
+TEST(MATH_TEST, log10l) {
   ASSERT_DOUBLE_EQ(3.0L, log10l(1000.0L));
 }
 
-TEST(math, cbrt) {
+TEST(MATH_TEST, cbrt) {
   ASSERT_DOUBLE_EQ(3.0, cbrt(27.0));
 }
 
-TEST(math, cbrtf) {
+TEST(MATH_TEST, cbrtf) {
   ASSERT_FLOAT_EQ(3.0f, cbrtf(27.0f));
 }
 
-TEST(math, cbrtl) {
+TEST(MATH_TEST, cbrtl) {
   ASSERT_DOUBLE_EQ(3.0L, cbrtl(27.0L));
 }
 
-TEST(math, sqrt) {
+TEST(MATH_TEST, sqrt) {
   ASSERT_DOUBLE_EQ(2.0, sqrt(4.0));
 }
 
-TEST(math, sqrtf) {
+TEST(MATH_TEST, sqrtf) {
   ASSERT_FLOAT_EQ(2.0f, sqrtf(4.0f));
 }
 
-TEST(math, sqrtl) {
+TEST(MATH_TEST, sqrtl) {
   ASSERT_DOUBLE_EQ(2.0L, sqrtl(4.0L));
 }
 
-TEST(math, exp) {
+TEST(MATH_TEST, exp) {
   ASSERT_DOUBLE_EQ(1.0, exp(0.0));
   ASSERT_DOUBLE_EQ(M_E, exp(1.0));
 }
 
-TEST(math, expf) {
+TEST(MATH_TEST, expf) {
   ASSERT_FLOAT_EQ(1.0f, expf(0.0f));
   ASSERT_FLOAT_EQ(static_cast<float>(M_E), expf(1.0f));
 }
 
-TEST(math, expl) {
+TEST(MATH_TEST, expl) {
   ASSERT_DOUBLE_EQ(1.0L, expl(0.0L));
   ASSERT_DOUBLE_EQ(M_E, expl(1.0L));
 }
 
-TEST(math, exp2) {
+TEST(MATH_TEST, exp2) {
   ASSERT_DOUBLE_EQ(8.0, exp2(3.0));
 }
 
-TEST(math, exp2f) {
+TEST(MATH_TEST, exp2f) {
   ASSERT_FLOAT_EQ(8.0f, exp2f(3.0f));
 }
 
-TEST(math, exp2l) {
+TEST(MATH_TEST, exp2l) {
   ASSERT_DOUBLE_EQ(8.0L, exp2l(3.0L));
 }
 
-TEST(math, expm1) {
+TEST(MATH_TEST, expm1) {
   ASSERT_DOUBLE_EQ(M_E - 1.0, expm1(1.0));
 }
 
-TEST(math, expm1f) {
+TEST(MATH_TEST, expm1f) {
   ASSERT_FLOAT_EQ(static_cast<float>(M_E) - 1.0f, expm1f(1.0f));
 }
 
-TEST(math, expm1l) {
+TEST(MATH_TEST, expm1l) {
   ASSERT_DOUBLE_EQ(M_E - 1.0L, expm1l(1.0L));
 }
 
-TEST(math, pow) {
+TEST(MATH_TEST, pow) {
   ASSERT_TRUE(isnan(pow(nan(""), 3.0)));
   ASSERT_DOUBLE_EQ(1.0, (pow(1.0, nan(""))));
   ASSERT_TRUE(isnan(pow(2.0, nan(""))));
   ASSERT_DOUBLE_EQ(8.0, pow(2.0, 3.0));
 }
 
-TEST(math, powf) {
+TEST(MATH_TEST, powf) {
   ASSERT_TRUE(isnanf(powf(nanf(""), 3.0f)));
   ASSERT_FLOAT_EQ(1.0f, (powf(1.0f, nanf(""))));
   ASSERT_TRUE(isnanf(powf(2.0f, nanf(""))));
   ASSERT_FLOAT_EQ(8.0f, powf(2.0f, 3.0f));
 }
 
-TEST(math, powl) {
+TEST(MATH_TEST, powl) {
   ASSERT_TRUE(__isnanl(powl(nanl(""), 3.0L)));
   ASSERT_DOUBLE_EQ(1.0L, (powl(1.0L, nanl(""))));
   ASSERT_TRUE(__isnanl(powl(2.0L, nanl(""))));
   ASSERT_DOUBLE_EQ(8.0L, powl(2.0L, 3.0L));
 }
 
-TEST(math, ceil) {
+TEST(MATH_TEST, ceil) {
   ASSERT_DOUBLE_EQ(1.0, ceil(0.9));
 }
 
-TEST(math, ceilf) {
+TEST(MATH_TEST, ceilf) {
   ASSERT_FLOAT_EQ(1.0f, ceilf(0.9f));
 }
 
-TEST(math, ceill) {
+TEST(MATH_TEST, ceill) {
   ASSERT_DOUBLE_EQ(1.0L, ceill(0.9L));
 }
 
-TEST(math, floor) {
+TEST(MATH_TEST, floor) {
   ASSERT_DOUBLE_EQ(1.0, floor(1.1));
 }
 
-TEST(math, floorf) {
+TEST(MATH_TEST, floorf) {
   ASSERT_FLOAT_EQ(1.0f, floorf(1.1f));
 }
 
-TEST(math, floorl) {
+TEST(MATH_TEST, floorl) {
   ASSERT_DOUBLE_EQ(1.0L, floorl(1.1L));
 }
 
-TEST(math, fabs) {
+TEST(MATH_TEST, fabs) {
   ASSERT_DOUBLE_EQ(1.0, fabs(-1.0));
 }
 
-TEST(math, fabsf) {
+TEST(MATH_TEST, fabsf) {
   ASSERT_FLOAT_EQ(1.0f, fabsf(-1.0f));
 }
 
-TEST(math, fabsl) {
+TEST(MATH_TEST, fabsl) {
   ASSERT_DOUBLE_EQ(1.0L, fabsl(-1.0L));
 }
 
-TEST(math, ldexp) {
+TEST(MATH_TEST, ldexp) {
   ASSERT_DOUBLE_EQ(16.0, ldexp(2.0, 3.0));
 }
 
-TEST(math, ldexpf) {
+TEST(MATH_TEST, ldexpf) {
   ASSERT_FLOAT_EQ(16.0f, ldexpf(2.0f, 3.0f));
 }
 
-TEST(math, ldexpl) {
+TEST(MATH_TEST, ldexpl) {
   ASSERT_DOUBLE_EQ(16.0L, ldexpl(2.0L, 3.0));
 }
 
-TEST(math, fmod) {
+TEST(MATH_TEST, fmod) {
   ASSERT_DOUBLE_EQ(2.0, fmod(12.0, 10.0));
 }
 
-TEST(math, fmodf) {
+TEST(MATH_TEST, fmodf) {
   ASSERT_FLOAT_EQ(2.0f, fmodf(12.0f, 10.0f));
 }
 
-TEST(math, fmodl) {
+TEST(MATH_TEST, fmodl) {
   ASSERT_DOUBLE_EQ(2.0L, fmodl(12.0L, 10.0L));
 }
 
-TEST(math, remainder) {
+TEST(MATH_TEST, remainder) {
   ASSERT_DOUBLE_EQ(2.0, remainder(12.0, 10.0));
 }
 
-TEST(math, remainderf) {
+TEST(MATH_TEST, remainderf) {
   ASSERT_FLOAT_EQ(2.0f, remainderf(12.0f, 10.0f));
 }
 
-TEST(math, remainderl) {
+TEST(MATH_TEST, remainderl) {
   ASSERT_DOUBLE_EQ(2.0L, remainderl(12.0L, 10.0L));
 }
 
-TEST(math, drem) {
+TEST(MATH_TEST, drem) {
   ASSERT_DOUBLE_EQ(2.0, drem(12.0, 10.0));
 }
 
-TEST(math, dremf) {
+TEST(MATH_TEST, dremf) {
   ASSERT_FLOAT_EQ(2.0f, dremf(12.0f, 10.0f));
 }
 
-TEST(math, fmax) {
+TEST(MATH_TEST, fmax) {
   ASSERT_DOUBLE_EQ(12.0, fmax(12.0, 10.0));
   ASSERT_DOUBLE_EQ(12.0, fmax(12.0, nan("")));
   ASSERT_DOUBLE_EQ(12.0, fmax(nan(""), 12.0));
 }
 
-TEST(math, fmaxf) {
+TEST(MATH_TEST, fmaxf) {
   ASSERT_FLOAT_EQ(12.0f, fmaxf(12.0f, 10.0f));
   ASSERT_FLOAT_EQ(12.0f, fmaxf(12.0f, nanf("")));
   ASSERT_FLOAT_EQ(12.0f, fmaxf(nanf(""), 12.0f));
 }
 
-TEST(math, fmaxl) {
+TEST(MATH_TEST, fmaxl) {
   ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, 10.0L));
   ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, nanl("")));
   ASSERT_DOUBLE_EQ(12.0L, fmaxl(nanl(""), 12.0L));
 }
 
-TEST(math, fmin) {
+TEST(MATH_TEST, fmin) {
   ASSERT_DOUBLE_EQ(10.0, fmin(12.0, 10.0));
   ASSERT_DOUBLE_EQ(12.0, fmin(12.0, nan("")));
   ASSERT_DOUBLE_EQ(12.0, fmin(nan(""), 12.0));
 }
 
-TEST(math, fminf) {
+TEST(MATH_TEST, fminf) {
   ASSERT_FLOAT_EQ(10.0f, fminf(12.0f, 10.0f));
   ASSERT_FLOAT_EQ(12.0f, fminf(12.0f, nanf("")));
   ASSERT_FLOAT_EQ(12.0f, fminf(nanf(""), 12.0f));
 }
 
-TEST(math, fminl) {
+TEST(MATH_TEST, fminl) {
   ASSERT_DOUBLE_EQ(10.0L, fminl(12.0L, 10.0L));
   ASSERT_DOUBLE_EQ(12.0L, fminl(12.0L, nanl("")));
   ASSERT_DOUBLE_EQ(12.0L, fminl(nanl(""), 12.0L));
 }
 
-TEST(math, fma) {
+TEST(MATH_TEST, fma) {
   ASSERT_DOUBLE_EQ(10.0, fma(2.0, 3.0, 4.0));
 }
 
-TEST(math, fmaf) {
+TEST(MATH_TEST, fmaf) {
   ASSERT_FLOAT_EQ(10.0f, fmaf(2.0f, 3.0f, 4.0f));
 }
 
-TEST(math, fmal) {
+TEST(MATH_TEST, fmal) {
   ASSERT_DOUBLE_EQ(10.0L, fmal(2.0L, 3.0L, 4.0L));
 }
 
-TEST(math, hypot) {
+TEST(MATH_TEST, hypot) {
   ASSERT_DOUBLE_EQ(5.0, hypot(3.0, 4.0));
 }
 
-TEST(math, hypotf) {
+TEST(MATH_TEST, hypotf) {
   ASSERT_FLOAT_EQ(5.0f, hypotf(3.0f, 4.0f));
 }
 
-TEST(math, hypotl) {
+TEST(MATH_TEST, hypotl) {
   ASSERT_DOUBLE_EQ(5.0L, hypotl(3.0L, 4.0L));
 }
 
-TEST(math, erf) {
+TEST(MATH_TEST, erf) {
   ASSERT_DOUBLE_EQ(0.84270079294971489, erf(1.0));
 }
 
-TEST(math, erff) {
+TEST(MATH_TEST, erff) {
   ASSERT_FLOAT_EQ(0.84270078f, erff(1.0f));
 }
 
-TEST(math, erfl) {
+TEST(MATH_TEST, erfl) {
   ASSERT_DOUBLE_EQ(0.84270079294971489L, erfl(1.0L));
 }
 
-TEST(math, erfc) {
+TEST(MATH_TEST, erfc) {
   ASSERT_DOUBLE_EQ(0.15729920705028513, erfc(1.0));
 }
 
-TEST(math, erfcf) {
+TEST(MATH_TEST, erfcf) {
   ASSERT_FLOAT_EQ(0.15729921f, erfcf(1.0f));
 }
 
-TEST(math, erfcl) {
+TEST(MATH_TEST, erfcl) {
   ASSERT_DOUBLE_EQ(0.15729920705028513l, erfcl(1.0L));
 }
 
-TEST(math, lrint) {
+TEST(MATH_TEST, lrint) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
 
   fesetround(FE_UPWARD); // lrint/lrintf/lrintl obey the rounding mode.
@@ -796,7 +802,7 @@
   ASSERT_EQ(1234L, llrintl(1234.01L));
 }
 
-TEST(math, rint) {
+TEST(MATH_TEST, rint) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
 
   fesetround(FE_UPWARD); // rint/rintf/rintl obey the rounding mode.
@@ -824,7 +830,7 @@
   ASSERT_EQ(1234.0, rintl(1234.01L));
 }
 
-TEST(math, nearbyint) {
+TEST(MATH_TEST, nearbyint) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_UPWARD); // nearbyint/nearbyintf/nearbyintl obey the rounding mode.
   feclearexcept(FE_ALL_EXCEPT); // nearbyint/nearbyintf/nearbyintl don't set the FE_INEXACT flag.
@@ -851,7 +857,7 @@
   ASSERT_EQ(1234.0, nearbyintl(1234.01L));
 }
 
-TEST(math, lround) {
+TEST(MATH_TEST, lround) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_UPWARD); // lround ignores the rounding mode.
   ASSERT_EQ(1234, lround(1234.01));
@@ -859,7 +865,7 @@
   ASSERT_EQ(1234, lroundl(1234.01L));
 }
 
-TEST(math, llround) {
+TEST(MATH_TEST, llround) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_UPWARD); // llround ignores the rounding mode.
   ASSERT_EQ(1234L, llround(1234.01));
@@ -867,7 +873,7 @@
   ASSERT_EQ(1234L, llroundl(1234.01L));
 }
 
-TEST(math, ilogb) {
+TEST(MATH_TEST, ilogb) {
   ASSERT_EQ(FP_ILOGB0, ilogb(0.0));
   ASSERT_EQ(FP_ILOGBNAN, ilogb(nan("")));
   ASSERT_EQ(INT_MAX, ilogb(HUGE_VAL));
@@ -875,7 +881,7 @@
   ASSERT_EQ(3, ilogb(10.0));
 }
 
-TEST(math, ilogbf) {
+TEST(MATH_TEST, ilogbf) {
   ASSERT_EQ(FP_ILOGB0, ilogbf(0.0f));
   ASSERT_EQ(FP_ILOGBNAN, ilogbf(nanf("")));
   ASSERT_EQ(INT_MAX, ilogbf(HUGE_VALF));
@@ -883,7 +889,7 @@
   ASSERT_EQ(3, ilogbf(10.0f));
 }
 
-TEST(math, ilogbl) {
+TEST(MATH_TEST, ilogbl) {
   ASSERT_EQ(FP_ILOGB0, ilogbl(0.0L));
   ASSERT_EQ(FP_ILOGBNAN, ilogbl(nanl("")));
   ASSERT_EQ(INT_MAX, ilogbl(HUGE_VALL));
@@ -891,7 +897,7 @@
   ASSERT_EQ(3L, ilogbl(10.0L));
 }
 
-TEST(math, logb) {
+TEST(MATH_TEST, logb) {
   ASSERT_EQ(-HUGE_VAL, logb(0.0));
   ASSERT_TRUE(isnan(logb(nan(""))));
   ASSERT_TRUE(isinf(logb(HUGE_VAL)));
@@ -899,7 +905,7 @@
   ASSERT_EQ(3.0, logb(10.0));
 }
 
-TEST(math, logbf) {
+TEST(MATH_TEST, logbf) {
   ASSERT_EQ(-HUGE_VALF, logbf(0.0f));
   ASSERT_TRUE(isnanf(logbf(nanf(""))));
   ASSERT_TRUE(__isinff(logbf(HUGE_VALF)));
@@ -907,7 +913,7 @@
   ASSERT_EQ(3.0f, logbf(10.0f));
 }
 
-TEST(math, logbl) {
+TEST(MATH_TEST, logbl) {
   ASSERT_EQ(-HUGE_VAL, logbl(0.0L));
   ASSERT_TRUE(isnan(logbl(nanl(""))));
   ASSERT_TRUE(isinf(logbl(HUGE_VALL)));
@@ -915,46 +921,46 @@
   ASSERT_EQ(3.0L, logbl(10.0L));
 }
 
-TEST(math, log1p) {
+TEST(MATH_TEST, log1p) {
   ASSERT_EQ(-HUGE_VAL, log1p(-1.0));
   ASSERT_TRUE(isnan(log1p(nan(""))));
   ASSERT_TRUE(isinf(log1p(HUGE_VAL)));
   ASSERT_DOUBLE_EQ(1.0, log1p(M_E - 1.0));
 }
 
-TEST(math, log1pf) {
+TEST(MATH_TEST, log1pf) {
   ASSERT_EQ(-HUGE_VALF, log1pf(-1.0f));
   ASSERT_TRUE(isnanf(log1pf(nanf(""))));
   ASSERT_TRUE(__isinff(log1pf(HUGE_VALF)));
   ASSERT_FLOAT_EQ(1.0f, log1pf(static_cast<float>(M_E) - 1.0f));
 }
 
-TEST(math, log1pl) {
+TEST(MATH_TEST, log1pl) {
   ASSERT_EQ(-HUGE_VALL, log1pl(-1.0L));
   ASSERT_TRUE(isnan(log1pl(nanl(""))));
   ASSERT_TRUE(isinf(log1pl(HUGE_VALL)));
   ASSERT_DOUBLE_EQ(1.0L, log1pl(M_E - 1.0L));
 }
 
-TEST(math, fdim) {
+TEST(MATH_TEST, fdim) {
   ASSERT_DOUBLE_EQ(0.0, fdim(1.0, 1.0));
   ASSERT_DOUBLE_EQ(1.0, fdim(2.0, 1.0));
   ASSERT_DOUBLE_EQ(0.0, fdim(1.0, 2.0));
 }
 
-TEST(math, fdimf) {
+TEST(MATH_TEST, fdimf) {
   ASSERT_FLOAT_EQ(0.0f, fdimf(1.0f, 1.0f));
   ASSERT_FLOAT_EQ(1.0f, fdimf(2.0f, 1.0f));
   ASSERT_FLOAT_EQ(0.0f, fdimf(1.0f, 2.0f));
 }
 
-TEST(math, fdiml) {
+TEST(MATH_TEST, fdiml) {
   ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 1.0L));
   ASSERT_DOUBLE_EQ(1.0L, fdiml(2.0L, 1.0L));
   ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 2.0L));
 }
 
-TEST(math, round) {
+TEST(MATH_TEST, round) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_TOWARDZERO); // round ignores the rounding mode and always rounds away from zero.
   ASSERT_DOUBLE_EQ(1.0, round(0.5));
@@ -965,7 +971,7 @@
   ASSERT_DOUBLE_EQ(HUGE_VAL, round(HUGE_VAL));
 }
 
-TEST(math, roundf) {
+TEST(MATH_TEST, roundf) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_TOWARDZERO); // roundf ignores the rounding mode and always rounds away from zero.
   ASSERT_FLOAT_EQ(1.0f, roundf(0.5f));
@@ -976,7 +982,7 @@
   ASSERT_FLOAT_EQ(HUGE_VALF, roundf(HUGE_VALF));
 }
 
-TEST(math, roundl) {
+TEST(MATH_TEST, roundl) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_TOWARDZERO); // roundl ignores the rounding mode and always rounds away from zero.
   ASSERT_DOUBLE_EQ(1.0L, roundl(0.5L));
@@ -987,7 +993,7 @@
   ASSERT_DOUBLE_EQ(HUGE_VALL, roundl(HUGE_VALL));
 }
 
-TEST(math, trunc) {
+TEST(MATH_TEST, trunc) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_UPWARD); // trunc ignores the rounding mode and always rounds toward zero.
   ASSERT_DOUBLE_EQ(1.0, trunc(1.5));
@@ -998,7 +1004,7 @@
   ASSERT_DOUBLE_EQ(HUGE_VAL, trunc(HUGE_VAL));
 }
 
-TEST(math, truncf) {
+TEST(MATH_TEST, truncf) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_UPWARD); // truncf ignores the rounding mode and always rounds toward zero.
   ASSERT_FLOAT_EQ(1.0f, truncf(1.5f));
@@ -1009,7 +1015,7 @@
   ASSERT_FLOAT_EQ(HUGE_VALF, truncf(HUGE_VALF));
 }
 
-TEST(math, truncl) {
+TEST(MATH_TEST, truncl) {
   auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
   fesetround(FE_UPWARD); // truncl ignores the rounding mode and always rounds toward zero.
   ASSERT_DOUBLE_EQ(1.0L, truncl(1.5L));
@@ -1020,19 +1026,19 @@
   ASSERT_DOUBLE_EQ(HUGE_VALL, truncl(HUGE_VALL));
 }
 
-TEST(math, nextafter) {
+TEST(MATH_TEST, nextafter) {
   ASSERT_DOUBLE_EQ(0.0, nextafter(0.0, 0.0));
   ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nextafter(0.0, 1.0));
   ASSERT_DOUBLE_EQ(-4.9406564584124654e-324, nextafter(0.0, -1.0));
 }
 
-TEST(math, nextafterf) {
+TEST(MATH_TEST, nextafterf) {
   ASSERT_FLOAT_EQ(0.0f, nextafterf(0.0f, 0.0f));
   ASSERT_FLOAT_EQ(1.4012985e-45f, nextafterf(0.0f, 1.0f));
   ASSERT_FLOAT_EQ(-1.4012985e-45f, nextafterf(0.0f, -1.0f));
 }
 
-TEST(math, nextafterl) {
+TEST(MATH_TEST, nextafterl) {
   ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, 0.0L));
   // Use a runtime value to accomodate the case when
   // sizeof(double) == sizeof(long double)
@@ -1041,19 +1047,19 @@
   ASSERT_DOUBLE_EQ(-smallest_positive, nextafterl(0.0L, -1.0L));
 }
 
-TEST(math, nexttoward) {
+TEST(MATH_TEST, nexttoward) {
   ASSERT_DOUBLE_EQ(0.0, nexttoward(0.0, 0.0L));
   ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nexttoward(0.0, 1.0L));
   ASSERT_DOUBLE_EQ(-4.9406564584124654e-324, nexttoward(0.0, -1.0L));
 }
 
-TEST(math, nexttowardf) {
+TEST(MATH_TEST, nexttowardf) {
   ASSERT_FLOAT_EQ(0.0f, nexttowardf(0.0f, 0.0L));
   ASSERT_FLOAT_EQ(1.4012985e-45f, nexttowardf(0.0f, 1.0L));
   ASSERT_FLOAT_EQ(-1.4012985e-45f, nexttowardf(0.0f, -1.0L));
 }
 
-TEST(math, nexttowardl) {
+TEST(MATH_TEST, nexttowardl) {
   ASSERT_DOUBLE_EQ(0.0L, nexttowardl(0.0L, 0.0L));
   // Use a runtime value to accomodate the case when
   // sizeof(double) == sizeof(long double)
@@ -1062,86 +1068,86 @@
   ASSERT_DOUBLE_EQ(-smallest_positive, nexttowardl(0.0L, -1.0L));
 }
 
-TEST(math, copysign) {
+TEST(MATH_TEST, copysign) {
   ASSERT_DOUBLE_EQ(0.0, copysign(0.0, 1.0));
   ASSERT_DOUBLE_EQ(-0.0, copysign(0.0, -1.0));
   ASSERT_DOUBLE_EQ(2.0, copysign(2.0, 1.0));
   ASSERT_DOUBLE_EQ(-2.0, copysign(2.0, -1.0));
 }
 
-TEST(math, copysignf) {
+TEST(MATH_TEST, copysignf) {
   ASSERT_FLOAT_EQ(0.0f, copysignf(0.0f, 1.0f));
   ASSERT_FLOAT_EQ(-0.0f, copysignf(0.0f, -1.0f));
   ASSERT_FLOAT_EQ(2.0f, copysignf(2.0f, 1.0f));
   ASSERT_FLOAT_EQ(-2.0f, copysignf(2.0f, -1.0f));
 }
 
-TEST(math, copysignl) {
+TEST(MATH_TEST, copysignl) {
   ASSERT_DOUBLE_EQ(0.0L, copysignl(0.0L, 1.0L));
   ASSERT_DOUBLE_EQ(-0.0L, copysignl(0.0L, -1.0L));
   ASSERT_DOUBLE_EQ(2.0L, copysignl(2.0L, 1.0L));
   ASSERT_DOUBLE_EQ(-2.0L, copysignl(2.0L, -1.0L));
 }
 
-TEST(math, significand) {
+TEST(MATH_TEST, significand) {
   ASSERT_DOUBLE_EQ(0.0, significand(0.0));
   ASSERT_DOUBLE_EQ(1.2, significand(1.2));
   ASSERT_DOUBLE_EQ(1.53125, significand(12.25));
 }
 
-TEST(math, significandf) {
+TEST(MATH_TEST, significandf) {
   ASSERT_FLOAT_EQ(0.0f, significandf(0.0f));
   ASSERT_FLOAT_EQ(1.2f, significandf(1.2f));
   ASSERT_FLOAT_EQ(1.53125f, significandf(12.25f));
 }
 
-TEST(math, significandl) {
+TEST(MATH_TEST, significandl) {
   ASSERT_DOUBLE_EQ(0.0L, significandl(0.0L));
   ASSERT_DOUBLE_EQ(1.2L, significandl(1.2L));
   ASSERT_DOUBLE_EQ(1.53125L, significandl(12.25L));
 }
 
-TEST(math, scalb) {
+TEST(MATH_TEST, scalb) {
   ASSERT_DOUBLE_EQ(12.0, scalb(3.0, 2.0));
 }
 
-TEST(math, scalbf) {
+TEST(MATH_TEST, scalbf) {
   ASSERT_FLOAT_EQ(12.0f, scalbf(3.0f, 2.0f));
 }
 
-TEST(math, scalbln) {
+TEST(MATH_TEST, scalbln) {
   ASSERT_DOUBLE_EQ(12.0, scalbln(3.0, 2L));
 }
 
-TEST(math, scalblnf) {
+TEST(MATH_TEST, scalblnf) {
   ASSERT_FLOAT_EQ(12.0f, scalblnf(3.0f, 2L));
 }
 
-TEST(math, scalblnl) {
+TEST(MATH_TEST, scalblnl) {
   ASSERT_DOUBLE_EQ(12.0L, scalblnl(3.0L, 2L));
 }
 
-TEST(math, scalbn) {
+TEST(MATH_TEST, scalbn) {
   ASSERT_DOUBLE_EQ(12.0, scalbn(3.0, 2));
 }
 
-TEST(math, scalbnf) {
+TEST(MATH_TEST, scalbnf) {
   ASSERT_FLOAT_EQ(12.0f, scalbnf(3.0f, 2));
 }
 
-TEST(math, scalbnl) {
+TEST(MATH_TEST, scalbnl) {
   ASSERT_DOUBLE_EQ(12.0L, scalbnl(3.0L, 2));
 }
 
-TEST(math, gamma) {
+TEST(MATH_TEST, gamma) {
   ASSERT_DOUBLE_EQ(log(24.0), gamma(5.0));
 }
 
-TEST(math, gammaf) {
+TEST(MATH_TEST, gammaf) {
   ASSERT_FLOAT_EQ(logf(24.0f), gammaf(5.0f));
 }
 
-TEST(math, gamma_r) {
+TEST(MATH_TEST, gamma_r) {
 #if defined(__BIONIC__)
   int sign;
   ASSERT_DOUBLE_EQ(log(24.0), gamma_r(5.0, &sign));
@@ -1151,7 +1157,7 @@
 #endif // __BIONIC__
 }
 
-TEST(math, gammaf_r) {
+TEST(MATH_TEST, gammaf_r) {
 #if defined(__BIONIC__)
   int sign;
   ASSERT_FLOAT_EQ(logf(24.0f), gammaf_r(5.0f, &sign));
@@ -1161,25 +1167,25 @@
 #endif // __BIONIC__
 }
 
-TEST(math, lgamma) {
+TEST(MATH_TEST, lgamma) {
   ASSERT_DOUBLE_EQ(log(24.0), lgamma(5.0));
 }
 
-TEST(math, lgammaf) {
+TEST(MATH_TEST, lgammaf) {
   ASSERT_FLOAT_EQ(logf(24.0f), lgammaf(5.0f));
 }
 
-TEST(math, lgammal) {
+TEST(MATH_TEST, lgammal) {
   ASSERT_DOUBLE_EQ(logl(24.0L), lgammal(5.0L));
 }
 
-TEST(math, lgamma_r) {
+TEST(MATH_TEST, lgamma_r) {
   int sign;
   ASSERT_DOUBLE_EQ(log(24.0), lgamma_r(5.0, &sign));
   ASSERT_EQ(1, sign);
 }
 
-TEST(math, lgamma_r_17471883) {
+TEST(MATH_TEST, lgamma_r_17471883) {
   int sign;
 
   sign = 0;
@@ -1190,13 +1196,13 @@
   ASSERT_EQ(-1, sign);
 }
 
-TEST(math, lgammaf_r) {
+TEST(MATH_TEST, lgammaf_r) {
   int sign;
   ASSERT_FLOAT_EQ(logf(24.0f), lgammaf_r(5.0f, &sign));
   ASSERT_EQ(1, sign);
 }
 
-TEST(math, lgammaf_r_17471883) {
+TEST(MATH_TEST, lgammaf_r_17471883) {
   int sign;
 
   sign = 0;
@@ -1207,13 +1213,13 @@
   ASSERT_EQ(-1, sign);
 }
 
-TEST(math, lgammal_r) {
+TEST(MATH_TEST, lgammal_r) {
   int sign;
   ASSERT_DOUBLE_EQ(log(24.0L), lgamma_r(5.0L, &sign));
   ASSERT_EQ(1, sign);
 }
 
-TEST(math, lgammal_r_17471883) {
+TEST(MATH_TEST, lgammal_r_17471883) {
   int sign;
 
   sign = 0;
@@ -1224,132 +1230,132 @@
   ASSERT_EQ(-1, sign);
 }
 
-TEST(math, tgamma) {
+TEST(MATH_TEST, tgamma) {
   ASSERT_DOUBLE_EQ(24.0, tgamma(5.0));
 }
 
-TEST(math, tgammaf) {
+TEST(MATH_TEST, tgammaf) {
   ASSERT_FLOAT_EQ(24.0f, tgammaf(5.0f));
 }
 
-TEST(math, tgammal) {
+TEST(MATH_TEST, tgammal) {
   ASSERT_DOUBLE_EQ(24.0L, tgammal(5.0L));
 }
 
-TEST(math, j0) {
+TEST(MATH_TEST, j0) {
   ASSERT_DOUBLE_EQ(1.0, j0(0.0));
   ASSERT_DOUBLE_EQ(0.76519768655796661, j0(1.0));
 }
 
-TEST(math, j0f) {
+TEST(MATH_TEST, j0f) {
   ASSERT_FLOAT_EQ(1.0f, j0f(0.0f));
   ASSERT_FLOAT_EQ(0.76519769f, j0f(1.0f));
 }
 
-TEST(math, j1) {
+TEST(MATH_TEST, j1) {
   ASSERT_DOUBLE_EQ(0.0, j1(0.0));
   ASSERT_DOUBLE_EQ(0.44005058574493355, j1(1.0));
 }
 
-TEST(math, j1f) {
+TEST(MATH_TEST, j1f) {
   ASSERT_FLOAT_EQ(0.0f, j1f(0.0f));
   ASSERT_FLOAT_EQ(0.44005057f, j1f(1.0f));
 }
 
-TEST(math, jn) {
+TEST(MATH_TEST, jn) {
   ASSERT_DOUBLE_EQ(0.0, jn(4, 0.0));
   ASSERT_DOUBLE_EQ(0.0024766389641099553, jn(4, 1.0));
 }
 
-TEST(math, jnf) {
+TEST(MATH_TEST, jnf) {
   ASSERT_FLOAT_EQ(0.0f, jnf(4, 0.0f));
   ASSERT_FLOAT_EQ(0.0024766389f, jnf(4, 1.0f));
 }
 
-TEST(math, y0) {
+TEST(MATH_TEST, y0) {
   ASSERT_DOUBLE_EQ(-HUGE_VAL, y0(0.0));
   ASSERT_DOUBLE_EQ(0.08825696421567697, y0(1.0));
 }
 
-TEST(math, y0f) {
+TEST(MATH_TEST, y0f) {
   ASSERT_FLOAT_EQ(-HUGE_VALF, y0f(0.0f));
   ASSERT_FLOAT_EQ(0.088256963f, y0f(1.0f));
 }
 
-TEST(math, y1) {
+TEST(MATH_TEST, y1) {
   ASSERT_DOUBLE_EQ(-HUGE_VAL, y1(0.0));
   ASSERT_DOUBLE_EQ(-0.78121282130028868, y1(1.0));
 }
 
-TEST(math, y1f) {
+TEST(MATH_TEST, y1f) {
   ASSERT_FLOAT_EQ(-HUGE_VALF, y1f(0.0f));
   ASSERT_FLOAT_EQ(-0.78121281f, y1f(1.0f));
 }
 
-TEST(math, yn) {
+TEST(MATH_TEST, yn) {
   ASSERT_DOUBLE_EQ(-HUGE_VAL, yn(4, 0.0));
   ASSERT_DOUBLE_EQ(-33.278423028972114, yn(4, 1.0));
 }
 
-TEST(math, ynf) {
+TEST(MATH_TEST, ynf) {
   ASSERT_FLOAT_EQ(-HUGE_VALF, ynf(4, 0.0f));
   ASSERT_FLOAT_EQ(-33.278423f, ynf(4, 1.0f));
 }
 
-TEST(math, frexp) {
+TEST(MATH_TEST, frexp) {
   int exp;
   double dr = frexp(1024.0, &exp);
   ASSERT_DOUBLE_EQ(1024.0, scalbn(dr, exp));
 }
 
-TEST(math, frexpf) {
+TEST(MATH_TEST, frexpf) {
   int exp;
   float fr = frexpf(1024.0f, &exp);
   ASSERT_FLOAT_EQ(1024.0f, scalbnf(fr, exp));
 }
 
-TEST(math, frexpl) {
+TEST(MATH_TEST, frexpl) {
   int exp;
   long double ldr = frexpl(1024.0L, &exp);
   ASSERT_DOUBLE_EQ(1024.0L, scalbnl(ldr, exp));
 }
 
-TEST(math, modf) {
+TEST(MATH_TEST, modf) {
   double di;
   double df = modf(123.75, &di);
   ASSERT_DOUBLE_EQ(123.0, di);
   ASSERT_DOUBLE_EQ(0.75, df);
 }
 
-TEST(math, modff) {
+TEST(MATH_TEST, modff) {
   float fi;
   float ff = modff(123.75f, &fi);
   ASSERT_FLOAT_EQ(123.0f, fi);
   ASSERT_FLOAT_EQ(0.75f, ff);
 }
 
-TEST(math, modfl) {
+TEST(MATH_TEST, modfl) {
   long double ldi;
   long double ldf = modfl(123.75L, &ldi);
   ASSERT_DOUBLE_EQ(123.0L, ldi);
   ASSERT_DOUBLE_EQ(0.75L, ldf);
 }
 
-TEST(math, remquo) {
+TEST(MATH_TEST, remquo) {
   int q;
   double d = remquo(13.0, 4.0, &q);
   ASSERT_EQ(3, q);
   ASSERT_DOUBLE_EQ(1.0, d);
 }
 
-TEST(math, remquof) {
+TEST(MATH_TEST, remquof) {
   int q;
   float f = remquof(13.0f, 4.0f, &q);
   ASSERT_EQ(3, q);
   ASSERT_FLOAT_EQ(1.0, f);
 }
 
-TEST(math, remquol) {
+TEST(MATH_TEST, remquol) {
   int q;
   long double ld = remquol(13.0L, 4.0L, &q);
   ASSERT_DOUBLE_EQ(3L, q);
@@ -1357,13 +1363,13 @@
 }
 
 // https://code.google.com/p/android/issues/detail?id=6697
-TEST(math, frexpf_public_bug_6697) {
+TEST(MATH_TEST, frexpf_public_bug_6697) {
   int exp;
   float fr = frexpf(14.1f, &exp);
   ASSERT_FLOAT_EQ(14.1f, scalbnf(fr, exp));
 }
 
-TEST(math, exp2_STRICT_ALIGN_OpenBSD_bug) {
+TEST(MATH_TEST, exp2_STRICT_ALIGN_OpenBSD_bug) {
   // OpenBSD/x86's libm had a bug here, but it was already fixed in FreeBSD:
   // http://svnweb.FreeBSD.org/base/head/lib/msun/src/math_private.h?revision=240827&view=markup
   ASSERT_DOUBLE_EQ(5.0, exp2(log2(5)));
@@ -1371,7 +1377,7 @@
   ASSERT_DOUBLE_EQ(5.0L, exp2l(log2l(5)));
 }
 
-TEST(math, nextafterl_OpenBSD_bug) {
+TEST(MATH_TEST, nextafterl_OpenBSD_bug) {
   // OpenBSD/x86's libm had a bug here.
   ASSERT_TRUE(nextafter(1.0, 0.0) - 1.0 < 0.0);
   ASSERT_TRUE(nextafterf(1.0f, 0.0f) - 1.0f < 0.0f);
@@ -1379,511 +1385,511 @@
 }
 
 #include "math_data/acos_intel_data.h"
-TEST(math, acos_intel) {
+TEST(MATH_TEST, acos_intel) {
   DoMathDataTest<1>(g_acos_intel_data, acos);
 }
 
 #include "math_data/acosf_intel_data.h"
-TEST(math, acosf_intel) {
+TEST(MATH_TEST, acosf_intel) {
   DoMathDataTest<1>(g_acosf_intel_data, acosf);
 }
 
 #include "math_data/acosh_intel_data.h"
-TEST(math, acosh_intel) {
+TEST(MATH_TEST, acosh_intel) {
   DoMathDataTest<2>(g_acosh_intel_data, acosh);
 }
 
 #include "math_data/acoshf_intel_data.h"
-TEST(math, acoshf_intel) {
+TEST(MATH_TEST, acoshf_intel) {
   DoMathDataTest<2>(g_acoshf_intel_data, acoshf);
 }
 
 #include "math_data/asin_intel_data.h"
-TEST(math, asin_intel) {
+TEST(MATH_TEST, asin_intel) {
   DoMathDataTest<1>(g_asin_intel_data, asin);
 }
 
 #include "math_data/asinf_intel_data.h"
-TEST(math, asinf_intel) {
+TEST(MATH_TEST, asinf_intel) {
   DoMathDataTest<1>(g_asinf_intel_data, asinf);
 }
 
 #include "math_data/asinh_intel_data.h"
-TEST(math, asinh_intel) {
+TEST(MATH_TEST, asinh_intel) {
   DoMathDataTest<2>(g_asinh_intel_data, asinh);
 }
 
 #include "math_data/asinhf_intel_data.h"
-TEST(math, asinhf_intel) {
+TEST(MATH_TEST, asinhf_intel) {
   DoMathDataTest<2>(g_asinhf_intel_data, asinhf);
 }
 
 #include "math_data/atan2_intel_data.h"
-TEST(math, atan2_intel) {
+TEST(MATH_TEST, atan2_intel) {
   DoMathDataTest<2>(g_atan2_intel_data, atan2);
 }
 
 #include "math_data/atan2f_intel_data.h"
-TEST(math, atan2f_intel) {
+TEST(MATH_TEST, atan2f_intel) {
   DoMathDataTest<2>(g_atan2f_intel_data, atan2f);
 }
 
 #include "math_data/atan_intel_data.h"
-TEST(math, atan_intel) {
+TEST(MATH_TEST, atan_intel) {
   DoMathDataTest<1>(g_atan_intel_data, atan);
 }
 
 #include "math_data/atanf_intel_data.h"
-TEST(math, atanf_intel) {
+TEST(MATH_TEST, atanf_intel) {
   DoMathDataTest<1>(g_atanf_intel_data, atanf);
 }
 
 #include "math_data/atanh_intel_data.h"
-TEST(math, atanh_intel) {
+TEST(MATH_TEST, atanh_intel) {
   DoMathDataTest<2>(g_atanh_intel_data, atanh);
 }
 
 #include "math_data/atanhf_intel_data.h"
-TEST(math, atanhf_intel) {
+TEST(MATH_TEST, atanhf_intel) {
   DoMathDataTest<2>(g_atanhf_intel_data, atanhf);
 }
 
 #include "math_data/cbrt_intel_data.h"
-TEST(math, cbrt_intel) {
+TEST(MATH_TEST, cbrt_intel) {
   DoMathDataTest<1>(g_cbrt_intel_data, cbrt);
 }
 
 #include "math_data/cbrtf_intel_data.h"
-TEST(math, cbrtf_intel) {
+TEST(MATH_TEST, cbrtf_intel) {
   DoMathDataTest<1>(g_cbrtf_intel_data, cbrtf);
 }
 
 #include "math_data/ceil_intel_data.h"
-TEST(math, ceil_intel) {
+TEST(MATH_TEST, ceil_intel) {
   DoMathDataTest<1>(g_ceil_intel_data, ceil);
 }
 
 #include "math_data/ceilf_intel_data.h"
-TEST(math, ceilf_intel) {
+TEST(MATH_TEST, ceilf_intel) {
   DoMathDataTest<1>(g_ceilf_intel_data, ceilf);
 }
 
 #include "math_data/copysign_intel_data.h"
-TEST(math, copysign_intel) {
+TEST(MATH_TEST, copysign_intel) {
   DoMathDataTest<1>(g_copysign_intel_data, copysign);
 }
 
 #include "math_data/copysignf_intel_data.h"
-TEST(math, copysignf_intel) {
+TEST(MATH_TEST, copysignf_intel) {
   DoMathDataTest<1>(g_copysignf_intel_data, copysignf);
 }
 
 #include "math_data/cos_intel_data.h"
-TEST(math, cos_intel) {
+TEST(MATH_TEST, cos_intel) {
   DoMathDataTest<1>(g_cos_intel_data, cos);
 }
 
 #include "math_data/cosf_intel_data.h"
-TEST(math, cosf_intel) {
+TEST(MATH_TEST, cosf_intel) {
   DoMathDataTest<1>(g_cosf_intel_data, cosf);
 }
 
 #include "math_data/cosh_intel_data.h"
-TEST(math, cosh_intel) {
+TEST(MATH_TEST, cosh_intel) {
   DoMathDataTest<2>(g_cosh_intel_data, cosh);
 }
 
 #include "math_data/coshf_intel_data.h"
-TEST(math, coshf_intel) {
+TEST(MATH_TEST, coshf_intel) {
   DoMathDataTest<2>(g_coshf_intel_data, coshf);
 }
 
 #include "math_data/exp_intel_data.h"
-TEST(math, exp_intel) {
+TEST(MATH_TEST, exp_intel) {
   DoMathDataTest<1>(g_exp_intel_data, exp);
 }
 
 #include "math_data/expf_intel_data.h"
-TEST(math, expf_intel) {
+TEST(MATH_TEST, expf_intel) {
   DoMathDataTest<1>(g_expf_intel_data, expf);
 }
 
 #include "math_data/exp2_intel_data.h"
-TEST(math, exp2_intel) {
+TEST(MATH_TEST, exp2_intel) {
   DoMathDataTest<1>(g_exp2_intel_data, exp2);
 }
 
 #include "math_data/exp2f_intel_data.h"
-TEST(math, exp2f_intel) {
+TEST(MATH_TEST, exp2f_intel) {
   DoMathDataTest<1>(g_exp2f_intel_data, exp2f);
 }
 
 #include "math_data/expm1_intel_data.h"
-TEST(math, expm1_intel) {
+TEST(MATH_TEST, expm1_intel) {
   DoMathDataTest<1>(g_expm1_intel_data, expm1);
 }
 
 #include "math_data/expm1f_intel_data.h"
-TEST(math, expm1f_intel) {
+TEST(MATH_TEST, expm1f_intel) {
   DoMathDataTest<1>(g_expm1f_intel_data, expm1f);
 }
 
 #include "math_data/fabs_intel_data.h"
-TEST(math, fabs_intel) {
+TEST(MATH_TEST, fabs_intel) {
   DoMathDataTest<1>(g_fabs_intel_data, fabs);
 }
 
 #include "math_data/fabsf_intel_data.h"
-TEST(math, fabsf_intel) {
+TEST(MATH_TEST, fabsf_intel) {
   DoMathDataTest<1>(g_fabsf_intel_data, fabsf);
 }
 
 #include "math_data/fdim_intel_data.h"
-TEST(math, fdim_intel) {
+TEST(MATH_TEST, fdim_intel) {
   DoMathDataTest<1>(g_fdim_intel_data, fdim);
 }
 
 #include "math_data/fdimf_intel_data.h"
-TEST(math, fdimf_intel) {
+TEST(MATH_TEST, fdimf_intel) {
   DoMathDataTest<1>(g_fdimf_intel_data, fdimf);
 }
 
 #include "math_data/floor_intel_data.h"
-TEST(math, floor_intel) {
+TEST(MATH_TEST, floor_intel) {
   DoMathDataTest<1>(g_floor_intel_data, floor);
 }
 
 #include "math_data/floorf_intel_data.h"
-TEST(math, floorf_intel) {
+TEST(MATH_TEST, floorf_intel) {
   DoMathDataTest<1>(g_floorf_intel_data, floorf);
 }
 
 #include "math_data/fma_intel_data.h"
-TEST(math, fma_intel) {
+TEST(MATH_TEST, fma_intel) {
   DoMathDataTest<1>(g_fma_intel_data, fma);
 }
 
 #include "math_data/fmaf_intel_data.h"
-TEST(math, fmaf_intel) {
+TEST(MATH_TEST, fmaf_intel) {
   DoMathDataTest<1>(g_fmaf_intel_data, fmaf);
 }
 
 #include "math_data/fmax_intel_data.h"
-TEST(math, fmax_intel) {
+TEST(MATH_TEST, fmax_intel) {
   DoMathDataTest<1>(g_fmax_intel_data, fmax);
 }
 
 #include "math_data/fmaxf_intel_data.h"
-TEST(math, fmaxf_intel) {
+TEST(MATH_TEST, fmaxf_intel) {
   DoMathDataTest<1>(g_fmaxf_intel_data, fmaxf);
 }
 
 #include "math_data/fmin_intel_data.h"
-TEST(math, fmin_intel) {
+TEST(MATH_TEST, fmin_intel) {
   DoMathDataTest<1>(g_fmin_intel_data, fmin);
 }
 
 #include "math_data/fminf_intel_data.h"
-TEST(math, fminf_intel) {
+TEST(MATH_TEST, fminf_intel) {
   DoMathDataTest<1>(g_fminf_intel_data, fminf);
 }
 
 #include "math_data/fmod_intel_data.h"
-TEST(math, fmod_intel) {
+TEST(MATH_TEST, fmod_intel) {
   DoMathDataTest<1>(g_fmod_intel_data, fmod);
 }
 
 #include "math_data/fmodf_intel_data.h"
-TEST(math, fmodf_intel) {
+TEST(MATH_TEST, fmodf_intel) {
   DoMathDataTest<1>(g_fmodf_intel_data, fmodf);
 }
 
 #include "math_data/frexp_intel_data.h"
-TEST(math, frexp_intel) {
+TEST(MATH_TEST, frexp_intel) {
   DoMathDataTest<1>(g_frexp_intel_data, frexp);
 }
 
 #include "math_data/frexpf_intel_data.h"
-TEST(math, frexpf_intel) {
+TEST(MATH_TEST, frexpf_intel) {
   DoMathDataTest<1>(g_frexpf_intel_data, frexpf);
 }
 
 #include "math_data/hypot_intel_data.h"
-TEST(math, hypot_intel) {
+TEST(MATH_TEST, hypot_intel) {
   DoMathDataTest<1>(g_hypot_intel_data, hypot);
 }
 
 #include "math_data/hypotf_intel_data.h"
-TEST(math, hypotf_intel) {
+TEST(MATH_TEST, hypotf_intel) {
   DoMathDataTest<1>(g_hypotf_intel_data, hypotf);
 }
 
 #include "math_data/ilogb_intel_data.h"
-TEST(math, ilogb_intel) {
+TEST(MATH_TEST, ilogb_intel) {
   DoMathDataTest<1>(g_ilogb_intel_data, ilogb);
 }
 
 #include "math_data/ilogbf_intel_data.h"
-TEST(math, ilogbf_intel) {
+TEST(MATH_TEST, ilogbf_intel) {
   DoMathDataTest<1>(g_ilogbf_intel_data, ilogbf);
 }
 
 #include "math_data/ldexp_intel_data.h"
-TEST(math, ldexp_intel) {
+TEST(MATH_TEST, ldexp_intel) {
   DoMathDataTest<1>(g_ldexp_intel_data, ldexp);
 }
 
 #include "math_data/ldexpf_intel_data.h"
-TEST(math, ldexpf_intel) {
+TEST(MATH_TEST, ldexpf_intel) {
   DoMathDataTest<1>(g_ldexpf_intel_data, ldexpf);
 }
 
 #include "math_data/llrint_intel_data.h"
-TEST(math, llrint_intel) {
+TEST(MATH_TEST, llrint_intel) {
   DoMathDataTest<1>(g_llrint_intel_data, llrint);
 }
 
 #include "math_data/llrintf_intel_data.h"
-TEST(math, llrintf_intel) {
+TEST(MATH_TEST, llrintf_intel) {
   DoMathDataTest<1>(g_llrintf_intel_data, llrintf);
 }
 
 #include "math_data/log_intel_data.h"
-TEST(math, log_intel) {
+TEST(MATH_TEST, log_intel) {
   DoMathDataTest<1>(g_log_intel_data, log);
 }
 
 #include "math_data/logf_intel_data.h"
-TEST(math, logf_intel) {
+TEST(MATH_TEST, logf_intel) {
   DoMathDataTest<1>(g_logf_intel_data, logf);
 }
 
 #include "math_data/log10_intel_data.h"
-TEST(math, log10_intel) {
+TEST(MATH_TEST, log10_intel) {
   DoMathDataTest<1>(g_log10_intel_data, log10);
 }
 
 #include "math_data/log10f_intel_data.h"
-TEST(math, log10f_intel) {
+TEST(MATH_TEST, log10f_intel) {
   DoMathDataTest<1>(g_log10f_intel_data, log10f);
 }
 
 #include "math_data/log1p_intel_data.h"
-TEST(math, log1p_intel) {
+TEST(MATH_TEST, log1p_intel) {
   DoMathDataTest<1>(g_log1p_intel_data, log1p);
 }
 
 #include "math_data/log1pf_intel_data.h"
-TEST(math, log1pf_intel) {
+TEST(MATH_TEST, log1pf_intel) {
   DoMathDataTest<1>(g_log1pf_intel_data, log1pf);
 }
 
 #include "math_data/log2_intel_data.h"
-TEST(math, log2_intel) {
+TEST(MATH_TEST, log2_intel) {
   DoMathDataTest<1>(g_log2_intel_data, log2);
 }
 
 #include "math_data/log2f_intel_data.h"
-TEST(math, log2f_intel) {
+TEST(MATH_TEST, log2f_intel) {
   DoMathDataTest<1>(g_log2f_intel_data, log2f);
 }
 
 #include "math_data/logb_intel_data.h"
-TEST(math, logb_intel) {
+TEST(MATH_TEST, logb_intel) {
   DoMathDataTest<1>(g_logb_intel_data, logb);
 }
 
 #include "math_data/logbf_intel_data.h"
-TEST(math, logbf_intel) {
+TEST(MATH_TEST, logbf_intel) {
   DoMathDataTest<1>(g_logbf_intel_data, logbf);
 }
 
 #include "math_data/lrint_intel_data.h"
-TEST(math, lrint_intel) {
+TEST(MATH_TEST, lrint_intel) {
   DoMathDataTest<1>(g_lrint_intel_data, lrint);
 }
 
 #include "math_data/lrintf_intel_data.h"
-TEST(math, lrintf_intel) {
+TEST(MATH_TEST, lrintf_intel) {
   DoMathDataTest<1>(g_lrintf_intel_data, lrintf);
 }
 
 #include "math_data/modf_intel_data.h"
-TEST(math, modf_intel) {
+TEST(MATH_TEST, modf_intel) {
   DoMathDataTest<1>(g_modf_intel_data, modf);
 }
 
 #include "math_data/modff_intel_data.h"
-TEST(math, modff_intel) {
+TEST(MATH_TEST, modff_intel) {
   DoMathDataTest<1>(g_modff_intel_data, modff);
 }
 
 #include "math_data/nearbyint_intel_data.h"
-TEST(math, nearbyint_intel) {
+TEST(MATH_TEST, nearbyint_intel) {
   DoMathDataTest<1>(g_nearbyint_intel_data, nearbyint);
 }
 
 #include "math_data/nearbyintf_intel_data.h"
-TEST(math, nearbyintf_intel) {
+TEST(MATH_TEST, nearbyintf_intel) {
   DoMathDataTest<1>(g_nearbyintf_intel_data, nearbyintf);
 }
 
 #include "math_data/nextafter_intel_data.h"
-TEST(math, nextafter_intel) {
+TEST(MATH_TEST, nextafter_intel) {
   DoMathDataTest<1>(g_nextafter_intel_data, nextafter);
 }
 
 #include "math_data/nextafterf_intel_data.h"
-TEST(math, nextafterf_intel) {
+TEST(MATH_TEST, nextafterf_intel) {
   DoMathDataTest<1>(g_nextafterf_intel_data, nextafterf);
 }
 
 #include "math_data/pow_intel_data.h"
-TEST(math, pow_intel) {
+TEST(MATH_TEST, pow_intel) {
   DoMathDataTest<1>(g_pow_intel_data, pow);
 }
 
 #include "math_data/powf_intel_data.h"
-TEST(math, powf_intel) {
+TEST(MATH_TEST, powf_intel) {
   DoMathDataTest<1>(g_powf_intel_data, powf);
 }
 
 #include "math_data/remainder_intel_data.h"
-TEST(math, remainder_intel) {
+TEST(MATH_TEST, remainder_intel) {
   DoMathDataTest<1>(g_remainder_intel_data, remainder);
 }
 
 #include "math_data/remainderf_intel_data.h"
-TEST(math, remainderf_intel) {
+TEST(MATH_TEST, remainderf_intel) {
   DoMathDataTest<1>(g_remainderf_intel_data, remainderf);
 }
 
 #include "math_data/remquo_intel_data.h"
-TEST(math, remquo_intel) {
+TEST(MATH_TEST, remquo_intel) {
   DoMathDataTest<1>(g_remquo_intel_data, remquo);
 }
 
 #include "math_data/remquof_intel_data.h"
-TEST(math, remquof_intel) {
+TEST(MATH_TEST, remquof_intel) {
   DoMathDataTest<1>(g_remquof_intel_data, remquof);
 }
 
 #include "math_data/rint_intel_data.h"
-TEST(math, rint_intel) {
+TEST(MATH_TEST, rint_intel) {
   DoMathDataTest<1>(g_rint_intel_data, rint);
 }
 
 #include "math_data/rintf_intel_data.h"
-TEST(math, rintf_intel) {
+TEST(MATH_TEST, rintf_intel) {
   DoMathDataTest<1>(g_rintf_intel_data, rintf);
 }
 
 #include "math_data/round_intel_data.h"
-TEST(math, round_intel) {
+TEST(MATH_TEST, round_intel) {
   DoMathDataTest<1>(g_round_intel_data, round);
 }
 
 #include "math_data/roundf_intel_data.h"
-TEST(math, roundf_intel) {
+TEST(MATH_TEST, roundf_intel) {
   DoMathDataTest<1>(g_roundf_intel_data, roundf);
 }
 
 #include "math_data/scalb_intel_data.h"
-TEST(math, scalb_intel) {
+TEST(MATH_TEST, scalb_intel) {
   DoMathDataTest<1>(g_scalb_intel_data, scalb);
 }
 
 #include "math_data/scalbf_intel_data.h"
-TEST(math, scalbf_intel) {
+TEST(MATH_TEST, scalbf_intel) {
   DoMathDataTest<1>(g_scalbf_intel_data, scalbf);
 }
 
 #include "math_data/scalbn_intel_data.h"
-TEST(math, scalbn_intel) {
+TEST(MATH_TEST, scalbn_intel) {
   DoMathDataTest<1>(g_scalbn_intel_data, scalbn);
 }
 
 #include "math_data/scalbnf_intel_data.h"
-TEST(math, scalbnf_intel) {
+TEST(MATH_TEST, scalbnf_intel) {
   DoMathDataTest<1>(g_scalbnf_intel_data, scalbnf);
 }
 
 #include "math_data/significand_intel_data.h"
-TEST(math, significand_intel) {
+TEST(MATH_TEST, significand_intel) {
   DoMathDataTest<1>(g_significand_intel_data, significand);
 }
 
 #include "math_data/significandf_intel_data.h"
-TEST(math, significandf_intel) {
+TEST(MATH_TEST, significandf_intel) {
   DoMathDataTest<1>(g_significandf_intel_data, significandf);
 }
 
 #include "math_data/sin_intel_data.h"
-TEST(math, sin_intel) {
+TEST(MATH_TEST, sin_intel) {
   DoMathDataTest<1>(g_sin_intel_data, sin);
 }
 
 #include "math_data/sinf_intel_data.h"
-TEST(math, sinf_intel) {
+TEST(MATH_TEST, sinf_intel) {
   DoMathDataTest<1>(g_sinf_intel_data, sinf);
 }
 
 #include "math_data/sinh_intel_data.h"
-TEST(math, sinh_intel) {
+TEST(MATH_TEST, sinh_intel) {
   DoMathDataTest<2>(g_sinh_intel_data, sinh);
 }
 
 #include "math_data/sinhf_intel_data.h"
-TEST(math, sinhf_intel) {
+TEST(MATH_TEST, sinhf_intel) {
   DoMathDataTest<2>(g_sinhf_intel_data, sinhf);
 }
 
 #include "math_data/sincos_intel_data.h"
-TEST(math, sincos_intel) {
+TEST(MATH_TEST, sincos_intel) {
   DoMathDataTest<1>(g_sincos_intel_data, sincos);
 }
 
 #include "math_data/sincosf_intel_data.h"
-TEST(math, sincosf_intel) {
+TEST(MATH_TEST, sincosf_intel) {
   DoMathDataTest<1>(g_sincosf_intel_data, sincosf);
 }
 
 #include "math_data/sqrt_intel_data.h"
-TEST(math, sqrt_intel) {
+TEST(MATH_TEST, sqrt_intel) {
   DoMathDataTest<1>(g_sqrt_intel_data, sqrt);
 }
 
 #include "math_data/sqrtf_intel_data.h"
-TEST(math, sqrtf_intel) {
+TEST(MATH_TEST, sqrtf_intel) {
   DoMathDataTest<1>(g_sqrtf_intel_data, sqrtf);
 }
 
 #include "math_data/tan_intel_data.h"
-TEST(math, tan_intel) {
+TEST(MATH_TEST, tan_intel) {
   DoMathDataTest<1>(g_tan_intel_data, tan);
 }
 
 #include "math_data/tanf_intel_data.h"
-TEST(math, tanf_intel) {
+TEST(MATH_TEST, tanf_intel) {
   DoMathDataTest<1>(g_tanf_intel_data, tanf);
 }
 
 #include "math_data/tanh_intel_data.h"
-TEST(math, tanh_intel) {
+TEST(MATH_TEST, tanh_intel) {
   DoMathDataTest<2>(g_tanh_intel_data, tanh);
 }
 
 #include "math_data/tanhf_intel_data.h"
-TEST(math, tanhf_intel) {
+TEST(MATH_TEST, tanhf_intel) {
   DoMathDataTest<2>(g_tanhf_intel_data, tanhf);
 }
 
 #include "math_data/trunc_intel_data.h"
-TEST(math, trunc_intel) {
+TEST(MATH_TEST, trunc_intel) {
   DoMathDataTest<1>(g_trunc_intel_data, trunc);
 }
 
 #include "math_data/truncf_intel_data.h"
-TEST(math, truncf_intel) {
+TEST(MATH_TEST, truncf_intel) {
   DoMathDataTest<1>(g_truncf_intel_data, truncf);
 }
diff --git a/tests/search_test.cpp b/tests/search_test.cpp
index d368f9f..d5ab67c 100644
--- a/tests/search_test.cpp
+++ b/tests/search_test.cpp
@@ -208,3 +208,80 @@
 
   remque(&zero);
 }
+
+static void AssertEntry(ENTRY* e, const char* expected_key, const char* expected_data) {
+  ASSERT_TRUE(e != nullptr);
+  ASSERT_STREQ(expected_key, reinterpret_cast<char*>(e->key));
+  ASSERT_STREQ(expected_data, reinterpret_cast<char*>(e->data));
+}
+
+TEST(search, hcreate_hsearch_hdestroy) {
+  ASSERT_NE(0, hcreate(13));
+
+  // Add some initial entries.
+  ENTRY* e;
+  e = hsearch(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("A")}, ENTER);
+  AssertEntry(e, "a", "A");
+  e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = const_cast<char*>("B")}, ENTER);
+  AssertEntry(e, "aa", "B");
+  e = hsearch(ENTRY{.key = const_cast<char*>("aaa"), .data = const_cast<char*>("C")}, ENTER);
+  AssertEntry(e, "aaa", "C");
+
+  // Check missing.
+  e = hsearch(ENTRY{.key = const_cast<char*>("aaaa"), .data = nullptr}, FIND);
+  ASSERT_FALSE(e != nullptr);
+
+  // Check present.
+  e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = nullptr}, FIND);
+  AssertEntry(e, "aa", "B");
+
+  // ENTER with an existing key just returns the existing ENTRY.
+  e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = const_cast<char*>("X")}, ENTER);
+  AssertEntry(e, "aa", "B");
+  e->data = const_cast<char*>("X");
+
+  // Check present and updated.
+  e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = nullptr}, FIND);
+  AssertEntry(e, "aa", "X");
+  // But other entries stayed the same.
+  e = hsearch(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND);
+  AssertEntry(e, "a", "A");
+  e = hsearch(ENTRY{.key = const_cast<char*>("aaa"), .data = nullptr}, FIND);
+  AssertEntry(e, "aaa", "C");
+
+  hdestroy();
+}
+
+TEST(search, hcreate_r_hsearch_r_hdestroy_r) {
+  hsearch_data h1 = {};
+  ASSERT_EQ(1, hcreate_r(13, &h1));
+
+  hsearch_data h2 = {};
+  ASSERT_EQ(1, hcreate_r(128, &h2));
+
+  // Add some initial entries.
+  ENTRY* e;
+  ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("A")},
+                         ENTER, &e, &h1));
+  AssertEntry(e, "a", "A");
+  ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("B")},
+                         ENTER, &e, &h2));
+  AssertEntry(e, "a", "B");
+
+  // Check missing.
+  errno = 0;
+  ASSERT_EQ(0, hsearch_r(ENTRY{.key = const_cast<char*>("b"), .data = nullptr}, FIND, &e, &h1));
+  ASSERT_EQ(ESRCH, errno);
+
+  // Check present.
+  ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h1));
+  AssertEntry(e, "a", "A");
+  ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h2));
+  AssertEntry(e, "a", "B");
+
+  // Destroying one doesn't affect the other.
+  hdestroy_r(&h1);
+  ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h2));
+  AssertEntry(e, "a", "B");
+  hdestroy_r(&h2);
+}
diff --git a/tests/stdalign_test.cpp b/tests/stdalign_test.cpp
new file mode 100644
index 0000000..fd6b81e
--- /dev/null
+++ b/tests/stdalign_test.cpp
@@ -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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdalign.h>
+
+TEST(stdalign, smoke) {
+#if !defined(__alignas_is_defined) || __alignas_is_defined != 1
+#error __alignas_is_defined
+#endif
+#if !defined(__alignof_is_defined) || __alignof_is_defined != 1
+#error __alignof_is_defined
+#endif
+  ASSERT_EQ(1U, alignof(char));
+  struct alignas(128) S128 {};
+  ASSERT_EQ(128U, alignof(S128));
+}
diff --git a/tests/stdarg_test.cpp b/tests/stdarg_test.cpp
new file mode 100644
index 0000000..3f33dc2
--- /dev/null
+++ b/tests/stdarg_test.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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 <stdarg.h>
+
+TEST(stdarg, smoke) {
+#if !defined(va_start)
+#error va_start
+#endif
+#if !defined(va_arg)
+#error va_arg
+#endif
+#if !defined(va_copy)
+#error va_copy
+#endif
+#if !defined(va_end)
+#error va_end
+#endif
+  va_list l __attribute__((__unused__));
+}
diff --git a/tests/stdbool_test.c b/tests/stdbool_test.c
new file mode 100644
index 0000000..cc23f29
--- /dev/null
+++ b/tests/stdbool_test.c
@@ -0,0 +1,23 @@
+/*
+ * 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 <stdbool.h>
+
+#if !defined(__bool_true_false_are_defined)
+#error __bool_true_false_are_defined
+#endif
+bool stdbool_true = true;
+bool stdbool_false = false;
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 7d2dc20..27495d8 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -650,3 +650,18 @@
 TEST(stdlib, strtoumax_smoke) {
   CheckStrToInt(strtoumax);
 }
+
+TEST(stdlib, abs) {
+  ASSERT_EQ(INT_MAX, abs(-INT_MAX));
+  ASSERT_EQ(INT_MAX, abs(INT_MAX));
+}
+
+TEST(stdlib, labs) {
+  ASSERT_EQ(LONG_MAX, labs(-LONG_MAX));
+  ASSERT_EQ(LONG_MAX, labs(LONG_MAX));
+}
+
+TEST(stdlib, llabs) {
+  ASSERT_EQ(LLONG_MAX, llabs(-LLONG_MAX));
+  ASSERT_EQ(LLONG_MAX, llabs(LLONG_MAX));
+}
diff --git a/tests/stdnoreturn_test.cpp b/tests/stdnoreturn_test.cpp
new file mode 100644
index 0000000..8d6f62f
--- /dev/null
+++ b/tests/stdnoreturn_test.cpp
@@ -0,0 +1,25 @@
+/*
+ * 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 <stdnoreturn.h>
+
+#if !defined(__noreturn_is_defined)
+#error __noreturn_is_defined
+#endif
+
+noreturn void stdnoreturn_h_test_function() {
+  for (;;) ;
+}
diff --git a/tests/sys_mman_test.cpp b/tests/sys_mman_test.cpp
index 62401a6..e44bfed 100644
--- a/tests/sys_mman_test.cpp
+++ b/tests/sys_mman_test.cpp
@@ -235,7 +235,7 @@
 
 TEST(sys_mman, mmap_bug_27265969) {
   char* base = reinterpret_cast<char*>(mmap(nullptr, PAGE_SIZE * 2, PROT_EXEC | PROT_READ,
-                                            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0));
+                                            MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
   // Some kernels had bugs that would cause segfaults here...
   __builtin___clear_cache(base, base + (PAGE_SIZE * 2));
 }
diff --git a/tests/tgmath_test.c b/tests/tgmath_test.c
new file mode 100644
index 0000000..f977306
--- /dev/null
+++ b/tests/tgmath_test.c
@@ -0,0 +1,22 @@
+/*
+ * 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 <tgmath.h>
+
+float complex tgmath_h_test_function() {
+  float complex z = 1 + 0.5*I;
+  return sqrt(z);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index cd51e1b..8af2263 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -784,6 +784,12 @@
   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.
diff --git a/tests/utils.h b/tests/utils.h
index 81df350..8638850 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -17,6 +17,7 @@
 #ifndef __TEST_UTILS_H
 #define __TEST_UTILS_H
 
+#include <dlfcn.h>
 #include <inttypes.h>
 #include <sys/mman.h>
 #include <sys/types.h>
@@ -43,6 +44,12 @@
 #define KNOWN_FAILURE_ON_BIONIC(x) x
 #endif
 
+// bionic's dlsym doesn't work in static binaries, so we can't access icu,
+// so any unicode test case will fail.
+static inline bool have_dl() {
+  return (dlopen("libc.so", 0) != nullptr);
+}
+
 #if defined(__linux__)
 
 #include <sys/sysmacros.h>
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index eb23cf3..6f90c6c 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -20,10 +20,11 @@
 #include <inttypes.h>
 #include <limits.h>
 #include <locale.h>
+#include <math.h>
 #include <stdint.h>
 #include <wchar.h>
 
-#include "math_data_test.h"
+#include "utils.h"
 
 #define NUM_WCHARS(num_bytes) ((num_bytes)/sizeof(wchar_t))
 
@@ -899,6 +900,8 @@
 }
 
 TEST(wchar, wcwidth_non_spacing_and_enclosing_marks_and_format) {
+  if (!have_dl()) return;
+
   EXPECT_EQ(0, wcwidth(0x0300)); // Combining grave.
   EXPECT_EQ(0, wcwidth(0x20dd)); // Combining enclosing circle.
   EXPECT_EQ(0, wcwidth(0x00ad)); // Soft hyphen (SHY).
@@ -906,6 +909,8 @@
 }
 
 TEST(wchar, wcwidth_cjk) {
+  if (!have_dl()) return;
+
   EXPECT_EQ(2, wcwidth(0x4e00)); // Start of CJK unified block.
   EXPECT_EQ(2, wcwidth(0x9fff)); // End of CJK unified block.
   EXPECT_EQ(2, wcwidth(0x3400)); // Start of CJK extension A block.
@@ -915,18 +920,24 @@
 }
 
 TEST(wchar, wcwidth_korean_combining_jamo) {
+  if (!have_dl()) return;
+
   AssertWcwidthRange(0x1160, 0x1200, 0); // Original range.
   EXPECT_EQ(0, wcwidth(0xd7b0)); // Newer.
   EXPECT_EQ(0, wcwidth(0xd7cb));
 }
 
 TEST(wchar, wcwidth_korean_jeongeul_syllables) {
+  if (!have_dl()) return;
+
   EXPECT_EQ(2, wcwidth(0xac00)); // Start of block.
   EXPECT_EQ(2, wcwidth(0xd7a3)); // End of defined code points in Unicode 7.
   // Undefined characters at the end of the block have width 1.
 }
 
 TEST(wchar, wcwidth_kana) {
+  if (!have_dl()) return;
+
   // Hiragana (most, not undefined).
   AssertWcwidthRange(0x3041, 0x3097, 2);
   // Katakana.
@@ -934,22 +945,30 @@
 }
 
 TEST(wchar, wcwidth_circled_two_digit_cjk) {
+  if (!have_dl()) return;
+
   // Circled two-digit CJK "speed sign" numbers are wide,
   // though EastAsianWidth is ambiguous.
   AssertWcwidthRange(0x3248, 0x3250, 2);
 }
 
 TEST(wchar, wcwidth_hexagrams) {
+  if (!have_dl()) return;
+
   // Hexagrams are wide, though EastAsianWidth is neutral.
   AssertWcwidthRange(0x4dc0, 0x4e00, 2);
 }
 
 TEST(wchar, wcwidth_default_ignorables) {
+  if (!have_dl()) return;
+
   AssertWcwidthRange(0xfff0, 0xfff8, 0); // Unassigned by default ignorable.
   EXPECT_EQ(0, wcwidth(0xe0000)); // ...through 0xe0fff.
 }
 
 TEST(wchar, wcwidth_korean_common_non_syllables) {
+  if (!have_dl()) return;
+
   EXPECT_EQ(2, wcwidth(L'ㅜ')); // Korean "crying" emoticon.
   EXPECT_EQ(2, wcwidth(L'ㅋ')); // Korean "laughing" emoticon.
 }
diff --git a/tests/wctype_test.cpp b/tests/wctype_test.cpp
index 1bc4128..7da53e0 100644
--- a/tests/wctype_test.cpp
+++ b/tests/wctype_test.cpp
@@ -20,6 +20,8 @@
 
 #include <gtest/gtest.h>
 
+#include "utils.h"
+
 class UtfLocale {
  public:
   UtfLocale() : l(newlocale(LC_ALL, "C.UTF-8", 0)) {}
@@ -27,12 +29,6 @@
   locale_t l;
 };
 
-// bionic's dlsym doesn't work in static binaries, so we can't access icu,
-// so any unicode test case will fail.
-static bool have_dl() {
-  return (dlopen("libc.so", 0) != nullptr);
-}
-
 static void TestIsWideFn(int fn(wint_t),
                          int fn_l(wint_t, locale_t),
                          const wchar_t* trues,