Merge "bionic: Add magic to abort message"
diff --git a/README.md b/README.md
index a6cf467..12c5235 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,17 @@
-Using bionic
-============
+# bionic
 
-See the [additional documentation](docs/).
+[bionic](https://en.wikipedia.org/wiki/Bionic_(software)) is Android's
+C library, math library, and dynamic linker.
 
-Working on bionic
-=================
+# Using bionic as an app developer
 
-What are the big pieces of bionic?
-----------------------------------
+See the [user documentation](docs/).
+
+# Working on bionic itself
+
+This documentation is about making changes to bionic itself.
+
+## What are the big pieces of bionic?
 
 #### libc/ --- libc.so, libc.a
 
@@ -51,10 +55,9 @@
 The `benchmarks/` directory contains benchmarks, with its own [documentation](benchmarks/README.md).
 
 
-What's in libc/?
-----------------
+## What's in libc/?
 
-<pre>
+```
 libc/
   arch-arm/
   arch-arm64/
@@ -69,12 +72,6 @@
     bionic/
       # Every architecture needs a handful of machine-specific assembler files.
       # They live here.
-    include/
-      machine/
-        # The majority of header files are actually in libc/include/, but many
-        # of them pull in a <machine/something.h> for things like limits,
-        # endianness, and how floating point numbers are represented. Those
-        # headers live here.
     string/
       # Most architectures have a handful of optional assembler files
       # implementing optimized versions of various routines. The <string.h>
@@ -141,11 +138,10 @@
   zoneinfo/
     # Android-format time zone data.
     # See 'Updating tzdata' later.
-</pre>
+```
 
 
-Adding libc wrappers for system calls
--------------------------------------
+## Adding libc wrappers for system calls
 
 The first question you should ask is "should I add a libc wrapper for
 this system call?". The answer is usually "no".
@@ -183,8 +179,7 @@
      correct system call is being made.)
 
 
-Updating kernel header files
-----------------------------
+## Updating kernel header files
 
 As mentioned above, this is currently a two-step process:
 
@@ -197,8 +192,7 @@
 `TARGET_DEVICE_KERNEL_HEADERS` and friends described in [config.mk](https://android.googlesource.com/platform/build/+/master/core/config.mk#186).
 
 
-Updating tzdata
----------------
+## Updating tzdata
 
 This is fully automated (and these days handled by the libcore team, because
 they own icu, and that needs to be updated in sync with bionic):
@@ -206,8 +200,7 @@
   1. Run update-tzdata.py in external/icu/tools/.
 
 
-Verifying changes
------------------
+## Verifying changes
 
 If you make a change that is likely to have a wide effect on the tree (such as a
 libc header change), you should run `make checkbuild`. A regular `make` will
@@ -218,8 +211,7 @@
 `make checkbuild` is enough.
 
 
-Running the tests
------------------
+## Running the tests
 
 The tests are all built from the tests/ directory.
 
@@ -285,8 +277,7 @@
     $ ./tests/run-on-host.sh glibc
 
 
-Gathering test coverage
------------------------
+## Gathering test coverage
 
 For either host or target coverage, you must first:
 
@@ -319,8 +310,7 @@
 The coverage report is now available at `covreport/index.html`.
 
 
-Attaching GDB to the tests
---------------------------
+## Attaching GDB to the tests
 
 Bionic's test runner will run each test in its own process by default to prevent
 tests failures from impacting other tests. This also has the added benefit of
@@ -330,7 +320,6 @@
 each test from being forked, run the tests with the flag `--no-isolate`.
 
 
-32-bit ABI bugs
----------------
+## 32-bit ABI bugs
 
 See [32-bit ABI bugs](docs/32-bit-abi.md).
diff --git a/docs/fdsan.md b/docs/fdsan.md
new file mode 100644
index 0000000..010a194
--- /dev/null
+++ b/docs/fdsan.md
@@ -0,0 +1,358 @@
+## fdsan
+
+[TOC]
+
+### Background
+*What problem is fdsan trying to solve? Why should I care?*
+
+fdsan (file descriptor sanitizer) detects mishandling of file descriptor ownership, which tend to manifest as *use-after-close* and *double-close*. These errors are direct analogues of the memory allocation *use-after-free* and *double-free* bugs, but tend to be much more difficult to diagnose and fix. With `malloc` and `free`, implementations have free reign to detect errors and abort on double free. File descriptors, on the other hand, are mandated by the C standard to be allocated with the lowest available number being returned for new allocations. As a result, many file descriptor bugs can *never* be noticed on the thread on which the error occurred, and will manifest as "impossible" behavior on another thread.
+
+For example, given two threads running the following code:
+```cpp
+void thread_one() {
+    int fd = open("/dev/null", O_RDONLY);
+    close(fd);
+    close(fd);
+}
+
+void thread_two() {
+    while (true) {
+        int fd = open("log", O_WRONLY | O_APPEND);
+        if (write(fd, "foo", 3) != 3) {
+            err(1, "write failed!");
+        }
+    }
+}
+```
+the following interleaving is possible:
+```cpp
+thread one                                thread two
+open("/dev/null", O_RDONLY) = 123
+close(123) = 0
+                                          open("log", O_WRONLY | APPEND) = 123
+close(123) = 0
+                                          write(123, "foo", 3) = -1 (EBADF)
+                                          err(1, "write failed!")
+```
+
+Assertion failures are probably the most innocuous result that can arise from these bugs: silent data corruption [[1](#footnotes), [2](#footnotes)] or security vulnerabilities are also possible (e.g. suppose thread two was saving user data to disk when a third thread came in and opened a socket to the Internet).
+
+### Design
+*What does fdsan do?*
+
+fdsan attempts to detect and/or prevent file descriptor mismanagement by enforcing file descriptor ownership. Like how most memory allocations can have their ownership handled by types such as `std::unique_ptr`, almost all file descriptors can be associated with a unique owner which is responsible for their closure. fdsan provides functions to associate a file descriptor with an owner; if someone tries to close a file descriptor that they don't own, depending on configuration, either a warning is emitted, or the process aborts.
+
+The way this is implemented is by providing functions to set a 64-bit closure tag on a file descriptor. The tag consists of an 8-bit type byte that identifies the type of the owner (`enum android_fdan_owner_type` in [`<android/fdsan.h>`](https://android.googlesource.com/platform/bionic/+/master/libc/include/android/fdsan.h)), and a 56-bit value. The value should ideally be something that uniquely identifies the object (object address for native objects and `System.identityHashCode` for Java objects), but in cases where it's hard to derive an identifier for the "owner" that should close a file descriptor, even using the same value for all file descriptors in the module can be useful, since it'll catch other code that closes your file descriptors.
+
+If a file descriptor that's been marked with a tag is closed with an incorrect tag, or without a tag, we know something has gone wrong, and can generate diagnostics or abort.
+
+### Enabling fdsan (as a user)
+*How do I use fdsan?*
+
+fdsan has four severity levels:
+ - disabled (`ANDROID_FDSAN_ERROR_LEVEL_DISABLED`)
+ - warn-once (`ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE`)
+   - Upon detecting an error, emit a warning to logcat, generate a tombstone, and then continue execution with fdsan disabled.
+ - warn-always (`ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS`)
+   - Same as warn-once, except without disabling after the first warning.
+ - fatal (`ANDROID_FDSAN_ERROR_LEVEL_FATAL`)
+   - Abort upon detecting an error.
+
+In Android Q, fdsan has a global default of warn-once. fdsan can be made more or less strict at runtime via the `android_fdsan_set_error_level` function in [`<android/fdsan.h>`](https://android.googlesource.com/platform/bionic/+/master/libc/include/android/fdsan.h).
+
+The likelihood of fdsan catching a file descriptor error is proportional to the percentage of file descriptors in your process that are tagged with an owner.
+
+### Using fdsan to fix a bug
+*No, really, how do I use fdsan?*
+
+Let's look at a simple contrived example that uses sleeps to force a particular interleaving of thread execution.
+
+```cpp
+#include <err.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <thread>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+
+using namespace std::chrono_literals;
+using std::this_thread::sleep_for;
+
+void victim() {
+  sleep_for(200ms);
+  int fd = dup(STDOUT_FILENO);
+  sleep_for(200ms);
+  ssize_t rc = write(fd, "good\n", 5);
+  if (rc == -1) {
+    err(1, "good failed to write?!");
+  }
+  close(fd);
+}
+
+void bystander() {
+  sleep_for(100ms);
+  int fd = dup(STDOUT_FILENO);
+  sleep_for(200ms);
+  close(fd);
+}
+
+void offender() {
+  int fd = dup(STDOUT_FILENO);
+  close(fd);
+  sleep_for(200ms);
+  close(fd);
+}
+
+int main() {
+  std::vector<std::thread> threads;
+  for (auto function : { victim, bystander, offender }) {
+    threads.emplace_back(function);
+  }
+  for (auto& thread : threads) {
+    thread.join();
+  }
+}
+```
+
+Running the program above will result in the `write` in `victim` failing, giving us the error:
+
+    fdsan_test: good failed to write?!: Bad file descriptor
+
+This implies that either we're accidentally closing out file descriptor too early, or someone else is helpfully closing it for us. Let's use `android::base::unique_fd` in `victim` to guard the file descriptor with fdsan:
+
+```diff
+--- a/fdsan_test.cpp
++++ b/fdsan_test.cpp
+@@ -12,13 +12,12 @@ using std::this_thread::sleep_for;
+
+ void victim() {
+   sleep_for(200ms);
+-  int fd = dup(STDOUT_FILENO);
++  android::base::unique_fd fd(dup(STDOUT_FILENO));
+   sleep_for(200ms);
+   ssize_t rc = write(fd, "good\n", 5);
+   if (rc == -1) {
+     err(1, "good failed to write?!");
+   }
+-  close(fd);
+ }
+
+ void bystander() {
+```
+
+Now that we've guarded the file descriptor with fdsan, we should be able to find where the double close is:
+
+```
+pid: 25587, tid: 25589, name: fdsan_test  >>> fdsan_test <<<
+signal 35 (<debuggerd signal>), code -1 (SI_QUEUE), fault addr --------
+Abort message: 'attempted to close file descriptor 3, expected to be unowned, actually owned by unique_fd 0x7bf15dc448'
+    x0  0000000000000000  x1  00000000000063f5  x2  0000000000000023  x3  0000007bf14de338
+    x4  0000007bf14de3b8  x5  3463643531666237  x6  3463643531666237  x7  3834346364353166
+    x8  00000000000000f0  x9  0000000000000000  x10 0000000000000059  x11 0000000000000035
+    x12 0000007bf1bebcfa  x13 0000007bf14ddf0a  x14 0000007bf14ddf0a  x15 0000000000000000
+    x16 0000007bf1c33048  x17 0000007bf1ba9990  x18 0000000000000000  x19 00000000000063f3
+    x20 00000000000063f5  x21 0000007bf14de588  x22 0000007bf1f1b864  x23 0000000000000001
+    x24 0000007bf14de130  x25 0000007bf13e1000  x26 0000007bf1f1f580  x27 0000005ab43ab8f0
+    x28 0000000000000000  x29 0000007bf14de400
+    sp  0000007bf14ddff0  lr  0000007bf1b5fd6c  pc  0000007bf1b5fd90
+
+backtrace:
+    #00 pc 0000000000008d90  /system/lib64/libc.so (fdsan_error(char const*, ...)+384)
+    #01 pc 0000000000008ba8  /system/lib64/libc.so (android_fdsan_close_with_tag+632)
+    #02 pc 00000000000092a0  /system/lib64/libc.so (close+16)
+    #03 pc 00000000000003e4  /system/bin/fdsan_test (bystander()+84)
+    #04 pc 0000000000000918  /system/bin/fdsan_test
+    #05 pc 000000000006689c  /system/lib64/libc.so (__pthread_start(void*)+36)
+    #06 pc 000000000000712c  /system/lib64/libc.so (__start_thread+68)
+```
+
+...in the obviously correct bystander? What's going on here?
+
+The reason for this is (hopefully!) not a bug in fdsan, and will commonly be seen when tracking down double-closes in processes that have sparse fdsan coverage. What actually happened is that the culprit closed `bystander`'s file descriptor between its open and close, which resulted in `bystander` being blamed for closing `victim`'s fd. If we store `bystander`'s fd in a `unique_fd` as well, we should get something more useful:
+```diff
+--- a/tmp/fdsan_test.cpp
++++ b/tmp/fdsan_test.cpp
+@@ -23,9 +23,8 @@ void victim() {
+
+ void bystander() {
+   sleep_for(100ms);
+-  int fd = dup(STDOUT_FILENO);
++  android::base::unique_fd fd(dup(STDOUT_FILENO));
+   sleep_for(200ms);
+-  close(fd);
+ }
+```
+giving us:
+```
+pid: 25779, tid: 25782, name: fdsan_test  >>> fdsan_test <<<
+signal 35 (<debuggerd signal>), code -1 (SI_QUEUE), fault addr --------
+Abort message: 'attempted to close file descriptor 3, expected to be unowned, actually owned by unique_fd 0x6fef9ff448'
+    x0  0000000000000000  x1  00000000000064b6  x2  0000000000000023  x3  0000006fef901338
+    x4  0000006fef9013b8  x5  3466663966656636  x6  3466663966656636  x7  3834346666396665
+    x8  00000000000000f0  x9  0000000000000000  x10 0000000000000059  x11 0000000000000039
+    x12 0000006ff0055cfa  x13 0000006fef900f0a  x14 0000006fef900f0a  x15 0000000000000000
+    x16 0000006ff009d048  x17 0000006ff0013990  x18 0000000000000000  x19 00000000000064b3
+    x20 00000000000064b6  x21 0000006fef901588  x22 0000006ff04ff864  x23 0000000000000001
+    x24 0000006fef901130  x25 0000006fef804000  x26 0000006ff0503580  x27 0000006368aa18f8
+    x28 0000000000000000  x29 0000006fef901400
+    sp  0000006fef900ff0  lr  0000006feffc9d6c  pc  0000006feffc9d90
+
+backtrace:
+    #00 pc 0000000000008d90  /system/lib64/libc.so (fdsan_error(char const*, ...)+384)
+    #01 pc 0000000000008ba8  /system/lib64/libc.so (android_fdsan_close_with_tag+632)
+    #02 pc 00000000000092a0  /system/lib64/libc.so (close+16)
+    #03 pc 000000000000045c  /system/bin/fdsan_test (offender()+68)
+    #04 pc 0000000000000920  /system/bin/fdsan_test
+    #05 pc 000000000006689c  /system/lib64/libc.so (__pthread_start(void*)+36)
+    #06 pc 000000000000712c  /system/lib64/libc.so (__start_thread+68)
+```
+
+Hooray!
+
+In a real application, things are probably not going to be as detectable or reproducible as our toy example, which is a good reason to try to maximize the usage of fdsan-enabled types like `unique_fd` and `ParcelFileDescriptor`, to improve the odds that double closes in other code get detected.
+
+### Enabling fdsan (as a C++ library implementer)
+
+fdsan operates via two main primitives. `android_fdsan_exchange_owner_tag` modifies a file descriptor's close tag, and `android_fdsan_close_with_tag` closes a file descriptor with its tag. In the `<android/fdsan.h>` header, these are marked with `__attribute__((weak))`, so instead of passing down the platform version from JNI, availability of the functions can be queried directly. An example implementation of unique_fd follows:
+
+```cpp
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <android/fdsan.h>
+#include <unistd.h>
+
+#include <utility>
+
+struct unique_fd {
+    unique_fd() = default;
+
+    explicit unique_fd(int fd) {
+        reset(fd);
+    }
+
+    unique_fd(const unique_fd& copy) = delete;
+    unique_fd(unique_fd&& move) {
+        *this = std::move(move);
+    }
+
+    ~unique_fd() {
+        reset();
+    }
+
+    unique_fd& operator=(const unique_fd& copy) = delete;
+    unique_fd& operator=(unique_fd&& move) {
+        if (this == &move) {
+            return *this;
+        }
+
+        reset();
+
+        if (move.fd_ != -1) {
+            fd_ = move.fd_;
+            move.fd_ = -1;
+
+            // Acquire ownership from the moved-from object.
+            exchange_tag(fd_, move.tag(), tag());
+        }
+
+        return *this;
+    }
+
+    int get() { return fd_; }
+
+    int release() {
+        if (fd_ == -1) {
+            return -1;
+        }
+
+        int fd = fd_;
+        fd_ = -1;
+
+        // Release ownership.
+        exchange_tag(fd, tag(), 0);
+        return fd;
+    }
+
+    void reset(int new_fd = -1) {
+        if (fd_ != -1) {
+            close(fd_, tag());
+            fd_ = -1;
+        }
+
+        if (new_fd != -1) {
+            fd_ = new_fd;
+
+            // Acquire ownership of the presumably unowned fd.
+            exchange_tag(fd_, 0, tag());
+        }
+    }
+
+  private:
+    int fd_ = -1;
+
+    // The obvious choice of tag to use is the address of the object.
+    uint64_t tag() {
+        return reinterpret_cast<uint64_t>(this);
+    }
+
+    // These functions are marked with __attribute__((weak)), so that their
+    // availability can be determined at runtime. These wrappers will use them
+    // if available, and fall back to no-ops or regular close on pre-Q devices.
+    static void exchange_tag(int fd, uint64_t old_tag, uint64_t new_tag) {
+        if (android_fdsan_exchange_owner_tag) {
+            android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
+        }
+    }
+
+    static int close(int fd, uint64_t tag) {
+        if (android_fdsan_close_with_tag) {
+            return android_fdsan_close_with_tag(fd, tag);
+        } else {
+            return ::close(fd);
+        }
+    }
+};
+```
+
+### Frequently seen bugs
+ * Native APIs not making it clear when they take ownership of a file descriptor. <br/>
+   * Solution: accept `unique_fd` instead of `int` in functions that take ownership.
+   * [Example one](https://android-review.googlesource.com/c/platform/system/core/+/721985), [two](https://android-review.googlesource.com/c/platform/frameworks/native/+/709451)
+ * Receiving a `ParcelFileDescriptor` via Intent, and then passing it into JNI code that ends up calling close on it. <br/>
+   * Solution: ¯\\\_(ツ)\_/¯. Use fdsan?
+   * [Example one](https://android-review.googlesource.com/c/platform/system/bt/+/710104), [two](https://android-review.googlesource.com/c/platform/frameworks/base/+/732305)
+
+### Footnotes
+1. [How To Corrupt An SQLite Database File](https://www.sqlite.org/howtocorrupt.html#_continuing_to_use_a_file_descriptor_after_it_has_been_closed)
+
+2. [<b><i>50%</i></b> of Facebook's iOS crashes caused by a file descriptor double close leading to SQLite database corruption](https://code.fb.com/ios/debugging-file-corruption-on-ios/)
diff --git a/docs/status.md b/docs/status.md
index d589721..c8c06c6 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -37,11 +37,17 @@
 
 Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/libc/libc.map.txt
 
-New libc functions in Q:
+New libc functions in Q (API level 29):
   * `timespec_get` (C11 `<time.h>` addition)
   * `res_randomid` (in `<resolv.h>`)
+  * `pthread_sigqueue` (GNU extension)
 
-New libc functions in P:
+New libc behavior in Q (API level 29):
+  * Whole printf family now supports the GNU `%m` extension, rather than a special-case hack in `syslog`
+  * `popen` now always uses `O_CLOEXEC`, not just with the `e` extension
+  * Bug fixes to handling of UTF-8 U+fffe/U+ffff and code points above U+10ffff
+
+New libc functions in P (API level 28):
   * `__freading`/`__fwriting` (completing <stdio_ext.h>)
   * `endhostent`/`endnetent`/`endprotoent`/`getnetent`/`getprotoent`/`sethostent`/`setnetent`/`setprotoent` (completing <netdb.h>)
   * `fexecve`
@@ -58,12 +64,12 @@
   * `swab`
   * `syncfs`
 
-New libc behavior in P:
+New libc behavior in P (API level 28):
   * `%C` and `%S` support in the printf family (previously only the wprintf family supported these)
   * `%mc`/`%ms`/`%m[` support in the scanf family
   * `%s` support in strptime (strftime already supported it)
 
-New libc functions in O:
+New libc functions in O (API level 26):
   * `sendto` FORTIFY support
   * `__system_property_read_callback`/`__system_property_wait`
   * legacy `bsd_signal`
@@ -86,18 +92,90 @@
   * `strtod_l`/`strtof_l`/`strtol_l`/`strtoul_l`
   * <wctype.h> `towctrans`/`towctrans_l`/`wctrans`/`wctrans_l`
 
-New libc functions in N:
+New libc functions in N (API level 24):
   * 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`
+  * <ifaddrs.h> `getifaddrs`/`freeifaddrs`/`if_freenameindex`/`if_nameindex`
   * `getgrgid_r`/`getgrnam_r`
   * GNU extensions `fileno_unlocked`/`strchrnul`
   * 32-bit `prlimit`
 
+New libc functions in M (API level 23):
+  * <dirent.h> `telldir`, `seekdir`.
+  * <malloc.h> `malloc_info`.
+  * <netdb.h> `gethostbyaddr_r`, `gethostbyname2_r`.
+  * <pthread.h> `pthread_rwlockattr_getkind_np`/`pthread_rwlockattr_setkind_np`.
+  * <pty.h> `forkpty`, `openpty`.
+  * <signal.h> `sigqueue`, `sigtimedwait`, `sigwaitinfo`.
+  * <stdio.h> `fmemopen`, `open_memstream`, `feof_unlocked`, `ferror_unlocked`, `clearerr_unlocked`.
+  * <stdio_ext.h> `__flbf`, `__freadable`, `__fsetlocking`, `__fwritable`, `__fbufsize`, `__fpending`, `_flushlbf`, `__fpurge`.
+  * <stdlib.h> `mkostemp`/`mkostemps`, `lcong48`.
+  * <string.h> `basename`, `strerror_l`, `strerror_r`, `mempcpy`.
+  * <sys/sysinfo.h> `get_nprocs_conf`/`get_nprocs`, `get_phys_pages`, `get_avphys_pages`.
+  * <sys/uio.h> `process_vm_readv`/`process_vm_writev`.
+  * `clock_getcpuclockid`, `login_tty`, `mkfifoat`, `posix_madvise`, `sethostname`, `strcasecmp_l`/`strncasecmp_l`.
+  * <wchar.h> `open_wmemstream`, `wcscasecmp_l`/`wcsncasecmp_l`, `wmempcpy`.
+  * all of <error.h>.
+  * re-introduced various <resolv.h> functions: `ns_format_ttl`, `ns_get16`, `ns_get32`, `ns_initparse`, `ns_makecanon`, `ns_msg_getflag`, `ns_name_compress`, `ns_name_ntol`, `ns_name_ntop`, `ns_name_pack`, `ns_name_pton`, `ns_name_rollback`, `ns_name_skip`, `ns_name_uncompress`, `ns_name_unpack`, `ns_parserr`, `ns_put16`, `ns_put32`, `ns_samename`, `ns_skiprr`, `ns_sprintrr`, and `ns_sprintrrf`.
+
+New libc functions in L (API level 21):
+  * <android/dlext.h>.
+  * <android/set_abort_message.h>.
+  * <arpa/inet.h> `inet_lnaof`, `inet_netof`, `inet_network`, `inet_makeaddr`.
+  * <wctype.h> `iswblank`.
+  * <ctype.h> `isalnum_l`, `isalpha_l`, `isblank_l`, `icntrl_l`, `isdigit_l`, `isgraph_l`, `islower_l`, `isprint_l`, `ispunct_l`, `isspace_l`, `isupper_l`, `isxdigit_l`, `_tolower`, `tolower_l`, `_toupper`, `toupper_l`.
+  * <fcntl.h> `fallocate`, `posix_fadvise`, `posix_fallocate`, `splice`, `tee`, `vmsplice`.
+  * <inttypes.h> `wcstoimax`, `wcstoumax`.
+  * <link.h> `dl_iterate_phdr`.
+  * <mntent.h> `setmntent`, `endmntent`, `getmntent_r`.
+  * <poll.h> `ppoll`.
+  * <pthread.h> `pthread_condattr_getclock`, `pthread_condattr_setclock`, `pthread_mutex_timedlock`, `pthread_gettid_np`.
+  * <sched.h> `setns`.
+  * <search.h> `insque`, `remque`, `lfind`, `lsearch`, `twalk`.
+  * <stdio.h> `dprintf`, `vdprintf`.
+  * <stdlib.h> `initstate`, `setstate`, `getprogname`/`setprogname`, `atof`/`strtof`, `at_quick_exit`/`_Exit`/`quick_exit`, `grantpt`, `mbtowc`/`wctomb`, `posix_openpt`, `rand_r`/`rand`/`random`/`srand`/`srandom`, `strtold_l`/`strtoll_l`/`strtoull_l`.
+  * <string.h> `strcoll_l`/`strxfrm_l`, `stpcpy`/`stpncpy`.
+  * <sys/resource.h> `prlimit`.
+  * <sys/socket.h> `accept4`, `sendmmsg`.
+  * <sys/stat.h> `mkfifo`/`mknodat`.
+  * <time.h> `strftime_l`.
+  * <unistd.h> `dup3`, `execvpe`, `getpagesize`, `linkat`/`symlinkat`/`readlinkat`, `truncate`.
+  * <wchar.h> `wcstof`, `vfwscanf`/`vswscanf`/`vwscanf`, `wcstold_l`/`wcstoll`/`wcstoll_l`/`wcstoull`/`wcstoull_l`, `mbsnrtowcs`/`wcsnrtombs`, `wcscoll_l`/`wcsxfrm_l`.
+  * <wctype.h> `iswalnum_l`/`iswalpha_l`/`iswblank_l`/`iswcntrl_l`/`iswctype_l`/`iswdigit_l`/`iswgraph_l`/`iswlower_l`/`iswprint_l`/`iswpunct_l`/`iswspace_l`/`iswupper_l`/`iswxdigit_l`, `wctype_l`, `towlower_l`/`towupper_l`.
+  * all of <fts.h>.
+  * all of <locale.h>.
+  * all of <sys/epoll.h>.
+  * all of <sys/fsuid.h>.
+  * all of <sys/inotify.h>.
+  * all of <uchar.h>.
+
+New libc functions in K (API level 19):
+  * <inttypes.h> `imaxabs`, `imaxdiv`.
+  * <stdlib.h> `abs`, `labs`, `llabs`.
+  * <sys/stat.h> `futimens`.
+  * all of <sys/statvfs.h>.
+  * all of <sys/swap.h>.
+  * all of <sys/timerfd.h>.
+
+New libc functions in J-MR2 (API level 18):
+  * <stdio.h> `getdelim` and `getline`.
+  * <sys/auxv.h> `getauxval`.
+  * <sys/signalfd.h> `signalfd`.
+
+New libc functions in J-MR1 (API level 17):
+  * <ftw.h>.
+  * <signal.h> `psiginfo` and `psignal`.
+  * `getsid`, `malloc_usable_size`, `mlockall`/`munlockall`, `posix_memalign`, `unshare`.
+
+New libc functions in J (API level 16):
+  * the <search.h> tree functions `tdelete`, `tdestroy`, `tfind`, and `tsearch`.
+  * `faccessat`, `readahead`, `tgkill`.
+  * all of <sys/xattr.h>.
+
 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
 
@@ -112,7 +190,19 @@
 
 0 remaining missing POSIX libm functions.
 
-19 new libm functions in O: complex trig/exp/log functions.
+New libm functions in O (API level 26):
+  * <complex.h> `clog`/`clogf`, `cpow`/`cpowf` functions.
+
+New libm functions in M (API level 23):
+  * <complex.h> `cabs`, `carg`, `cimag`, `cacos`, `cacosh`, `casin`, `casinh`, `catan`, `catanh`, `ccos`, `ccosh`, `cexp`, `conj`, `cproj`, `csin`, `csinh`, `csqrt`, `ctan`, `ctanh`, `creal`, `cabsf`, `cargf`, `cimagf`, `cacosf`, `cacoshf`, `casinf`, `casinhf`, `catanf`, `catanhf`, `ccosf`, `ccoshf`, `cexpf`, `conjf`, `cprojf`, `csinf`, `csinhf`, `csqrtf`, `ctanf`, `ctanhf`, `crealf`, `cabsl`, `cprojl`, `csqrtl`.
+  * <math.h> `lgammal_r`.
+
+New libm functions in L (API level 21):
+  * <complex.h> `cabsl`, `cprojl`, `csqrtl`.
+  * <math.h> `isinf`, `significandl`.
+
+New libm functions in J-MR2 (API level 18):
+  * <math.h> `log2`, `log2f`.
 
 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 61d00cd..fe65ace 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1456,6 +1456,7 @@
         "bionic/pthread_mutex.cpp",
         "bionic/pthread_once.cpp",
         "bionic/pthread_rwlock.cpp",
+        "bionic/pthread_sigqueue.cpp",
         "bionic/pthread_self.cpp",
         "bionic/pthread_setname_np.cpp",
         "bionic/pthread_setschedparam.cpp",
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index ee618b1..5e62c28 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -191,6 +191,28 @@
   bne __bionic_setjmp_checksum_mismatch
 #endif
 
+#if __has_feature(hwaddress_sanitizer)
+  stp x0, x30, [sp, #-16]!
+  .cfi_adjust_cfa_offset 16
+  .cfi_rel_offset x0, 0
+  .cfi_rel_offset x30, 8
+  mov x19, x1 // Save 'value'.
+
+  // load and unmangle destination SP
+  ldr x2, [x0, #(_JB_SIGFLAG * 8)]
+  bic x2, x2, #1
+  ldr x0, [x0, #(_JB_X30_SP  * 8 + 8)]
+  eor x0, x0, x2
+  bl __hwasan_handle_longjmp
+
+  mov x1, x19 // Restore 'value'.
+  // Restore original x0 and lr.
+  ldp x0, x30, [sp], #16
+  .cfi_adjust_cfa_offset -16
+  .cfi_restore x0
+  .cfi_restore x30
+#endif
+
   // Do we need to restore the signal mask?
   ldr x2, [x0, #(_JB_SIGFLAG * 8)]
   tbz w2, #0, 1f
diff --git a/libc/arch-arm64/generic/bionic/__memcpy_chk.S b/libc/arch-arm64/generic/bionic/__memcpy_chk.S
index 4217775..a6eeca4 100644
--- a/libc/arch-arm64/generic/bionic/__memcpy_chk.S
+++ b/libc/arch-arm64/generic/bionic/__memcpy_chk.S
@@ -30,8 +30,11 @@
 
 ENTRY(__memcpy_chk)
   cmp x2, x3
-  bls memcpy
+  // Direct b.ls memcpy may not have enough range
+  b.hi .L_memcpy_chk_fail
+  b memcpy
 
+.L_memcpy_chk_fail:
   // Preserve for accurate backtrace.
   stp x29, x30, [sp, -16]!
   .cfi_def_cfa_offset 16
diff --git a/libc/bionic/NetdClient.cpp b/libc/bionic/NetdClient.cpp
index a1071d2..966cbcc 100644
--- a/libc/bionic/NetdClient.cpp
+++ b/libc/bionic/NetdClient.cpp
@@ -24,6 +24,8 @@
 
 #include <dlfcn.h>
 #include <pthread.h>
+#include <string.h>
+#include <unistd.h>
 
 template <typename FunctionType>
 static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) {
@@ -35,6 +37,14 @@
 }
 
 static void netdClientInitImpl() {
+    // Prevent netd from looping back fwmarkd connections to itself. It would work, but it's
+    // a deadlock hazard and unnecessary overhead for the resolver.
+    if (getuid() == 0 && strcmp(getprogname(), "netd") == 0) {
+        async_safe_format_log(ANDROID_LOG_INFO, "netdClient",
+                              "Skipping libnetd_client init since *we* are netd");
+        return;
+    }
+
     void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
     if (netdClientHandle == NULL) {
         // If the library is not available, it's not an error. We'll just use
@@ -54,6 +64,6 @@
 
 extern "C" __LIBC_HIDDEN__ void netdClientInit() {
     if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) {
-        async_safe_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize netd_client");
+        async_safe_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize libnetd_client");
     }
 }
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index d2c99a5..c8bba01 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -32,32 +32,9 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
-// We call tgkill(2) directly instead of raise (or even the libc tgkill wrapper), to reduce the
-// number of uninteresting stack frames at the top of a crash.
-static inline __always_inline void inline_tgkill(pid_t pid, pid_t tid, int sig) {
-#if defined(__arm__)
-  register int r0 __asm__("r0") = pid;
-  register int r1 __asm__("r1") = tid;
-  register int r2 __asm__("r2") = sig;
-  register int r7 __asm__("r7") = __NR_tgkill;
-  __asm__("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r7) : "memory");
-#elif defined(__aarch64__)
-  register long x0 __asm__("x0") = pid;
-  register long x1 __asm__("x1") = tid;
-  register long x2 __asm__("x2") = sig;
-  register long x8 __asm__("x8") = __NR_tgkill;
-  __asm__("svc #0" : "=r"(x0) : "r"(x0), "r"(x1), "r"(x2), "r"(x8) : "memory");
-#else
-  syscall(__NR_tgkill, pid, tid, sig);
-#endif
-}
+#include "private/bionic_inline_raise.h"
 
 void abort() {
-  // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
-  // http://b/37769298
-  pid_t pid = syscall(__NR_getpid);
-  pid_t tid = syscall(__NR_gettid);
-
   // Don't block SIGABRT to give any signal handler a chance; we ignore
   // any errors -- X311J doesn't allow abort to return anyway.
   sigset64_t mask;
@@ -65,7 +42,7 @@
   sigdelset64(&mask, SIGABRT);
 
   sigprocmask64(SIG_SETMASK, &mask, nullptr);
-  inline_tgkill(pid, tid, SIGABRT);
+  inline_raise(SIGABRT);
 
   // If SIGABRT is ignored or it's caught and the handler returns,
   // remove the SIGABRT signal handler and raise SIGABRT again.
@@ -73,7 +50,7 @@
   sigaction64(SIGABRT, &sa, nullptr);
 
   sigprocmask64(SIG_SETMASK, &mask, nullptr);
-  inline_tgkill(pid, tid, SIGABRT);
+  inline_raise(SIGABRT);
 
   // If we get this far, just exit.
   _exit(127);
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 0f17184..31ffa96 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -43,6 +43,7 @@
 #include <sys/system_properties.h>
 
 #include "private/bionic_globals.h"
+#include "private/bionic_inline_raise.h"
 #include "pthread_internal.h"
 
 extern "C" int ___close(int fd);
@@ -176,12 +177,20 @@
     return;
   }
 
+  struct {
+    size_t size;
+    char buf[512];
+  } abort_message;
+
   va_list va;
   va_start(va, fmt);
   if (error_level == ANDROID_FDSAN_ERROR_LEVEL_FATAL) {
     async_safe_fatal_va_list("fdsan", fmt, va);
   } else {
     async_safe_format_log_va_list(ANDROID_LOG_ERROR, "fdsan", fmt, va);
+    size_t len =
+        async_safe_format_buffer_va_list(abort_message.buf, sizeof(abort_message.buf), fmt, va);
+    abort_message.size = len + sizeof(size_t);
   }
   va_end(va);
 
@@ -192,10 +201,11 @@
       __BIONIC_FALLTHROUGH;
     case ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS:
       // DEBUGGER_SIGNAL
-      raise(__SIGRTMIN + 3);
+      inline_raise(__SIGRTMIN + 3, &abort_message);
       break;
 
     case ANDROID_FDSAN_ERROR_LEVEL_FATAL:
+      inline_raise(SIGABRT);
       abort();
 
     case ANDROID_FDSAN_ERROR_LEVEL_DISABLED:
@@ -218,7 +228,7 @@
   return result;
 }
 
-static const char* __tag_to_type(uint64_t tag) {
+const char* android_fdsan_get_tag_type(uint64_t tag) {
   uint64_t type = tag >> 56;
   switch (type) {
     case ANDROID_FDSAN_OWNER_TYPE_FILE:
@@ -235,6 +245,10 @@
       return "RandomAccessFile";
     case ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR:
       return "ParcelFileDescriptor";
+    case ANDROID_FDSAN_OWNER_TYPE_SQLITE:
+      return "sqlite";
+    case ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE:
+      return "ART FdFile";
 
     case ANDROID_FDSAN_OWNER_TYPE_GENERIC_00:
     default:
@@ -251,7 +265,7 @@
   }
 }
 
-static uint64_t __tag_to_owner(uint64_t tag) {
+uint64_t android_fdsan_get_tag_value(uint64_t tag) {
   // Lop off the most significant byte and sign extend.
   return static_cast<uint64_t>(static_cast<int64_t>(tag << 8) >> 8);
 }
@@ -264,10 +278,10 @@
 
   uint64_t tag = expected_tag;
   if (!atomic_compare_exchange_strong(&fde->close_tag, &tag, 0)) {
-    const char* expected_type = __tag_to_type(expected_tag);
-    uint64_t expected_owner = __tag_to_owner(expected_tag);
-    const char* actual_type = __tag_to_type(tag);
-    uint64_t actual_owner = __tag_to_owner(tag);
+    const char* expected_type = android_fdsan_get_tag_type(expected_tag);
+    uint64_t expected_owner = android_fdsan_get_tag_value(expected_tag);
+    const char* actual_type = android_fdsan_get_tag_type(tag);
+    uint64_t actual_owner = android_fdsan_get_tag_value(tag);
     if (expected_tag && tag) {
       fdsan_error(
           "attempted to close file descriptor %d, "
@@ -297,6 +311,14 @@
   return rc;
 }
 
+uint64_t android_fdsan_get_owner_tag(int fd) {
+  FdEntry* fde = GetFdEntry(fd);
+  if (!fde) {
+    return 0;
+  }
+  return fde->close_tag;
+}
+
 void android_fdsan_exchange_owner_tag(int fd, uint64_t expected_tag, uint64_t new_tag) {
   FdEntry* fde = GetFdEntry(fd);
   if (!fde) {
@@ -309,18 +331,18 @@
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "owned by %s 0x%" PRIx64 ", was expected to be owned by %s 0x%" PRIx64,
-          fd, __tag_to_type(tag), __tag_to_owner(tag), __tag_to_type(expected_tag),
-          __tag_to_owner(expected_tag));
+          fd, android_fdsan_get_tag_type(tag), android_fdsan_get_tag_value(tag),
+          android_fdsan_get_tag_type(expected_tag), android_fdsan_get_tag_value(expected_tag));
     } else if (expected_tag && !tag) {
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "unowned, was expected to be owned by %s 0x%" PRIx64,
-          fd, __tag_to_type(expected_tag), __tag_to_owner(expected_tag));
+          fd, android_fdsan_get_tag_type(expected_tag), android_fdsan_get_tag_value(expected_tag));
     } else if (!expected_tag && tag) {
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "owned by %s 0x%" PRIx64 ", was expected to be unowned",
-          fd, __tag_to_type(tag), __tag_to_owner(tag));
+          fd, android_fdsan_get_tag_type(tag), android_fdsan_get_tag_value(tag));
     } else if (!expected_tag && !tag) {
       // This should never happen: our CAS failed, but expected == actual?
       async_safe_fatal(
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 98d1726..15366af 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <unistd.h>
 
 #include "pthread_internal.h"
@@ -39,7 +40,6 @@
 
 #include "private/bionic_defs.h"
 #include "private/bionic_macros.h"
-#include "private/bionic_prctl.h"
 #include "private/bionic_ssp.h"
 #include "private/bionic_tls.h"
 #include "private/ErrnoRestorer.h"
diff --git a/libc/bionic/pthread_sigqueue.cpp b/libc/bionic/pthread_sigqueue.cpp
new file mode 100644
index 0000000..34bda38
--- /dev/null
+++ b/libc/bionic/pthread_sigqueue.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "private/ErrnoRestorer.h"
+#include "pthread_internal.h"
+
+int pthread_sigqueue(pthread_t t, int sig, const union sigval value) {
+  ErrnoRestorer errno_restorer;
+
+  pid_t tid = pthread_gettid_np(t);
+  if (tid == -1) return ESRCH;
+
+  siginfo_t siginfo;
+  siginfo.si_code = SI_QUEUE;
+  siginfo.si_pid = getpid();
+  siginfo.si_uid = getuid();
+  siginfo.si_value = value;
+
+  return syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, sig, &siginfo) ? errno : 0;
+}
diff --git a/libc/bionic/syslog.cpp b/libc/bionic/syslog.cpp
index d1a0c5b..6b17d26 100644
--- a/libc/bionic/syslog.cpp
+++ b/libc/bionic/syslog.cpp
@@ -49,8 +49,6 @@
 }
 
 void vsyslog(int priority, const char* fmt, va_list args) {
-  int caller_errno = errno;
-
   // Check whether we're supposed to be logging messages of this priority.
   if ((syslog_priority_mask & LOG_MASK(LOG_PRI(priority))) == 0) {
     return;
@@ -75,48 +73,10 @@
     android_log_priority = ANDROID_LOG_DEBUG;
   }
 
-  // glibc's printf family support %m directly, but our BSD-based one doesn't.
-  // If the format string seems to contain "%m", rewrite it.
-  const char* log_fmt = fmt;
-  if (strstr(fmt, "%m") != nullptr) {
-    size_t dst_len = 1024;
-    char* dst = reinterpret_cast<char*>(malloc(dst_len));
-    log_fmt = dst;
-
-    const char* src = fmt;
-    for (; dst_len > 0 && *src != '\0'; ++src) {
-      if (*src == '%' && *(src + 1) == 'm') {
-        // Expand %m.
-        size_t n = strlcpy(dst, strerror(caller_errno), dst_len);
-        if (n >= dst_len) {
-          n = dst_len;
-        }
-        dst += n;
-        dst_len -= n;
-        ++src;
-      } else if (*src == '%' && *(src + 1) == '%') {
-        // We need to copy pairs of '%'s so the %m test works.
-        if (dst_len <= 2) {
-          break;
-        }
-        *dst++ = '%'; --dst_len;
-        *dst++ = '%'; --dst_len;
-        ++src;
-      } else {
-        *dst++ = *src; --dst_len;
-      }
-    }
-    *dst = '\0';
-  }
-
   // We can't let async_safe_format_log do the formatting because it doesn't support
   // all the printf functionality.
   char log_line[1024];
-  vsnprintf(log_line, sizeof(log_line), log_fmt, args);
-
-  if (log_fmt != fmt) {
-    free(const_cast<char*>(log_fmt));
-  }
+  vsnprintf(log_line, sizeof(log_line), fmt, args);
 
   async_safe_format_log(android_log_priority, log_tag, "%s", log_line);
 }
diff --git a/libc/include/alloca.h b/libc/include/alloca.h
index 0508d31..e05dea6 100644
--- a/libc/include/alloca.h
+++ b/libc/include/alloca.h
@@ -26,12 +26,21 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _ALLOCA_H
-#define _ALLOCA_H
+#pragma once
+
+/**
+ * @file alloca.h
+ * @brief Allocate space on the stack.
+ */
 
 #include <sys/cdefs.h>
 
+/**
+ * [alloca(3)](http://man7.org/linux/man-pages/man3/alloca.3.html) allocates space on the stack.
+ *
+ * New code should not use alloca because it cannot report failure.
+ * Use regular heap allocation instead.
+ *
+ * @return a pointer to the space on success, but has undefined behavior on failure.
+ */
 #define alloca(size)   __builtin_alloca(size)
-
-#endif /* _ALLOCA_H */
-
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 7a909d7..6ed6c0a 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -59,5 +59,6 @@
 #define __ANDROID_API_O__ 26
 #define __ANDROID_API_O_MR1__ 27
 #define __ANDROID_API_P__ 28
+#define __ANDROID_API_Q__ 29
 
 #endif
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index d0200c4..431e5ce 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -178,6 +178,8 @@
  * Opens the given library. The `__filename` and `__flags` arguments are
  * the same as for [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html),
  * with the Android-specific flags supplied via the `flags` member of `__info`.
+ *
+ * Available since API level 21.
  */
 void* android_dlopen_ext(const char* __filename, int __flags, const android_dlextinfo* __info)
   __INTRODUCED_IN(21);
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index 2aa29e3..dc2bbd5 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -97,17 +97,23 @@
   /* android::base::unique_fd */
   ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD = 3,
 
+  /* sqlite-owned file descriptors */
+  ANDROID_FDSAN_OWNER_TYPE_SQLITE = 4,
+
   /* java.io.FileInputStream */
-  ANDROID_FDSAN_OWNER_TYPE_FILEINPUTSTREAM = 251,
+  ANDROID_FDSAN_OWNER_TYPE_FILEINPUTSTREAM = 5,
 
   /* java.io.FileOutputStream */
-  ANDROID_FDSAN_OWNER_TYPE_FILEOUTPUTSTREAM = 252,
+  ANDROID_FDSAN_OWNER_TYPE_FILEOUTPUTSTREAM = 6,
 
   /* java.io.RandomAccessFile */
-  ANDROID_FDSAN_OWNER_TYPE_RANDOMACCESSFILE = 253,
+  ANDROID_FDSAN_OWNER_TYPE_RANDOMACCESSFILE = 7,
 
   /* android.os.ParcelFileDescriptor */
-  ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 254,
+  ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 8,
+
+  /* ART FdFile */
+  ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE = 9,
 };
 
 /*
@@ -129,6 +135,25 @@
  */
 int android_fdsan_close_with_tag(int fd, uint64_t tag) __INTRODUCED_IN_FUTURE __attribute__((__weak__));
 
+/*
+ * Get a file descriptor's current owner tag.
+ *
+ * Returns 0 for untagged and invalid file descriptors.
+ */
+uint64_t android_fdsan_get_owner_tag(int fd);
+
+/*
+ * Get an owner tag's string representation.
+ *
+ * The return value points to memory with static lifetime, do not attempt to modify it.
+ */
+const char* android_fdsan_get_tag_type(uint64_t tag);
+
+/*
+ * Get an owner tag's value, with the type masked off.
+ */
+uint64_t android_fdsan_get_tag_value(uint64_t tag);
+
 enum android_fdsan_error_level {
   // No errors.
   ANDROID_FDSAN_ERROR_LEVEL_DISABLED,
diff --git a/libc/include/android/legacy_fenv_inlines_arm.h b/libc/include/android/legacy_fenv_inlines_arm.h
index 6f2c959..5ec5582 100644
--- a/libc/include/android/legacy_fenv_inlines_arm.h
+++ b/libc/include/android/legacy_fenv_inlines_arm.h
@@ -1,141 +1,43 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 1. Redistributions of source code must retain the above copyright
+ *  * Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
- * 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.
+ *  * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.1 2004/06/06 10:03:59 das Exp $
  */
 
-#ifndef ANDROID_LEGACY_FENV_INLINES_ARM_H
-#define ANDROID_LEGACY_FENV_INLINES_ARM_H
+#pragma once
+
+/**
+ * @file legacy_fenv_inlines_arm.h
+ * @brief Inline ARM-specific definitions of fenv for old API levels.
+ */
 
 #include <sys/cdefs.h>
 
 #if __ANDROID_API__ < __ANDROID_API_L__ && defined(__arm__)
 
-#include <fenv.h>
+#define __BIONIC_FENV_INLINE static __inline
+#include <bits/fenv_inlines_arm.h>
 
-__BEGIN_DECLS
-
-#define FPSCR_RMODE_SHIFT 22
-
-static __inline int fegetenv(fenv_t* __envp) {
-  fenv_t _fpscr;
-  __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
-  *__envp = _fpscr;
-  return 0;
-}
-
-static __inline int fesetenv(const fenv_t* __envp) {
-  fenv_t _fpscr = *__envp;
-  __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
-  return 0;
-}
-
-static __inline int feclearexcept(int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  __fpscr &= ~__excepts;
-  fesetenv(&__fpscr);
-  return 0;
-}
-
-static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  *__flagp = __fpscr & __excepts;
-  return 0;
-}
-
-static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  __fpscr &= ~__excepts;
-  __fpscr |= *__flagp & __excepts;
-  fesetenv(&__fpscr);
-  return 0;
-}
-
-static __inline int feraiseexcept(int __excepts) {
-  fexcept_t __ex = __excepts;
-  fesetexceptflag(&__ex, __excepts);
-  return 0;
-}
-
-static __inline int fetestexcept(int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  return (__fpscr & __excepts);
-}
-
-static __inline int fegetround(void) {
-  fenv_t _fpscr;
-  fegetenv(&_fpscr);
-  return ((_fpscr >> FPSCR_RMODE_SHIFT) & 0x3);
-}
-
-static __inline int fesetround(int __round) {
-  fenv_t _fpscr;
-  fegetenv(&_fpscr);
-  _fpscr &= ~(0x3 << FPSCR_RMODE_SHIFT);
-  _fpscr |= (__round << FPSCR_RMODE_SHIFT);
-  fesetenv(&_fpscr);
-  return 0;
-}
-
-static __inline int feholdexcept(fenv_t* __envp) {
-  fenv_t __env;
-  fegetenv(&__env);
-  *__envp = __env;
-  __env &= ~FE_ALL_EXCEPT;
-  fesetenv(&__env);
-  return 0;
-}
-
-static __inline int feupdateenv(const fenv_t* __envp) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  fesetenv(__envp);
-  feraiseexcept(__fpscr & FE_ALL_EXCEPT);
-  return 0;
-}
-
-static __inline int feenableexcept(int __mask __unused) {
-  return -1;
-}
-
-static __inline int fedisableexcept(int __mask __unused) {
-  return 0;
-}
-
-static __inline int fegetexcept(void) {
-  return 0;
-}
-
-#undef FPSCR_RMODE_SHIFT
-
-__END_DECLS
-
-#endif /* __ANDROID_API__ < __ANDROID_API_L__ && defined(__arm__) */
-
-#endif /* ANDROID_LEGACY_FENV_INLINES_ARM_H */
+#endif
diff --git a/libc/include/android/legacy_fenv_inlines_mips.h b/libc/include/android/legacy_fenv_inlines_mips.h
index 43ad360..ccc824c 100644
--- a/libc/include/android/legacy_fenv_inlines_mips.h
+++ b/libc/include/android/legacy_fenv_inlines_mips.h
@@ -1,170 +1,43 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 1. Redistributions of source code must retain the above copyright
+ *  * Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
- * 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.
+ *  * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
  */
 
-#ifndef ANDROID_LEGACY_FENV_INLINES_MIPS_H
-#define ANDROID_LEGACY_FENV_INLINES_MIPS_H
+#pragma once
+
+/**
+ * @file legacy_fenv_inlines_mips.h
+ * @brief Inline MIPS-specific definitions of fenv for old API levels.
+ */
 
 #include <sys/cdefs.h>
 
 #if __ANDROID_API__ < __ANDROID_API_L__ && (defined(__mips__) && !defined(__LP64__))
 
-#include <fenv.h>
+#define __BIONIC_FENV_INLINE static __inline
+#include <bits/fenv_inlines_mips.h>
 
-__BEGIN_DECLS
-
-#define FCSR_CAUSE_SHIFT 10
-#define FCSR_ENABLE_SHIFT 5
-#define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT)
-
-#define FCSR_RMASK       0x3
-
-static __inline int fegetenv(fenv_t* __envp) {
-  fenv_t _fcsr = 0;
-#ifdef  __mips_hard_float
-  __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
 #endif
-  *__envp = _fcsr;
-  return 0;
-}
-
-static __inline int fesetenv(const fenv_t* __envp) {
-  fenv_t _fcsr = *__envp;
-#ifdef  __mips_hard_float
-  __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
-#endif
-  return 0;
-}
-
-static __inline int feclearexcept(int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  __excepts &= FE_ALL_EXCEPT;
-  __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT));
-  fesetenv(&__fcsr);
-  return 0;
-}
-
-static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
-  return 0;
-}
-
-static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  /* Ensure that flags are all legal */
-  __excepts &= FE_ALL_EXCEPT;
-  __fcsr &= ~__excepts;
-  __fcsr |= *__flagp & __excepts;
-  fesetenv(&__fcsr);
-  return 0;
-}
-
-static __inline int feraiseexcept(int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  /* Ensure that flags are all legal */
-  __excepts &= FE_ALL_EXCEPT;
-  /* Cause bit needs to be set as well for generating the exception*/
-  __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT);
-  fesetenv(&__fcsr);
-  return 0;
-}
-
-static __inline int fetestexcept(int __excepts) {
-  fexcept_t __FCSR;
-  fegetenv(&__FCSR);
-  return (__FCSR & __excepts & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetround(void) {
-  fenv_t _fcsr;
-  fegetenv(&_fcsr);
-  return (_fcsr & FCSR_RMASK);
-}
-
-static __inline int fesetround(int __round) {
-  fenv_t _fcsr;
-  fegetenv(&_fcsr);
-  _fcsr &= ~FCSR_RMASK;
-  _fcsr |= (__round & FCSR_RMASK);
-  fesetenv(&_fcsr);
-  return 0;
-}
-
-static __inline int feholdexcept(fenv_t* __envp) {
-  fenv_t __env;
-  fegetenv(&__env);
-  *__envp = __env;
-  __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK);
-  fesetenv(&__env);
-  return 0;
-}
-
-static __inline int feupdateenv(const fenv_t* __envp) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  fesetenv(__envp);
-  feraiseexcept(__fcsr & FE_ALL_EXCEPT);
-  return 0;
-}
-
-static __inline int feenableexcept(int __mask) {
-  fenv_t __old_fcsr, __new_fcsr;
-  fegetenv(&__old_fcsr);
-  __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT;
-  fesetenv(&__new_fcsr);
-  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fedisableexcept(int __mask) {
-  fenv_t __old_fcsr, __new_fcsr;
-  fegetenv(&__old_fcsr);
-  __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT);
-  fesetenv(&__new_fcsr);
-  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetexcept(void) {
-  fenv_t __fcsr;
-  fegetenv(&__fcsr);
-  return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT);
-}
-
-#undef FCSR_CAUSE_SHIFT
-#undef FCSR_ENABLE_SHIFT
-#undef FCSR_ENABLE_MASK
-#undef FCSR_RMASK
-
-__END_DECLS
-
-#endif /* __ANDROID_API__ < __ANDROID_API_L__ && (defined(__mips__) && !defined(__LP64__)) */
-
-#endif /* ANDROID_LEGACY_FENV_INLINES_MIPS_H */
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index 4e1a185..cab1156 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -17,15 +17,15 @@
 #ifndef ANDROID_VERSIONING_H
 #define ANDROID_VERSIONING_H
 
-#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" #api_level)))
+#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" __STRING(api_level))))
 #define __INTRODUCED_IN_FUTURE __attribute__((annotate("introduced_in_future")))
-#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" #api_level)))
-#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" #api_level)))
-#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" #api_level)))
-#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" #api_level)))
-#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" #api_level)))
-#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" #api_level)))
-#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" #api_level)))
+#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" __STRING(api_level))))
+#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" __STRING(api_level))))
+#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" __STRING(api_level))))
+#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" __STRING(api_level))))
+#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" __STRING(api_level))))
+#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" __STRING(api_level))))
+#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" __STRING(api_level))))
 
 #define __VERSIONER_NO_GUARD __attribute__((annotate("versioner_no_guard")))
 
diff --git a/libc/include/ar.h b/libc/include/ar.h
index 413f767..e79fa49 100644
--- a/libc/include/ar.h
+++ b/libc/include/ar.h
@@ -1,6 +1,3 @@
-/*	$OpenBSD: ar.h,v 1.3 2003/06/02 19:34:12 millert Exp $	*/
-/*	$NetBSD: ar.h,v 1.4 1994/10/26 00:55:43 cgd Exp $	*/
-
 /*-
  * Copyright (c) 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -40,29 +37,36 @@
  *	@(#)ar.h	8.2 (Berkeley) 1/21/94
  */
 
-#ifndef _AR_H_
-#define	_AR_H_
+#pragma once
+
+/**
+ * @file ar.h
+ * @brief Constants for reading/writing `.a` files.
+ */
 
 #include <sys/cdefs.h>
 
-/* Pre-4BSD archives had these magic numbers in them. */
-#define	OARMAG1	0177555
-#define	OARMAG2	0177545
+/** The magic at the beginning of a `.a` file. */
+#define ARMAG  "!<arch>\n"
+/** The length of the magic at the beginning of a `.a` file. */
+#define SARMAG  8
 
-#define	ARMAG		"!<arch>\n"	/* ar "magic number" */
-#define	SARMAG		8		/* strlen(ARMAG); */
-
-#define	AR_EFMT1	"#1/"		/* extended format #1 */
+/** The contents of every `ar_hdr::ar_fmag` field.*/
+#define	ARFMAG	"`\n"
 
 struct ar_hdr {
-	char ar_name[16];		/* name */
-	char ar_date[12];		/* modification time */
-	char ar_uid[6];			/* user id */
-	char ar_gid[6];			/* group id */
-	char ar_mode[8];		/* octal file permissions */
-	char ar_size[10];		/* size in bytes */
-#define	ARFMAG	"`\n"
-	char ar_fmag[2];		/* consistency check */
+  /* Name. */
+  char ar_name[16];
+  /* Modification time. */
+  char ar_date[12];
+  /** User id. */
+  char ar_uid[6];
+  /** Group id. */
+  char ar_gid[6];
+  /** Octal file permissions. */
+  char ar_mode[8];
+  /** Size in bytes. */
+  char ar_size[10];
+  /** Consistency check. Always contains `ARFMAG`. */
+  char ar_fmag[2];
 };
-
-#endif /* !_AR_H_ */
diff --git a/libc/include/assert.h b/libc/include/assert.h
index 7a9d84d..79e7b86 100644
--- a/libc/include/assert.h
+++ b/libc/include/assert.h
@@ -32,7 +32,10 @@
  * SUCH DAMAGE.
  */
 
-/*
+/**
+ * @file assert.h
+ * @brief Assertions.
+ *
  * There's no include guard in this file because <assert.h> may usefully be
  * included multiple times, with and without NDEBUG defined.
  */
@@ -42,6 +45,7 @@
 #undef assert
 #undef __assert_no_op
 
+/** Internal implementation detail. Do not use. */
 #define __assert_no_op __BIONIC_CAST(static_cast, void, 0)
 
 #ifdef NDEBUG
@@ -50,6 +54,12 @@
 # if defined(__cplusplus) || __STDC_VERSION__ >= 199901L
 #  define assert(e) ((e) ? __assert_no_op : __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, #e))
 # else
+/**
+ * assert() aborts the program after logging an error message, if the
+ * expression evaluates to false.
+ *
+ * On Android, the error goes to both stderr and logcat.
+ */
 #  define assert(e) ((e) ? __assert_no_op : __assert(__FILE__, __LINE__, #e))
 # endif
 #endif
@@ -60,6 +70,17 @@
 #endif
 
 __BEGIN_DECLS
+
+/**
+ * __assert() is called by assert() on failure. Most users want assert()
+ * instead, but this can be useful for reporting other failures.
+ */
 void __assert(const char* __file, int __line, const char* __msg) __noreturn;
+
+/**
+ * __assert2() is called by assert() on failure. Most users want assert()
+ * instead, but this can be useful for reporting other failures.
+ */
 void __assert2(const char* __file, int __line, const char* __function, const char* __msg) __noreturn;
+
 __END_DECLS
diff --git a/libc/include/bits/fenv_arm.h b/libc/include/bits/fenv_arm.h
index 042fec3..0cd4844 100644
--- a/libc/include/bits/fenv_arm.h
+++ b/libc/include/bits/fenv_arm.h
@@ -26,8 +26,7 @@
  * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
  */
 
-#ifndef _BITS_FENV_ARM_H_
-#define _BITS_FENV_ARM_H_
+#pragma once
 
 #include <sys/types.h>
 
@@ -73,5 +72,3 @@
 #define FE_TOWARDZERO 0x3
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/bits/fenv_inlines_arm.h b/libc/include/bits/fenv_inlines_arm.h
new file mode 100644
index 0000000..e8b89ea
--- /dev/null
+++ b/libc/include/bits/fenv_inlines_arm.h
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.1 2004/06/06 10:03:59 das Exp $
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#if defined(__arm__)
+
+#if !defined(__BIONIC_FENV_INLINE)
+#define __BIONIC_FENV_INLINE static __inline
+#endif
+
+#include <bits/fenv_arm.h>
+
+__BEGIN_DECLS
+
+#define FPSCR_RMODE_SHIFT 22
+
+__BIONIC_FENV_INLINE int fegetenv(fenv_t* __envp) {
+  fenv_t _fpscr;
+  __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
+  *__envp = _fpscr;
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetenv(const fenv_t* __envp) {
+  fenv_t _fpscr = *__envp;
+  __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feclearexcept(int __excepts) {
+  fexcept_t __fpscr;
+  fegetenv(&__fpscr);
+  __fpscr &= ~__excepts;
+  fesetenv(&__fpscr);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fpscr;
+  fegetenv(&__fpscr);
+  *__flagp = __fpscr & __excepts;
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fpscr;
+  fegetenv(&__fpscr);
+  __fpscr &= ~__excepts;
+  __fpscr |= *__flagp & __excepts;
+  fesetenv(&__fpscr);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feraiseexcept(int __excepts) {
+  fexcept_t __ex = __excepts;
+  fesetexceptflag(&__ex, __excepts);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fetestexcept(int __excepts) {
+  fexcept_t __fpscr;
+  fegetenv(&__fpscr);
+  return (__fpscr & __excepts);
+}
+
+__BIONIC_FENV_INLINE int fegetround(void) {
+  fenv_t _fpscr;
+  fegetenv(&_fpscr);
+  return ((_fpscr >> FPSCR_RMODE_SHIFT) & 0x3);
+}
+
+__BIONIC_FENV_INLINE int fesetround(int __round) {
+  fenv_t _fpscr;
+  fegetenv(&_fpscr);
+  _fpscr &= ~(0x3 << FPSCR_RMODE_SHIFT);
+  _fpscr |= (__round << FPSCR_RMODE_SHIFT);
+  fesetenv(&_fpscr);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feholdexcept(fenv_t* __envp) {
+  fenv_t __env;
+  fegetenv(&__env);
+  *__envp = __env;
+  __env &= ~FE_ALL_EXCEPT;
+  fesetenv(&__env);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feupdateenv(const fenv_t* __envp) {
+  fexcept_t __fpscr;
+  fegetenv(&__fpscr);
+  fesetenv(__envp);
+  feraiseexcept(__fpscr & FE_ALL_EXCEPT);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feenableexcept(int __mask __unused) {
+  return -1;
+}
+
+__BIONIC_FENV_INLINE int fedisableexcept(int __mask __unused) {
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fegetexcept(void) {
+  return 0;
+}
+
+#undef FPSCR_RMODE_SHIFT
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/fenv_inlines_mips.h b/libc/include/bits/fenv_inlines_mips.h
new file mode 100644
index 0000000..dc7f707
--- /dev/null
+++ b/libc/include/bits/fenv_inlines_mips.h
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#if defined(__mips__)
+
+#if !defined(__BIONIC_FENV_INLINE)
+#define __BIONIC_FENV_INLINE static __inline
+#endif
+
+#include <bits/fenv_mips.h>
+
+__BEGIN_DECLS
+
+#define FCSR_CAUSE_SHIFT 10
+#define FCSR_ENABLE_SHIFT 5
+#define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT)
+
+#define FCSR_RMASK       0x3
+
+__BIONIC_FENV_INLINE int fegetenv(fenv_t* __envp) {
+  fenv_t _fcsr = 0;
+#ifdef  __mips_hard_float
+  __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
+#endif
+  *__envp = _fcsr;
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetenv(const fenv_t* __envp) {
+  fenv_t _fcsr = *__envp;
+#ifdef  __mips_hard_float
+  __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
+#endif
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feclearexcept(int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  __excepts &= FE_ALL_EXCEPT;
+  __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT));
+  fesetenv(&__fcsr);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  /* Ensure that flags are all legal */
+  __excepts &= FE_ALL_EXCEPT;
+  __fcsr &= ~__excepts;
+  __fcsr |= *__flagp & __excepts;
+  fesetenv(&__fcsr);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feraiseexcept(int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  /* Ensure that flags are all legal */
+  __excepts &= FE_ALL_EXCEPT;
+  /* Cause bit needs to be set as well for generating the exception*/
+  __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT);
+  fesetenv(&__fcsr);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int fetestexcept(int __excepts) {
+  fexcept_t __FCSR;
+  fegetenv(&__FCSR);
+  return (__FCSR & __excepts & FE_ALL_EXCEPT);
+}
+
+__BIONIC_FENV_INLINE int fegetround(void) {
+  fenv_t _fcsr;
+  fegetenv(&_fcsr);
+  return (_fcsr & FCSR_RMASK);
+}
+
+__BIONIC_FENV_INLINE int fesetround(int __round) {
+  fenv_t _fcsr;
+  fegetenv(&_fcsr);
+  _fcsr &= ~FCSR_RMASK;
+  _fcsr |= (__round & FCSR_RMASK);
+  fesetenv(&_fcsr);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feholdexcept(fenv_t* __envp) {
+  fenv_t __env;
+  fegetenv(&__env);
+  *__envp = __env;
+  __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK);
+  fesetenv(&__env);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feupdateenv(const fenv_t* __envp) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  fesetenv(__envp);
+  feraiseexcept(__fcsr & FE_ALL_EXCEPT);
+  return 0;
+}
+
+__BIONIC_FENV_INLINE int feenableexcept(int __mask) {
+  fenv_t __old_fcsr, __new_fcsr;
+  fegetenv(&__old_fcsr);
+  __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT;
+  fesetenv(&__new_fcsr);
+  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+__BIONIC_FENV_INLINE int fedisableexcept(int __mask) {
+  fenv_t __old_fcsr, __new_fcsr;
+  fegetenv(&__old_fcsr);
+  __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT);
+  fesetenv(&__new_fcsr);
+  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+__BIONIC_FENV_INLINE int fegetexcept(void) {
+  fenv_t __fcsr;
+  fegetenv(&__fcsr);
+  return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT);
+}
+
+#undef FCSR_CAUSE_SHIFT
+#undef FCSR_ENABLE_SHIFT
+#undef FCSR_ENABLE_MASK
+#undef FCSR_RMASK
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/fenv_mips.h b/libc/include/bits/fenv_mips.h
index 9298e86..dafccac 100644
--- a/libc/include/bits/fenv_mips.h
+++ b/libc/include/bits/fenv_mips.h
@@ -68,8 +68,7 @@
  * 11 - rounding (down)toward minus infinity (RM)
  */
 
-#ifndef _BITS_FENV_MIPS_H_
-#define _BITS_FENV_MIPS_H_
+#pragma once
 
 #include <sys/types.h>
 
@@ -94,5 +93,3 @@
 #define FE_DOWNWARD   0x0003
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/bits/fenv_x86.h b/libc/include/bits/fenv_x86.h
index 75b109b..3381cea 100644
--- a/libc/include/bits/fenv_x86.h
+++ b/libc/include/bits/fenv_x86.h
@@ -26,8 +26,7 @@
  * $FreeBSD: src/lib/msun/i387/fenv.h,v 1.4 2005/03/17 22:21:46 das Exp $
  */
 
-#ifndef _BITS_FENV_X86_H_
-#define _BITS_FENV_X86_H_
+#pragma once
 
 #include <sys/types.h>
 
@@ -65,5 +64,3 @@
 #define FE_TOWARDZERO 0x0c00
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/bits/fenv_x86_64.h b/libc/include/bits/fenv_x86_64.h
index 006d19e..ddb6a5c 100644
--- a/libc/include/bits/fenv_x86_64.h
+++ b/libc/include/bits/fenv_x86_64.h
@@ -24,8 +24,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _BITS_FENV_X86_64_H_
-#define _BITS_FENV_X86_64_H_
+#pragma once
 
 #include <sys/types.h>
 
@@ -91,5 +90,3 @@
 typedef __uint32_t fexcept_t;
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/byteswap.h b/libc/include/byteswap.h
index 0838e6c..0773426 100644
--- a/libc/include/byteswap.h
+++ b/libc/include/byteswap.h
@@ -26,14 +26,30 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _BYTESWAP_H_
-#define _BYTESWAP_H_
+#pragma once
+
+/**
+ * @file byteswap.h
+ * @brief Byte-swapping macros.
+ */
 
 #include <sys/cdefs.h>
 #include <sys/endian.h>
 
+/**
+ * [bswap_16(3)](http://man7.org/linux/man-pages/man3/bswap_16.3.html) swaps the bytes in a
+ * 16-bit value.
+ */
 #define bswap_16(x) __swap16(x)
-#define bswap_32(x) __swap32(x)
-#define bswap_64(x) __swap64(x)
 
-#endif /* _BYTESWAP_H_ */
+/**
+ * [bswap_32(3)](http://man7.org/linux/man-pages/man3/bswap_32.3.html) swaps the bytes in a
+ * 32-bit value.
+ */
+#define bswap_32(x) __swap32(x)
+
+/**
+ * [bswap_64(3)](http://man7.org/linux/man-pages/man3/bswap_64.3.html) swaps the bytes in a
+ * 64-bit value.
+ */
+#define bswap_64(x) __swap64(x)
diff --git a/libc/include/cpio.h b/libc/include/cpio.h
index ceeeb87..c2c20c2 100644
--- a/libc/include/cpio.h
+++ b/libc/include/cpio.h
@@ -26,32 +26,55 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _CPIO_H_
-#define _CPIO_H_
+#pragma once
+
+/**
+ * @file cpio.h
+ * @brief Constants for reading/writing cpio files.
+ */
 
 #include <sys/cdefs.h>
 
+/** Readable by user mode field bit. */
 #define C_IRUSR 0000400
+/** Writable by user mode field bit. */
 #define C_IWUSR 0000200
+/** Executable by user mode field bit. */
 #define C_IXUSR 0000100
+/** Readable by group mode field bit. */
 #define C_IRGRP 0000040
+/** Writable by group mode field bit. */
 #define C_IWGRP 0000020
+/** Executable by group mode field bit. */
 #define C_IXGRP 0000010
+/** Readable by other mode field bit. */
 #define C_IROTH 0000004
+/** Writable by other mode field bit. */
 #define C_IWOTH 0000002
+/** Executable by other mode field bit. */
 #define C_IXOTH 0000001
+/** Set-UID mode field bit. */
 #define C_ISUID 0004000
+/** Set-GID mode field bit. */
 #define C_ISGID 0002000
+/** Directory restricted deletion mode field bit. */
 #define C_ISVTX 0001000
+/** Directory mode field type. */
 #define C_ISDIR 0040000
+/** FIFO mode field type. */
 #define C_ISFIFO 0010000
+/** Regular file mode field type. */
 #define C_ISREG 0100000
+/** Block special file mode field type. */
 #define C_ISBLK 0060000
+/** Character special file mode field type. */
 #define C_ISCHR 0020000
+/** Reserved. */
 #define C_ISCTG 0110000
+/** Symbolic link mode field type. */
 #define C_ISLNK 0120000
+/** Socket mode field type. */
 #define C_ISSOCK 0140000
 
+/** cpio file magic. */
 #define MAGIC "070707"
-
-#endif /* _CPIO_H_ */
diff --git a/libc/include/endian.h b/libc/include/endian.h
index 65e2930..ed237b9 100644
--- a/libc/include/endian.h
+++ b/libc/include/endian.h
@@ -1 +1,10 @@
+#pragma once
+
+/*
+ * @file endian.h
+ * @brief Historical alternative to `<sys/endian.h>`.
+ *
+ * New code should use `<sys/endian.h>` directly.
+ */
+
 #include <sys/endian.h>
diff --git a/libc/include/err.h b/libc/include/err.h
index a64d01d..e91dac9 100644
--- a/libc/include/err.h
+++ b/libc/include/err.h
@@ -1,6 +1,3 @@
-/*	$OpenBSD: err.h,v 1.10 2006/01/06 18:53:04 millert Exp $	*/
-/*	$NetBSD: err.h,v 1.11 1994/10/26 00:55:52 cgd Exp $	*/
-
 /*-
  * Copyright (c) 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -32,8 +29,12 @@
  *	@(#)err.h	8.1 (Berkeley) 6/2/93
  */
 
-#ifndef _ERR_H_
-#define _ERR_H_
+#pragma once
+
+/**
+ * @file err.h
+ * @brief BSD error reporting functions. See `<error.h>` for the GNU equivalent.
+ */
 
 #include <stdarg.h>
 #include <sys/cdefs.h>
@@ -41,15 +42,76 @@
 
 __BEGIN_DECLS
 
+/**
+ * [err(3)](http://man7.org/linux/man-pages/man3/err.3.html) outputs the program name,
+ * the printf()-like formatted message, and the result of strerror() if `errno` is non-zero.
+ *
+ * Calls exit() with `__status`.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 __noreturn void err(int __status, const char* __fmt, ...) __printflike(2, 3);
+
+/**
+ * [verr(3)](http://man7.org/linux/man-pages/man3/verr.3.html) outputs the program name,
+ * the vprintf()-like formatted message, and the result of strerror() if `errno` is non-zero.
+ *
+ * Calls exit() with `__status`.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 __noreturn void verr(int __status, const char* __fmt, va_list __args) __printflike(2, 0);
+
+/**
+ * [errx(3)](http://man7.org/linux/man-pages/man3/errx.3.html) outputs the program name, and
+ * the printf()-like formatted message.
+ *
+ * Calls exit() with `__status`.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 __noreturn void errx(int __status, const char* __fmt, ...) __printflike(2, 3);
+
+/**
+ * [verrx(3)](http://man7.org/linux/man-pages/man3/err.3.html) outputs the program name, and
+ * the vprintf()-like formatted message.
+ *
+ * Calls exit() with `__status`.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 __noreturn void verrx(int __status, const char* __fmt, va_list __args) __printflike(2, 0);
+
+/**
+ * [warn(3)](http://man7.org/linux/man-pages/man3/warn.3.html) outputs the program name,
+ * the printf()-like formatted message, and the result of strerror() if `errno` is non-zero.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 void warn(const char* __fmt, ...) __printflike(1, 2);
+
+/**
+ * [vwarn(3)](http://man7.org/linux/man-pages/man3/vwarn.3.html) outputs the program name,
+ * the vprintf()-like formatted message, and the result of strerror() if `errno` is non-zero.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 void vwarn(const char* __fmt, va_list __args) __printflike(1, 0);
+
+/**
+ * [warnx(3)](http://man7.org/linux/man-pages/man3/warnx.3.html) outputs the program name, and
+ * the printf()-like formatted message.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 void warnx(const char* __fmt, ...) __printflike(1, 2);
+
+/**
+ * [vwarnx(3)](http://man7.org/linux/man-pages/man3/warn.3.html) outputs the program name, and
+ * the vprintf()-like formatted message.
+ *
+ * New code should consider error() in `<error.h>`.
+ */
 void vwarnx(const char* __fmt, va_list __args) __printflike(1, 0);
 
 __END_DECLS
-
-#endif /* !_ERR_H_ */
diff --git a/libc/include/errno.h b/libc/include/errno.h
index cbe67fa..b6a4c7e 100644
--- a/libc/include/errno.h
+++ b/libc/include/errno.h
@@ -26,24 +26,37 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _ERRNO_H
-#define _ERRNO_H
+#pragma once
+
+/**
+ * @file errno.h
+ * @brief Standard C error handling.
+ */
 
 #include <sys/cdefs.h>
 #include <linux/errno.h>
 
 __BEGIN_DECLS
 
-/* On Linux, ENOTSUP and EOPNOTSUPP are the same despite POSIX saying they should be distinct. */
 #ifndef ENOTSUP
+/** On Linux, ENOTSUP and EOPNOTSUPP are the same despite POSIX saying they should be distinct. */
 #define ENOTSUP EOPNOTSUPP
 #endif
 
+/**
+ * Returns the address of the calling thread's `errno` storage.
+ * Non-portable and should not be used directly. Use `errno` instead.
+ *
+ * @private
+ */
 int* __errno(void) __attribute_const__;
+
+/**
+ * [errno(3)](http://man7.org/linux/man-pages/man3/errno.3.html) is the last error on the calling
+ * thread.
+ */
 #define errno (*__errno())
 
 __END_DECLS
 
 #include <android/legacy_errno_inlines.h>
-
-#endif /* _ERRNO_H */
diff --git a/libc/include/error.h b/libc/include/error.h
index d612994..036a831 100644
--- a/libc/include/error.h
+++ b/libc/include/error.h
@@ -26,21 +26,60 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _ERROR_H
-#define _ERROR_H 1
+#pragma once
+
+/**
+ * @file error.h
+ * @brief GNU error reporting functions.
+ */
 
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
+/**
+ * [error_print_progname(3)](http://man7.org/linux/man-pages/man3/error_print_progname.3.html) is
+ * a function pointer that, if non-null, is called by error() instead of prefixing errors with the
+ * program name.
+ *
+ * Available since API level 23.
+ */
 extern void (*error_print_progname)(void) __INTRODUCED_IN(23);
+
+/**
+ * [error_message_count(3)](http://man7.org/linux/man-pages/man3/error_message_count.3.html) is
+ * a global count of the number of calls to error() and error_at_line().
+ *
+ * Available since API level 23.
+ */
 extern unsigned int error_message_count __INTRODUCED_IN(23);
+
+/**
+ * [error_one_per_line(3)](http://man7.org/linux/man-pages/man3/error_one_per_line.3.html) is
+ * a global flag that if non-zero disables printing multiple errors with the same filename and
+ * line number.
+ *
+ * Available since API level 23.
+ */
 extern int error_one_per_line __INTRODUCED_IN(23);
 
+/**
+ * [error(3)](http://man7.org/linux/man-pages/man3/error.3.html) formats the given printf()-like
+ * error message, preceded by the program name. Calls exit if `__status` is non-zero, and appends
+ * the result of strerror() if `__errno` is non-zero.
+ *
+ * Available since API level 23.
+ */
 void error(int __status, int __errno, const char* __fmt, ...) __printflike(3, 4) __INTRODUCED_IN(23);
-void error_at_line(int __status, int __errno, const char* __filename, unsigned int __line_number, const char* __fmt, ...)
-    __printflike(5, 6) __INTRODUCED_IN(23);
+
+/**
+ * [error_at_line(3)](http://man7.org/linux/man-pages/man3/error_at_line.3.html) formats the given
+ * printf()-like error message, preceded by the program name and the given filename and line number.
+ * Calls exit if `__status` is non-zero, and appends the result of strerror() if `__errno` is
+ * non-zero.
+ *
+ * Available since API level 23.
+ */
+void error_at_line(int __status, int __errno, const char* __filename, unsigned int __line_number, const char* __fmt, ...) __printflike(5, 6) __INTRODUCED_IN(23);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/features.h b/libc/include/features.h
index a279c7f..a915fe7 100644
--- a/libc/include/features.h
+++ b/libc/include/features.h
@@ -26,10 +26,11 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _FEATURES_H_
-#define _FEATURES_H_
+#pragma once
 
-/* Our <features.h> macro fun is all in <sys/cdefs.h>. */
+/**
+ * @file features.h
+ * @brief Synonym for `<sys/cdefs.h>` for source compatibility with glibc.
+ */
+
 #include <sys/cdefs.h>
-
-#endif /* _FEATURES_H_ */
diff --git a/libc/include/fenv.h b/libc/include/fenv.h
index 2b607f5..886612e 100644
--- a/libc/include/fenv.h
+++ b/libc/include/fenv.h
@@ -27,8 +27,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef _FENV_H_
-#define _FENV_H_
+#pragma once
 
 #include <sys/cdefs.h>
 
@@ -79,11 +78,12 @@
  * environment, namely fesetenv() and feupdateenv().
  */
 extern const fenv_t __fe_dfl_env;
-#define FE_DFL_ENV  (&__fe_dfl_env)
+#define FE_DFL_ENV (&__fe_dfl_env)
 
 __END_DECLS
 
+#if defined(__arm__)
 #include <android/legacy_fenv_inlines_arm.h>
+#elif defined(__mips__)
 #include <android/legacy_fenv_inlines_mips.h>
-
-#endif  /* ! _FENV_H_ */
+#endif
diff --git a/libc/include/fnmatch.h b/libc/include/fnmatch.h
index 3fcc665..1788a27 100644
--- a/libc/include/fnmatch.h
+++ b/libc/include/fnmatch.h
@@ -26,27 +26,45 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _FNMATCH_H
-#define _FNMATCH_H
+#pragma once
+
+/**
+ * @file fnmatch.h
+ * @brief Filename matching.
+ */
 
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
-#define FNM_NOMATCH      1     /* Match failed. */
-#define FNM_NOSYS        2     /* Function not supported (unused). */
+/** Returned by fnmatch() if matching failed. */
+#define FNM_NOMATCH 1
 
-#define FNM_NOESCAPE     0x01        /* Disable backslash escaping. */
-#define FNM_PATHNAME     0x02        /* Slash must be matched by slash. */
-#define FNM_PERIOD       0x04        /* Period must be matched by period. */
-#define FNM_LEADING_DIR  0x08        /* Ignore /<tail> after Imatch. */
-#define FNM_CASEFOLD     0x10        /* Case insensitive search. */
+/** Returned by fnmatch() if the function is not supported. This is never returned on Android. */
+#define FNM_NOSYS 2
 
+/** fnmatch() flag to disable backslash escaping. */
+#define FNM_NOESCAPE     0x01
+/** fnmatch() flag to ensure that slashes must be matched by slashes. */
+#define FNM_PATHNAME     0x02
+/** fnmatch() flag to ensure that periods must be matched by periods. */
+#define FNM_PERIOD       0x04
+/** fnmatch() flag to ignore /... after a match. */
+#define FNM_LEADING_DIR  0x08
+/** fnmatch() flag for a case-insensitive search. */
+#define FNM_CASEFOLD     0x10
+
+/** Synonym for `FNM_CASEFOLD`: case-insensitive search. */
 #define FNM_IGNORECASE   FNM_CASEFOLD
+/** Synonym for `FNM_PATHNAME`: slashes must be matched by slashes. */
 #define FNM_FILE_NAME    FNM_PATHNAME
 
-int fnmatch(const char* __pattern, const char* __string, int __flags);
+/**
+ * [fnmatch(3)](http://man7.org/linux/man-pages/man3/fnmatch.3.html) matches `__string` against
+ * the shell wildcard `__pattern`.
+ *
+ * Returns 0 on success, and returns `FNM_NOMATCH` on failure.
+ */
+int fnmatch(const char* _Nonnull __pattern, const char* _Nonnull __string, int __flags);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/iconv.h b/libc/include/iconv.h
index df8fa6d..ec4bdea 100644
--- a/libc/include/iconv.h
+++ b/libc/include/iconv.h
@@ -26,21 +26,58 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _ICONV_H_
-#define _ICONV_H_
+#pragma once
+
+/**
+ * @file iconv.h
+ * @brief Character encoding conversion.
+ */
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
+/* If we just use void* in the typedef, the compiler exposes that in error messages. */
 struct __iconv_t;
+
+/**
+ * The `iconv_t` type that represents an instance of a converter.
+ */
 typedef struct __iconv_t* iconv_t;
 
+/**
+ * [iconv_open(3)](http://man7.org/linux/man-pages/man3/iconv_open.3.html) allocates a new converter
+ * from `__src_encoding` to `__dst_encoding`.
+ *
+ * Returns a new `iconv_t` on success and returns `((iconv_t) -1)` and sets `errno` on failure.
+ *
+ * Available since API level 28.
+ */
 iconv_t iconv_open(const char* __src_encoding, const char* __dst_encoding) __INTRODUCED_IN(28);
+
+/**
+ * [iconv(3)](http://man7.org/linux/man-pages/man3/iconv.3.html) converts characters from one
+ * encoding to another.
+ *
+ * Android supports the `utf8`, `ascii`, `usascii`, `utf16be`, `utf16le`, `utf32be`, `utf32le`,
+ * and `wchart` encodings. Android also supports the GNU `//IGNORE` and `//TRANSLIT` extensions.
+ *
+ * Returns the number of characters converted on success and returns `((size_t) -1)` and
+ * sets `errno` on failure.
+ *
+ * Available since API level 28.
+ */
 size_t iconv(iconv_t __converter, char** __src_buf, size_t* __src_bytes_left, char** __dst_buf, size_t* __dst_bytes_left) __INTRODUCED_IN(28);
+
+/**
+ * [iconv_close(3)](http://man7.org/linux/man-pages/man3/iconv_close.3.html) deallocates a converter
+ * returned by iconv_open().
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 28.
+ */
 int iconv_close(iconv_t __converter) __INTRODUCED_IN(28);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/ifaddrs.h b/libc/include/ifaddrs.h
index 0e2b0ea..9eaabbd 100644
--- a/libc/include/ifaddrs.h
+++ b/libc/include/ifaddrs.h
@@ -26,8 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _IFADDRS_H_
-#define _IFADDRS_H_
+#pragma once
+
+/**
+ * @file ifaddrs.h
+ * @brief Access to network interface addresses.
+ */
 
 #include <sys/cdefs.h>
 #include <netinet/in.h>
@@ -35,25 +39,55 @@
 
 __BEGIN_DECLS
 
+/**
+ * Returned by getifaddrs() and freed by freeifaddrs().
+ */
 struct ifaddrs {
+  /** Pointer to the next element in the linked list. */
   struct ifaddrs* ifa_next;
+
+  /** Interface name. */
   char* ifa_name;
+  /** Interface flags (like `SIOCGIFFLAGS`). */
   unsigned int ifa_flags;
+  /** Interface address. */
   struct sockaddr* ifa_addr;
+  /** Interface netmask. */
   struct sockaddr* ifa_netmask;
+
   union {
+    /** Interface broadcast address (if IFF_BROADCAST is set). */
     struct sockaddr* ifu_broadaddr;
+    /** Interface destination address (if IFF_POINTOPOINT is set). */
     struct sockaddr* ifu_dstaddr;
   } ifa_ifu;
+
+  /** Unused. */
   void* ifa_data;
 };
 
+/** Synonym for `ifa_ifu.ifu_broadaddr` in `struct ifaddrs`. */
 #define ifa_broadaddr ifa_ifu.ifu_broadaddr
+/** Synonym for `ifa_ifu.ifu_dstaddr` in `struct ifaddrs`. */
 #define ifa_dstaddr ifa_ifu.ifu_dstaddr
 
-void freeifaddrs(struct ifaddrs* __ptr) __INTRODUCED_IN(24);
+/**
+ * [getifaddrs(3)](http://man7.org/linux/man-pages/man3/getifaddrs.3.html) creates a linked list
+ * of `struct ifaddrs`. The list must be freed by freeifaddrs().
+ *
+ * Returns 0 and stores the list in `*__list_ptr` on success,
+ * and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 24.
+ */
 int getifaddrs(struct ifaddrs** __list_ptr) __INTRODUCED_IN(24);
 
-__END_DECLS
+/**
+ * [freeifaddrs(3)](http://man7.org/linux/man-pages/man3/freeifaddrs.3.html) frees a linked list
+ * of `struct ifaddrs` returned by getifaddrs().
+ *
+ * Available since API level 24.
+ */
+void freeifaddrs(struct ifaddrs* __ptr) __INTRODUCED_IN(24);
 
-#endif
+__END_DECLS
diff --git a/libc/include/lastlog.h b/libc/include/lastlog.h
index 4f46106..ef1b032 100644
--- a/libc/include/lastlog.h
+++ b/libc/include/lastlog.h
@@ -1,2 +1,10 @@
-/* This is a BSD synonym for <utmp.h> that's also provided by glibc. */
+#pragma once
+
+/**
+ * @file lastlog.h
+ * @brief Historical alternative to `<utmp.h>`.
+ *
+ * New code should use `<utmp.h>` directly.
+ */
+
 #include <utmp.h>
diff --git a/libc/include/libgen.h b/libc/include/libgen.h
index 5fa9089..b910790 100644
--- a/libc/include/libgen.h
+++ b/libc/include/libgen.h
@@ -26,34 +26,52 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _LIBGEN_H
-#define _LIBGEN_H
+#pragma once
+
+/**
+ * @file libgen.h
+ * @brief POSIX basename() and dirname().
+ *
+ * This file contains the POSIX basename() and dirname(). See `<string.h>` for the GNU basename().
+ */
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
-/*
- * Including <string.h> will get you the GNU basename, unless <libgen.h> is
- * included, either before or after including <string.h>.
+/**
+ * [basename(3)](http://man7.org/linux/man-pages/man3/basename.3.html)
+ * returns the final component of the given path.
  *
- * Note that this has the wrong argument cv-qualifiers, but doesn't modify its
- * input and uses thread-local storage for the result if necessary.
+ * See `<string.h>` for the GNU basename(). Including `<libgen.h>`,
+ * either before or after including <string.h>, will override the GNU variant.
+ *
+ * Note that Android's cv-qualifiers differ from POSIX; Android's implementation doesn't
+ * modify its input and uses thread-local storage for the result if necessary.
  */
 char* __posix_basename(const char* __path) __RENAME(basename);
 
+/**
+ * This macro ensures that callers get the POSIX basename() if they include this header,
+ * no matter what order `<libgen.h>` and `<string.h>` are included in.
+ */
 #define basename __posix_basename
 
-/* This has the wrong argument cv-qualifiers, but doesn't modify its input and uses thread-local storage for the result if necessary. */
+/**
+ * [dirname(3)](http://man7.org/linux/man-pages/man3/dirname.3.html)
+ * returns all but the final component of the given path.
+ *
+ * Note that Android's cv-qualifiers differ from POSIX; Android's implementation doesn't
+ * modify its input and uses thread-local storage for the result if necessary.
+ */
 char* dirname(const char* __path);
 
 #if !defined(__LP64__)
-/* These non-standard functions are not needed on Android; basename and dirname use thread-local storage. */
+/** Deprecated. Use dirname() instead. */
 int dirname_r(const char* __path, char* __buf, size_t __n);
+/** Deprecated. Use basename() instead. */
 int basename_r(const char* __path, char* __buf, size_t __n);
 #endif
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index f7adfbb..7144224 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -14,8 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef LIBC_INCLUDE_MALLOC_H_
-#define LIBC_INCLUDE_MALLOC_H_
+#pragma once
+
+/**
+ * @file malloc.h
+ * @brief Heap memory allocation.
+ *
+ * [Debugging Native Memory Use](https://source.android.com/devices/tech/debug/native-memory)
+ * is the canonical source for documentation on Android's heap debugging
+ * features.
+ */
 
 #include <sys/cdefs.h>
 #include <stddef.h>
@@ -30,35 +38,96 @@
 #define __BIONIC_ALLOC_SIZE(...) __attribute__((__alloc_size__(__VA_ARGS__)))
 #endif
 
+/**
+ * [malloc(3)](http://man7.org/linux/man-pages/man3/malloc.3.html) allocates
+ * memory on the heap.
+ *
+ * Returns a pointer to the allocated memory on success and returns a null
+ * pointer and sets `errno` on failure.
+ */
 void* malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
+
+/**
+ * [calloc(3)](http://man7.org/linux/man-pages/man3/calloc.3.html) allocates
+ * and clears memory on the heap.
+ *
+ * Returns a pointer to the allocated memory on success and returns a null
+ * pointer and sets `errno` on failure.
+ */
 void* calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
+
+/**
+ * [realloc(3)](http://man7.org/linux/man-pages/man3/realloc.3.html) resizes
+ * allocated memory on the heap.
+ *
+ * Returns a pointer (which may be different from `__ptr`) to the resized
+ * memory on success and returns a null pointer and sets `errno` on failure.
+ */
 void* realloc(void* __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
+
+/**
+ * [free(3)](http://man7.org/linux/man-pages/man3/free.3.html) deallocates
+ * memory on the heap.
+ */
 void free(void* __ptr);
 
+/**
+ * [memalign(3)](http://man7.org/linux/man-pages/man3/memalign.3.html) allocates
+ * memory on the heap with the required alignment.
+ *
+ * Returns a pointer to the allocated memory on success and returns a null
+ * pointer and sets `errno` on failure.
+ *
+ * See also posix_memalign().
+ */
 void* memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
+
+/**
+ * [malloc_usable_size(3)](http://man7.org/linux/man-pages/man3/malloc_usable_size.3.html)
+ * returns the actual size of the given heap block.
+ *
+ * Available since API level 17.
+ */
 size_t malloc_usable_size(const void* __ptr) __INTRODUCED_IN(17);
 
 #ifndef STRUCT_MALLINFO_DECLARED
 #define STRUCT_MALLINFO_DECLARED 1
 struct mallinfo {
-  size_t arena;    /* Total number of non-mmapped bytes currently allocated from OS. */
-  size_t ordblks;  /* Number of free chunks. */
-  size_t smblks;   /* (Unused.) */
-  size_t hblks;    /* (Unused.) */
-  size_t hblkhd;   /* Total number of bytes in mmapped regions. */
-  size_t usmblks;  /* Maximum total allocated space; greater than total if trimming has occurred. */
-  size_t fsmblks;  /* (Unused.) */
-  size_t uordblks; /* Total allocated space (normal or mmapped.) */
-  size_t fordblks; /* Total free space. */
-  size_t keepcost; /* Upper bound on number of bytes releasable by malloc_trim. */
+  /** Total number of non-mmapped bytes currently allocated from OS. */
+  size_t arena;
+  /** Number of free chunks. */
+  size_t ordblks;
+  /** (Unused.) */
+  size_t smblks;
+  /** (Unused.) */
+  size_t hblks;
+  /** Total number of bytes in mmapped regions. */
+  size_t hblkhd;
+  /** Maximum total allocated space; greater than total if trimming has occurred. */
+  size_t usmblks;
+  /** (Unused.) */
+  size_t fsmblks;
+  /** Total allocated space (normal or mmapped.) */
+  size_t uordblks;
+  /** Total free space. */
+  size_t fordblks;
+  /** Upper bound on number of bytes releasable by a trim operation. */
+  size_t keepcost;
 };
-#endif  /* STRUCT_MALLINFO_DECLARED */
+#endif
 
+/**
+ * [mallinfo(3)](http://man7.org/linux/man-pages/man3/mallinfo.3.html) returns
+ * information about the current state of the heap.
+ */
 struct mallinfo mallinfo(void);
 
-/*
- * XML structure for malloc_info(3) is in the following format:
+/**
+ * [malloc_info(3)](http://man7.org/linux/man-pages/man3/malloc_info.3.html)
+ * writes information about the current state of the heap to the given stream.
  *
+ * The XML structure for malloc_info() is as follows:
+ * ```
  * <malloc version="jemalloc-1">
  *   <heap nr="INT">
  *     <allocated-large>INT</allocated-large>
@@ -74,21 +143,67 @@
  *   </heap>
  *   <!-- more heaps -->
  * </malloc>
+ * ```
+ *
+ * Available since API level 23.
  */
 int malloc_info(int __must_be_zero, FILE* __fp) __INTRODUCED_IN(23);
 
-/* mallopt options */
+/** mallopt() option to set the decay time. Valid values are 0 and 1. */
 #define M_DECAY_TIME -100
+
+/**
+ * [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
+ * heap behavior. Values of `__option` are the `M_` constants from this header.
+ *
+ * Returns 1 on success, 0 on error.
+ *
+ * Available since API level 26.
+ */
 int mallopt(int __option, int __value) __INTRODUCED_IN(26);
 
-/*
- * Memory Allocation Hooks
+/**
+ * [__malloc_hook(3)](http://man7.org/linux/man-pages/man3/__malloc_hook.3.html)
+ * is called to implement malloc(). By default this points to the system's
+ * implementation.
+ *
+ * Available since API level 28.
+ *
+ * See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
  */
-extern void* (*volatile __malloc_hook)(size_t, const void*) __INTRODUCED_IN(28);
-extern void* (*volatile __realloc_hook)(void*, size_t, const void*) __INTRODUCED_IN(28);
-extern void (*volatile __free_hook)(void*, const void*) __INTRODUCED_IN(28);
-extern void* (*volatile __memalign_hook)(size_t, size_t, const void*) __INTRODUCED_IN(28);
+extern void* (*volatile __malloc_hook)(size_t __byte_count, const void* __caller) __INTRODUCED_IN(28);
+
+/**
+ * [__realloc_hook(3)](http://man7.org/linux/man-pages/man3/__realloc_hook.3.html)
+ * is called to implement realloc(). By default this points to the system's
+ * implementation.
+ *
+ * Available since API level 28.
+ *
+ * See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
+ */
+extern void* (*volatile __realloc_hook)(void* __ptr, size_t __byte_count, const void* __caller) __INTRODUCED_IN(28);
+
+/**
+ * [__free_hook(3)](http://man7.org/linux/man-pages/man3/__free_hook.3.html)
+ * is called to implement free(). By default this points to the system's
+ * implementation.
+ *
+ * Available since API level 28.
+ *
+ * See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
+ */
+extern void (*volatile __free_hook)(void* __ptr, const void* __caller) __INTRODUCED_IN(28);
+
+/**
+ * [__memalign_hook(3)](http://man7.org/linux/man-pages/man3/__memalign_hook.3.html)
+ * is called to implement memalign(). By default this points to the system's
+ * implementation.
+ *
+ * Available since API level 28.
+ *
+ * See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_hooks/README.md)
+ */
+extern void* (*volatile __memalign_hook)(size_t __alignment, size_t __byte_count, const void* __caller) __INTRODUCED_IN(28);
 
 __END_DECLS
-
-#endif  /* LIBC_INCLUDE_MALLOC_H_ */
diff --git a/libc/include/memory.h b/libc/include/memory.h
index 3b2f590..c2baef6 100644
--- a/libc/include/memory.h
+++ b/libc/include/memory.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file memory.h
+ * @brief Historical alternative to `<string.h>`.
+ *
+ * New code should use `<string.h>` directly.
+ */
+
 #include <string.h>
diff --git a/libc/include/nl_types.h b/libc/include/nl_types.h
index b25b7a3..622880a 100644
--- a/libc/include/nl_types.h
+++ b/libc/include/nl_types.h
@@ -26,23 +26,59 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _NL_TYPES_H_
-#define _NL_TYPES_H_
+#pragma once
+
+/**
+ * @file nl_types.h
+ * @brief Message catalogs.
+ *
+ * Android offers a dummy implementation of these functions to ease porting of historical software.
+ */
 
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
+/**
+ * catopen() flag to use the current locale.
+ */
 #define NL_CAT_LOCALE 1
+
+/**
+ * catgets() default set number.
+ */
 #define NL_SETD 1
 
+/** Message catalog type. */
 typedef void* nl_catd;
+
+/** The type of the constants in `<langinfo.h>`, used by nl_langinfo(). */
 typedef int nl_item;
 
+/**
+ * [catopen(3)](http://man7.org/linux/man-pages/man3/catopen.3.html) opens a message catalog.
+ *
+ * On Android, this always returns failure: `((nl_catd) -1)`.
+ *
+ * Available since API level 28.
+ */
 nl_catd catopen(const char* __name, int __flag) __INTRODUCED_IN(26);
+
+/**
+ * [catgets(3)](http://man7.org/linux/man-pages/man3/catgets.3.html) translates the given message
+ * using the given message catalog.
+ *
+ * On Android, this always returns `__msg`.
+ *
+ * Available since API level 28.
+ */
 char* catgets(nl_catd __catalog, int __set_number, int __msg_number, const char* __msg) __INTRODUCED_IN(26);
+
+/**
+ * [catclose(3)](http://man7.org/linux/man-pages/man3/catclose.3.html) closes a message catalog.
+ *
+ * On Android, this always returns -1 with `errno` set to `EBADF`.
+ */
 int catclose(nl_catd __catalog) __INTRODUCED_IN(26);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/paths.h b/libc/include/paths.h
index 922d1ce..dc1c523 100644
--- a/libc/include/paths.h
+++ b/libc/include/paths.h
@@ -29,20 +29,37 @@
  *	@(#)paths.h	8.1 (Berkeley) 6/2/93
  */
 
-#ifndef _PATHS_H_
-#define	_PATHS_H_
+#pragma once
+
+/**
+ * @file paths.h
+ * @brief Default paths.
+ */
 
 #include <sys/cdefs.h>
 
 #ifndef _PATH_BSHELL
-#define	_PATH_BSHELL	"/system/bin/sh"
+/** Path to the default system shell. Historically the 'B' was to specify the Bourne shell. */
+#define _PATH_BSHELL "/system/bin/sh"
 #endif
-#define	_PATH_CONSOLE	"/dev/console"
-#define	_PATH_DEFPATH	"/sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin"
-#define	_PATH_DEV	"/dev/"
-#define	_PATH_DEVNULL	"/dev/null"
-#define	_PATH_KLOG	"/proc/kmsg"
-#define	_PATH_MOUNTED	"/proc/mounts"
-#define	_PATH_TTY	"/dev/tty"
 
-#endif /* !_PATHS_H_ */
+/** Path to the system console. */
+#define _PATH_CONSOLE "/dev/console"
+
+/** Default shell search path. */
+#define _PATH_DEFPATH "/sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin"
+
+/** Path to the directory containing device files. */
+#define _PATH_DEV "/dev/"
+
+/** Path to `/dev/null`. */
+#define _PATH_DEVNULL "/dev/null"
+
+/** Path to the kernel log. */
+#define _PATH_KLOG "/proc/kmsg"
+
+/** Path to `/proc/mounts` for setmntent(). */
+#define _PATH_MOUNTED "/proc/mounts"
+
+/** Path to the calling process' tty. */
+#define _PATH_TTY "/dev/tty"
diff --git a/libc/include/poll.h b/libc/include/poll.h
index 6a8f757..e3a9039 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -26,8 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _POLL_H_
-#define _POLL_H_
+#pragma once
+
+/**
+ * @file poll.h
+ * @brief Wait for events on a set of file descriptors.
+ */
 
 #include <sys/cdefs.h>
 #include <linux/poll.h>
@@ -36,16 +40,38 @@
 
 __BEGIN_DECLS
 
+/** The type of a file descriptor count, used by poll() and ppoll(). */
 typedef unsigned int nfds_t;
 
-int poll(struct pollfd* __fds, nfds_t __count, int __timeout_ms);
-int ppoll(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset_t* __mask) __INTRODUCED_IN(21);
-int ppoll64(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset64_t* __mask) __INTRODUCED_IN(28);
+/**
+ * [poll(3)](http://man7.org/linux/man-pages/man3/poll.3.html) waits on a set of file descriptors.
+ *
+ * Returns the number of ready file descriptors on success, 0 for timeout,
+ * and returns -1 and sets `errno` on failure.
+ */
+int poll(struct pollfd* _Nullable __fds, nfds_t __count, int __timeout_ms);
+
+/**
+ * [ppoll(3)](http://man7.org/linux/man-pages/man3/ppoll.3.html) waits on a set of file descriptors
+ * or a signal. Set `__timeout` to null for no timeout. Set `__mask` to null to not set the signal
+ * mask.
+ *
+ * Returns the number of ready file descriptors on success, 0 for timeout,
+ * and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 28.
+ */
+int ppoll(struct pollfd* _Nullable __fds, nfds_t __count, const struct timespec* _Nullable __timeout, const sigset_t* _Nullable __mask) __INTRODUCED_IN(21);
+
+/**
+ * Like ppoll() but allows setting a signal mask with RT signals even from a 32-bit process.
+ */
+int ppoll64(struct pollfd* _Nullable  __fds, nfds_t __count, const struct timespec* _Nullable __timeout, const sigset64_t* _Nullable __mask) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
+#define _POLL_H_
 #include <bits/fortify/poll.h>
+#undef _POLL_H_
 #endif
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/pty.h b/libc/include/pty.h
index cf9ccb9..90d6686 100644
--- a/libc/include/pty.h
+++ b/libc/include/pty.h
@@ -26,8 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _PTY_H
-#define _PTY_H
+#pragma once
+
+/**
+ * @file pty.h
+ * @brief Pseudoterminal functions.
+ */
 
 #include <sys/cdefs.h>
 
@@ -36,9 +40,25 @@
 
 __BEGIN_DECLS
 
-int openpty(int* __master_fd, int* __slave_fd, char* __slave_name, const struct termios* __termios_ptr, const struct winsize* __winsize_ptr) __INTRODUCED_IN(23);
-int forkpty(int* __master_fd, char* __slave_name, const struct termios* __termios_ptr, const struct winsize* __winsize_ptr) __INTRODUCED_IN(23);
+/**
+ * [openpty(3)](http://man7.org/linux/man-pages/man3/openpty.3.html) finds
+ * a free pseudoterminal and configures it with the given terminal and window
+ * size settings.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 23.
+ */
+int openpty(int* _Nonnull __master_fd, int* _Nonnull __slave_fd, char* _Nullable __slave_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
+
+/**
+ * [forkpty(3)](http://man7.org/linux/man-pages/man3/forkpty.3.html) creates
+ * a new process connected to a pseudoterminal from openpty().
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 23.
+ */
+int forkpty(int* _Nonnull __master_fd, char* _Nullable __slave_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 00860d5..9d1030a 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -113,6 +113,10 @@
 void psignal(int __signal, const char* __msg) __INTRODUCED_IN(17);
 
 int pthread_kill(pthread_t __pthread, int __signal);
+#if defined(__USE_GNU)
+int pthread_sigqueue(pthread_t __pthread, int __signal, const union sigval __value) __INTRODUCED_IN(__ANDROID_API_Q__);
+#endif
+
 int pthread_sigmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
 int pthread_sigmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28);
 
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index b8aa68d..3aa183d 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -26,32 +26,113 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _STDIO_EXT_H
-#define _STDIO_EXT_H
+#pragma once
+
+/**
+ * @file stdio_ext.h
+ * @brief Extra standard I/O functionality. See also `<stdio.h>`.
+ */
 
 #include <sys/cdefs.h>
 #include <stdio.h>
 
-
 __BEGIN_DECLS
 
+/**
+ * [__fbufsize(3)](http://man7.org/linux/man-pages/man3/__fbufsize.3.html) returns the size of
+ * the stream's buffer.
+ *
+ * Available since API level 23.
+ */
 size_t __fbufsize(FILE* __fp) __INTRODUCED_IN(23);
+
+/**
+ * [__freadable(3)](http://man7.org/linux/man-pages/man3/__freadable.3.html) returns non-zero if
+ * the stream allows reading, 0 otherwise.
+ *
+ * Available since API level 23.
+ */
 int __freadable(FILE* __fp) __INTRODUCED_IN(23);
+
+/**
+ * [__freading(3)](http://man7.org/linux/man-pages/man3/__freading.3.html) returns non-zero if
+ * the stream's last operation was a read, 0 otherwise.
+ *
+ * Available since API level 28.
+ */
 int __freading(FILE* __fp) __INTRODUCED_IN(28);
+
+/**
+ * [__fwritable(3)](http://man7.org/linux/man-pages/man3/__fwritable.3.html) returns non-zero if
+ * the stream allows writing, 0 otherwise.
+ *
+ * Available since API level 23.
+ */
 int __fwritable(FILE* __fp) __INTRODUCED_IN(23);
+
+/**
+ * [__fwriting(3)](http://man7.org/linux/man-pages/man3/__fwriting.3.html) returns non-zero if
+ * the stream's last operation was a write, 0 otherwise.
+ *
+ * Available since API level 28.
+ */
 int __fwriting(FILE* __fp) __INTRODUCED_IN(28);
+
+/**
+ * [__flbf(3)](http://man7.org/linux/man-pages/man3/__flbf.3.html) returns non-zero if
+ * the stream is line-buffered, 0 otherwise.
+ *
+ * Available since API level 23.
+ */
 int __flbf(FILE* __fp) __INTRODUCED_IN(23);
+
+/**
+ * [__fpurge(3)](http://man7.org/linux/man-pages/man3/__fpurge.3.html) discards the contents of
+ * the stream's buffer.
+ *
+ * Available since API level 23.
+ */
 void __fpurge(FILE* __fp) __INTRODUCED_IN(23);
+
+/**
+ * [__fpending(3)](http://man7.org/linux/man-pages/man3/__fpending.3.html) returns the number of
+ * bytes in the output buffer.
+ *
+ * Available since API level 23.
+ */
 size_t __fpending(FILE* __fp) __INTRODUCED_IN(23);
+
+/**
+ * [_flushlbf(3)](http://man7.org/linux/man-pages/man3/_flushlbf.3.html) flushes all
+ * line-buffered streams.
+ *
+ * Available since API level 23.
+ */
 void _flushlbf(void) __INTRODUCED_IN(23);
 
+/**
+ * `__fseterr` sets the
+ * stream's error flag (as tested by ferror() and cleared by fclearerr()).
+ *
+ * Available since API level 28.
+ */
 void __fseterr(FILE* __fp) __INTRODUCED_IN(28);
 
+/** __fsetlocking() constant to query locking type. */
 #define FSETLOCKING_QUERY 0
+/** __fsetlocking() constant to set locking to be maintained by stdio. */
 #define FSETLOCKING_INTERNAL 1
+/** __fsetlocking() constant to set locking to be maintained by the caller. */
 #define FSETLOCKING_BYCALLER 2
+
+/**
+ * [__fsetlocking(3)](http://man7.org/linux/man-pages/man3/__fsetlocking.3.html) sets the
+ * stream's locking mode to one of the `FSETLOCKING_` types.
+ *
+ * Returns the current locking style, `FSETLOCKING_INTERNAL` or `FSETLOCKING_BYCALLER`.
+ *
+ * Available since API level 23.
+ */
 int __fsetlocking(FILE* __fp, int __type) __INTRODUCED_IN(23);
 
 __END_DECLS
-
-#endif /* _STDIO_EXT_H */
diff --git a/libc/include/strings.h b/libc/include/strings.h
index c2e0a5e..ccdac04 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -36,8 +36,12 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef _STRINGS_H_
-#define _STRINGS_H_
+#pragma once
+
+/**
+ * @file strings.h
+ * @brief Extra string functions.
+ */
 
 #include <sys/types.h>
 #include <sys/cdefs.h>
@@ -46,20 +50,28 @@
 #include <bits/strcasecmp.h>
 
 __BEGIN_DECLS
+
 #if defined(__BIONIC_FORTIFY)
+/** Deprecated. Use memmove() instead. */
 #define bcopy(b1, b2, len) (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
+/** Deprecated. Use memset() instead. */
 #define bzero(b, len) (void)(__builtin___memset_chk((b), '\0', (len), __bos0(b)))
 #else
+/** Deprecated. Use memmove() instead. */
 #define bcopy(b1, b2, len) (void)(__builtin_memmove((b2), (b1), (len)))
+/** Deprecated. Use memset() instead. */
 #define bzero(b, len) (void)(__builtin_memset((b), '\0', (len)))
 #endif
 
 #if !defined(__i386__) || __ANDROID_API__ >= __ANDROID_API_J_MR2__
+/**
+ * [ffs(3)](http://man7.org/linux/man-pages/man3/ffs.3.html) finds the first set bit in `__i`.
+ *
+ * Returns 0 if no bit is set, or the index of the lowest set bit (counting from 1) otherwise.
+ */
 int ffs(int __i) __INTRODUCED_IN_X86(18);
 #endif
 
 __END_DECLS
 
 #include <android/legacy_strings_inlines.h>
-
-#endif
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 13ad4fe..26a05c8 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -38,7 +38,6 @@
 #define	_SYS_CDEFS_H_
 
 #include <android/api-level.h>
-#include <android/versioning.h>
 
 #define __BIONIC__ 1
 
@@ -92,7 +91,6 @@
 #define	___STRING(x)	__STRING(x)
 #define	___CONCAT(x,y)	__CONCAT(x,y)
 
-#if defined(__STDC__) || defined(__cplusplus)
 #define	__P(protos)	protos		/* full-blown ANSI C */
 #define	__CONCAT1(x,y)	x ## y
 #define	__CONCAT(x,y)	__CONCAT1(x,y)
@@ -102,12 +100,9 @@
 #define	__inline	inline		/* convert to C++ keyword */
 #endif /* !__cplusplus */
 
-#else	/* !(__STDC__ || __cplusplus) */
-#define	__P(protos)	()		/* traditional C preprocessor */
-#define	__CONCAT(x,y)	x/**/y
-#define	__STRING(x)	"x"
+#include <android/versioning.h>
 
-#endif	/* !(__STDC__ || __cplusplus) */
+#include <android/versioning.h>
 
 #define __always_inline __attribute__((__always_inline__))
 #define __attribute_const__ __attribute__((__const__))
diff --git a/libc/include/sys/errno.h b/libc/include/sys/errno.h
index 339f4fc..77526a9 100644
--- a/libc/include/sys/errno.h
+++ b/libc/include/sys/errno.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file sys/errno.h
+ * @brief Historical synonym for `<errno.h>`.
+ *
+ * New code should use `<errno.h>` directly.
+ */
+
 #include <errno.h>
diff --git a/libc/include/sys/fcntl.h b/libc/include/sys/fcntl.h
index cd30455..35e677a 100644
--- a/libc/include/sys/fcntl.h
+++ b/libc/include/sys/fcntl.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file sys/fcntl.h
+ * @brief Historical synonym for `<fcntl.h>`.
+ *
+ * New code should use `<fcntl.h>` directly.
+ */
+
 #include <fcntl.h>
diff --git a/libc/include/sys/limits.h b/libc/include/sys/limits.h
index 1e189a1..33ccaee 100644
--- a/libc/include/sys/limits.h
+++ b/libc/include/sys/limits.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file sys/limits.h
+ * @brief Historical synonym for `<limits.h>`.
+ *
+ * New code should use `<limits.h>` directly.
+ */
+
 #include <limits.h>
diff --git a/libc/include/sys/poll.h b/libc/include/sys/poll.h
index 779ec77..0323e37 100644
--- a/libc/include/sys/poll.h
+++ b/libc/include/sys/poll.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file sys/poll.h
+ * @brief Historical synonym for `<poll.h>`.
+ *
+ * New code should use `<poll.h>` directly.
+ */
+
 #include <poll.h>
diff --git a/libc/include/sys/prctl.h b/libc/include/sys/prctl.h
index 64f5954..bd42411 100644
--- a/libc/include/sys/prctl.h
+++ b/libc/include/sys/prctl.h
@@ -26,17 +26,40 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _SYS_PRCTL_H
-#define _SYS_PRCTL_H
+#pragma once
+
+/**
+ * @file sys/prctl.h
+ * @brief Process-specific operations.
+ */
 
 #include <sys/cdefs.h>
 
 #include <linux/prctl.h>
 
+/**
+ * Names a VMA (mmap'ed region). The second argument must be `PR_SET_VMA_ANON_NAME`,
+ * the third and fourth are a `void*` pointer to the VMA and its `size_t` length in
+ * bytes, and the final argument is a `const char*` pointer to the name.
+ *
+ * Note that the kernel keeps the pointer to the name rather than copying the name,
+ * so the lifetime of the string should be at least as long as that of the VMA.
+ */
+#define PR_SET_VMA 0x53564d41
+
+/**
+ * For use with `PR_SET_VMA`.
+ */
+#define PR_SET_VMA_ANON_NAME 0
+
 __BEGIN_DECLS
 
+/**
+ * [prctl(2)](http://man7.org/linux/man-pages/man2/prctl.2.html) performs a variety of
+ * operations based on the `PR_` constant passed as the first argument.
+ *
+ * Returns -1 and sets `errno` on failure; success values vary by option.
+ */
 int prctl(int __option, ...);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/sys/signal.h b/libc/include/sys/signal.h
index 2e602da..fde0819 100644
--- a/libc/include/sys/signal.h
+++ b/libc/include/sys/signal.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file sys/signal.h
+ * @brief Historical synonym for `<signal.h>`.
+ *
+ * New code should use `<signal.h>` directly.
+ */
+
 #include <signal.h>
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index bbde88b..e54dd65 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -288,6 +288,7 @@
 #define SOL_ALG 279
 #define SOL_NFC 280
 #define SOL_KCM 281
+#define SOL_TLS 282
 
 #define IPX_TYPE 1
 
diff --git a/libc/include/sys/sysconf.h b/libc/include/sys/sysconf.h
index eb30faf..060ba7e 100644
--- a/libc/include/sys/sysconf.h
+++ b/libc/include/sys/sysconf.h
@@ -1,6 +1,14 @@
-/*
+#pragma once
+
+/**
+ * @file sys/sysconf.h
+ * @brief Historical synonym for `<sysconf.h>`.
+ *
  * This file used to contain the declarations of sysconf and its associated constants.
- * No standard mentions a <sys/sysconf.h>, but there are enough users in vendor (and potential ones
- * in the NDK) to warrant not breaking source compatibility.
+ * No standard mentions a `<sys/sysconf.h>`, but there are enough users in vendor (and
+ * potential NDK users) to warrant not breaking source compatibility.
+ *
+ * New code should use `<sysconf.h>` directly.
  */
+
 #include <bits/sysconf.h>
diff --git a/libc/include/sys/syslog.h b/libc/include/sys/syslog.h
index 7761ece..4b89c10 100644
--- a/libc/include/sys/syslog.h
+++ b/libc/include/sys/syslog.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file sys/syslog.h
+ * @brief Historical synonym for `<syslog.h>`.
+ *
+ * New code should use `<syslog.h>` directly.
+ */
+
 #include <syslog.h>
diff --git a/libc/include/sys/unistd.h b/libc/include/sys/unistd.h
index 1e823fb..eb7694d 100644
--- a/libc/include/sys/unistd.h
+++ b/libc/include/sys/unistd.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file sys/unistd.h
+ * @brief Historical synonym for `<unistd.h>`.
+ *
+ * New code should use `<unistd.h>` directly.
+ */
+
 #include <unistd.h>
diff --git a/libc/include/syscall.h b/libc/include/syscall.h
index 4c30578..11d9655 100644
--- a/libc/include/syscall.h
+++ b/libc/include/syscall.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file syscall.h
+ * @brief Historical alternative to `<sys/syscall.h>`.
+ *
+ * New code should use `<sys/syscall.h>` directly.
+ */
+
 #include <sys/syscall.h>
diff --git a/libc/include/sysexits.h b/libc/include/sysexits.h
index 97f5366..b0001e6 100644
--- a/libc/include/sysexits.h
+++ b/libc/include/sysexits.h
@@ -32,90 +32,134 @@
  *	@(#)sysexits.h	4.8 (Berkeley) 4/3/91
  */
 
-#ifndef	_SYSEXITS_H_
-#define	_SYSEXITS_H_
+#pragma once
+
+/**
+ * @file sysexits.h
+ * @brief Exit status codes for system programs.
+ *
+ * This include file attempts to categorize possible error
+ * exit statuses for system programs such as sendmail.
+ */
 
 #include <sys/cdefs.h>
 
-/*
- *  SYSEXITS.H -- Exit status codes for system programs.
- *
- *	This include file attempts to categorize possible error
- *	exit statuses for system programs, notably delivermail
- *	and the Berkeley network.
- *
- *	Error numbers begin at EX__BASE to reduce the possibility of
- *	clashing with other exit statuses that random programs may
- *	already return.  The meaning of the codes is approximately
- *	as follows:
- *
- *	EX_USAGE -- The command was used incorrectly, e.g., with
- *		the wrong number of arguments, a bad flag, a bad
- *		syntax in a parameter, or whatever.
- *	EX_DATAERR -- The input data was incorrect in some way.
- *		This should only be used for user's data & not
- *		system files.
- *	EX_NOINPUT -- An input file (not a system file) did not
- *		exist or was not readable.  This could also include
- *		errors like "No message" to a mailer (if it cared
- *		to catch it).
- *	EX_NOUSER -- The user specified did not exist.  This might
- *		be used for mail addresses or remote logins.
- *	EX_NOHOST -- The host specified did not exist.  This is used
- *		in mail addresses or network requests.
- *	EX_UNAVAILABLE -- A service is unavailable.  This can occur
- *		if a support program or file does not exist.  This
- *		can also be used as a catchall message when something
- *		you wanted to do doesn't work, but you don't know
- *		why.
- *	EX_SOFTWARE -- An internal software error has been detected.
- *		This should be limited to non-operating system related
- *		errors as possible.
- *	EX_OSERR -- An operating system error has been detected.
- *		This is intended to be used for such things as "cannot
- *		fork", "cannot create pipe", or the like.  It includes
- *		things like getuid returning a user that does not
- *		exist in the passwd file.
- *	EX_OSFILE -- Some system file (e.g., /etc/passwd, /var/run/utmp,
- *		etc.) does not exist, cannot be opened, or has some
- *		sort of error (e.g., syntax error).
- *	EX_CANTCREAT -- A (user specified) output file cannot be
- *		created.
- *	EX_IOERR -- An error occurred while doing I/O on some file.
- *	EX_TEMPFAIL -- temporary failure, indicating something that
- *		is not really an error.  In sendmail, this means
- *		that a mailer (e.g.) could not create a connection,
- *		and the request should be reattempted later.
- *	EX_PROTOCOL -- the remote system returned something that
- *		was "not possible" during a protocol exchange.
- *	EX_NOPERM -- You did not have sufficient permission to
- *		perform the operation.  This is not intended for
- *		file system problems, which should use EX_NOINPUT or
- *		EX_CANTCREAT, but rather for higher level permissions.
- *	EX_CONFIG -- Something was found in an unconfigured or
- *		misconfigured state.
+/** Successful termination. */
+#define EX_OK  0
+
+/**
+ * Base value for error messages.
+ * Error numbers begin at `EX__BASE` to reduce the possibility of
+ * clashing with other exit statuses that random programs may
+ * already return.
  */
+#define EX__BASE 64
 
-#define EX_OK		0	/* successful termination */
+/**
+ * Command line usage error.
+ * The command was used incorrectly, such as the wrong number of
+ * arguments, a bad flag, or bad syntax for a parameter.
+ */
+#define EX_USAGE 64
 
-#define EX__BASE	64	/* base value for error messages */
+/**
+ * Data format error.
+ * The input data was incorrect in some way.
+ * This should only be used for user's data and not for system files.
+ */
+#define EX_DATAERR 65
 
-#define EX_USAGE	64	/* command line usage error */
-#define EX_DATAERR	65	/* data format error */
-#define EX_NOINPUT	66	/* cannot open input */
-#define EX_NOUSER	67	/* addressee unknown */
-#define EX_NOHOST	68	/* host name unknown */
-#define EX_UNAVAILABLE	69	/* service unavailable */
-#define EX_SOFTWARE	70	/* internal software error */
-#define EX_OSERR	71	/* system error (e.g., can't fork) */
-#define EX_OSFILE	72	/* critical OS file missing */
-#define EX_CANTCREAT	73	/* can't create (user) output file */
-#define EX_IOERR	74	/* input/output error */
-#define EX_TEMPFAIL	75	/* temp failure; user is invited to retry */
-#define EX_PROTOCOL	76	/* remote error in protocol */
-#define EX_NOPERM	77	/* permission denied */
-#define EX_CONFIG	78	/* configuration error */
+/**
+ * Cannot open input.
+ * An input file (not a system file) did not exist or was not readable.
+ * This could also include errors like "No message" to a mailer (if it cared
+ * to catch it).
+ */
+#define EX_NOINPUT 66
 
-#define EX__MAX		78	/* maximum listed value */
+/**
+ * The specified user did not exist.
+ * This might be used for mail addresses or remote logins.
+ */
+#define EX_NOUSER 67
 
-#endif /* !_SYSEXITS_H_ */
+/**
+ * The specified host did not exist.
+ * This is used in mail addresses or network requests.
+ */
+#define EX_NOHOST 68
+
+/**
+ * A service is unavailable.
+ * This can occur if a support program or file does not exist.
+ * This can also be used as a catchall message when something
+ * you wanted to do doesn't work, but you don't know why.
+ */
+#define EX_UNAVAILABLE 69
+
+/**
+ * An internal software error has been detected.
+ * This should be limited to non-operating system related errors.
+ */
+#define EX_SOFTWARE 70
+
+/**
+ * An operating system error has been detected.
+ * This is intended to be used for such things as "cannot
+ * fork", "cannot create pipe", or the like.  It includes
+ * things like getuid returning a user that does not
+ * exist in the passwd file.
+ */
+#define EX_OSERR 71
+
+/**
+ * Critical OS file error.
+ * A system file (such as /etc/passwd) does not exist, cannot be opened,
+ * or has some other problem (such as a syntax error).
+ */
+#define EX_OSFILE 72
+
+/**
+ * Can't create (user) output file.
+ * A (user specified) output file cannot be created.
+ */
+#define EX_CANTCREAT 73
+
+/**
+ * Input/output error.
+ * An error occurred while doing I/O on some file.
+ */
+#define EX_IOERR 74
+
+/**
+ * Temporary failure; user is invited to retry.
+ * A temporary failure, indicating something that
+ * is not really an error.  In sendmail, this might mean
+ * that a mailer could not create a connection,
+ * and the request should be reattempted later.
+ */
+#define EX_TEMPFAIL 75
+
+/**
+ * Remote error in protocol.
+ * The remote system returned something that
+ * was "not possible" during a protocol exchange.
+ */
+#define EX_PROTOCOL 76
+
+/**
+ * Permission denied.
+ * You did not have sufficient permission to perform the operation.
+ * This is not intended for file system problems, which should use EX_NOINPUT or
+ * EX_CANTCREAT, but rather for higher level permissions.
+ */
+#define EX_NOPERM 77
+
+/**
+ * Configuration error.
+ * Something was found in an unconfigured or misconfigured state.
+ */
+#define EX_CONFIG 78
+
+/** Maximum listed value. */
+#define EX__MAX  78
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index fff565e..45de253 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _SYSLOG_H
-#define _SYSLOG_H
+#pragma once
 
 #include <stdio.h>
 #include <sys/cdefs.h>
@@ -35,63 +34,128 @@
 
 __BEGIN_DECLS
 
-/* Priorities are translated to Android log priorities as shown. */
-#define LOG_EMERG   0 /* ERROR */
-#define LOG_ALERT   1 /* ERROR */
-#define LOG_CRIT    2 /* ERROR */
-#define LOG_ERR     3 /* ERROR */
-#define LOG_WARNING 4 /* WARN */
-#define LOG_NOTICE  5 /* INFO */
-#define LOG_INFO    6 /* INFO */
-#define LOG_DEBUG   7 /* DEBUG */
+/** Corresponds to the Android ERROR log priority. */
+#define LOG_EMERG 0
+/** Corresponds to the Android ERROR log priority. */
+#define LOG_ALERT 1
+/** Corresponds to the Android ERROR log priority. */
+#define LOG_CRIT 2
+/** Corresponds to the Android ERROR log priority. */
+#define LOG_ERR 3
+/** Corresponds to the Android WARN log priority. */
+#define LOG_WARNING 4
+/** Corresponds to the Android INFO log priority. */
+#define LOG_NOTICE 5
+/** Corresponds to the Android INFO log priority. */
+#define LOG_INFO 6
+/** Corresponds to the Android DEBUG log priority. */
+#define LOG_DEBUG 7
 
 #define LOG_PRIMASK 7
 #define LOG_PRI(x) ((x) & LOG_PRIMASK)
 #define LOG_MAKEPRI(fac, pri) ((fac) | (pri))
 
-/* Facilities are currently ignored on Android. */
+/** Currently ignored on Android. */
 #define LOG_KERN     (0<<3)
+/** Currently ignored on Android. */
 #define LOG_USER     (1<<3)
+/** Currently ignored on Android. */
 #define LOG_MAIL     (2<<3)
+/** Currently ignored on Android. */
 #define LOG_DAEMON   (3<<3)
+/** Currently ignored on Android. */
 #define LOG_AUTH     (4<<3)
+/** Currently ignored on Android. */
 #define LOG_SYSLOG   (5<<3)
+/** Currently ignored on Android. */
 #define LOG_LPR      (6<<3)
+/** Currently ignored on Android. */
 #define LOG_NEWS     (7<<3)
+/** Currently ignored on Android. */
 #define LOG_UUCP     (8<<3)
+/** Currently ignored on Android. */
 #define LOG_CRON     (9<<3)
+/** Currently ignored on Android. */
 #define LOG_AUTHPRIV (10<<3)
+/** Currently ignored on Android. */
 #define LOG_FTP      (11<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL0   (16<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL1   (17<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL2   (18<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL3   (19<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL4   (20<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL5   (21<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL6   (22<<3)
+/** Currently ignored on Android. */
 #define LOG_LOCAL7   (23<<3)
 
 #define LOG_NFACILITIES 24
 #define LOG_FACMASK 0x3f8
 #define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3))
 
+/**
+ * Converts a log priority into a mask enabling that single priority,
+ * for use with setlogmask().
+ */
 #define LOG_MASK(pri) (1 << (pri))
+
+/**
+ * Converts a log priority into a mask enabling that priority and all lower
+ * priorities, for use with setlogmask().
+ */
 #define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1)
 
-/* openlog(3) flags are currently ignored on Android. */
+/** openlog() options are currently ignored on Android. */
 #define LOG_PID    0x01
+/** openlog() options are currently ignored on Android. */
 #define LOG_CONS   0x02
+/** openlog() options are currently ignored on Android. */
 #define LOG_ODELAY 0x04
+/** openlog() options are currently ignored on Android. */
 #define LOG_NDELAY 0x08
+/** openlog() options are currently ignored on Android. */
 #define LOG_NOWAIT 0x10
+/** openlog() options are currently ignored on Android. */
 #define LOG_PERROR 0x20
 
+/**
+ * [closelog(3)](http://man7.org/linux/man-pages/man3/closelog.3.html) does
+ * nothing on Android.
+ */
 void closelog(void);
+
+/**
+ * [openlog(3)](http://man7.org/linux/man-pages/man3/openlog.3.html) sets
+ * the log tag to `__prefix`. On Android, the other two arguments are ignored.
+ */
 void openlog(const char* __prefix, int __option, int __facility);
+
+/**
+ * [setlogmask(3)](http://man7.org/linux/man-pages/man3/setlogmask.3.html)
+ * sets which log priorities will actually be logged. See `LOG_MASK` and
+ * `LOG_UPTO`.
+ */
 int setlogmask(int __mask);
+
+/**
+ * [syslog(3)](http://man7.org/linux/man-pages/man3/syslog.3.html) formats
+ * the printf()-like message and logs it with the given priority, unless
+ * suppressed by setlogmask(). On Android, the output goes to logcat.
+ */
 void syslog(int __priority, const char* __fmt, ...) __printflike(2, 3);
+
+/**
+ * [vsyslog(3)](http://man7.org/linux/man-pages/man3/vsyslog.3.html) formats
+ * the vprintf()-like message and logs it with the given priority, unless
+ * suppressed by setlogmask(). On Android, the output goes to logcat.
+ */
 void vsyslog(int __priority, const char* __fmt, va_list __args) __printflike(2, 0);
 
 __END_DECLS
-
-#endif /* _SYSLOG_H */
diff --git a/libc/include/tar.h b/libc/include/tar.h
index a5d7a36..9d0c3ba 100644
--- a/libc/include/tar.h
+++ b/libc/include/tar.h
@@ -26,37 +26,64 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _TAR_H_
-#define _TAR_H_
+#pragma once
+
+/**
+ * @file tar.h
+ * @brief Constants for reading/writing `.tar` files.
+ */
 
 #include <sys/cdefs.h>
 
+/** `.tar` file magic. (Includes the NUL.) */
 #define TMAGIC "ustar"
+/** `.tar` file magic length in bytes. */
 #define TMAGLEN 6
+/** `.tar` file version. (Does not include the NUL.) */
 #define TVERSION "00"
+/** `.tar` file version length in bytes. */
 #define TVERSLEN 2
 
+/** Regular file type flag. */
 #define REGTYPE '0'
+/** Alternate regular file type flag. */
 #define AREGTYPE '\0'
+/** Link type flag. */
 #define LNKTYPE '1'
+/** Symbolic link type flag. */
 #define SYMTYPE '2'
+/** Character special file type flag. */
 #define CHRTYPE '3'
+/** Block special file type flag. */
 #define BLKTYPE '4'
+/** Directory type flag. */
 #define DIRTYPE '5'
+/** FIFO special file type flag. */
 #define FIFOTYPE '6'
+/** Reserved type flag. */
 #define CONTTYPE '7'
 
+/** Set-UID mode field bit. */
 #define TSUID 04000
+/** Set-GID mode field bit. */
 #define TSGID 02000
+/** Directory restricted deletion mode field bit. */
 #define TSVTX 01000
+/** Readable by user mode field bit. */
 #define TUREAD 00400
+/** Writable by user mode field bit. */
 #define TUWRITE 00200
+/** Executable by user mode field bit. */
 #define TUEXEC 00100
+/** Readable by group mode field bit. */
 #define TGREAD 00040
+/** Writable by group mode field bit. */
 #define TGWRITE 00020
+/** Executable by group mode field bit. */
 #define TGEXEC 00010
+/** Readable by other mode field bit. */
 #define TOREAD 00004
+/** Writable by other mode field bit. */
 #define TOWRITE 00002
+/** Executable by other mode field bit. */
 #define TOEXEC 00001
-
-#endif /* _TAR_H_ */
diff --git a/libc/include/termio.h b/libc/include/termio.h
index 9e26956..9ba3ce8 100644
--- a/libc/include/termio.h
+++ b/libc/include/termio.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file termio.h
+ * @brief Historical alternative to `<termios.h>`.
+ *
+ * New code should use `<termios.h>` directly.
+ */
+
 #include <termios.h>
diff --git a/libc/include/termios.h b/libc/include/termios.h
index 3eaab00..0fd5c95 100644
--- a/libc/include/termios.h
+++ b/libc/include/termios.h
@@ -25,8 +25,13 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef _TERMIOS_H_
-#define _TERMIOS_H_
+
+#pragma once
+
+/**
+ * @file termios.h
+ * @brief General terminal interfaces.
+ */
 
 #include <sys/cdefs.h>
 #include <sys/ioctl.h>
@@ -36,24 +41,112 @@
 __BEGIN_DECLS
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
-// Implemented as static inlines before 21.
+// This file is implemented as static inlines before API level 21.
+
+/**
+ * [cfgetispeed(3)](http://man7.org/linux/man-pages/man3/cfgetispeed.3.html)
+ * returns the terminal input baud rate.
+ */
 speed_t cfgetispeed(const struct termios* __t) __INTRODUCED_IN(21);
+
+/**
+ * [cfgetospeed(3)](http://man7.org/linux/man-pages/man3/cfgetospeed.3.html)
+ * returns the terminal output baud rate.
+ */
 speed_t cfgetospeed(const struct termios* __t) __INTRODUCED_IN(21);
+
+/**
+ * [cfmakeraw(3)](http://man7.org/linux/man-pages/man3/cfmakeraw.3.html)
+ * configures the terminal for "raw" mode.
+ */
 void cfmakeraw(struct termios* __t) __INTRODUCED_IN(21);
+
+/**
+ * [cfsetspeed(3)](http://man7.org/linux/man-pages/man3/cfsetspeed.3.html)
+ * sets the terminal input and output baud rate.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int cfsetspeed(struct termios* __t, speed_t __speed) __INTRODUCED_IN(21);
+
+/**
+ * [cfsetispeed(3)](http://man7.org/linux/man-pages/man3/cfsetispeed.3.html)
+ * sets the terminal input baud rate.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int cfsetispeed(struct termios* __t, speed_t __speed) __INTRODUCED_IN(21);
+
+/**
+ * [cfsetospeed(3)](http://man7.org/linux/man-pages/man3/cfsetospeed.3.html)
+ * sets the terminal output baud rate.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int cfsetospeed(struct termios* __t, speed_t __speed) __INTRODUCED_IN(21);
+
+/**
+ * [tcdrain(3)](http://man7.org/linux/man-pages/man3/tcdrain.3.html)
+ * waits until all output has been written.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int tcdrain(int __fd) __INTRODUCED_IN(21);
+
+/**
+ * [tcflow(3)](http://man7.org/linux/man-pages/man3/tcflow.3.html)
+ * suspends (`TCOOFF`) or resumes (`TCOON`) output, or transmits a
+ * stop (`TCIOFF`) or start (`TCION`) to suspend or resume input.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int tcflow(int __fd, int __action) __INTRODUCED_IN(21);
+
+/**
+ * [tcflush(3)](http://man7.org/linux/man-pages/man3/tcflush.3.html)
+ * discards pending input (`TCIFLUSH`), output (`TCOFLUSH`), or
+ * both (`TCIOFLUSH`). (In `<stdio.h>` terminology, this is a purge rather
+ * than a flush.)
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int tcflush(int __fd, int __queue) __INTRODUCED_IN(21);
+
+/**
+ * [tcgetattr(3)](http://man7.org/linux/man-pages/man3/tcgetattr.3.html)
+ * reads the configuration of the given terminal.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int tcgetattr(int __fd, struct termios* __t) __INTRODUCED_IN(21);
+
+/**
+ * [tcgetsid(3)](http://man7.org/linux/man-pages/man3/tcgetsid.3.html)
+ * returns the session id corresponding to the given fd.
+ *
+ * Returns a non-negative session id on success and
+ * returns -1 and sets `errno` on failure.
+ */
 pid_t tcgetsid(int __fd) __INTRODUCED_IN(21);
+
+/**
+ * [tcsendbreak(3)](http://man7.org/linux/man-pages/man3/tcsendbreak.3.html)
+ * sends a break.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int tcsendbreak(int __fd, int __duration) __INTRODUCED_IN(21);
+
+/**
+ * [tcsetattr(3)](http://man7.org/linux/man-pages/man3/tcsetattr.3.html)
+ * writes the configuration of the given terminal.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int tcsetattr(int __fd, int __optional_actions, const struct termios* __t) __INTRODUCED_IN(21);
+
 #endif
 
 __END_DECLS
 
 #include <android/legacy_termios_inlines.h>
-
-#endif
diff --git a/libc/include/uchar.h b/libc/include/uchar.h
index e59d6a9..90af651 100644
--- a/libc/include/uchar.h
+++ b/libc/include/uchar.h
@@ -26,8 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _UCHAR_H_
-#define _UCHAR_H_
+#pragma once
+
+/**
+ * @file uchar.h
+ * @brief Unicode functions.
+ */
 
 #include <stddef.h>
 #include <sys/cdefs.h>
@@ -36,18 +40,54 @@
 __BEGIN_DECLS
 
 #if !defined(__cplusplus)
+/** The UTF-16 character type. */
 typedef __CHAR16_TYPE__ char16_t;
+/** The UTF-32 character type. */
 typedef __CHAR32_TYPE__ char32_t;
 #endif
 
+/** On Android, char16_t is UTF-16. */
 #define __STD_UTF_16__ 1
+
+/** On Android, char32_t is UTF-32. */
 #define __STD_UTF_32__ 1
 
-size_t c16rtomb(char* __buf, char16_t __ch16, mbstate_t* __ps) __INTRODUCED_IN(21);
-size_t c32rtomb(char* __buf, char32_t __ch32, mbstate_t* __ps) __INTRODUCED_IN(21);
-size_t mbrtoc16(char16_t* __ch16, const char* __s, size_t __n, mbstate_t* __ps) __INTRODUCED_IN(21);
-size_t mbrtoc32(char32_t* __ch32, const char* __s, size_t __n, mbstate_t* __ps) __INTRODUCED_IN(21);
+/**
+ * [c16rtomb(3)](http://man7.org/linux/man-pages/man3/c16rtomb.3.html) converts a single UTF-16
+ * character to UTF-8.
+ *
+ * Returns the number of bytes written to `__buf` on success, and returns -1 and sets `errno`
+ * on failure.
+ *
+ * Available since API level 21.
+ */
+size_t c16rtomb(char* _Nullable __buf, char16_t __ch16, mbstate_t* _Nullable __ps) __INTRODUCED_IN(21);
+
+/**
+ * [c32rtomb(3)](http://man7.org/linux/man-pages/man3/c32rtomb.3.html) converts a single UTF-32
+ * character to UTF-8.
+ *
+ * Returns the number of bytes written to `__buf` on success, and returns -1 and sets `errno`
+ * on failure.
+ *
+ * Available since API level 21.
+ */
+size_t c32rtomb(char* _Nullable __buf, char32_t __ch32, mbstate_t* _Nullable __ps) __INTRODUCED_IN(21);
+
+/**
+ * [mbrtoc16(3)](http://man7.org/linux/man-pages/man3/mbrtoc16.3.html) converts the next UTF-8
+ * sequence to a UTF-16 code point.
+ *
+ * Available since API level 21.
+ */
+size_t mbrtoc16(char16_t* _Nullable __ch16, const char* _Nullable __s, size_t __n, mbstate_t* _Nullable __ps) __INTRODUCED_IN(21);
+
+/**
+ * [mbrtoc32(3)](http://man7.org/linux/man-pages/man3/mbrtoc32.3.html) converts the next UTF-8
+ * sequence to a UTF-32 code point.
+ *
+ * Available since API level 21.
+ */
+size_t mbrtoc32(char32_t* _Nullable __ch32, const char* _Nullable __s, size_t __n, mbstate_t* _Nullable __ps) __INTRODUCED_IN(21);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/ucontext.h b/libc/include/ucontext.h
index 73c2166..99201d2 100644
--- a/libc/include/ucontext.h
+++ b/libc/include/ucontext.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file ucontext.h
+ * @brief Historical alternative to `<sys/ucontext.h>`.
+ *
+ * New code should use `<sys/ucontext.h>` directly.
+ */
+
 #include <sys/ucontext.h>
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index e0f8b43..90173aa 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _UNISTD_H_
-#define _UNISTD_H_
+#pragma once
 
 #include <stddef.h>
 #include <sys/cdefs.h>
@@ -102,20 +101,100 @@
 
 int nice(int __incr);
 
-int setuid(uid_t __uid);
-uid_t getuid(void);
-int seteuid(uid_t __uid);
-uid_t geteuid(void);
-int setgid(gid_t __gid);
-gid_t getgid(void);
+/**
+ * [setegid(2)](http://man7.org/linux/man-pages/man2/setegid.2.html) sets
+ * the effective group ID.
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
 int setegid(gid_t __gid);
+
+/**
+ * [seteuid(2)](http://man7.org/linux/man-pages/man2/seteuid.2.html) sets
+ * the effective user ID.
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int seteuid(uid_t __uid);
+
+/**
+ * [setgid(2)](http://man7.org/linux/man-pages/man2/setgid.2.html) sets
+ * the group ID.
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int setgid(gid_t __gid);
+
+/**
+ * [setregid(2)](http://man7.org/linux/man-pages/man2/setregid.2.html) sets
+ * the real and effective group IDs (use -1 to leave an ID unchanged).
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int setregid(gid_t __rgid, gid_t __egid);
+
+/**
+ * [setresgid(2)](http://man7.org/linux/man-pages/man2/setresgid.2.html) sets
+ * the real, effective, and saved group IDs (use -1 to leave an ID unchanged).
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int setresgid(gid_t __rgid, gid_t __egid, gid_t __sgid);
+
+/**
+ * [setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html) sets
+ * the real, effective, and saved user IDs (use -1 to leave an ID unchanged).
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int setresuid(uid_t __ruid, uid_t __euid, uid_t __suid);
+
+/**
+ * [setreuid(2)](http://man7.org/linux/man-pages/man2/setreuid.2.html) sets
+ * the real and effective group IDs (use -1 to leave an ID unchanged).
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int setreuid(uid_t __ruid, uid_t __euid);
+
+/**
+ * [setuid(2)](http://man7.org/linux/man-pages/man2/setuid.2.html) sets
+ * the user ID.
+ *
+ * On Android, this function only affects the calling thread, not all threads
+ * in the process.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int setuid(uid_t __uid);
+
+uid_t getuid(void);
+uid_t geteuid(void);
+gid_t getgid(void);
 gid_t getegid(void);
 int getgroups(int __size, gid_t* __list);
 int setgroups(size_t __size, const gid_t* __list);
-int setreuid(uid_t __ruid, uid_t __euid);
-int setregid(gid_t __rgid, gid_t __egid);
-int setresuid(uid_t __ruid, uid_t __euid, uid_t __suid);
-int setresgid(gid_t __rgid, gid_t __egid, gid_t __sgid);
 int getresuid(uid_t* __ruid, uid_t* __euid, uid_t* __suid);
 int getresgid(gid_t* __rgid, gid_t* __egid, gid_t* __sgid);
 char* getlogin(void);
@@ -239,9 +318,9 @@
 void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
+#define _UNISTD_H_
 #include <bits/fortify/unistd.h>
+#undef _UNISTD_H_
 #endif
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/utime.h b/libc/include/utime.h
index be6b894..4d181a8 100644
--- a/libc/include/utime.h
+++ b/libc/include/utime.h
@@ -26,8 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _UTIME_H_
-#define _UTIME_H_
+#pragma once
+
+/**
+ * @file utime.h
+ * @brief Historical access/modification time functionality.
+ */
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
@@ -35,8 +39,14 @@
 
 __BEGIN_DECLS
 
-int utime(const char* __filename, const struct utimbuf* __times);
+/**
+ * [utime(2)](http://man7.org/linux/man-pages/man2/utime.2.html) changes the access and
+ * modification time of `__filename`. If `__times` is null, the current time is used.
+ *
+ * New code should prefer utimensat().
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
+int utime(const char* _Nonnull __filename, const struct utimbuf* _Nullable __times);
 
 __END_DECLS
-
-#endif
diff --git a/libc/include/wait.h b/libc/include/wait.h
index d01b811..e375daa 100644
--- a/libc/include/wait.h
+++ b/libc/include/wait.h
@@ -1 +1,10 @@
+#pragma once
+
+/**
+ * @file wait.h
+ * @brief Historical alternative to `<sys/wait.h>`.
+ *
+ * New code should use `<sys/wait.h>` directly.
+ */
+
 #include <sys/wait.h>
diff --git a/libc/include/xlocale.h b/libc/include/xlocale.h
index 559d24d..d04a711 100644
--- a/libc/include/xlocale.h
+++ b/libc/include/xlocale.h
@@ -26,13 +26,24 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _XLOCALE_H_
-#define _XLOCALE_H_
+#pragma once
+
+/**
+ * @file xlocale.h
+ * @brief `locale_t` definition.
+ *
+ * Most users will want `<locale.h>` instead. `<xlocale.h>` is used by the C
+ * library itself to export the `locale_t` type without exporting the
+ * `<locale.h>` functions in other headers that export locale-sensitive
+ * functions (such as `<string.h>`).
+ */
 
 #include <sys/cdefs.h>
 
-/* If we just use void* here, GCC exposes that in error messages. */
+/* If we just use void* in the typedef, the compiler exposes that in error messages. */
 struct __locale_t;
-typedef struct __locale_t* locale_t;
 
-#endif /* _XLOCALE_H_ */
+/**
+ * The `locale_t` type that represents a locale.
+ */
+typedef struct __locale_t* locale_t;
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 6d39812..8fb07f7 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1426,8 +1426,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 1cf48b1..8c5eb89 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1347,8 +1347,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 135206e..c5f0910 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1451,8 +1451,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index a330a45..fbaf508 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1410,8 +1410,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 1cf48b1..8c5eb89 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1347,8 +1347,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 7a2fe9a..db86e55 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1408,8 +1408,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 1cf48b1..8c5eb89 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1347,8 +1347,12 @@
     android_fdsan_close_with_tag;
     android_fdsan_create_owner_tag;
     android_fdsan_exchange_owner_tag;
+    android_fdsan_get_owner_tag;
+    android_fdsan_get_tag_type;
+    android_fdsan_get_tag_value;
     android_fdsan_get_error_level;
     android_fdsan_set_error_level;
+    pthread_sigqueue;
     timespec_get;
 } LIBC_P;
 
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 20afdec..7a6b098 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -26,7 +26,6 @@
 #include <async_safe/log.h>
 
 #include "private/bionic_macros.h"
-#include "private/bionic_prctl.h"
 
 template <typename T>
 union WriteProtectedContents {
diff --git a/libc/private/bionic_inline_raise.h b/libc/private/bionic_inline_raise.h
new file mode 100644
index 0000000..7223b4e
--- /dev/null
+++ b/libc/private/bionic_inline_raise.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// An inline version of pthread_sigqueue(pthread_self(), ...), to reduce the number of
+// uninteresting stack frames at the top of a crash.
+static inline __always_inline void inline_raise(int sig, void* value = nullptr) {
+  // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
+  // http://b/37769298
+  pid_t pid = syscall(__NR_getpid);
+  pid_t tid = syscall(__NR_gettid);
+  siginfo_t info = {};
+  info.si_code = SI_QUEUE;
+  info.si_pid = pid;
+  info.si_uid = getuid();
+  info.si_value.sival_ptr = value;
+
+#if defined(__arm__)
+  register long r0 __asm__("r0") = pid;
+  register long r1 __asm__("r1") = tid;
+  register long r2 __asm__("r2") = sig;
+  register long r3 __asm__("r3") = reinterpret_cast<long>(&info);
+  register long r7 __asm__("r7") = __NR_rt_tgsigqueueinfo;
+  __asm__("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r7) : "memory");
+#elif defined(__aarch64__)
+  register long x0 __asm__("x0") = pid;
+  register long x1 __asm__("x1") = tid;
+  register long x2 __asm__("x2") = sig;
+  register long x3 __asm__("x3") = reinterpret_cast<long>(&info);
+  register long x8 __asm__("x8") = __NR_rt_tgsigqueueinfo;
+  __asm__("svc #0" : "=r"(x0) : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
+#else
+  syscall(__NR_rt_tgsigqueueinfo, pid, tid, sig, &info);
+#endif
+}
+
diff --git a/libc/private/bionic_prctl.h b/libc/private/bionic_prctl.h
deleted file mode 100644
index 103cccb..0000000
--- a/libc/private/bionic_prctl.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BIONIC_PRCTL_H
-#define BIONIC_PRCTL_H
-
-#include <sys/prctl.h>
-
-// This is only supported by Android kernels, so it's not in the uapi headers.
-#define PR_SET_VMA   0x53564d41
-#define PR_SET_VMA_ANON_NAME    0
-
-#endif // BIONIC_PRCTL_H
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index a14963e..d99d09c 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -43,6 +43,7 @@
 #include "printf_common.h"
 
 int FUNCTION_NAME(FILE* fp, const CHAR_TYPE* fmt0, va_list ap) {
+  int caller_errno = errno;
   int n, n2;
   CHAR_TYPE* cp;            /* handy char pointer (short term usage) */
   CHAR_TYPE sign;           /* sign prefix (' ', '+', '-', or \0) */
@@ -451,6 +452,9 @@
         break;
       case 'n':
         __fortify_fatal("%%n not allowed on Android");
+      case 'm':
+        cp = strerror_r(caller_errno, buf, sizeof(buf));
+        goto string;
       case 'O':
         flags |= LONGINT;
         __BIONIC_FALLTHROUGH;
@@ -493,6 +497,7 @@
         } else if ((cp = GETARG(char*)) == nullptr) {
           cp = const_cast<char*>("(null)");
         }
+  string:
         if (prec >= 0) {
           size = CHAR_TYPE_STRNLEN(cp, prec);
         } else {
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index 1c3b80d..dd51eec 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -43,6 +43,7 @@
 #include "printf_common.h"
 
 int FUNCTION_NAME(FILE* fp, const CHAR_TYPE* fmt0, va_list ap) {
+  int caller_errno = errno;
   int n, n2;
   CHAR_TYPE* cp;   /* handy char pointer (short term usage) */
   CHAR_TYPE sign;  /* sign prefix (' ', '+', '-', or \0) */
@@ -436,6 +437,17 @@
         break;
       case 'n':
         __fortify_fatal("%%n not allowed on Android");
+      case 'm':
+        free(convbuf);
+        convbuf = helpers::mbsconv(strerror_r(caller_errno,
+                                              reinterpret_cast<char*>(buf), sizeof(buf)), prec);
+        if (convbuf == nullptr) {
+            fp->_flags |= __SERR;
+            goto error;
+        } else {
+            cp = convbuf;
+        }
+        goto string;
       case 'O':
         flags |= LONGINT;
         __BIONIC_FALLTHROUGH;
@@ -474,6 +486,7 @@
             cp = convbuf;
           }
         }
+  string:
         if (prec >= 0) {
           size = CHAR_TYPE_STRNLEN(cp, prec);
         } else {
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index a26bee4..bd6ac3d 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -36,12 +36,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <sys/types.h>
 
-/* BEGIN android-changed */
-#include "private/bionic_prctl.h"
-/* END android-changed */
-
 static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
 #define _ATEXIT_LOCK() pthread_mutex_lock(&g_atexit_lock)
 #define _ATEXIT_UNLOCK() pthread_mutex_unlock(&g_atexit_lock)
diff --git a/libc/system_properties/contexts_serialized.cpp b/libc/system_properties/contexts_serialized.cpp
index 12e9715..6ccd46c 100644
--- a/libc/system_properties/contexts_serialized.cpp
+++ b/libc/system_properties/contexts_serialized.cpp
@@ -31,6 +31,7 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -38,7 +39,6 @@
 
 #include <async_safe/log.h>
 
-#include "private/bionic_prctl.h"
 #include "system_properties/system_properties.h"
 
 bool ContextsSerialized::InitializeContextNodes() {
diff --git a/libc/upstream-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
index afa8d14..5f0b15e 100644
--- a/libc/upstream-openbsd/android/include/arc4random.h
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -26,11 +26,10 @@
 #include <pthread.h>
 #include <signal.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 
 #include <async_safe/log.h>
 
-#include "private/bionic_prctl.h"
-
 // Android gets these from "thread_private.h".
 #include "thread_private.h"
 //static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
diff --git a/libm/arm/fenv.c b/libm/arm/fenv.c
index c988e4f..67c6456 100644
--- a/libm/arm/fenv.c
+++ b/libm/arm/fenv.c
@@ -1,126 +1,34 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 1. Redistributions of source code must retain the above copyright
+ *  * Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
- * 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.
+ *  * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.1 2004/06/06 10:03:59 das Exp $
  */
 
 #include <fenv.h>
 
-#define FPSCR_RMODE_SHIFT 22
+#define __BIONIC_FENV_INLINE /* Out of line. */
+#include <bits/fenv_inlines_arm.h>
 
 const fenv_t __fe_dfl_env = 0;
-
-int fegetenv(fenv_t* __envp) {
-  fenv_t _fpscr;
-  __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
-  *__envp = _fpscr;
-  return 0;
-}
-
-int fesetenv(const fenv_t* __envp) {
-  fenv_t _fpscr = *__envp;
-  __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
-  return 0;
-}
-
-int feclearexcept(int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  __fpscr &= ~__excepts;
-  fesetenv(&__fpscr);
-  return 0;
-}
-
-int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  *__flagp = __fpscr & __excepts;
-  return 0;
-}
-
-int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  __fpscr &= ~__excepts;
-  __fpscr |= *__flagp & __excepts;
-  fesetenv(&__fpscr);
-  return 0;
-}
-
-int feraiseexcept(int __excepts) {
-  fexcept_t __ex = __excepts;
-  fesetexceptflag(&__ex, __excepts);
-  return 0;
-}
-
-int fetestexcept(int __excepts) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  return (__fpscr & __excepts);
-}
-
-int fegetround(void) {
-  fenv_t _fpscr;
-  fegetenv(&_fpscr);
-  return ((_fpscr >> FPSCR_RMODE_SHIFT) & 0x3);
-}
-
-int fesetround(int __round) {
-  fenv_t _fpscr;
-  fegetenv(&_fpscr);
-  _fpscr &= ~(0x3 << FPSCR_RMODE_SHIFT);
-  _fpscr |= (__round << FPSCR_RMODE_SHIFT);
-  fesetenv(&_fpscr);
-  return 0;
-}
-
-int feholdexcept(fenv_t* __envp) {
-  fenv_t __env;
-  fegetenv(&__env);
-  *__envp = __env;
-  __env &= ~FE_ALL_EXCEPT;
-  fesetenv(&__env);
-  return 0;
-}
-
-int feupdateenv(const fenv_t* __envp) {
-  fexcept_t __fpscr;
-  fegetenv(&__fpscr);
-  fesetenv(__envp);
-  feraiseexcept(__fpscr & FE_ALL_EXCEPT);
-  return 0;
-}
-
-int feenableexcept(int __mask __unused) {
-  return -1;
-}
-
-int fedisableexcept(int __mask __unused) {
-  return 0;
-}
-
-int fegetexcept(void) {
-  return 0;
-}
diff --git a/libm/mips/fenv.c b/libm/mips/fenv.c
index aacd526..f380b74 100644
--- a/libm/mips/fenv.c
+++ b/libm/mips/fenv.c
@@ -1,156 +1,34 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 1. Redistributions of source code must retain the above copyright
+ *  * Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
- * 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.
+ *  * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
  */
 
 #include <fenv.h>
 
-#define FCSR_CAUSE_SHIFT 10
-#define FCSR_ENABLE_SHIFT 5
-#define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT)
+#define __BIONIC_FENV_INLINE /* Out of line. */
+#include <bits/fenv_inlines_mips.h>
 
-#define FCSR_RMASK       0x3
-
-/*
- * Hopefully the system ID byte is immutable, so it's valid to use
- * this as a default environment.
- */
 const fenv_t __fe_dfl_env = 0;
-
-int fegetenv(fenv_t* __envp) {
-  fenv_t _fcsr = 0;
-#ifdef  __mips_hard_float
-  __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
-#endif
-  *__envp = _fcsr;
-  return 0;
-}
-
-int fesetenv(const fenv_t* __envp) {
-  fenv_t _fcsr = *__envp;
-#ifdef  __mips_hard_float
-  __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
-#endif
-  return 0;
-}
-
-int feclearexcept(int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  __excepts &= FE_ALL_EXCEPT;
-  __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT));
-  fesetenv(&__fcsr);
-  return 0;
-}
-
-int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
-  return 0;
-}
-
-int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  /* Ensure that flags are all legal */
-  __excepts &= FE_ALL_EXCEPT;
-  __fcsr &= ~__excepts;
-  __fcsr |= *__flagp & __excepts;
-  fesetenv(&__fcsr);
-  return 0;
-}
-
-int feraiseexcept(int __excepts) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  /* Ensure that flags are all legal */
-  __excepts &= FE_ALL_EXCEPT;
-  /* Cause bit needs to be set as well for generating the exception*/
-  __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT);
-  fesetenv(&__fcsr);
-  return 0;
-}
-
-int fetestexcept(int __excepts) {
-  fexcept_t __FCSR;
-  fegetenv(&__FCSR);
-  return (__FCSR & __excepts & FE_ALL_EXCEPT);
-}
-
-int fegetround(void) {
-  fenv_t _fcsr;
-  fegetenv(&_fcsr);
-  return (_fcsr & FCSR_RMASK);
-}
-
-int fesetround(int __round) {
-  fenv_t _fcsr;
-  fegetenv(&_fcsr);
-  _fcsr &= ~FCSR_RMASK;
-  _fcsr |= (__round & FCSR_RMASK);
-  fesetenv(&_fcsr);
-  return 0;
-}
-
-int feholdexcept(fenv_t* __envp) {
-  fenv_t __env;
-  fegetenv(&__env);
-  *__envp = __env;
-  __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK);
-  fesetenv(&__env);
-  return 0;
-}
-
-int feupdateenv(const fenv_t* __envp) {
-  fexcept_t __fcsr;
-  fegetenv(&__fcsr);
-  fesetenv(__envp);
-  feraiseexcept(__fcsr & FE_ALL_EXCEPT);
-  return 0;
-}
-
-int feenableexcept(int __mask) {
-  fenv_t __old_fcsr, __new_fcsr;
-  fegetenv(&__old_fcsr);
-  __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT;
-  fesetenv(&__new_fcsr);
-  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-int fedisableexcept(int __mask) {
-  fenv_t __old_fcsr, __new_fcsr;
-  fegetenv(&__old_fcsr);
-  __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT);
-  fesetenv(&__new_fcsr);
-  return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-int fegetexcept(void) {
-  fenv_t __fcsr;
-  fegetenv(&__fcsr);
-  return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT);
-}
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 4b84537..dfe8e8c 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -303,9 +303,7 @@
 static soinfo* __libdl_info = nullptr;
 
 // This is used by the dynamic linker. Every process gets these symbols for free.
-soinfo* get_libdl_info(const char* linker_path,
-                       const soinfo& linker_si,
-                       const link_map& linker_map) {
+soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si) {
   CHECK((linker_si.flags_ & FLAG_GNU_HASH) != 0);
 
   if (__libdl_info == nullptr) {
@@ -314,6 +312,8 @@
     __libdl_info->strtab_ = linker_si.strtab_;
     __libdl_info->symtab_ = linker_si.symtab_;
     __libdl_info->load_bias = linker_si.load_bias;
+    __libdl_info->phdr = linker_si.phdr;
+    __libdl_info->phnum = linker_si.phnum;
 
     __libdl_info->gnu_nbucket_ = linker_si.gnu_nbucket_;
     __libdl_info->gnu_maskwords_ = linker_si.gnu_maskwords_;
@@ -328,9 +328,6 @@
     __libdl_info->soname_ = linker_si.soname_;
     __libdl_info->target_sdk_version_ = __ANDROID_API__;
     __libdl_info->generate_handle();
-    __libdl_info->link_map_head.l_addr = linker_map.l_addr;
-    __libdl_info->link_map_head.l_name = linker_map.l_name;
-    __libdl_info->link_map_head.l_ld = linker_map.l_ld;
 #if defined(__work_around_b_24465209__)
     strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_));
 #endif
diff --git a/linker/linker.h b/linker/linker.h
index 260c89d..7aa7e5f 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -99,9 +99,7 @@
 
 void count_relocation(RelocationKind kind);
 
-soinfo* get_libdl_info(const char* linker_path,
-                       const soinfo& linker_si,
-                       const link_map& linker_map);
+soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si);
 
 soinfo* find_containing_library(const void* p);
 
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index a37e910..de3309b 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -35,12 +35,11 @@
 
 #include <stdlib.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <unistd.h>
 
 #include <async_safe/log.h>
 
-#include "private/bionic_prctl.h"
-
 //
 // LinkerMemeoryAllocator is general purpose allocator
 // designed to provide the same functionality as the malloc/free/realloc
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index 82e4ef4..8c4198b 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -32,6 +32,7 @@
 #include <stdlib.h>
 #include <sys/cdefs.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <stddef.h>
 #include <unistd.h>
 
@@ -39,8 +40,6 @@
 
 #include <async_safe/log.h>
 
-#include "private/bionic_prctl.h"
-
 const uint32_t kSmallObjectMaxSizeLog2 = 10;
 const uint32_t kSmallObjectMinSizeLog2 = 4;
 const uint32_t kSmallObjectAllocatorsCount = kSmallObjectMaxSizeLog2 - kSmallObjectMinSizeLog2 + 1;
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index abb1ebd..dca944e 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -30,10 +30,9 @@
 #include <inttypes.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <unistd.h>
 
-#include "private/bionic_prctl.h"
-
 // the multiplier should be power of 2
 static constexpr size_t round_up(size_t size, size_t multiplier) {
   return (size + (multiplier - 1)) & ~(multiplier-1);
diff --git a/linker/linker_cfi.cpp b/linker/linker_cfi.cpp
index 8910c3f..782ebc6 100644
--- a/linker/linker_cfi.cpp
+++ b/linker/linker_cfi.cpp
@@ -31,9 +31,9 @@
 #include "linker_debug.h"
 #include "linker_globals.h"
 #include "private/bionic_page.h"
-#include "private/bionic_prctl.h"
 
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <sys/types.h>
 #include <cstdint>
 
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index af47619..c5e0b96 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -67,6 +67,7 @@
 static soinfo* solist;
 static soinfo* sonext;
 static soinfo* somain; // main process, always the one after libdl_info
+static soinfo* solinker;
 static soinfo* vdso; // vdso if present
 
 void solist_add_soinfo(soinfo* si) {
@@ -170,29 +171,13 @@
   vdso = si;
 }
 
-/* gdb expects the linker to be in the debug shared object list.
- * Without this, gdb has trouble locating the linker's ".text"
- * and ".plt" sections. Gdb could also potentially use this to
- * relocate the offset of our exported 'rtld_db_dlactivity' symbol.
- * Note that the linker shouldn't be on the soinfo list.
- */
-static link_map linker_link_map;
-
-static void init_linker_info_for_gdb(ElfW(Addr) linker_base, char* linker_path) {
-  linker_link_map.l_addr = linker_base;
-  linker_link_map.l_name = linker_path;
-
-  /*
-   * Set the dynamic field in the link map otherwise gdb will complain with
-   * the following:
-   *   warning: .dynamic section for "/system/bin/linker" is not at the
-   *   expected address (wrong library or version mismatch?)
-   */
-  ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_base);
-  ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_base + elf_hdr->e_phoff);
-  phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base,
-                                 &linker_link_map.l_ld, nullptr);
-
+// Initializes an soinfo's link_map_head field using other fields from the
+// soinfo (phdr, phnum, load_bias).
+static void init_link_map_head(soinfo& info, const char* linker_path) {
+  auto& map = info.link_map_head;
+  map.l_addr = info.load_bias;
+  map.l_name = const_cast<char*>(linker_path);
+  phdr_table_get_dynamic_section(info.phdr, info.phnum, info.load_bias, &map.l_ld, nullptr);
 }
 
 extern "C" int __system_properties_init(void);
@@ -303,32 +288,32 @@
     stat("/init", &file_stat);
   }
 
+  // Initialize the main exe's soinfo.
   const char* executable_path = get_executable_path();
   soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL);
-
-  // Bootstrap the link map, the main exe always needs to be first.
+  somain = si;
+  si->phdr = reinterpret_cast<ElfW(Phdr)*>(args.getauxval(AT_PHDR));
+  si->phnum = args.getauxval(AT_PHNUM);
+  get_elf_base_from_phdr(si->phdr, si->phnum, &si->base, &si->load_bias);
+  si->size = phdr_table_get_load_size(si->phdr, si->phnum);
+  si->dynamic = nullptr;
   si->set_main_executable();
-  link_map* map = &(si->link_map_head);
+  init_link_map_head(*si, executable_path);
 
   // Register the main executable and the linker upfront to have
   // gdb aware of them before loading the rest of the dependency
   // tree.
-  map->l_addr = 0;
-  map->l_name = const_cast<char*>(executable_path);
-  insert_link_map_into_debug_map(map);
-  insert_link_map_into_debug_map(&linker_link_map);
+  //
+  // gdb expects the linker to be in the debug shared object list.
+  // Without this, gdb has trouble locating the linker's ".text"
+  // and ".plt" sections. Gdb could also potentially use this to
+  // relocate the offset of our exported 'rtld_db_dlactivity' symbol.
+  //
+  insert_link_map_into_debug_map(&si->link_map_head);
+  insert_link_map_into_debug_map(&solinker->link_map_head);
 
   add_vdso(args);
 
-  // Extract information passed from the kernel.
-  si->phdr = reinterpret_cast<ElfW(Phdr)*>(args.getauxval(AT_PHDR));
-  si->phnum = args.getauxval(AT_PHNUM);
-
-  get_elf_base_from_phdr(si->phdr, si->phnum, &si->base, &si->load_bias);
-  si->size = phdr_table_get_load_size(si->phdr, si->phnum);
-
-  si->dynamic = nullptr;
-
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
 
   // We haven't supported non-PIE since Lollipop for security reasons.
@@ -351,8 +336,6 @@
   parse_LD_LIBRARY_PATH(ldpath_env);
   parse_LD_PRELOAD(ldpreload_env);
 
-  somain = si;
-
   std::vector<android_namespace_t*> namespaces = init_default_namespaces(executable_path);
 
   if (!si->prelink_image()) __linker_cannot_link(g_argv[0]);
@@ -411,13 +394,6 @@
   __get_tls()[TLS_SLOT_BIONIC_PREINIT] = &args;
 
   si->call_pre_init_constructors();
-
-  /* After the prelink_image, the si->load_bias is initialized.
-   * For so lib, the map->l_addr will be updated in notify_gdb_of_load.
-   * We need to update this value for so exe here. So Unwind_Backtrace
-   * for some arch like x86 could work correctly within so exe.
-   */
-  map->l_addr = si->load_bias;
   si->call_constructors();
 
 #if TIMING
@@ -508,9 +484,7 @@
 }
 
 static ElfW(Addr) __attribute__((noinline))
-__linker_init_post_relocation(KernelArgumentBlock& args,
-                              ElfW(Addr) linker_addr,
-                              soinfo& linker_so);
+__linker_init_post_relocation(KernelArgumentBlock& args, soinfo& linker_so);
 
 /*
  * This is the entry point for the linker, called from begin.S. This
@@ -543,18 +517,18 @@
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
   ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
 
-  soinfo linker_so(nullptr, nullptr, nullptr, 0, 0);
+  soinfo tmp_linker_so(nullptr, nullptr, nullptr, 0, 0);
 
-  linker_so.base = linker_addr;
-  linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
-  linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);
-  linker_so.dynamic = nullptr;
-  linker_so.phdr = phdr;
-  linker_so.phnum = elf_hdr->e_phnum;
-  linker_so.set_linker_flag();
+  tmp_linker_so.base = linker_addr;
+  tmp_linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
+  tmp_linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);
+  tmp_linker_so.dynamic = nullptr;
+  tmp_linker_so.phdr = phdr;
+  tmp_linker_so.phnum = elf_hdr->e_phnum;
+  tmp_linker_so.set_linker_flag();
 
   // Prelink the linker so we can access linker globals.
-  if (!linker_so.prelink_image()) __linker_cannot_link(args.argv[0]);
+  if (!tmp_linker_so.prelink_image()) __linker_cannot_link(args.argv[0]);
 
   // This might not be obvious... The reasons why we pass g_empty_list
   // in place of local_group here are (1) we do not really need it, because
@@ -562,9 +536,9 @@
   // itself without having to look into local_group and (2) allocators
   // are not yet initialized, and therefore we cannot use linked_list.push_*
   // functions at this point.
-  if (!linker_so.link_image(g_empty_list, g_empty_list, nullptr)) __linker_cannot_link(args.argv[0]);
+  if (!tmp_linker_so.link_image(g_empty_list, g_empty_list, nullptr)) __linker_cannot_link(args.argv[0]);
 
-  return __linker_init_post_relocation(args, linker_addr, linker_so);
+  return __linker_init_post_relocation(args, tmp_linker_so);
 }
 
 /*
@@ -574,15 +548,13 @@
  * function, so avoid inlining this function (http://b/80503879).
  */
 static ElfW(Addr) __attribute__((noinline))
-__linker_init_post_relocation(KernelArgumentBlock& args,
-                              ElfW(Addr) linker_addr,
-                              soinfo& linker_so) {
+__linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) {
   // Initialize the main thread (including TLS, so system calls really work).
   __libc_init_main_thread(args);
 
   // We didn't protect the linker's RELRO pages in link_image because we
   // couldn't make system calls on x86 at that point, but we can now...
-  if (!linker_so.protect_relro()) __linker_cannot_link(args.argv[0]);
+  if (!tmp_linker_so.protect_relro()) __linker_cannot_link(args.argv[0]);
 
   // Initialize the linker/libc.so shared global inside the linker.
   static libc_shared_globals shared_globals;
@@ -599,7 +571,7 @@
   g_envp = args.envp;
 
   // Initialize the linker's own global variables
-  linker_so.call_constructors();
+  tmp_linker_so.call_constructors();
 
   // If the linker is not acting as PT_INTERP entry_point is equal to
   // _start. Which means that the linker is running as an executable and
@@ -615,13 +587,12 @@
     exit(0);
   }
 
-  init_linker_info_for_gdb(linker_addr, kLinkerPath);
-
   // Initialize static variables. Note that in order to
   // get correct libdl_info we need to call constructors
   // before get_libdl_info().
-  sonext = solist = get_libdl_info(kLinkerPath, linker_so, linker_link_map);
-  g_default_namespace.add_soinfo(solist);
+  sonext = solist = solinker = get_libdl_info(kLinkerPath, tmp_linker_so);
+  g_default_namespace.add_soinfo(solinker);
+  init_link_map_head(*solinker, kLinkerPath);
 
   args.abort_message_ptr = &g_abort_message;
   ElfW(Addr) start_address = linker_main(args);
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 54354a8..0a7ccd8 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -41,7 +42,6 @@
 #include "linker_debug.h"
 #include "linker_utils.h"
 
-#include "private/bionic_prctl.h"
 #include "private/CFIShadow.h" // For kLibraryAlignment
 
 static int GetTargetElfMachine() {
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 09e5065..7331b2f 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -361,9 +361,7 @@
   android_namespace_list_t secondary_namespaces_;
   uintptr_t handle_;
 
-  friend soinfo* get_libdl_info(const char* linker_path,
-                                const soinfo& linker_si,
-                                const link_map& linker_map);
+  friend soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si);
 
   // version >= 4
   ElfW(Relr)* relr_;
diff --git a/tests/Android.bp b/tests/Android.bp
index ccd1126..fa66f93 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -112,6 +112,7 @@
         "netinet_ip_icmp_test.cpp",
         "netinet_udp_test.cpp",
         "nl_types_test.cpp",
+        "poll_test.cpp",
         "pthread_test.cpp",
         "pty_test.cpp",
         "regex_test.cpp",
diff --git a/tests/bug_26110743_test.cpp b/tests/bug_26110743_test.cpp
index 89c6dcc..883280f 100644
--- a/tests/bug_26110743_test.cpp
+++ b/tests/bug_26110743_test.cpp
@@ -22,6 +22,8 @@
 #include <sys/stat.h>
 #include <sys/prctl.h>
 
+#include <string>
+
 #include <android-base/scopeguard.h>
 
 extern "C" pid_t gettid();
@@ -35,8 +37,9 @@
   const char* ERRORMSG = "Please apply the following two kernel patches:\n"
     "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=73af963f9f3036dffed55c3a2898598186db1045\n"
     "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=96d0df79f2644fc823f26c06491e182d87a90c2a\n";
-  ASSERT_NE(-1, readlink(buf, buf2, sizeof(buf2))) << ERRORMSG;
-  ASSERT_STREQ("/dev/null", buf2);
+  ssize_t length = readlink(buf, buf2, sizeof(buf2));
+  ASSERT_LT(0, length) << ERRORMSG;
+  ASSERT_EQ("/dev/null", std::string(buf2, length));
   close(fd);
 }
 
@@ -79,8 +82,9 @@
   snprintf(buf, sizeof(buf), "/proc/%d/task/%d/fd/%d", mypid, mytid, fd);
   const char* ERRORMSG = "Please apply the following kernel patch:\n"
     "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=54708d2858e79a2bdda10bf8a20c80eb96c20613\n";
-  ASSERT_NE(-1, readlink(buf, buf2, sizeof(buf2))) << ERRORMSG;
-  ASSERT_STREQ("/dev/null", buf2);
+  ssize_t length = readlink(buf, buf2, sizeof(buf2));
+  ASSERT_LT(0, length) << ERRORMSG;
+  ASSERT_EQ("/dev/null", std::string(buf2, length));
   close(fd);
 }
 
diff --git a/tests/link_test.cpp b/tests/link_test.cpp
index a5430a9..1bdee9f 100644
--- a/tests/link_test.cpp
+++ b/tests/link_test.cpp
@@ -29,6 +29,12 @@
 #include <gtest/gtest.h>
 
 #include <link.h>
+#if __has_include(<sys/auxv.h>)
+#include <sys/auxv.h>
+#endif
+
+#include <string>
+#include <unordered_map>
 
 TEST(link, dl_iterate_phdr_early_exit) {
   static size_t call_count = 0;
@@ -40,7 +46,7 @@
 TEST(link, dl_iterate_phdr) {
   struct Functor {
     static int Callback(dl_phdr_info* i, size_t s, void* data) {
-      reinterpret_cast<Functor*>(data)->DoChecks(i, s);
+      static_cast<Functor*>(data)->DoChecks(i, s);
       return 0;
     }
     void DoChecks(dl_phdr_info* info, size_t s) {
@@ -48,7 +54,12 @@
 
       ASSERT_TRUE(info->dlpi_name != nullptr);
 
+      // An ELF file must have at least a PT_LOAD program header.
+      ASSERT_NE(nullptr, info->dlpi_phdr);
+      ASSERT_NE(0, info->dlpi_phnum);
+
       // Find the first PT_LOAD program header so we can find the ELF header.
+      bool found_load = false;
       for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) {
         const ElfW(Phdr)* phdr = reinterpret_cast<const ElfW(Phdr)*>(&info->dlpi_phdr[i]);
         if (phdr->p_type == PT_LOAD) {
@@ -58,15 +69,124 @@
           ASSERT_EQ(0, memcmp(ehdr, ELFMAG, SELFMAG));
           // Does the e_phnum match what dl_iterate_phdr told us?
           ASSERT_EQ(info->dlpi_phnum, ehdr->e_phnum);
+          found_load = true;
           break;
         }
       }
+      ASSERT_EQ(true, found_load);
     }
     size_t count;
   } f = {};
   ASSERT_EQ(0, dl_iterate_phdr(Functor::Callback, &f));
 }
 
+struct ProgHdr {
+  const ElfW(Phdr)* table;
+  size_t size;
+};
+
+__attribute__((__unused__))
+static ElfW(Addr) find_exe_load_bias(const ProgHdr& phdr) {
+  for (size_t i = 0; i < phdr.size; ++i) {
+    if (phdr.table[i].p_type == PT_PHDR) {
+      return reinterpret_cast<ElfW(Addr)>(phdr.table) - phdr.table[i].p_vaddr;
+    }
+  }
+  return 0;
+}
+
+__attribute__((__unused__))
+static ElfW(Dyn)* find_dynamic(const ProgHdr& phdr, ElfW(Addr) load_bias) {
+  for (size_t i = 0; i < phdr.size; ++i) {
+    if (phdr.table[i].p_type == PT_DYNAMIC) {
+      return reinterpret_cast<ElfW(Dyn)*>(phdr.table[i].p_vaddr + load_bias);
+    }
+  }
+  return nullptr;
+}
+
+__attribute__((__unused__))
+static r_debug* find_exe_r_debug(ElfW(Dyn)* dynamic) {
+  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
+    if (d->d_tag == DT_DEBUG) {
+      return reinterpret_cast<r_debug*>(d->d_un.d_val);
+    }
+  }
+  return nullptr;
+}
+
+// Walk the DT_DEBUG/_r_debug global module list and compare it with the same
+// information from dl_iterate_phdr. Verify that the executable appears first
+// in _r_debug.
+TEST(link, r_debug) {
+#if __has_include(<sys/auxv.h>)
+  // Find the executable's PT_DYNAMIC segment and DT_DEBUG value. The linker
+  // will write the address of its _r_debug global into the .dynamic section.
+  ProgHdr exe_phdr = {
+    .table = reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)),
+    .size = getauxval(AT_PHNUM)
+  };
+  ASSERT_NE(nullptr, exe_phdr.table);
+  ElfW(Addr) exe_load_bias = find_exe_load_bias(exe_phdr);
+  ASSERT_NE(0u, exe_load_bias);
+  ElfW(Dyn)* exe_dynamic = find_dynamic(exe_phdr, exe_load_bias);
+  ASSERT_NE(nullptr, exe_dynamic);
+  r_debug* dbg = find_exe_r_debug(exe_dynamic);
+  ASSERT_NE(nullptr, dbg);
+
+  // Use dl_iterate_phdr to build a table mapping from load bias values to
+  // solib names and PT_DYNAMIC segments.
+  struct DlIterateInfo {
+    std::string name;
+    ElfW(Dyn)* dynamic;
+  };
+  struct Functor {
+    std::unordered_map<ElfW(Addr), DlIterateInfo> dl_iter_mods;
+    static int Callback(dl_phdr_info* i, size_t s, void* data) {
+      static_cast<Functor*>(data)->AddModule(i, s);
+      return 0;
+    }
+    void AddModule(dl_phdr_info* info, size_t s) {
+      ASSERT_EQ(sizeof(dl_phdr_info), s);
+      ASSERT_TRUE(dl_iter_mods.find(info->dlpi_addr) == dl_iter_mods.end());
+      ASSERT_TRUE(info->dlpi_name != nullptr);
+      dl_iter_mods[info->dlpi_addr] = {
+        .name = info->dlpi_name,
+        .dynamic = find_dynamic({ info->dlpi_phdr, info->dlpi_phnum }, info->dlpi_addr)
+      };
+    }
+  } f = {};
+  ASSERT_EQ(0, dl_iterate_phdr(Functor::Callback, &f));
+
+  size_t map_size = 0;
+
+  for (link_map* map = dbg->r_map; map != nullptr; map = map->l_next) {
+    ASSERT_NE(0u, map->l_addr);
+    ASSERT_NE(nullptr, map->l_ld);
+    ASSERT_NE(nullptr, map->l_name);
+
+    auto it = f.dl_iter_mods.find(map->l_addr);
+    ASSERT_TRUE(it != f.dl_iter_mods.end());
+    const DlIterateInfo& info = it->second;
+    ASSERT_EQ(info.name, map->l_name);
+    ASSERT_EQ(info.dynamic, map->l_ld);
+
+    ++map_size;
+  }
+
+  // _r_debug and dl_iterate_phdr should report the same set of modules. We
+  // verified above that every _r_debug module was reported by dl_iterate_phdr,
+  // so checking the sizes verifies the converse.
+  ASSERT_EQ(f.dl_iter_mods.size(), map_size);
+
+  // Make sure the first entry is the executable. gdbserver assumes this and
+  // removes the first entry from its list of shared objects that it sends back
+  // to gdb.
+  ASSERT_EQ(exe_load_bias, dbg->r_map->l_addr);
+  ASSERT_EQ(exe_dynamic, dbg->r_map->l_ld);
+#endif
+}
+
 #if __arm__
 static uintptr_t read_exidx_func(uintptr_t* entry) {
   int32_t offset = *entry;
diff --git a/tests/poll_test.cpp b/tests/poll_test.cpp
new file mode 100644
index 0000000..2a3e5e0
--- /dev/null
+++ b/tests/poll_test.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <poll.h>
+
+TEST(poll, poll_null_fds) {
+  // Because nanosleep(2) is relatively new to POSIX, code sometimes abuses poll.
+  errno = 0;
+  ASSERT_EQ(0, poll(nullptr, 0, 1));
+  ASSERT_EQ(0, errno);
+}
+
+TEST(poll, ppoll_null_fds) {
+  // Because nanosleep(2) is relatively new to POSIX, code sometimes abuses poll.
+  errno = 0;
+  timespec ts = { .tv_nsec = 100 };
+  ASSERT_EQ(0, ppoll(nullptr, 0, &ts, nullptr));
+  ASSERT_EQ(0, errno);
+}
+
+TEST(poll, ppoll64_null_fds) {
+#if __BIONIC__
+  // Because nanosleep(2) is relatively new to POSIX, code sometimes abuses poll.
+  errno = 0;
+  timespec ts = { .tv_nsec = 100 };
+  ASSERT_EQ(0, ppoll64(nullptr, 0, &ts, nullptr));
+  ASSERT_EQ(0, errno);
+#endif
+}
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index cc95ef7..52a097b 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -597,6 +597,42 @@
   ASSERT_EQ(1, g_sigqueue_signal_handler_call_count);
 }
 
+TEST(signal, pthread_sigqueue_self) {
+  ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO);
+  sigval_t sigval;
+  sigval.sival_int = 1;
+  errno = 0;
+  ASSERT_EQ(0, pthread_sigqueue(pthread_self(), SIGALRM, sigval));
+  ASSERT_EQ(0, errno);
+  ASSERT_EQ(1, g_sigqueue_signal_handler_call_count);
+}
+
+TEST(signal, pthread_sigqueue_other) {
+  ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO);
+  sigval_t sigval;
+  sigval.sival_int = 1;
+
+  sigset_t mask;
+  sigfillset(&mask);
+  pthread_sigmask(SIG_SETMASK, &mask, nullptr);
+  pthread_t thread;
+  int rc = pthread_create(&thread, nullptr,
+                          [](void*) -> void* {
+                            sigset_t mask;
+                            sigemptyset(&mask);
+                            sigsuspend(&mask);
+                            return nullptr;
+                          },
+                          nullptr);
+  ASSERT_EQ(0, rc);
+
+  errno = 0;
+  ASSERT_EQ(0, pthread_sigqueue(thread, SIGALRM, sigval));
+  ASSERT_EQ(0, errno);
+  pthread_join(thread, nullptr);
+  ASSERT_EQ(1, g_sigqueue_signal_handler_call_count);
+}
+
 TEST(signal, sigwaitinfo) {
   SignalMaskRestorer smr;
 
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 844a9c0..54b913a 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -2356,6 +2356,52 @@
   ASSERT_EQ(buf, "hello");
 }
 
+TEST(STDIO_TEST, printf_m) {
+  char buf[BUFSIZ];
+  errno = 0;
+  snprintf(buf, sizeof(buf), "<%m>");
+  ASSERT_STREQ("<Success>", buf);
+  errno = -1;
+  snprintf(buf, sizeof(buf), "<%m>");
+  ASSERT_STREQ("<Unknown error -1>", buf);
+  errno = EINVAL;
+  snprintf(buf, sizeof(buf), "<%m>");
+  ASSERT_STREQ("<Invalid argument>", buf);
+}
+
+TEST(STDIO_TEST, printf_m_does_not_clobber_strerror) {
+  char buf[BUFSIZ];
+  const char* m = strerror(-1);
+  ASSERT_STREQ("Unknown error -1", m);
+  errno = -2;
+  snprintf(buf, sizeof(buf), "<%m>");
+  ASSERT_STREQ("<Unknown error -2>", buf);
+  ASSERT_STREQ("Unknown error -1", m);
+}
+
+TEST(STDIO_TEST, wprintf_m) {
+  wchar_t buf[BUFSIZ];
+  errno = 0;
+  swprintf(buf, sizeof(buf), L"<%m>");
+  ASSERT_EQ(std::wstring(L"<Success>"), buf);
+  errno = -1;
+  swprintf(buf, sizeof(buf), L"<%m>");
+  ASSERT_EQ(std::wstring(L"<Unknown error -1>"), buf);
+  errno = EINVAL;
+  swprintf(buf, sizeof(buf), L"<%m>");
+  ASSERT_EQ(std::wstring(L"<Invalid argument>"), buf);
+}
+
+TEST(STDIO_TEST, wprintf_m_does_not_clobber_strerror) {
+  wchar_t buf[BUFSIZ];
+  const char* m = strerror(-1);
+  ASSERT_STREQ("Unknown error -1", m);
+  errno = -2;
+  swprintf(buf, sizeof(buf), L"<%m>");
+  ASSERT_EQ(std::wstring(L"<Unknown error -2>"), buf);
+  ASSERT_STREQ("Unknown error -1", m);
+}
+
 TEST(STDIO_TEST, fopen_append_mode_and_ftell) {
   TemporaryFile tf;
   SetFileTo(tf.filename, "0123456789");
@@ -2506,3 +2552,19 @@
 
   fclose(fp);
 }
+
+TEST(STDIO_TEST, dev_std_files) {
+  // POSIX only mentions /dev/stdout, but we should have all three (http://b/31824379).
+  char path[PATH_MAX];
+  ssize_t length = readlink("/dev/stdin", path, sizeof(path));
+  ASSERT_LT(0, length);
+  ASSERT_EQ("/proc/self/fd/0", std::string(path, length));
+
+  length = readlink("/dev/stdout", path, sizeof(path));
+  ASSERT_LT(0, length);
+  ASSERT_EQ("/proc/self/fd/1", std::string(path, length));
+
+  length = readlink("/dev/stderr", path, sizeof(path));
+  ASSERT_LT(0, length);
+  ASSERT_EQ("/proc/self/fd/2", std::string(path, length));
+}
diff --git a/tests/sys_prctl_test.cpp b/tests/sys_prctl_test.cpp
index 2123c94..7afa626 100644
--- a/tests/sys_prctl_test.cpp
+++ b/tests/sys_prctl_test.cpp
@@ -29,11 +29,10 @@
 
 #include "android-base/file.h"
 #include "android-base/strings.h"
-#include "private/bionic_prctl.h"
 
 // http://b/20017123.
 TEST(sys_prctl, bug_20017123) {
-#if defined(__ANDROID__) // PR_SET_VMA is only available in Android kernels.
+#if defined(PR_SET_VMA) // PR_SET_VMA is only available in Android kernels.
   size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
   void* p = mmap(NULL, page_size * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   ASSERT_NE(MAP_FAILED, p);