Merge "Increase the size of the shadow call stack guard region to 16MB."
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 376c250..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-bionic_mountpoint {
-    name: "libc.mountpoint",
-    stem: "libc.so",
-    src: "dummy_mountpoint",
-    library: true,
-    symlinks: ["libc.so"],
-}
-
-bionic_mountpoint {
-    name: "libdl.mountpoint",
-    stem: "libdl.so",
-    src: "dummy_mountpoint",
-    library: true,
-    symlinks: ["libdl.so"],
-}
-
-bionic_mountpoint {
-    name: "libm.mountpoint",
-    stem: "libm.so",
-    src: "dummy_mountpoint",
-    library: true,
-    symlinks: ["libm.so"],
-}
-
-bionic_mountpoint {
-    name: "linker.mountpoint",
-    stem: "linker",
-    multilib: {
-        lib64: {
-            suffix: "64",
-        },
-    },
-    src: "dummy_mountpoint",
-    binary: true,
-    symlinks: ["linker", "linker_asan"],
-}
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 9421e26..8865723 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -53,6 +53,10 @@
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib/libGLES*)
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib64/libGLES*)
 
+# /bionic is removed
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/bionic)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/bionic)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..e4d3d5e
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsBionicTestCases"
+    }
+  ]
+}
diff --git a/build/Android.bp b/build/Android.bp
deleted file mode 100644
index 6cc160a..0000000
--- a/build/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-
-bootstrap_go_package {
-    name: "soong-bionic",
-    pkgPath: "android/soong/bionic",
-    deps: [
-        "blueprint",
-        "blueprint-pathtools",
-        "blueprint-proptools",
-        "soong",
-        "soong-android",
-    ],
-    srcs: [
-        "bionic.go",
-    ],
-    pluginFor: ["soong_build"],
-}
diff --git a/build/bionic.go b/build/bionic.go
deleted file mode 100644
index 3522aca..0000000
--- a/build/bionic.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright (C) 2019 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.
-
-package bionic
-
-import (
-	"fmt"
-	"io"
-	"strings"
-
-	"github.com/google/blueprint/proptools"
-
-	"android/soong/android"
-)
-
-// bionic_mountpoint is a module type that is specialized to create
-// mount points for Bionic files (libc, libdl, libm, and linker).
-//
-// With following description,
-//
-// bionic_mountpoint {
-//    name: "libc.mountpoint",
-//    stem: "libc.so",
-//    src: "dummy_mountpoint",
-//    library: true,
-//    symlinks: ["libc.so"],
-// }
-//
-// , the build system does following jobs:
-//
-// A mount point /bionic/lib[64]/libc.so is created. Its content
-// is from the file 'dummy_mountpoint'.
-//
-// Then a symlink is created at /system/lib[64]/libc.so which points to
-// the created mountpoint.
-//
-// At runtime, on the mount point, either bootstrap Bionic or default Bionic
-// (which is from the runtime APEX) is mounted by the init process. The
-// symlink exists to provide consistent legacy path for compatibility
-// reason.
-func init() {
-	android.RegisterModuleType("bionic_mountpoint", bionicMountpointFactory)
-}
-
-type bionicMountpoint struct {
-	android.ModuleBase
-	properties bionicMountpointProperties
-
-	outputFile android.Path
-	pathInPartition string
-	stem string
-}
-
-type bionicMountpointProperties struct {
-	// The file that is installed as the mount point
-	Src *string
-
-	// True if the mount point is for a Bionic library such libc.so
-	Library *bool
-	// True if the mount point is for a Bionic binary such as linker
-	Binary *bool
-
-	// Base name of the mount point
-	Stem *string `android:"arch_variant"`
-
-	// Append to the name of the output
-	Suffix *string `android:"arch_variant"`
-
-	// Symlinks to the mountpoints from the system and recovery partitions
-	// Symlinks names will have the same suffix as the mount point
-	Symlinks []string
-}
-
-func (m *bionicMountpoint) DepsMutator(ctx android.BottomUpMutatorContext) {
-	if Bool(m.properties.Library) == Bool(m.properties.Binary) {
-		ctx.ModuleErrorf("either binary or library must be set to true")
-		return
-	}
-	if m.properties.Stem == nil {
-		ctx.PropertyErrorf("stem", "stem must be set")
-		return
-	}
-	if m.properties.Src == nil {
-		ctx.PropertyErrorf("src", "src must be set")
-	}
-	android.ExtractSourceDeps(ctx, m.properties.Src)
-}
-
-func (m *bionicMountpoint) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	if Bool(m.properties.Library) {
-		m.pathInPartition = "lib"
-		if m.Arch().ArchType.Multilib == "lib64" {
-			m.pathInPartition = "lib64"
-		}
-	} else if Bool(m.properties.Binary) {
-		m.pathInPartition = "bin"
-	}
-
-	m.stem = String(m.properties.Stem) + String(m.properties.Suffix)
-
-	m.outputFile = ctx.ExpandSource(String(m.properties.Src), "src")
-}
-
-func (m *bionicMountpoint) AndroidMk() android.AndroidMkData {
-	return android.AndroidMkData {
-		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
-			if !m.Arch().Native {
-				return
-			}
-			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
-			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
-			fmt.Fprintln(w, "LOCAL_MODULE :=", name)
-			fmt.Fprintln(w, "LOCAL_USE_CLANG_LLD := false")
-			fmt.Fprintln(w, "LOCAL_STRIP_MODULE := false")
-			if Bool(m.properties.Library) {
-				fmt.Fprintln(w, "LOCAL_MODULE_CLASS := SHARED_LIBRARIES")
-			} else if Bool(m.properties.Binary) {
-				fmt.Fprintln(w, "LOCAL_MODULE_CLASS := EXECUTABLES")
-			}
-			fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
-			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", m.outputFile.String())
-			fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", m.Arch().ArchType.String())
-			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(TARGET_ROOT_OUT)/bionic/" + m.pathInPartition)
-			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem)
-
-			if len(m.properties.Symlinks) > 0 {
-				symlink_dir_in_system := "$(TARGET_OUT)/" + m.pathInPartition + "/"
-				symlink_dir_in_recovery := "$(TARGET_RECOVERY_ROOT_OUT)/system/" + m.pathInPartition + "/"
-				symlink_target := "/bionic/" + m.pathInPartition + "/" + m.stem
-				cmds := []string{}
-				cmds = append(cmds, "$(hide) mkdir -p " + symlink_dir_in_system)
-				cmds = append(cmds, "mkdir -p " + symlink_dir_in_recovery)
-				for _, s := range m.properties.Symlinks {
-					symlink := s + String(m.properties.Suffix)
-					cmds = append(cmds, "ln -sf " + symlink_target + " " + symlink_dir_in_system +  symlink)
-					cmds = append(cmds, "ln -sf " + symlink_target + " " + symlink_dir_in_recovery +  symlink)
-				}
-				fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD := " + strings.Join(cmds, " && "))
-			}
-			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
-		},
-	}
-}
-
-func bionicMountpointFactory() android.Module {
-	m := &bionicMountpoint{}
-        m.AddProperties(&m.properties)
-	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibBoth)
-	return m
-}
-
-var Bool = proptools.Bool
-var String = proptools.String
diff --git a/build/run-on-host.sh b/build/run-on-host.sh
deleted file mode 100644
index c3a2751..0000000
--- a/build/run-on-host.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash -e
-
-source ${ANDROID_BUILD_TOP}/build/envsetup.sh
-
-TARGET_ARCH=$(get_build_var TARGET_ARCH)
-TARGET_OUT=$(get_build_var TARGET_OUT)
-TARGET_OUT_EXECUTABLES=$(get_build_var TARGET_OUT_EXECUTABLES)
-TARGET_OUT_DATA=$(get_build_var TARGET_OUT_DATA)
-HOST_OS=$(get_build_var HOST_OS)
-HOST_ARCH=$(get_build_var HOST_ARCH)
-HOST_OUT=$(get_build_var HOST_OUT)
-
-function prepare()
-{
-    BITS=$1
-    shift
-
-    NATIVETEST=${TARGET_OUT_DATA}/nativetest
-    if [ "${BITS}" = 64 ]; then
-        NATIVETEST=${NATIVETEST}64
-    fi
-
-    if [ ${TARGET_ARCH} = arm -o ${TARGET_ARCH} = mips -o ${TARGET_ARCH} = x86 ]; then
-        LINKER=${TARGET_OUT_EXECUTABLES}/linker
-    else
-        LINKER="${TARGET_OUT_EXECUTABLES}/linker64 ${TARGET_OUT_EXECUTABLES}/linker"
-    fi
-
-    if [ ${TARGET_ARCH} = x86 -o ${TARGET_ARCH} = x86_64 ]; then
-        m -j ${LINKER} ${TARGET_OUT}/etc/hosts ${TARGET_OUT_EXECUTABLES}/sh $@
-
-        if [ ! -d /system ]; then
-            echo "Attempting to create /system";
-            sudo mkdir -p -m 0777 /system;
-        fi
-        (
-            cd ${ANDROID_BUILD_TOP}
-            mkdir -p ${TARGET_OUT_DATA}/local/tmp
-            ln -fs `realpath ${TARGET_OUT}/bin` /system/
-            ln -fs `realpath ${TARGET_OUT}/etc` /system/
-            ln -fs `realpath ${TARGET_OUT}/lib` /system/
-            if [ -d "${TARGET_OUT}/lib64" ]; then
-                ln -fs `realpath ${TARGET_OUT}/lib64` /system/;
-            fi
-        )
-    fi
-}
diff --git a/docs/status.md b/docs/status.md
index 54385a4..85f9b60 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -48,8 +48,10 @@
   * 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
+  * `aligned_alloc` correctly verifies that `size` is a multiple of `alignment`
 
 New libc functions in P (API level 28):
+  * `aligned_alloc`
   * `__freading`/`__fwriting` (completing <stdio_ext.h>)
   * `endhostent`/`endnetent`/`endprotoent`/`getnetent`/`getprotoent`/`sethostent`/`setnetent`/`setprotoent` (completing <netdb.h>)
   * `fexecve`
diff --git a/dummy_mountpoint b/dummy_mountpoint
deleted file mode 100644
index 2d13c55..0000000
--- a/dummy_mountpoint
+++ /dev/null
@@ -1 +0,0 @@
-This file serves as a mount point for bionic files either from /system partition or from /apex/com.android.runtime. This file is never meant to be accessed directly.
diff --git a/libc/Android.bp b/libc/Android.bp
index 4cf31bc..a27b1ce 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -77,8 +77,17 @@
     native_coverage: false,
     recovery_available: true,
 
-    // TODO(ivanlozano): Remove after b/118321713
-    xom: false,
+    arch: {
+        x86: {
+            no_libcrt: true,
+        },
+        x86_64: {
+            no_libcrt: true,
+        },
+    },
+    // lld complains about duplicate symbols in libcrt and libgcc. Suppress the
+    // warning since this is intended right now.
+    ldflags: ["-Wl,-z,muldefs"],
 }
 
 // ========================================================
@@ -328,13 +337,10 @@
         "upstream-netbsd/lib/libc/regex/regexec.c",
         "upstream-netbsd/lib/libc/regex/regfree.c",
         "upstream-netbsd/lib/libc/stdlib/bsearch.c",
-        "upstream-netbsd/lib/libc/stdlib/div.c",
         "upstream-netbsd/lib/libc/stdlib/drand48.c",
         "upstream-netbsd/lib/libc/stdlib/erand48.c",
         "upstream-netbsd/lib/libc/stdlib/jrand48.c",
         "upstream-netbsd/lib/libc/stdlib/lcong48.c",
-        "upstream-netbsd/lib/libc/stdlib/ldiv.c",
-        "upstream-netbsd/lib/libc/stdlib/lldiv.c",
         "upstream-netbsd/lib/libc/stdlib/lrand48.c",
         "upstream-netbsd/lib/libc/stdlib/mrand48.c",
         "upstream-netbsd/lib/libc/stdlib/nrand48.c",
@@ -343,10 +349,6 @@
         "upstream-netbsd/lib/libc/stdlib/reallocarr.c",
         "upstream-netbsd/lib/libc/stdlib/seed48.c",
         "upstream-netbsd/lib/libc/stdlib/srand48.c",
-        "upstream-netbsd/lib/libc/string/memccpy.c",
-        "upstream-netbsd/lib/libc/string/strcasestr.c",
-        "upstream-netbsd/lib/libc/string/strcoll.c",
-        "upstream-netbsd/lib/libc/string/strxfrm.c",
     ],
     multilib: {
         lib32: {
@@ -456,19 +458,25 @@
         "upstream-openbsd/lib/libc/stdio/wbuf.c",
         "upstream-openbsd/lib/libc/stdio/wsetup.c",
         "upstream-openbsd/lib/libc/stdlib/abs.c",
+        "upstream-openbsd/lib/libc/stdlib/div.c",
         "upstream-openbsd/lib/libc/stdlib/getenv.c",
         "upstream-openbsd/lib/libc/stdlib/getsubopt.c",
         "upstream-openbsd/lib/libc/stdlib/insque.c",
         "upstream-openbsd/lib/libc/stdlib/imaxabs.c",
         "upstream-openbsd/lib/libc/stdlib/imaxdiv.c",
         "upstream-openbsd/lib/libc/stdlib/labs.c",
+        "upstream-openbsd/lib/libc/stdlib/ldiv.c",
         "upstream-openbsd/lib/libc/stdlib/llabs.c",
+        "upstream-openbsd/lib/libc/stdlib/lldiv.c",
         "upstream-openbsd/lib/libc/stdlib/lsearch.c",
         "upstream-openbsd/lib/libc/stdlib/remque.c",
         "upstream-openbsd/lib/libc/stdlib/setenv.c",
         "upstream-openbsd/lib/libc/stdlib/tfind.c",
         "upstream-openbsd/lib/libc/stdlib/tsearch.c",
+        "upstream-openbsd/lib/libc/string/memccpy.c",
         "upstream-openbsd/lib/libc/string/strcasecmp.c",
+        "upstream-openbsd/lib/libc/string/strcasestr.c",
+        "upstream-openbsd/lib/libc/string/strcoll.c",
         "upstream-openbsd/lib/libc/string/strcspn.c",
         "upstream-openbsd/lib/libc/string/strdup.c",
         "upstream-openbsd/lib/libc/string/strndup.c",
@@ -477,6 +485,7 @@
         "upstream-openbsd/lib/libc/string/strspn.c",
         "upstream-openbsd/lib/libc/string/strstr.c",
         "upstream-openbsd/lib/libc/string/strtok.c",
+        "upstream-openbsd/lib/libc/string/strxfrm.c",
         "upstream-openbsd/lib/libc/string/wcslcpy.c",
         "upstream-openbsd/lib/libc/string/wcswidth.c",
     ],
@@ -764,7 +773,7 @@
                 "arch-arm/bionic/atomics_arm.c",
                 "arch-arm/bionic/__bionic_clone.S",
                 "arch-arm/bionic/_exit_with_stack_teardown.S",
-                "arch-arm/bionic/libgcc_compat.c",
+                "arch-arm/bionic/libcrt_compat.c",
                 "arch-arm/bionic/popcount_tab.c",
                 "arch-arm/bionic/__restore.S",
                 "arch-arm/bionic/setjmp.S",
@@ -848,7 +857,7 @@
                 "arch-mips/bionic/__bionic_clone.S",
                 "arch-mips/bionic/cacheflush.cpp",
                 "arch-mips/bionic/_exit_with_stack_teardown.S",
-                "arch-mips/bionic/libgcc_compat.c",
+                "arch-mips/bionic/libcrt_compat.c",
                 "arch-mips/bionic/setjmp.S",
                 "arch-mips/bionic/syscall.S",
                 "arch-mips/bionic/vfork.S",
@@ -918,7 +927,7 @@
 
                 "arch-x86/bionic/__bionic_clone.S",
                 "arch-x86/bionic/_exit_with_stack_teardown.S",
-                "arch-x86/bionic/libgcc_compat.c",
+                "arch-x86/bionic/libcrt_compat.c",
                 "arch-x86/bionic/__restore.S",
                 "arch-x86/bionic/setjmp.S",
                 "arch-x86/bionic/syscall.S",
@@ -1080,7 +1089,6 @@
         "bionic/locale.cpp",
         "bionic/lockf.cpp",
         "bionic/lstat.cpp",
-        "bionic/malloc_info.cpp",
         "bionic/mblen.cpp",
         "bionic/mbrtoc16.cpp",
         "bionic/mbrtoc32.cpp",
@@ -1300,7 +1308,10 @@
 cc_library_static {
     name: "libc_ndk",
     defaults: ["libc_defaults"],
-    srcs: libc_common_src_files + ["bionic/malloc_common.cpp"],
+    srcs: libc_common_src_files + [
+        "bionic/malloc_common.cpp",
+        "bionic/malloc_limit.cpp",
+    ],
     multilib: {
         lib32: {
             srcs: libc_common_src_files_32,
@@ -1493,6 +1504,9 @@
         "arch-common/bionic/crtbrand.S",
         "bionic/icu.cpp",
         "bionic/malloc_common.cpp",
+        "bionic/malloc_common_dynamic.cpp",
+        "bionic/malloc_heapprofd.cpp",
+        "bionic/malloc_limit.cpp",
         "bionic/NetdClient.cpp",
         "arch-common/bionic/crtend_so.S",
     ],
@@ -1503,6 +1517,7 @@
     srcs: [
         "bionic/dl_iterate_phdr_static.cpp",
         "bionic/malloc_common.cpp",
+        "bionic/malloc_limit.cpp",
     ],
 }
 
@@ -1548,7 +1563,7 @@
         ],
     },
 
-    required: ["tzdata", "libc.mountpoint"],
+    required: ["tzdata"],
 
     // Leave the symbols in the shared library so that stack unwinders can produce
     // meaningful name resolution.
diff --git a/libc/arch-arm/bionic/libgcc_compat.c b/libc/arch-arm/bionic/libcrt_compat.c
similarity index 83%
rename from libc/arch-arm/bionic/libgcc_compat.c
rename to libc/arch-arm/bionic/libcrt_compat.c
index abd1422..ce77a5d 100644
--- a/libc/arch-arm/bionic/libgcc_compat.c
+++ b/libc/arch-arm/bionic/libcrt_compat.c
@@ -31,8 +31,12 @@
 extern char __aeabi_cdcmpeq;
 extern char __aeabi_cdcmple;
 extern char __aeabi_cdrcmple;
+extern char __aeabi_cfcmpeq;
+extern char __aeabi_cfcmple;
+extern char __aeabi_cfrcmple;
 extern char __aeabi_d2f;
 extern char __aeabi_d2iz;
+extern char __aeabi_d2uiz;
 extern char __aeabi_dadd;
 extern char __aeabi_dcmpeq;
 extern char __aeabi_dcmpge;
@@ -48,6 +52,11 @@
 extern char __aeabi_f2iz;
 extern char __aeabi_f2uiz;
 extern char __aeabi_fadd;
+extern char __aeabi_fcmpeq;
+extern char __aeabi_fcmpge;
+extern char __aeabi_fcmpgt;
+extern char __aeabi_fcmple;
+extern char __aeabi_fcmplt;
 extern char __aeabi_fcmpun;
 extern char __aeabi_fdiv;
 extern char __aeabi_fmul;
@@ -74,12 +83,15 @@
 extern char __aeabi_unwind_cpp_pr0;
 extern char __aeabi_unwind_cpp_pr1;
 extern char __cmpdf2;
+extern char __cmpsf2;
 extern char __divdf3;
 extern char __divsf3;
 extern char __eqdf2;
+extern char __eqsf2;
 extern char __extendsfdf2;
 extern char __fixdfsi;
 extern char __fixsfsi;
+extern char __fixunsdfsi;
 extern char __floatdidf;
 extern char __floatdisf;
 extern char __floatsidf;
@@ -89,29 +101,41 @@
 extern char __floatunsidf;
 extern char __floatunsisf;
 extern char __gedf2;
+extern char __gesf2;
 extern char __gtdf2;
+extern char __gtsf2;
+extern char __gnu_ldivmod_helper;
+extern char __gnu_uldivmod_helper;
 extern char __ledf2;
+extern char __lesf2;
 extern char __ltdf2;
+extern char __ltsf2;
 extern char __muldf3;
 extern char __muldi3;
 extern char __mulsf3;
 extern char __nedf2;
+extern char __nesf2;
 extern char __popcount_tab;
 extern char __popcountsi2;
 extern char __subdf3;
 extern char __subsf3;
 extern char __truncdfsf2;
+extern char __udivdi3;
 extern char __unorddf2;
 extern char __unordsf2;
 
-void* __bionic_libgcc_compat_symbols[] = {
+void* __bionic_libcrt_compat_symbols[] = {
     &__adddf3,
     &__addsf3,
     &__aeabi_cdcmpeq,
     &__aeabi_cdcmple,
     &__aeabi_cdrcmple,
+    &__aeabi_cfcmpeq,
+    &__aeabi_cfcmple,
+    &__aeabi_cfrcmple,
     &__aeabi_d2f,
     &__aeabi_d2iz,
+    &__aeabi_d2uiz,
     &__aeabi_dadd,
     &__aeabi_dcmpeq,
     &__aeabi_dcmpge,
@@ -127,6 +151,11 @@
     &__aeabi_f2iz,
     &__aeabi_f2uiz,
     &__aeabi_fadd,
+    &__aeabi_fcmpeq,
+    &__aeabi_fcmpge,
+    &__aeabi_fcmpgt,
+    &__aeabi_fcmple,
+    &__aeabi_fcmplt,
     &__aeabi_fcmpun,
     &__aeabi_fdiv,
     &__aeabi_fmul,
@@ -153,12 +182,15 @@
     &__aeabi_unwind_cpp_pr0,
     &__aeabi_unwind_cpp_pr1,
     &__cmpdf2,
+    &__cmpsf2,
     &__divdf3,
     &__divsf3,
     &__eqdf2,
+    &__eqsf2,
     &__extendsfdf2,
     &__fixdfsi,
     &__fixsfsi,
+    &__fixunsdfsi,
     &__floatdidf,
     &__floatdisf,
     &__floatsidf,
@@ -168,18 +200,26 @@
     &__floatunsidf,
     &__floatunsisf,
     &__gedf2,
+    &__gesf2,
     &__gtdf2,
+    &__gtsf2,
+    &__gnu_ldivmod_helper,
+    &__gnu_uldivmod_helper,
     &__ledf2,
+    &__lesf2,
     &__ltdf2,
+    &__ltsf2,
     &__muldf3,
     &__muldi3,
     &__mulsf3,
     &__nedf2,
+    &__nesf2,
     &__popcount_tab,
     &__popcountsi2,
     &__subdf3,
     &__subsf3,
     &__truncdfsf2,
+    &__udivdi3,
     &__unorddf2,
     &__unordsf2,
 };
diff --git a/libc/arch-mips/bionic/libgcc_compat.c b/libc/arch-mips/bionic/libcrt_compat.c
similarity index 97%
rename from libc/arch-mips/bionic/libgcc_compat.c
rename to libc/arch-mips/bionic/libcrt_compat.c
index 1a0f566..cfa41f2 100644
--- a/libc/arch-mips/bionic/libgcc_compat.c
+++ b/libc/arch-mips/bionic/libcrt_compat.c
@@ -32,7 +32,7 @@
 extern char __udivdi3;
 extern char __umoddi3;
 
-void* __bionic_libgcc_compat_symbols[] = {
+void* __bionic_libcrt_compat_symbols[] = {
     &__divdi3,
     &__moddi3,
     &__popcountsi2,
diff --git a/libc/arch-x86/bionic/__libc_init_sysinfo.cpp b/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
index 849d253..5c44b4e 100644
--- a/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
+++ b/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
@@ -32,6 +32,10 @@
 // This file is compiled without stack protection, because it runs before TLS
 // has been set up.
 
+__LIBC_HIDDEN__ __attribute__((__naked__)) void __libc_int0x80() {
+  __asm__ volatile("int $0x80; ret");
+}
+
 __LIBC_HIDDEN__ void __libc_init_sysinfo() {
   bool dummy;
   __libc_sysinfo = reinterpret_cast<void*>(__bionic_getauxval(AT_SYSINFO, dummy));
diff --git a/libc/arch-x86/bionic/libgcc_compat.c b/libc/arch-x86/bionic/libcrt_compat.c
similarity index 97%
rename from libc/arch-x86/bionic/libgcc_compat.c
rename to libc/arch-x86/bionic/libcrt_compat.c
index 1a0f566..cfa41f2 100644
--- a/libc/arch-x86/bionic/libgcc_compat.c
+++ b/libc/arch-x86/bionic/libcrt_compat.c
@@ -32,7 +32,7 @@
 extern char __udivdi3;
 extern char __umoddi3;
 
-void* __bionic_libgcc_compat_symbols[] = {
+void* __bionic_libcrt_compat_symbols[] = {
     &__divdi3,
     &__moddi3,
     &__popcountsi2,
diff --git a/libc/async_safe/Android.bp b/libc/async_safe/Android.bp
index a54d3b0..fbaaad1 100644
--- a/libc/async_safe/Android.bp
+++ b/libc/async_safe/Android.bp
@@ -12,7 +12,20 @@
     recovery_available: true,
 
     include_dirs: ["bionic/libc"],
-    header_libs: ["libc_headers"],
+    header_libs: ["libc_headers", "liblog_headers"],
 
     export_include_dirs: ["include"],
+    export_header_lib_headers: ["liblog_headers"],
+    stl: "none",
+}
+
+cc_library_headers {
+    name: "libasync_safe_headers",
+    recovery_available: true,
+    defaults: ["linux_bionic_supported"],
+
+    export_include_dirs: ["include"],
+
+    system_shared_libs: [],
+    stl: "none",
 }
diff --git a/libc/arch-mips/bionic/libgcc_compat.c b/libc/async_safe/include/async_safe/CHECK.h
similarity index 74%
copy from libc/arch-mips/bionic/libgcc_compat.c
copy to libc/async_safe/include/async_safe/CHECK.h
index 1a0f566..bec89a3 100644
--- a/libc/arch-mips/bionic/libgcc_compat.c
+++ b/libc/async_safe/include/async_safe/CHECK.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,16 +26,22 @@
  * SUCH DAMAGE.
  */
 
-extern char __divdi3;
-extern char __moddi3;
-extern char __popcountsi2;
-extern char __udivdi3;
-extern char __umoddi3;
+#pragma once
 
-void* __bionic_libgcc_compat_symbols[] = {
-    &__divdi3,
-    &__moddi3,
-    &__popcountsi2,
-    &__udivdi3,
-    &__umoddi3,
-};
+#include <sys/cdefs.h>
+
+#include <async_safe/log.h>
+
+__BEGIN_DECLS
+
+// TODO: replace this with something more like <android-base/logging.h>'s family of macros.
+
+#define CHECK(predicate) \
+  do { \
+    if (!(predicate)) { \
+      async_safe_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
+          __FILE__, __LINE__, __FUNCTION__); \
+    } \
+  } while(0)
+
+__END_DECLS
diff --git a/libc/async_safe/include/async_safe/log.h b/libc/async_safe/include/async_safe/log.h
index df68062..0e02ea7 100644
--- a/libc/async_safe/include/async_safe/log.h
+++ b/libc/async_safe/include/async_safe/log.h
@@ -34,36 +34,14 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+// This file is an alternative to <android/log.h>, but reuses
+// `android_LogPriority` and should not have conflicting identifiers.
+#include <android/log.h>
+
 // These functions do not allocate memory to send data to the log.
 
 __BEGIN_DECLS
 
-enum {
-  ANDROID_LOG_UNKNOWN = 0,
-  ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
-
-  ANDROID_LOG_VERBOSE,
-  ANDROID_LOG_DEBUG,
-  ANDROID_LOG_INFO,
-  ANDROID_LOG_WARN,
-  ANDROID_LOG_ERROR,
-  ANDROID_LOG_FATAL,
-
-  ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
-};
-
-enum {
-  LOG_ID_MIN = 0,
-
-  LOG_ID_MAIN = 0,
-  LOG_ID_RADIO = 1,
-  LOG_ID_EVENTS = 2,
-  LOG_ID_SYSTEM = 3,
-  LOG_ID_CRASH = 4,
-
-  LOG_ID_MAX
-};
-
 // Formats a message to the log (priority 'fatal'), then aborts.
 // Implemented as a macro so that async_safe_fatal isn't on the stack when we crash:
 // we appear to go straight from the caller to abort, saving an uninteresting stack
@@ -91,16 +69,8 @@
 
 int async_safe_format_fd(int fd, const char* format , ...) __printflike(2, 3);
 int async_safe_format_fd_va_list(int fd, const char* format, va_list args);
-int async_safe_format_log(int pri, const char* tag, const char* fmt, ...) __printflike(3, 4);
-int async_safe_format_log_va_list(int pri, const char* tag, const char* fmt, va_list ap);
-int async_safe_write_log(int pri, const char* tag, const char* msg);
-
-#define CHECK(predicate) \
-  do { \
-    if (!(predicate)) { \
-      async_safe_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
-          __FILE__, __LINE__, __FUNCTION__); \
-    } \
-  } while(0)
+int async_safe_format_log(int priority, const char* tag, const char* fmt, ...) __printflike(3, 4);
+int async_safe_format_log_va_list(int priority, const char* tag, const char* fmt, va_list ap);
+int async_safe_write_log(int priority, const char* tag, const char* msg);
 
 __END_DECLS
diff --git a/libc/bionic/bionic_allocator.cpp b/libc/bionic/bionic_allocator.cpp
index d9302ad..da0f7d0 100644
--- a/libc/bionic/bionic_allocator.cpp
+++ b/libc/bionic/bionic_allocator.cpp
@@ -38,6 +38,7 @@
 #include <new>
 
 #include <async_safe/log.h>
+#include <async_safe/CHECK.h>
 
 #include "private/bionic_macros.h"
 #include "private/bionic_page.h"
diff --git a/libc/bionic/icu.cpp b/libc/bionic/icu.cpp
index 41a0729..72dac9b 100644
--- a/libc/bionic/icu.cpp
+++ b/libc/bionic/icu.cpp
@@ -36,53 +36,12 @@
 
 #include <async_safe/log.h>
 
-// Allowed icu4c version numbers are in the range [44, 999].
-// Gingerbread's icu4c 4.4 is the minimum supported ICU version.
-static constexpr auto ICUDATA_VERSION_MIN_LENGTH = 2;
-static constexpr auto ICUDATA_VERSION_MAX_LENGTH = 3;
-static constexpr auto ICUDATA_VERSION_MIN = 44;
-
-static char g_icudata_version[ICUDATA_VERSION_MAX_LENGTH + 1];
-
 static void* g_libicuuc_handle = nullptr;
 
-static int __icu_dat_file_filter(const dirent* dirp) {
-  const char* name = dirp->d_name;
-
-  // Is the name the right length to match 'icudt(\d\d\d)l.dat'?
-  const size_t len = strlen(name);
-  if (len < 10 + ICUDATA_VERSION_MIN_LENGTH || len > 10 + ICUDATA_VERSION_MAX_LENGTH) return 0;
-
-  return !strncmp(name, "icudt", 5) && !strncmp(&name[len - 5], "l.dat", 5);
-}
-
 static bool __find_icu() {
-  dirent** namelist = nullptr;
-  int n = scandir("/apex/com.android.runtime/etc/icu", &namelist, &__icu_dat_file_filter,
-                  alphasort);
-  if (n < 0) {
-    async_safe_write_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find ICU folder");
-    return false;
-  }
-  int max_version = -1;
-  while (n--) {
-    // We prefer the latest version available.
-    int version = atoi(&namelist[n]->d_name[strlen("icudt")]);
-    if (version != 0 && version > max_version) max_version = version;
-    free(namelist[n]);
-  }
-  free(namelist);
-
-  if (max_version < ICUDATA_VERSION_MIN) {
-    async_safe_write_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find an ICU .dat file");
-    return false;
-  }
-
-  snprintf(g_icudata_version, sizeof(g_icudata_version), "_%d", max_version);
-
-  g_libicuuc_handle = dlopen("libicuuc.so", RTLD_LOCAL);
+  g_libicuuc_handle = dlopen("libandroidicu.so", RTLD_LOCAL);
   if (g_libicuuc_handle == nullptr) {
-    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't open libicuuc.so: %s",
+    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't open libandroidicu.so: %s",
                           dlerror());
     return false;
   }
@@ -94,9 +53,9 @@
   static bool found_icu = __find_icu();
   if (!found_icu) return nullptr;
 
-  char versioned_symbol_name[strlen(symbol_name) + sizeof(g_icudata_version)];
-  snprintf(versioned_symbol_name, sizeof(versioned_symbol_name), "%s%s",
-           symbol_name, g_icudata_version);
+  char versioned_symbol_name[strlen(symbol_name) + strlen("_android") + 1];
+  snprintf(versioned_symbol_name, sizeof(versioned_symbol_name), "%s_android",
+           symbol_name);
 
   void* symbol = dlsym(g_libicuuc_handle, versioned_symbol_name);
   if (symbol == nullptr) {
diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h
index 79a4f72..b9a4e99 100644
--- a/libc/bionic/jemalloc.h
+++ b/libc/bionic/jemalloc.h
@@ -22,14 +22,20 @@
 // Need to wrap memalign since je_memalign fails on non-power of 2 alignments.
 #define je_memalign je_memalign_round_up_boundary
 
+// Need to wrap aligned_alloc since je_aligned_alloc does not enforce
+// that size is a multiple of alignment.
+#define je_aligned_alloc je_aligned_alloc_wrapper
+
 __BEGIN_DECLS
 
-struct mallinfo je_mallinfo();
-int je_mallopt(int, int);
+void* je_aligned_alloc_wrapper(size_t, size_t);
 int je_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
+int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+struct mallinfo je_mallinfo();
 void je_malloc_disable();
 void je_malloc_enable();
-int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+int je_malloc_info(int options, FILE* fp);
+int je_mallopt(int, int);
 void* je_memalign_round_up_boundary(size_t, size_t);
 void* je_pvalloc(size_t);
 
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index ef0d384..bc3a9dc 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+#include <errno.h>
 #include <malloc.h>
 #include <sys/param.h>
 #include <unistd.h>
 
+#include <private/MallocXmlElem.h>
+
 #include "jemalloc.h"
-#include "private/bionic_macros.h"
 
 void* je_pvalloc(size_t bytes) {
   size_t pagesize = getpagesize();
@@ -48,6 +50,20 @@
   return je_memalign(boundary, size);
 }
 
+#ifdef je_aligned_alloc
+#undef je_aligned_alloc
+#endif
+
+// The aligned_alloc function requires that size is a multiple of alignment.
+// jemalloc doesn't enforce this, so add enforcement here.
+void* je_aligned_alloc_wrapper(size_t alignment, size_t size) {
+  if ((size % alignment) != 0) {
+    errno = EINVAL;
+    return nullptr;
+  }
+  return je_aligned_alloc(alignment, size);
+}
+
 int je_mallopt(int param, int value) {
   // The only parameter we currently understand is M_DECAY_TIME.
   if (param == M_DECAY_TIME) {
@@ -101,3 +117,49 @@
   }
   return 0;
 }
+
+__BEGIN_DECLS
+
+size_t __mallinfo_narenas();
+size_t __mallinfo_nbins();
+struct mallinfo __mallinfo_arena_info(size_t);
+struct mallinfo __mallinfo_bin_info(size_t, size_t);
+
+__END_DECLS
+
+int je_malloc_info(int options, FILE* fp) {
+  if (options != 0) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  MallocXmlElem root(fp, "malloc", "version=\"jemalloc-1\"");
+
+  // Dump all of the large allocations in the arenas.
+  for (size_t i = 0; i < __mallinfo_narenas(); i++) {
+    struct mallinfo mi = __mallinfo_arena_info(i);
+    if (mi.hblkhd != 0) {
+      MallocXmlElem arena_elem(fp, "heap", "nr=\"%d\"", i);
+      {
+        MallocXmlElem(fp, "allocated-large").Contents("%zu", mi.ordblks);
+        MallocXmlElem(fp, "allocated-huge").Contents("%zu", mi.uordblks);
+        MallocXmlElem(fp, "allocated-bins").Contents("%zu", mi.fsmblks);
+
+        size_t total = 0;
+        for (size_t j = 0; j < __mallinfo_nbins(); j++) {
+          struct mallinfo mi = __mallinfo_bin_info(i, j);
+          if (mi.ordblks != 0) {
+            MallocXmlElem bin_elem(fp, "bin", "nr=\"%d\"", j);
+            MallocXmlElem(fp, "allocated").Contents("%zu", mi.ordblks);
+            MallocXmlElem(fp, "nmalloc").Contents("%zu", mi.uordblks);
+            MallocXmlElem(fp, "ndalloc").Contents("%zu", mi.fordblks);
+            total += mi.ordblks;
+          }
+        }
+        MallocXmlElem(fp, "bins-total").Contents("%zu", total);
+      }
+    }
+  }
+
+  return 0;
+}
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index f1fbfa9..b229cda 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -298,11 +298,26 @@
   unsigned long is_AT_SECURE = getauxval(AT_SECURE);
   if (errno != 0) __early_abort(__LINE__);
 
-  if (is_AT_SECURE) {
-    // If this is a setuid/setgid program, close the security hole described in
-    // https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc
+  // Always ensure that STDIN/STDOUT/STDERR exist. This prevents file
+  // descriptor confusion bugs where a parent process closes
+  // STD*, the exec()d process calls open() for an unrelated reason,
+  // the newly created file descriptor is assigned
+  // 0<=FD<=2, and unrelated code attempts to read / write to the STD*
+  // FDs.
+  // In particular, this can be a security bug for setuid/setgid programs.
+  // For example:
+  // https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc
+  // However, for robustness reasons, we don't limit these protections to
+  // just security critical executables.
+  //
+  // Init is excluded from these protections unless AT_SECURE is set, as
+  // /dev/null and/or /sys/fs/selinux/null will not be available at
+  // early boot.
+  if ((getpid() != 1) || is_AT_SECURE) {
     __nullify_closed_stdio();
+  }
 
+  if (is_AT_SECURE) {
     __sanitize_environment_variables(env);
   }
 
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 7140776..4f3b4f7 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -66,9 +66,6 @@
 // Use an initializer so __libc_sysinfo will have a fallback implementation
 // while .preinit_array constructors run.
 #if defined(__i386__)
-static __attribute__((__naked__)) void __libc_int0x80() {
-  __asm__ volatile("int $0x80; ret");
-}
 __LIBC_HIDDEN__ void* __libc_sysinfo = reinterpret_cast<void*>(__libc_int0x80);
 #endif
 
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 514423d..41f100d 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -66,6 +66,52 @@
   }
 }
 
+#if defined(__aarch64__) || defined(__x86_64__)
+extern __LIBC_HIDDEN__ __attribute__((weak)) ElfW(Rela) __rela_iplt_start[], __rela_iplt_end[];
+
+static void call_ifunc_resolvers() {
+  if (__rela_iplt_start == nullptr || __rela_iplt_end == nullptr) {
+    // These symbols are not emitted by gold. Gold has code to do so, but for
+    // whatever reason it is not being run. In these cases ifuncs cannot be
+    // resolved, so we do not support using ifuncs in static executables linked
+    // with gold.
+    //
+    // Since they are weak, they will be non-null when linked with bfd/lld and
+    // null when linked with gold.
+    return;
+  }
+
+  typedef ElfW(Addr) (*ifunc_resolver_t)(void);
+  for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) {
+    ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
+    ElfW(Addr) resolver = r->r_addend;
+    *offset = reinterpret_cast<ifunc_resolver_t>(resolver)();
+  }
+}
+#else
+extern __LIBC_HIDDEN__ __attribute__((weak)) ElfW(Rel) __rel_iplt_start[], __rel_iplt_end[];
+
+static void call_ifunc_resolvers() {
+  if (__rel_iplt_start == nullptr || __rel_iplt_end == nullptr) {
+    // These symbols are not emitted by gold. Gold has code to do so, but for
+    // whatever reason it is not being run. In these cases ifuncs cannot be
+    // resolved, so we do not support using ifuncs in static executables linked
+    // with gold.
+    //
+    // Since they are weak, they will be non-null when linked with bfd/lld and
+    // null when linked with gold.
+    return;
+  }
+
+  typedef ElfW(Addr) (*ifunc_resolver_t)(void);
+  for (ElfW(Rel) *r = __rel_iplt_start; r != __rel_iplt_end; ++r) {
+    ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
+    ElfW(Addr) resolver = *offset;
+    *offset = reinterpret_cast<ifunc_resolver_t>(resolver)();
+  }
+}
+#endif
+
 static void apply_gnu_relro() {
   ElfW(Phdr)* phdr_start = reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR));
   unsigned long int phdr_ct = getauxval(AT_PHNUM);
@@ -137,6 +183,7 @@
   __libc_init_main_thread_final();
   __libc_init_common();
 
+  call_ifunc_resolvers();
   apply_gnu_relro();
 
   // Several Linux ABIs don't pass the onexit pointer, and the ones that
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 50c2fec..f817281 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -41,14 +41,219 @@
 //                          get_malloc_leak_info.
 //   write_malloc_leak_info: Writes the leak info data to a file.
 
-#include <pthread.h>
-#include <stdatomic.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
 
-#include <private/bionic_defs.h>
 #include <private/bionic_config.h>
-#include <private/bionic_globals.h>
 #include <private/bionic_malloc.h>
-#include <private/bionic_malloc_dispatch.h>
+
+#include "malloc_common.h"
+#include "malloc_limit.h"
+
+// =============================================================================
+// Global variables instantations.
+// =============================================================================
+
+// Malloc hooks globals.
+void* (*volatile __malloc_hook)(size_t, const void*);
+void* (*volatile __realloc_hook)(void*, size_t, const void*);
+void (*volatile __free_hook)(void*, const void*);
+void* (*volatile __memalign_hook)(size_t, size_t, const void*);
+
+// In a VM process, this is set to 1 after fork()ing out of zygote.
+int gMallocLeakZygoteChild = 0;
+// =============================================================================
+
+// =============================================================================
+// Allocation functions
+// =============================================================================
+extern "C" void* calloc(size_t n_elements, size_t elem_size) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->calloc(n_elements, elem_size);
+  }
+  void* result = Malloc(calloc)(n_elements, elem_size);
+  if (__predict_false(result == nullptr)) {
+    warning_log("calloc(%zu, %zu) failed: returning null pointer", n_elements, elem_size);
+  }
+  return result;
+}
+
+extern "C" void free(void* mem) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    dispatch_table->free(mem);
+  } else {
+    Malloc(free)(mem);
+  }
+}
+
+extern "C" struct mallinfo mallinfo() {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->mallinfo();
+  }
+  return Malloc(mallinfo)();
+}
+
+extern "C" int malloc_info(int options, FILE* fp) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->malloc_info(options, fp);
+  }
+  return Malloc(malloc_info)(options, fp);
+}
+
+extern "C" int mallopt(int param, int value) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->mallopt(param, value);
+  }
+  return Malloc(mallopt)(param, value);
+}
+
+extern "C" void* malloc(size_t bytes) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->malloc(bytes);
+  }
+  void* result = Malloc(malloc)(bytes);
+  if (__predict_false(result == nullptr)) {
+    warning_log("malloc(%zu) failed: returning null pointer", bytes);
+  }
+  return result;
+}
+
+extern "C" size_t malloc_usable_size(const void* mem) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->malloc_usable_size(mem);
+  }
+  return Malloc(malloc_usable_size)(mem);
+}
+
+extern "C" void* memalign(size_t alignment, size_t bytes) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->memalign(alignment, bytes);
+  }
+  void* result = Malloc(memalign)(alignment, bytes);
+  if (__predict_false(result == nullptr)) {
+    warning_log("memalign(%zu, %zu) failed: returning null pointer", alignment, bytes);
+  }
+  return result;
+}
+
+extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->posix_memalign(memptr, alignment, size);
+  }
+  return Malloc(posix_memalign)(memptr, alignment, size);
+}
+
+extern "C" void* aligned_alloc(size_t alignment, size_t size) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->aligned_alloc(alignment, size);
+  }
+  void* result = Malloc(aligned_alloc)(alignment, size);
+  if (__predict_false(result == nullptr)) {
+    warning_log("aligned_alloc(%zu, %zu) failed: returning null pointer", alignment, size);
+  }
+  return result;
+}
+
+extern "C" void* realloc(void* old_mem, size_t bytes) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->realloc(old_mem, bytes);
+  }
+  void* result = Malloc(realloc)(old_mem, bytes);
+  if (__predict_false(result == nullptr && bytes != 0)) {
+    warning_log("realloc(%p, %zu) failed: returning null pointer", old_mem, bytes);
+  }
+  return result;
+}
+
+extern "C" void* reallocarray(void* old_mem, size_t item_count, size_t item_size) {
+  size_t new_size;
+  if (__builtin_mul_overflow(item_count, item_size, &new_size)) {
+    warning_log("reallocaray(%p, %zu, %zu) failed: returning null pointer",
+                old_mem, item_count, item_size);
+    errno = ENOMEM;
+    return nullptr;
+  }
+  return realloc(old_mem, new_size);
+}
+
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+extern "C" void* pvalloc(size_t bytes) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->pvalloc(bytes);
+  }
+  void* result = Malloc(pvalloc)(bytes);
+  if (__predict_false(result == nullptr)) {
+    warning_log("pvalloc(%zu) failed: returning null pointer", bytes);
+  }
+  return result;
+}
+
+extern "C" void* valloc(size_t bytes) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->valloc(bytes);
+  }
+  void* result = Malloc(valloc)(bytes);
+  if (__predict_false(result == nullptr)) {
+    warning_log("valloc(%zu) failed: returning null pointer", bytes);
+  }
+  return result;
+}
+#endif
+// =============================================================================
+
+// =============================================================================
+// Exported for use by libmemunreachable.
+// =============================================================================
+
+// Calls callback for every allocation in the anonymous heap mapping
+// [base, base+size).  Must be called between malloc_disable and malloc_enable.
+extern "C" int malloc_iterate(uintptr_t base, size_t size,
+    void (*callback)(uintptr_t base, size_t size, void* arg), void* arg) {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->iterate(base, size, callback, arg);
+  }
+  return Malloc(iterate)(base, size, callback, arg);
+}
+
+// Disable calls to malloc so malloc_iterate gets a consistent view of
+// allocated memory.
+extern "C" void malloc_disable() {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->malloc_disable();
+  }
+  return Malloc(malloc_disable)();
+}
+
+// Re-enable calls to malloc after a previous call to malloc_disable.
+extern "C" void malloc_enable() {
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->malloc_enable();
+  }
+  return Malloc(malloc_enable)();
+}
+
+#if defined(LIBC_STATIC)
+extern "C" ssize_t malloc_backtrace(void*, uintptr_t*, size_t) {
+  return 0;
+}
+#endif
 
 #if __has_feature(hwaddress_sanitizer)
 // FIXME: implement these in HWASan allocator.
@@ -63,824 +268,24 @@
 
 extern "C" void __sanitizer_malloc_enable() {
 }
-#include <sanitizer/hwasan_interface.h>
-#define Malloc(function)  __sanitizer_ ## function
 
-#else // __has_feature(hwaddress_sanitizer)
-#include "jemalloc.h"
-#define Malloc(function)  je_ ## function
-#endif
-
-template <typename T>
-static T* RemoveConst(const T* x) {
-  return const_cast<T*>(x);
-}
-
-// RemoveConst is a workaround for bug in current libcxx. Fix in
-// https://reviews.llvm.org/D47613
-#define atomic_load_explicit_const(obj, order) atomic_load_explicit(RemoveConst(obj), order)
-
-static constexpr memory_order default_read_memory_order = memory_order_acquire;
-
-static constexpr MallocDispatch __libc_malloc_default_dispatch
-  __attribute__((unused)) = {
-    Malloc(calloc),
-    Malloc(free),
-    Malloc(mallinfo),
-    Malloc(malloc),
-    Malloc(malloc_usable_size),
-    Malloc(memalign),
-    Malloc(posix_memalign),
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-    Malloc(pvalloc),
-#endif
-    Malloc(realloc),
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-    Malloc(valloc),
-#endif
-    Malloc(iterate),
-    Malloc(malloc_disable),
-    Malloc(malloc_enable),
-    Malloc(mallopt),
-    Malloc(aligned_alloc),
-  };
-
-// Malloc hooks.
-void* (*volatile __malloc_hook)(size_t, const void*);
-void* (*volatile __realloc_hook)(void*, size_t, const void*);
-void (*volatile __free_hook)(void*, const void*);
-void* (*volatile __memalign_hook)(size_t, size_t, const void*);
-
-// In a VM process, this is set to 1 after fork()ing out of zygote.
-int gMallocLeakZygoteChild = 0;
-
-// =============================================================================
-// Allocation functions
-// =============================================================================
-extern "C" void* calloc(size_t n_elements, size_t elem_size) {
-  auto _calloc = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.calloc,
-      default_read_memory_order);
-  if (__predict_false(_calloc != nullptr)) {
-    return _calloc(n_elements, elem_size);
-  }
-  return Malloc(calloc)(n_elements, elem_size);
-}
-
-extern "C" void free(void* mem) {
-  auto _free = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.free,
-      default_read_memory_order);
-  if (__predict_false(_free != nullptr)) {
-    _free(mem);
-  } else {
-    Malloc(free)(mem);
-  }
-}
-
-extern "C" struct mallinfo mallinfo() {
-  auto _mallinfo = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.mallinfo,
-      default_read_memory_order);
-  if (__predict_false(_mallinfo != nullptr)) {
-    return _mallinfo();
-  }
-  return Malloc(mallinfo)();
-}
-
-extern "C" int mallopt(int param, int value) {
-  auto _mallopt = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.mallopt,
-      default_read_memory_order);
-  if (__predict_false(_mallopt != nullptr)) {
-    return _mallopt(param, value);
-  }
-  return Malloc(mallopt)(param, value);
-}
-
-extern "C" void* malloc(size_t bytes) {
-  auto _malloc = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.malloc,
-      default_read_memory_order);
-  if (__predict_false(_malloc != nullptr)) {
-    return _malloc(bytes);
-  }
-  return Malloc(malloc)(bytes);
-}
-
-extern "C" size_t malloc_usable_size(const void* mem) {
-  auto _malloc_usable_size = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.malloc_usable_size,
-      default_read_memory_order);
-  if (__predict_false(_malloc_usable_size != nullptr)) {
-    return _malloc_usable_size(mem);
-  }
-  return Malloc(malloc_usable_size)(mem);
-}
-
-extern "C" void* memalign(size_t alignment, size_t bytes) {
-  auto _memalign = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.memalign,
-      default_read_memory_order);
-  if (__predict_false(_memalign != nullptr)) {
-    return _memalign(alignment, bytes);
-  }
-  return Malloc(memalign)(alignment, bytes);
-}
-
-extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
-  auto _posix_memalign = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.posix_memalign,
-      default_read_memory_order);
-  if (__predict_false(_posix_memalign != nullptr)) {
-    return _posix_memalign(memptr, alignment, size);
-  }
-  return Malloc(posix_memalign)(memptr, alignment, size);
-}
-
-extern "C" void* aligned_alloc(size_t alignment, size_t size) {
-  auto _aligned_alloc = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.aligned_alloc,
-      default_read_memory_order);
-  if (__predict_false(_aligned_alloc != nullptr)) {
-    return _aligned_alloc(alignment, size);
-  }
-  return Malloc(aligned_alloc)(alignment, size);
-}
-
-extern "C" void* realloc(void* old_mem, size_t bytes) {
-  auto _realloc = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.realloc,
-      default_read_memory_order);
-  if (__predict_false(_realloc != nullptr)) {
-    return _realloc(old_mem, bytes);
-  }
-  return Malloc(realloc)(old_mem, bytes);
-}
-
-extern "C" void* reallocarray(void* old_mem, size_t item_count, size_t item_size) {
-  size_t new_size;
-  if (__builtin_mul_overflow(item_count, item_size, &new_size)) {
-    errno = ENOMEM;
-    return nullptr;
-  }
-  return realloc(old_mem, new_size);
-}
-
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-extern "C" void* pvalloc(size_t bytes) {
-  auto _pvalloc = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.pvalloc,
-      default_read_memory_order);
-  if (__predict_false(_pvalloc != nullptr)) {
-    return _pvalloc(bytes);
-  }
-  return Malloc(pvalloc)(bytes);
-}
-
-extern "C" void* valloc(size_t bytes) {
-  auto _valloc = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.valloc,
-      default_read_memory_order);
-  if (__predict_false(_valloc != nullptr)) {
-    return _valloc(bytes);
-  }
-  return Malloc(valloc)(bytes);
+extern "C" int __sanitizer_malloc_info(int, FILE*) {
+  errno = ENOTSUP;
+  return -1;
 }
 #endif
-
-// We implement malloc debugging only in libc.so, so the code below
-// must be excluded if we compile this file for static libc.a
-#if !defined(LIBC_STATIC)
-
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <async_safe/log.h>
-#include <sys/system_properties.h>
-
-extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
-
-static const char* HOOKS_SHARED_LIB = "libc_malloc_hooks.so";
-static const char* HOOKS_PROPERTY_ENABLE = "libc.debug.hooks.enable";
-static const char* HOOKS_ENV_ENABLE = "LIBC_HOOKS_ENABLE";
-
-static const char* DEBUG_SHARED_LIB = "libc_malloc_debug.so";
-static const char* DEBUG_PROPERTY_OPTIONS = "libc.debug.malloc.options";
-static const char* DEBUG_PROPERTY_PROGRAM = "libc.debug.malloc.program";
-static const char* DEBUG_ENV_OPTIONS = "LIBC_DEBUG_MALLOC_OPTIONS";
-
-static const char* HEAPPROFD_SHARED_LIB = "heapprofd_client.so";
-static const char* HEAPPROFD_PREFIX = "heapprofd";
-static const char* HEAPPROFD_PROPERTY_ENABLE = "heapprofd.enable";
-static const int HEAPPROFD_SIGNAL = __SIGRTMIN + 4;
-
-enum FunctionEnum : uint8_t {
-  FUNC_INITIALIZE,
-  FUNC_FINALIZE,
-  FUNC_GET_MALLOC_LEAK_INFO,
-  FUNC_FREE_MALLOC_LEAK_INFO,
-  FUNC_MALLOC_BACKTRACE,
-  FUNC_WRITE_LEAK_INFO,
-  FUNC_LAST,
-};
-static void* g_functions[FUNC_LAST];
-
-typedef void (*finalize_func_t)();
-typedef bool (*init_func_t)(const MallocDispatch*, int*, const char*);
-typedef void (*get_malloc_leak_info_func_t)(uint8_t**, size_t*, size_t*, size_t*, size_t*);
-typedef void (*free_malloc_leak_info_func_t)(uint8_t*);
-typedef bool (*write_malloc_leak_info_func_t)(FILE*);
-typedef ssize_t (*malloc_backtrace_func_t)(void*, uintptr_t*, size_t);
-
 // =============================================================================
-// Log functions
-// =============================================================================
-#define error_log(format, ...)  \
-    async_safe_format_log(ANDROID_LOG_ERROR, "libc", (format), ##__VA_ARGS__ )
-#define info_log(format, ...)  \
-    async_safe_format_log(ANDROID_LOG_INFO, "libc", (format), ##__VA_ARGS__ )
-// =============================================================================
-
-// In a Zygote child process, this is set to true if profiling of this process
-// is allowed. Note that this set at a later time than the above
-// gMallocLeakZygoteChild. The latter is set during the fork (while still in
-// zygote's SELinux domain). While this bit is set after the child is
-// specialized (and has transferred SELinux domains if applicable).
-static _Atomic bool gMallocZygoteChildProfileable = false;
-
-// =============================================================================
-// Exported for use by ddms.
-// =============================================================================
-
-// Retrieve native heap information.
-//
-// "*info" is set to a buffer we allocate
-// "*overall_size" is set to the size of the "info" buffer
-// "*info_size" is set to the size of a single entry
-// "*total_memory" is set to the sum of all allocations we're tracking; does
-//   not include heap overhead
-// "*backtrace_size" is set to the maximum number of entries in the back trace
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size,
-    size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
-  void* func = g_functions[FUNC_GET_MALLOC_LEAK_INFO];
-  if (func == nullptr) {
-    return;
-  }
-  reinterpret_cast<get_malloc_leak_info_func_t>(func)(info, overall_size, info_size, total_memory,
-                                                      backtrace_size);
-}
-
-extern "C" void free_malloc_leak_info(uint8_t* info) {
-  void* func = g_functions[FUNC_FREE_MALLOC_LEAK_INFO];
-  if (func == nullptr) {
-    return;
-  }
-  reinterpret_cast<free_malloc_leak_info_func_t>(func)(info);
-}
-
-extern "C" void write_malloc_leak_info(FILE* fp) {
-  if (fp == nullptr) {
-    error_log("write_malloc_leak_info called with a nullptr");
-    return;
-  }
-
-  void* func = g_functions[FUNC_WRITE_LEAK_INFO];
-  bool written = false;
-  if (func != nullptr) {
-    written = reinterpret_cast<write_malloc_leak_info_func_t>(func)(fp);
-  }
-
-  if (!written) {
-    fprintf(fp, "Native heap dump not available. To enable, run these commands (requires root):\n");
-    fprintf(fp, "# adb shell stop\n");
-    fprintf(fp, "# adb shell setprop libc.debug.malloc.options backtrace\n");
-    fprintf(fp, "# adb shell start\n");
-  }
-}
-
-// =============================================================================
-
-template<typename FunctionType>
-static bool InitMallocFunction(void* malloc_impl_handler, _Atomic(FunctionType)* func, const char* prefix, const char* suffix) {
-  char symbol[128];
-  snprintf(symbol, sizeof(symbol), "%s_%s", prefix, suffix);
-  *func = reinterpret_cast<FunctionType>(dlsym(malloc_impl_handler, symbol));
-  if (*func == nullptr) {
-    error_log("%s: dlsym(\"%s\") failed", getprogname(), symbol);
-    return false;
-  }
-  return true;
-}
-
-static bool InitMallocFunctions(void* impl_handler, MallocDispatch* table, const char* prefix) {
-  if (!InitMallocFunction<MallocFree>(impl_handler, &table->free, prefix, "free")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocCalloc>(impl_handler, &table->calloc, prefix, "calloc")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocMallinfo>(impl_handler, &table->mallinfo, prefix, "mallinfo")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocMallopt>(impl_handler, &table->mallopt, prefix, "mallopt")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocMalloc>(impl_handler, &table->malloc, prefix, "malloc")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocMallocUsableSize>(impl_handler, &table->malloc_usable_size, prefix,
-                                                  "malloc_usable_size")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocMemalign>(impl_handler, &table->memalign, prefix, "memalign")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocPosixMemalign>(impl_handler, &table->posix_memalign, prefix,
-                                               "posix_memalign")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocAlignedAlloc>(impl_handler, &table->aligned_alloc,
-                                              prefix, "aligned_alloc")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocRealloc>(impl_handler, &table->realloc, prefix, "realloc")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocIterate>(impl_handler, &table->iterate, prefix, "iterate")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocMallocDisable>(impl_handler, &table->malloc_disable, prefix,
-                                               "malloc_disable")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocMallocEnable>(impl_handler, &table->malloc_enable, prefix,
-                                              "malloc_enable")) {
-    return false;
-  }
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-  if (!InitMallocFunction<MallocPvalloc>(impl_handler, &table->pvalloc, prefix, "pvalloc")) {
-    return false;
-  }
-  if (!InitMallocFunction<MallocValloc>(impl_handler, &table->valloc, prefix, "valloc")) {
-    return false;
-  }
-#endif
-
-  return true;
-}
-
-static void malloc_fini_impl(void*) {
-  // Our BSD stdio implementation doesn't close the standard streams,
-  // it only flushes them. Other unclosed FILE*s will show up as
-  // malloc leaks, but to avoid the standard streams showing up in
-  // leak reports, close them here.
-  fclose(stdin);
-  fclose(stdout);
-  fclose(stderr);
-
-  reinterpret_cast<finalize_func_t>(g_functions[FUNC_FINALIZE])();
-}
-
-static bool CheckLoadMallocHooks(char** options) {
-  char* env = getenv(HOOKS_ENV_ENABLE);
-  if ((env == nullptr || env[0] == '\0' || env[0] == '0') &&
-    (__system_property_get(HOOKS_PROPERTY_ENABLE, *options) == 0 || *options[0] == '\0' || *options[0] == '0')) {
-    return false;
-  }
-  *options = nullptr;
-  return true;
-}
-
-static bool CheckLoadMallocDebug(char** options) {
-  // If DEBUG_MALLOC_ENV_OPTIONS is set then it overrides the system properties.
-  char* env = getenv(DEBUG_ENV_OPTIONS);
-  if (env == nullptr || env[0] == '\0') {
-    if (__system_property_get(DEBUG_PROPERTY_OPTIONS, *options) == 0 || *options[0] == '\0') {
-      return false;
-    }
-
-    // Check to see if only a specific program should have debug malloc enabled.
-    char program[PROP_VALUE_MAX];
-    if (__system_property_get(DEBUG_PROPERTY_PROGRAM, program) != 0 &&
-        strstr(getprogname(), program) == nullptr) {
-      return false;
-    }
-  } else {
-    *options = env;
-  }
-  return true;
-}
-
-static bool GetHeapprofdProgramProperty(char* data, size_t size) {
-  constexpr char prefix[] = "heapprofd.enable.";
-  // - 1 to skip nullbyte, which we will write later.
-  constexpr size_t prefix_size = sizeof(prefix) - 1;
-  if (size < prefix_size) {
-    error_log("%s: Overflow constructing heapprofd property", getprogname());
-    return false;
-  }
-  memcpy(data, prefix, prefix_size);
-
-  int fd = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
-  if (fd == -1) {
-    error_log("%s: Failed to open /proc/self/cmdline", getprogname());
-    return false;
-  }
-  char cmdline[128];
-  ssize_t rd = read(fd, cmdline, sizeof(cmdline) - 1);
-  close(fd);
-  if (rd == -1) {
-    error_log("%s: Failed to read /proc/self/cmdline", getprogname());
-    return false;
-  }
-  cmdline[rd] = '\0';
-  char* first_arg = static_cast<char*>(memchr(cmdline, '\0', rd));
-  if (first_arg == nullptr || first_arg == cmdline + size - 1) {
-    error_log("%s: Overflow reading cmdline", getprogname());
-    return false;
-  }
-  // For consistency with what we do with Java app cmdlines, trim everything
-  // after the @ sign of the first arg.
-  char* first_at = static_cast<char*>(memchr(cmdline, '@', rd));
-  if (first_at != nullptr && first_at < first_arg) {
-    *first_at = '\0';
-    first_arg = first_at;
-  }
-
-  char* start = static_cast<char*>(memrchr(cmdline, '/', first_arg - cmdline));
-  if (start == first_arg) {
-    // The first argument ended in a slash.
-    error_log("%s: cmdline ends in /", getprogname());
-    return false;
-  } else if (start == nullptr) {
-    start = cmdline;
-  } else {
-    // Skip the /.
-    start++;
-  }
-
-  size_t name_size = static_cast<size_t>(first_arg - start);
-  if (name_size >= size - prefix_size) {
-    error_log("%s: overflow constructing heapprofd property.", getprogname());
-    return false;
-  }
-  // + 1 to also copy the trailing null byte.
-  memcpy(data + prefix_size, start, name_size + 1);
-  return true;
-}
-
-static bool CheckLoadHeapprofd() {
-  // First check for heapprofd.enable. If it is set to "all", enable
-  // heapprofd for all processes. Otherwise, check heapprofd.enable.${prog},
-  // if it is set and not 0, enable heap profiling for this process.
-  char property_value[PROP_VALUE_MAX];
-  if (__system_property_get(HEAPPROFD_PROPERTY_ENABLE, property_value) == 0) {
-    return false;
-  }
-  if (strcmp(property_value, "all") == 0) {
-    return true;
-  }
-
-  char program_property[128];
-  if (!GetHeapprofdProgramProperty(program_property,
-                                   sizeof(program_property))) {
-    return false;
-  }
-  if (__system_property_get(program_property, property_value) == 0) {
-    return false;
-  }
-  return program_property[0] != '\0';
-}
-
-static void ClearGlobalFunctions() {
-  for (size_t i = 0; i < FUNC_LAST; i++) {
-    g_functions[i] = nullptr;
-  }
-}
-
-static bool InitSharedLibrary(void* impl_handle, const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
-  static constexpr const char* names[] = {
-    "initialize",
-    "finalize",
-    "get_malloc_leak_info",
-    "free_malloc_leak_info",
-    "malloc_backtrace",
-    "write_malloc_leak_info",
-  };
-  for (size_t i = 0; i < FUNC_LAST; i++) {
-    char symbol[128];
-    snprintf(symbol, sizeof(symbol), "%s_%s", prefix, names[i]);
-    g_functions[i] = dlsym(impl_handle, symbol);
-    if (g_functions[i] == nullptr) {
-      error_log("%s: %s routine not found in %s", getprogname(), symbol, shared_lib);
-      ClearGlobalFunctions();
-      return false;
-    }
-  }
-
-  if (!InitMallocFunctions(impl_handle, dispatch_table, prefix)) {
-    ClearGlobalFunctions();
-    return false;
-  }
-  return true;
-}
-
-static void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
-  void* impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
-  if (impl_handle == nullptr) {
-    error_log("%s: Unable to open shared library %s: %s", getprogname(), shared_lib, dlerror());
-    return nullptr;
-  }
-
-  if (!InitSharedLibrary(impl_handle, shared_lib, prefix, dispatch_table)) {
-    dlclose(impl_handle);
-    impl_handle = nullptr;
-  }
-
-  return impl_handle;
-}
-
-// The handle returned by dlopen when previously loading the heapprofd
-// hooks. nullptr if they had not been loaded before.
-static _Atomic (void*) g_heapprofd_handle = nullptr;
-
-static void install_hooks(libc_globals* globals, const char* options,
-                          const char* prefix, const char* shared_lib) {
-  MallocDispatch dispatch_table;
-
-  void* impl_handle = atomic_load(&g_heapprofd_handle);
-  bool reusing_handle = impl_handle != nullptr;
-  if (reusing_handle) {
-    if (!InitSharedLibrary(impl_handle, shared_lib, prefix, &dispatch_table)) {
-      return;
-    }
-  } else {
-    impl_handle = LoadSharedLibrary(shared_lib, prefix, &dispatch_table);
-    if (impl_handle == nullptr) {
-      return;
-    }
-  }
-  init_func_t init_func = reinterpret_cast<init_func_t>(g_functions[FUNC_INITIALIZE]);
-  if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
-    error_log("%s: failed to enable malloc %s", getprogname(), prefix);
-    if (!reusing_handle) {
-      // We should not close if we are re-using an old handle, as we cannot be
-      // sure other threads are not currently in the hooks.
-      dlclose(impl_handle);
-    }
-    ClearGlobalFunctions();
-    return;
-  }
-
-  // We assign free  first explicitly to prevent the case where we observe a
-  // alloc, but miss the corresponding free because of initialization order.
-  //
-  // This is safer than relying on the declaration order inside
-  // MallocDispatch at the cost of an extra atomic pointer write on
-  // initialization.
-  atomic_store(&globals->malloc_dispatch.free, dispatch_table.free);
-  // The struct gets assigned elementwise and each of the elements is an
-  // _Atomic. Assigning to an _Atomic is an atomic_store operation.
-  // The assignment is done in declaration order.
-  globals->malloc_dispatch = dispatch_table;
-  atomic_store(&g_heapprofd_handle, impl_handle);
-
-  info_log("%s: malloc %s enabled", getprogname(), prefix);
-
-  // Use atexit to trigger the cleanup function. This avoids a problem
-  // where another atexit function is used to cleanup allocated memory,
-  // but the finalize function was already called. This particular error
-  // seems to be triggered by a zygote spawned process calling exit.
-  int ret_value = __cxa_atexit(malloc_fini_impl, nullptr, nullptr);
-  if (ret_value != 0) {
-    error_log("failed to set atexit cleanup function: %d", ret_value);
-  }
-}
-
-// The logic for triggering heapprofd (at runtime) is as follows:
-// 1. HEAPPROFD_SIGNAL is received by the process, entering the
-//    MaybeInstallInitHeapprofdHook signal handler.
-// 2. If the initialization is not already in flight
-//    (g_heapprofd_init_in_progress is false), the malloc hook is set to
-//    point at InitHeapprofdHook, and g_heapprofd_init_in_progress is set to
-//    true.
-// 3. The next malloc call enters InitHeapprofdHook, which removes the malloc
-//    hook, and spawns a detached pthread to run the InitHeapprofd task.
-//    (g_heapprofd_init_hook_installed atomic is used to perform this once.)
-// 4. InitHeapprofd, on a dedicated pthread, loads the heapprofd client library,
-//    installs the full set of heapprofd hooks, and invokes the client's
-//    initializer. The dedicated pthread then terminates.
-// 5. g_heapprofd_init_in_progress and g_heapprofd_init_hook_installed are
-//    reset to false such that heapprofd can be reinitialized. Reinitialization
-//    means that a new profiling session is started, and any still active is
-//    torn down.
-//
-// The incremental hooking and a dedicated task thread are used since we cannot
-// do heavy work within a signal handler, or when blocking a malloc invocation.
-
-static _Atomic bool g_heapprofd_init_in_progress = false;
-static _Atomic bool g_heapprofd_init_hook_installed = false;
-
-extern "C" void MaybeInstallInitHeapprofdHook(int);
-
-// Initializes memory allocation framework once per process.
-static void malloc_init_impl(libc_globals* globals) {
-  struct sigaction action = {};
-  action.sa_handler = MaybeInstallInitHeapprofdHook;
-  sigaction(HEAPPROFD_SIGNAL, &action, nullptr);
-
-  const char* prefix;
-  const char* shared_lib;
-  char prop[PROP_VALUE_MAX];
-  char* options = prop;
-  // Prefer malloc debug since it existed first and is a more complete
-  // malloc interceptor than the hooks.
-  if (CheckLoadMallocDebug(&options)) {
-    prefix = "debug";
-    shared_lib = DEBUG_SHARED_LIB;
-  } else if (CheckLoadMallocHooks(&options)) {
-    prefix = "hooks";
-    shared_lib = HOOKS_SHARED_LIB;
-  } else if (CheckLoadHeapprofd()) {
-    prefix = "heapprofd";
-    shared_lib = HEAPPROFD_SHARED_LIB;
-  } else {
-    return;
-  }
-  if (!atomic_exchange(&g_heapprofd_init_in_progress, true)) {
-    install_hooks(globals, options, prefix, shared_lib);
-    atomic_store(&g_heapprofd_init_in_progress, false);
-  }
-}
-
-// Initializes memory allocation framework.
-// This routine is called from __libc_init routines in libc_init_dynamic.cpp.
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
-  malloc_init_impl(globals);
-}
-
-static void* InitHeapprofd(void*) {
-  __libc_globals.mutate([](libc_globals* globals) {
-    install_hooks(globals, nullptr, HEAPPROFD_PREFIX, HEAPPROFD_SHARED_LIB);
-  });
-  atomic_store(&g_heapprofd_init_in_progress, false);
-  // Allow to install hook again to re-initialize heap profiling after the
-  // current session finished.
-  atomic_store(&g_heapprofd_init_hook_installed, false);
-  return nullptr;
-}
-
-static void* InitHeapprofdHook(size_t bytes) {
-  if (!atomic_exchange(&g_heapprofd_init_hook_installed, true)) {
-    __libc_globals.mutate([](libc_globals* globals) {
-      atomic_store(&globals->malloc_dispatch.malloc, nullptr);
-    });
-
-    pthread_t thread_id;
-    if (pthread_create(&thread_id, nullptr, InitHeapprofd, nullptr) == -1)
-      error_log("%s: heapprofd: failed to pthread_create.", getprogname());
-    else if (pthread_detach(thread_id) == -1)
-      error_log("%s: heapprofd: failed to pthread_detach", getprogname());
-    if (pthread_setname_np(thread_id, "heapprofdinit") == -1)
-      error_log("%s: heapprod: failed to pthread_setname_np", getprogname());
-  }
-  return Malloc(malloc)(bytes);
-}
-
-extern "C" void MaybeInstallInitHeapprofdHook(int) {
-  // Zygote child processes must be marked profileable.
-  if (gMallocLeakZygoteChild &&
-      !atomic_load_explicit_const(&gMallocZygoteChildProfileable, memory_order_acquire)) {
-    return;
-  }
-
-  if (!atomic_exchange(&g_heapprofd_init_in_progress, true)) {
-    __libc_globals.mutate([](libc_globals* globals) {
-      atomic_store(&globals->malloc_dispatch.malloc, InitHeapprofdHook);
-    });
-  }
-}
-
-#endif  // !LIBC_STATIC
 
 // =============================================================================
 // Platform-internal mallopt variant.
 // =============================================================================
-
-#if !defined(LIBC_STATIC)
-bool MallocDispatchReset() {
-  if (!atomic_exchange(&g_heapprofd_init_in_progress, true)) {
-    __libc_globals.mutate([](libc_globals* globals) {
-      globals->malloc_dispatch = __libc_malloc_default_dispatch;
-    });
-    atomic_store(&g_heapprofd_init_in_progress, false);
-    return true;
+#if defined(LIBC_STATIC)
+extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
+  if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
+    return LimitEnable(arg, arg_size);
   }
-  errno = EAGAIN;
-  return false;
-}
-
-// Marks this process as a profileable zygote child.
-bool HandleInitZygoteChildProfiling() {
-  atomic_store_explicit(&gMallocZygoteChildProfileable, true,
-                        memory_order_release);
-
-  // Conditionally start "from startup" profiling.
-  if (CheckLoadHeapprofd()) {
-    // Directly call the signal handler (will correctly guard against
-    // concurrent signal delivery).
-    MaybeInstallInitHeapprofdHook(HEAPPROFD_SIGNAL);
-  }
-  return true;
-}
-
-#else
-
-bool MallocDispatchReset() {
-  return true;
-}
-
-bool HandleInitZygoteChildProfiling() {
-  return true;
-}
-
-#endif  // !defined(LIBC_STATIC)
-
-bool android_mallopt(int opcode, void* arg, size_t arg_size) {
-  if (opcode == M_INIT_ZYGOTE_CHILD_PROFILING) {
-    if (arg != nullptr || arg_size != 0) {
-      errno = EINVAL;
-      return false;
-    }
-    return HandleInitZygoteChildProfiling();
-  }
-  if (opcode == M_RESET_HOOKS) {
-    if (arg != nullptr || arg_size != 0) {
-      errno = EINVAL;
-      return false;
-    }
-    return MallocDispatchReset();
-  }
-
   errno = ENOTSUP;
   return false;
 }
-
-// =============================================================================
-// Exported for use by libmemunreachable.
-// =============================================================================
-
-// Calls callback for every allocation in the anonymous heap mapping
-// [base, base+size).  Must be called between malloc_disable and malloc_enable.
-extern "C" int malloc_iterate(uintptr_t base, size_t size,
-    void (*callback)(uintptr_t base, size_t size, void* arg), void* arg) {
-  auto _iterate = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.iterate,
-      default_read_memory_order);
-  if (__predict_false(_iterate != nullptr)) {
-    return _iterate(base, size, callback, arg);
-  }
-  return Malloc(iterate)(base, size, callback, arg);
-}
-
-// Disable calls to malloc so malloc_iterate gets a consistent view of
-// allocated memory.
-extern "C" void malloc_disable() {
-  auto _malloc_disable = atomic_load_explicit_const(
-     & __libc_globals->malloc_dispatch.malloc_disable,
-      default_read_memory_order);
-  if (__predict_false(_malloc_disable != nullptr)) {
-    return _malloc_disable();
-  }
-  return Malloc(malloc_disable)();
-}
-
-// Re-enable calls to malloc after a previous call to malloc_disable.
-extern "C" void malloc_enable() {
-  auto _malloc_enable = atomic_load_explicit_const(
-      &__libc_globals->malloc_dispatch.malloc_enable,
-      default_read_memory_order);
-  if (__predict_false(_malloc_enable != nullptr)) {
-    return _malloc_enable();
-  }
-  return Malloc(malloc_enable)();
-}
-
-#ifndef LIBC_STATIC
-extern "C" ssize_t malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count) {
-  void* func = g_functions[FUNC_MALLOC_BACKTRACE];
-  if (func == nullptr) {
-    return 0;
-  }
-  return reinterpret_cast<malloc_backtrace_func_t>(func)(pointer, frames, frame_count);
-}
-#else
-extern "C" ssize_t malloc_backtrace(void*, uintptr_t*, size_t) {
-  return 0;
-}
 #endif
+// =============================================================================
diff --git a/libc/bionic/malloc_common.h b/libc/bionic/malloc_common.h
new file mode 100644
index 0000000..a40501d
--- /dev/null
+++ b/libc/bionic/malloc_common.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 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 <stdatomic.h>
+#include <stdio.h>
+
+#include <async_safe/log.h>
+#include <private/bionic_globals.h>
+#include <private/bionic_malloc_dispatch.h>
+
+#if __has_feature(hwaddress_sanitizer)
+
+#include <sanitizer/hwasan_interface.h>
+
+__BEGIN_DECLS
+
+// FIXME: implement these in HWASan allocator.
+int __sanitizer_iterate(uintptr_t base, size_t size,
+                        void (*callback)(uintptr_t base, size_t size, void* arg),
+                        void* arg);
+void __sanitizer_malloc_disable();
+void __sanitizer_malloc_enable();
+int __sanitizer_malloc_info(int options, FILE* fp);
+
+__END_DECLS
+
+#define Malloc(function)  __sanitizer_ ## function
+
+#else // __has_feature(hwaddress_sanitizer)
+
+#include "jemalloc.h"
+#define Malloc(function)  je_ ## function
+
+#endif
+
+extern int gMallocLeakZygoteChild;
+
+static inline const MallocDispatch* GetDispatchTable() {
+  return atomic_load_explicit(&__libc_globals->current_dispatch_table, memory_order_acquire);
+}
+
+static inline const MallocDispatch* GetDefaultDispatchTable() {
+  return atomic_load_explicit(&__libc_globals->default_dispatch_table, memory_order_acquire);
+}
+
+// =============================================================================
+// Log functions
+// =============================================================================
+#define error_log(format, ...)  \
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", (format), ##__VA_ARGS__ )
+#define info_log(format, ...)  \
+    async_safe_format_log(ANDROID_LOG_INFO, "libc", (format), ##__VA_ARGS__ )
+#define warning_log(format, ...)  \
+    async_safe_format_log(ANDROID_LOG_WARN, "libc", (format), ##__VA_ARGS__ )
+// =============================================================================
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
new file mode 100644
index 0000000..40f497e
--- /dev/null
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#if defined(LIBC_STATIC)
+#error This file should not be compiled for static targets.
+#endif
+
+// Contains a thin layer that calls whatever real native allocator
+// has been defined. For the libc shared library, this allows the
+// implementation of a debug malloc that can intercept all of the allocation
+// calls and add special debugging code to attempt to catch allocation
+// errors. All of the debugging code is implemented in a separate shared
+// library that is only loaded when the property "libc.debug.malloc.options"
+// is set to a non-zero value. There are three functions exported to
+// allow ddms, or other external users to get information from the debug
+// allocation.
+//   get_malloc_leak_info: Returns information about all of the known native
+//                         allocations that are currently in use.
+//   free_malloc_leak_info: Frees the data allocated by the call to
+//                          get_malloc_leak_info.
+//   write_malloc_leak_info: Writes the leak info data to a file.
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <private/bionic_config.h>
+#include <private/bionic_defs.h>
+#include <private/bionic_malloc_dispatch.h>
+#include <private/bionic_malloc.h>
+
+#include <sys/system_properties.h>
+
+#include "malloc_common.h"
+#include "malloc_common_dynamic.h"
+#include "malloc_heapprofd.h"
+#include "malloc_limit.h"
+
+// =============================================================================
+// Global variables instantations.
+// =============================================================================
+pthread_mutex_t gGlobalsMutateLock = PTHREAD_MUTEX_INITIALIZER;
+
+_Atomic bool gGlobalsMutating = false;
+// =============================================================================
+
+static constexpr MallocDispatch __libc_malloc_default_dispatch
+  __attribute__((unused)) = {
+    Malloc(calloc),
+    Malloc(free),
+    Malloc(mallinfo),
+    Malloc(malloc),
+    Malloc(malloc_usable_size),
+    Malloc(memalign),
+    Malloc(posix_memalign),
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+    Malloc(pvalloc),
+#endif
+    Malloc(realloc),
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+    Malloc(valloc),
+#endif
+    Malloc(iterate),
+    Malloc(malloc_disable),
+    Malloc(malloc_enable),
+    Malloc(mallopt),
+    Malloc(aligned_alloc),
+    Malloc(malloc_info),
+  };
+
+static constexpr char kHooksSharedLib[] = "libc_malloc_hooks.so";
+static constexpr char kHooksPrefix[] = "hooks";
+static constexpr char kHooksPropertyEnable[] = "libc.debug.hooks.enable";
+static constexpr char kHooksEnvEnable[] = "LIBC_HOOKS_ENABLE";
+
+static constexpr char kDebugSharedLib[] = "libc_malloc_debug.so";
+static constexpr char kDebugPrefix[] = "debug";
+static constexpr char kDebugPropertyOptions[] = "libc.debug.malloc.options";
+static constexpr char kDebugPropertyProgram[] = "libc.debug.malloc.program";
+static constexpr char kDebugEnvOptions[] = "LIBC_DEBUG_MALLOC_OPTIONS";
+
+typedef void (*finalize_func_t)();
+typedef bool (*init_func_t)(const MallocDispatch*, int*, const char*);
+typedef void (*get_malloc_leak_info_func_t)(uint8_t**, size_t*, size_t*, size_t*, size_t*);
+typedef void (*free_malloc_leak_info_func_t)(uint8_t*);
+typedef bool (*write_malloc_leak_info_func_t)(FILE*);
+typedef ssize_t (*malloc_backtrace_func_t)(void*, uintptr_t*, size_t);
+
+enum FunctionEnum : uint8_t {
+  FUNC_INITIALIZE,
+  FUNC_FINALIZE,
+  FUNC_GET_MALLOC_LEAK_INFO,
+  FUNC_FREE_MALLOC_LEAK_INFO,
+  FUNC_MALLOC_BACKTRACE,
+  FUNC_WRITE_LEAK_INFO,
+  FUNC_LAST,
+};
+static void* gFunctions[FUNC_LAST];
+
+extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
+
+template<typename FunctionType>
+static bool InitMallocFunction(void* malloc_impl_handler, FunctionType* func, const char* prefix, const char* suffix) {
+  char symbol[128];
+  snprintf(symbol, sizeof(symbol), "%s_%s", prefix, suffix);
+  *func = reinterpret_cast<FunctionType>(dlsym(malloc_impl_handler, symbol));
+  if (*func == nullptr) {
+    error_log("%s: dlsym(\"%s\") failed", getprogname(), symbol);
+    return false;
+  }
+  return true;
+}
+
+static bool InitMallocFunctions(void* impl_handler, MallocDispatch* table, const char* prefix) {
+  if (!InitMallocFunction<MallocFree>(impl_handler, &table->free, prefix, "free")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocCalloc>(impl_handler, &table->calloc, prefix, "calloc")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMallinfo>(impl_handler, &table->mallinfo, prefix, "mallinfo")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMallopt>(impl_handler, &table->mallopt, prefix, "mallopt")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMalloc>(impl_handler, &table->malloc, prefix, "malloc")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMallocInfo>(impl_handler, &table->malloc_info, prefix,
+                                                "malloc_info")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMallocUsableSize>(impl_handler, &table->malloc_usable_size, prefix,
+                                                  "malloc_usable_size")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMemalign>(impl_handler, &table->memalign, prefix, "memalign")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocPosixMemalign>(impl_handler, &table->posix_memalign, prefix,
+                                               "posix_memalign")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocAlignedAlloc>(impl_handler, &table->aligned_alloc,
+                                              prefix, "aligned_alloc")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocRealloc>(impl_handler, &table->realloc, prefix, "realloc")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocIterate>(impl_handler, &table->iterate, prefix, "iterate")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMallocDisable>(impl_handler, &table->malloc_disable, prefix,
+                                               "malloc_disable")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMallocEnable>(impl_handler, &table->malloc_enable, prefix,
+                                              "malloc_enable")) {
+    return false;
+  }
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+  if (!InitMallocFunction<MallocPvalloc>(impl_handler, &table->pvalloc, prefix, "pvalloc")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocValloc>(impl_handler, &table->valloc, prefix, "valloc")) {
+    return false;
+  }
+#endif
+
+  return true;
+}
+
+static void MallocFiniImpl(void*) {
+  // Our BSD stdio implementation doesn't close the standard streams,
+  // it only flushes them. Other unclosed FILE*s will show up as
+  // malloc leaks, but to avoid the standard streams showing up in
+  // leak reports, close them here.
+  fclose(stdin);
+  fclose(stdout);
+  fclose(stderr);
+
+  reinterpret_cast<finalize_func_t>(gFunctions[FUNC_FINALIZE])();
+}
+
+static bool CheckLoadMallocHooks(char** options) {
+  char* env = getenv(kHooksEnvEnable);
+  if ((env == nullptr || env[0] == '\0' || env[0] == '0') &&
+    (__system_property_get(kHooksPropertyEnable, *options) == 0 || *options[0] == '\0' || *options[0] == '0')) {
+    return false;
+  }
+  *options = nullptr;
+  return true;
+}
+
+static bool CheckLoadMallocDebug(char** options) {
+  // If kDebugMallocEnvOptions is set then it overrides the system properties.
+  char* env = getenv(kDebugEnvOptions);
+  if (env == nullptr || env[0] == '\0') {
+    if (__system_property_get(kDebugPropertyOptions, *options) == 0 || *options[0] == '\0') {
+      return false;
+    }
+
+    // Check to see if only a specific program should have debug malloc enabled.
+    char program[PROP_VALUE_MAX];
+    if (__system_property_get(kDebugPropertyProgram, program) != 0 &&
+        strstr(getprogname(), program) == nullptr) {
+      return false;
+    }
+  } else {
+    *options = env;
+  }
+  return true;
+}
+
+static void ClearGlobalFunctions() {
+  for (size_t i = 0; i < FUNC_LAST; i++) {
+    gFunctions[i] = nullptr;
+  }
+}
+
+bool InitSharedLibrary(void* impl_handle, const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
+  static constexpr const char* names[] = {
+    "initialize",
+    "finalize",
+    "get_malloc_leak_info",
+    "free_malloc_leak_info",
+    "malloc_backtrace",
+    "write_malloc_leak_info",
+  };
+  for (size_t i = 0; i < FUNC_LAST; i++) {
+    char symbol[128];
+    snprintf(symbol, sizeof(symbol), "%s_%s", prefix, names[i]);
+    gFunctions[i] = dlsym(impl_handle, symbol);
+    if (gFunctions[i] == nullptr) {
+      error_log("%s: %s routine not found in %s", getprogname(), symbol, shared_lib);
+      ClearGlobalFunctions();
+      return false;
+    }
+  }
+
+  if (!InitMallocFunctions(impl_handle, dispatch_table, prefix)) {
+    ClearGlobalFunctions();
+    return false;
+  }
+  return true;
+}
+
+void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
+  void* impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
+  if (impl_handle == nullptr) {
+    error_log("%s: Unable to open shared library %s: %s", getprogname(), shared_lib, dlerror());
+    return nullptr;
+  }
+
+  if (!InitSharedLibrary(impl_handle, shared_lib, prefix, dispatch_table)) {
+    dlclose(impl_handle);
+    impl_handle = nullptr;
+  }
+
+  return impl_handle;
+}
+
+bool FinishInstallHooks(libc_globals* globals, const char* options, const char* prefix) {
+  init_func_t init_func = reinterpret_cast<init_func_t>(gFunctions[FUNC_INITIALIZE]);
+  if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
+    error_log("%s: failed to enable malloc %s", getprogname(), prefix);
+    ClearGlobalFunctions();
+    return false;
+  }
+
+  // Do a pointer swap so that all of the functions become valid at once to
+  // avoid any initialization order problems.
+  atomic_store(&globals->default_dispatch_table, &globals->malloc_dispatch_table);
+  if (GetDispatchTable() == nullptr) {
+    atomic_store(&globals->current_dispatch_table, &globals->malloc_dispatch_table);
+  }
+
+  info_log("%s: malloc %s enabled", getprogname(), prefix);
+
+  // Use atexit to trigger the cleanup function. This avoids a problem
+  // where another atexit function is used to cleanup allocated memory,
+  // but the finalize function was already called. This particular error
+  // seems to be triggered by a zygote spawned process calling exit.
+  int ret_value = __cxa_atexit(MallocFiniImpl, nullptr, nullptr);
+  if (ret_value != 0) {
+    // We don't consider this a fatal error.
+    info_log("failed to set atexit cleanup function: %d", ret_value);
+  }
+  return true;
+}
+
+static bool InstallHooks(libc_globals* globals, const char* options, const char* prefix,
+                         const char* shared_lib) {
+  void* impl_handle = LoadSharedLibrary(shared_lib, prefix, &globals->malloc_dispatch_table);
+  if (impl_handle == nullptr) {
+    return false;
+  }
+
+  init_func_t init_func = reinterpret_cast<init_func_t>(gFunctions[FUNC_INITIALIZE]);
+  if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
+    error_log("%s: failed to enable malloc %s", getprogname(), prefix);
+    ClearGlobalFunctions();
+    return false;
+  }
+
+  if (!FinishInstallHooks(globals, options, prefix)) {
+    dlclose(impl_handle);
+    return false;
+  }
+  return true;
+}
+
+// Initializes memory allocation framework once per process.
+static void MallocInitImpl(libc_globals* globals) {
+  char prop[PROP_VALUE_MAX];
+  char* options = prop;
+
+  // Prefer malloc debug since it existed first and is a more complete
+  // malloc interceptor than the hooks.
+  bool hook_installed = false;
+  if (CheckLoadMallocDebug(&options)) {
+    hook_installed = InstallHooks(globals, options, kDebugPrefix, kDebugSharedLib);
+  } else if (CheckLoadMallocHooks(&options)) {
+    hook_installed = InstallHooks(globals, options, kHooksPrefix, kHooksSharedLib);
+  }
+
+  if (!hook_installed) {
+    if (HeapprofdShouldLoad()) {
+      HeapprofdInstallHooksAtInit(globals);
+    }
+
+    // Install this last to avoid as many race conditions as possible.
+    HeapprofdInstallSignalHandler();
+  } else {
+    // Install a signal handler that prints an error since we don't support
+    // heapprofd and any other hook to be installed at the same time.
+    HeapprofdInstallErrorSignalHandler();
+  }
+}
+
+// Initializes memory allocation framework.
+// This routine is called from __libc_init routines in libc_init_dynamic.cpp.
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
+  MallocInitImpl(globals);
+}
+
+// =============================================================================
+// Functions to support dumping of native heap allocations using malloc debug.
+// =============================================================================
+
+// Retrieve native heap information.
+//
+// "*info" is set to a buffer we allocate
+// "*overall_size" is set to the size of the "info" buffer
+// "*info_size" is set to the size of a single entry
+// "*total_memory" is set to the sum of all allocations we're tracking; does
+//   not include heap overhead
+// "*backtrace_size" is set to the maximum number of entries in the back trace
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size,
+    size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
+  void* func = gFunctions[FUNC_GET_MALLOC_LEAK_INFO];
+  if (func == nullptr) {
+    return;
+  }
+  reinterpret_cast<get_malloc_leak_info_func_t>(func)(info, overall_size, info_size, total_memory,
+                                                      backtrace_size);
+}
+
+extern "C" void free_malloc_leak_info(uint8_t* info) {
+  void* func = gFunctions[FUNC_FREE_MALLOC_LEAK_INFO];
+  if (func == nullptr) {
+    return;
+  }
+  reinterpret_cast<free_malloc_leak_info_func_t>(func)(info);
+}
+
+extern "C" void write_malloc_leak_info(FILE* fp) {
+  if (fp == nullptr) {
+    error_log("write_malloc_leak_info called with a nullptr");
+    return;
+  }
+
+  void* func = gFunctions[FUNC_WRITE_LEAK_INFO];
+  bool written = false;
+  if (func != nullptr) {
+    written = reinterpret_cast<write_malloc_leak_info_func_t>(func)(fp);
+  }
+
+  if (!written) {
+    fprintf(fp, "Native heap dump not available. To enable, run these commands (requires root):\n");
+    fprintf(fp, "# adb shell stop\n");
+    fprintf(fp, "# adb shell setprop libc.debug.malloc.options backtrace\n");
+    fprintf(fp, "# adb shell start\n");
+  }
+}
+// =============================================================================
+
+// =============================================================================
+// Exported for use by libmemunreachable.
+// =============================================================================
+extern "C" ssize_t malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count) {
+  void* func = gFunctions[FUNC_MALLOC_BACKTRACE];
+  if (func == nullptr) {
+    return 0;
+  }
+  return reinterpret_cast<malloc_backtrace_func_t>(func)(pointer, frames, frame_count);
+}
+// =============================================================================
+
+// =============================================================================
+// Platform-internal mallopt variant.
+// =============================================================================
+extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
+  if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
+    return LimitEnable(arg, arg_size);
+  }
+  return HeapprofdMallopt(opcode, arg, arg_size);
+}
+// =============================================================================
diff --git a/libc/arch-mips/bionic/libgcc_compat.c b/libc/bionic/malloc_common_dynamic.h
similarity index 65%
copy from libc/arch-mips/bionic/libgcc_compat.c
copy to libc/bionic/malloc_common_dynamic.h
index 1a0f566..755af8f 100644
--- a/libc/arch-mips/bionic/libgcc_compat.c
+++ b/libc/bionic/malloc_common_dynamic.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,16 +26,22 @@
  * SUCH DAMAGE.
  */
 
-extern char __divdi3;
-extern char __moddi3;
-extern char __popcountsi2;
-extern char __udivdi3;
-extern char __umoddi3;
+#pragma once
 
-void* __bionic_libgcc_compat_symbols[] = {
-    &__divdi3,
-    &__moddi3,
-    &__popcountsi2,
-    &__udivdi3,
-    &__umoddi3,
-};
+#include <pthread.h>
+#include <stdatomic.h>
+
+#include <private/bionic_globals.h>
+#include <private/bionic_malloc_dispatch.h>
+
+// Function prototypes.
+bool InitSharedLibrary(void* impl_handle, const char* shared_lib, const char* prefix,
+                       MallocDispatch* dispatch_table);
+
+void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table);
+
+bool FinishInstallHooks(libc_globals* globals, const char* options, const char* prefix);
+
+// Lock for globals, to guarantee that only one thread is doing a mutate.
+extern pthread_mutex_t gGlobalsMutateLock;
+extern _Atomic bool gGlobalsMutating;
diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp
new file mode 100644
index 0000000..eda54ce
--- /dev/null
+++ b/libc/bionic/malloc_heapprofd.cpp
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#if defined(LIBC_STATIC)
+#error This file should not be compiled for static targets.
+#endif
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <private/bionic_config.h>
+#include <private/bionic_malloc.h>
+#include <private/bionic_malloc_dispatch.h>
+#include <sys/system_properties.h>
+
+#include "malloc_common.h"
+#include "malloc_common_dynamic.h"
+#include "malloc_heapprofd.h"
+
+static constexpr char kHeapprofdSharedLib[] = "heapprofd_client.so";
+static constexpr char kHeapprofdPrefix[] = "heapprofd";
+static constexpr char kHeapprofdPropertyEnable[] = "heapprofd.enable";
+static constexpr int kHeapprofdSignal = __SIGRTMIN + 4;
+
+// The logic for triggering heapprofd (at runtime) is as follows:
+// 1. HEAPPROFD_SIGNAL is received by the process, entering the
+//    MaybeInstallInitHeapprofdHook signal handler.
+// 2. If the initialization is not already in flight
+//    (gHeapprofdInitInProgress is false), the malloc hook is set to
+//    point at InitHeapprofdHook, and gHeapprofdInitInProgress is set to
+//    true.
+// 3. The next malloc call enters InitHeapprofdHook, which removes the malloc
+//    hook, and spawns a detached pthread to run the InitHeapprofd task.
+//    (gHeapprofdInitHook_installed atomic is used to perform this once.)
+// 4. InitHeapprofd, on a dedicated pthread, loads the heapprofd client library,
+//    installs the full set of heapprofd hooks, and invokes the client's
+//    initializer. The dedicated pthread then terminates.
+// 5. gHeapprofdInitInProgress and gHeapprofdInitHookInstalled are
+//    reset to false such that heapprofd can be reinitialized. Reinitialization
+//    means that a new profiling session is started, and any still active is
+//    torn down.
+//
+// The incremental hooking and a dedicated task thread are used since we cannot
+// do heavy work within a signal handler, or when blocking a malloc invocation.
+
+// The handle returned by dlopen when previously loading the heapprofd
+// hooks. nullptr if shared library has not been already been loaded.
+static _Atomic (void*) gHeapprofdHandle = nullptr;
+
+static _Atomic bool gHeapprofdInitInProgress = false;
+static _Atomic bool gHeapprofdInitHookInstalled = false;
+
+// In a Zygote child process, this is set to true if profiling of this process
+// is allowed. Note that this is set at a later time than the global
+// gMallocLeakZygoteChild. The latter is set during the fork (while still in
+// zygote's SELinux domain). While this bit is set after the child is
+// specialized (and has transferred SELinux domains if applicable).
+static _Atomic bool gMallocZygoteChildProfileable = false;
+
+extern "C" void* MallocInitHeapprofdHook(size_t);
+
+static constexpr MallocDispatch __heapprofd_init_dispatch
+  __attribute__((unused)) = {
+    Malloc(calloc),
+    Malloc(free),
+    Malloc(mallinfo),
+    MallocInitHeapprofdHook,
+    Malloc(malloc_usable_size),
+    Malloc(memalign),
+    Malloc(posix_memalign),
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+    Malloc(pvalloc),
+#endif
+    Malloc(realloc),
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+    Malloc(valloc),
+#endif
+    Malloc(iterate),
+    Malloc(malloc_disable),
+    Malloc(malloc_enable),
+    Malloc(mallopt),
+    Malloc(aligned_alloc),
+    Malloc(malloc_info),
+  };
+
+static void MaybeInstallInitHeapprofdHook(int) {
+  // Zygote child processes must be marked profileable.
+  if (gMallocLeakZygoteChild &&
+      !atomic_load_explicit(&gMallocZygoteChildProfileable, memory_order_acquire)) {
+    return;
+  }
+
+  // Checking this variable is only necessary when this could conflict with
+  // the change to enable the allocation limit. All other places will
+  // not ever have a conflict modifying the globals.
+  if (!atomic_exchange(&gGlobalsMutating, true)) {
+    if (!atomic_exchange(&gHeapprofdInitInProgress, true)) {
+      __libc_globals.mutate([](libc_globals* globals) {
+        atomic_store(&globals->default_dispatch_table, &__heapprofd_init_dispatch);
+        auto dispatch_table = GetDispatchTable();
+        if (dispatch_table == nullptr || dispatch_table == &globals->malloc_dispatch_table) {
+          atomic_store(&globals->current_dispatch_table, &__heapprofd_init_dispatch);
+        }
+      });
+    }
+    atomic_store(&gGlobalsMutating, false);
+  } else {
+    // The only way you can get to this point is if the signal has been
+    // blocked by a call to HeapprofdMaskSignal. The raise below will
+    // do nothing until a call to HeapprofdUnmaskSignal, which will cause
+    // the signal to be resent. Using this avoids the need for a busy loop
+    // waiting for gGlobalsMutating to change back to false.
+    raise(kHeapprofdSignal);
+  }
+}
+
+static bool GetHeapprofdProgramProperty(char* data, size_t size) {
+  constexpr char prefix[] = "heapprofd.enable.";
+  // - 1 to skip nullbyte, which we will write later.
+  constexpr size_t prefix_size = sizeof(prefix) - 1;
+  if (size < prefix_size) {
+    error_log("%s: Overflow constructing heapprofd property", getprogname());
+    return false;
+  }
+  memcpy(data, prefix, prefix_size);
+
+  int fd = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
+  if (fd == -1) {
+    error_log("%s: Failed to open /proc/self/cmdline", getprogname());
+    return false;
+  }
+  char cmdline[128];
+  ssize_t rd = read(fd, cmdline, sizeof(cmdline) - 1);
+  close(fd);
+  if (rd == -1) {
+    error_log("%s: Failed to read /proc/self/cmdline", getprogname());
+    return false;
+  }
+  cmdline[rd] = '\0';
+  char* first_arg = static_cast<char*>(memchr(cmdline, '\0', rd));
+  if (first_arg == nullptr || first_arg == cmdline + size - 1) {
+    error_log("%s: Overflow reading cmdline", getprogname());
+    return false;
+  }
+  // For consistency with what we do with Java app cmdlines, trim everything
+  // after the @ sign of the first arg.
+  char* first_at = static_cast<char*>(memchr(cmdline, '@', rd));
+  if (first_at != nullptr && first_at < first_arg) {
+    *first_at = '\0';
+    first_arg = first_at;
+  }
+
+  char* start = static_cast<char*>(memrchr(cmdline, '/', first_arg - cmdline));
+  if (start == first_arg) {
+    // The first argument ended in a slash.
+    error_log("%s: cmdline ends in /", getprogname());
+    return false;
+  } else if (start == nullptr) {
+    start = cmdline;
+  } else {
+    // Skip the /.
+    start++;
+  }
+
+  size_t name_size = static_cast<size_t>(first_arg - start);
+  if (name_size >= size - prefix_size) {
+    error_log("%s: overflow constructing heapprofd property.", getprogname());
+    return false;
+  }
+  // + 1 to also copy the trailing null byte.
+  memcpy(data + prefix_size, start, name_size + 1);
+  return true;
+}
+
+bool HeapprofdShouldLoad() {
+  // First check for heapprofd.enable. If it is set to "all", enable
+  // heapprofd for all processes. Otherwise, check heapprofd.enable.${prog},
+  // if it is set and not 0, enable heap profiling for this process.
+  char property_value[PROP_VALUE_MAX];
+  if (__system_property_get(kHeapprofdPropertyEnable, property_value) == 0) {
+    return false;
+  }
+  if (strcmp(property_value, "all") == 0) {
+    return true;
+  }
+
+  char program_property[128];
+  if (!GetHeapprofdProgramProperty(program_property,
+                                   sizeof(program_property))) {
+    return false;
+  }
+  if (__system_property_get(program_property, property_value) == 0) {
+    return false;
+  }
+  return property_value[0] != '\0';
+}
+
+void HeapprofdInstallSignalHandler() {
+  struct sigaction action = {};
+  action.sa_handler = MaybeInstallInitHeapprofdHook;
+  sigaction(kHeapprofdSignal, &action, nullptr);
+}
+
+extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
+
+void HeapprofdMaskSignal() {
+  sigset64_t mask_set;
+  // Need to use this function instead because sigprocmask64 filters
+  // out this signal.
+  __rt_sigprocmask(SIG_SETMASK, nullptr, &mask_set, sizeof(mask_set));
+  sigaddset64(&mask_set, kHeapprofdSignal);
+  __rt_sigprocmask(SIG_SETMASK, &mask_set, nullptr, sizeof(mask_set));
+}
+
+void HeapprofdUnmaskSignal() {
+  sigset64_t mask_set;
+  __rt_sigprocmask(SIG_SETMASK, nullptr, &mask_set, sizeof(mask_set));
+  sigdelset64(&mask_set, kHeapprofdSignal);
+  __rt_sigprocmask(SIG_SETMASK, &mask_set, nullptr, sizeof(mask_set));
+}
+
+static void DisplayError(int) {
+  error_log("Cannot install heapprofd while malloc debug/malloc hooks are enabled.");
+}
+
+void HeapprofdInstallErrorSignalHandler() {
+  struct sigaction action = {};
+  action.sa_handler = DisplayError;
+  sigaction(kHeapprofdSignal, &action, nullptr);
+}
+
+static void CommonInstallHooks(libc_globals* globals) {
+  void* impl_handle = atomic_load(&gHeapprofdHandle);
+  bool reusing_handle = impl_handle != nullptr;
+  if (!reusing_handle) {
+    impl_handle = LoadSharedLibrary(kHeapprofdSharedLib, kHeapprofdPrefix, &globals->malloc_dispatch_table);
+    if (impl_handle == nullptr) {
+      return;
+    }
+  } else if (!InitSharedLibrary(impl_handle, kHeapprofdSharedLib, kHeapprofdPrefix, &globals->malloc_dispatch_table)) {
+    return;
+  }
+
+  if (FinishInstallHooks(globals, nullptr, kHeapprofdPrefix)) {
+    atomic_store(&gHeapprofdHandle, impl_handle);
+  } else if (!reusing_handle) {
+    dlclose(impl_handle);
+  }
+
+  atomic_store(&gHeapprofdInitInProgress, false);
+}
+
+void HeapprofdInstallHooksAtInit(libc_globals* globals) {
+  if (atomic_exchange(&gHeapprofdInitInProgress, true)) {
+    return;
+  }
+  CommonInstallHooks(globals);
+}
+
+static void* InitHeapprofd(void*) {
+  pthread_mutex_lock(&gGlobalsMutateLock);
+  __libc_globals.mutate([](libc_globals* globals) {
+    CommonInstallHooks(globals);
+  });
+  pthread_mutex_unlock(&gGlobalsMutateLock);
+
+  // Allow to install hook again to re-initialize heap profiling after the
+  // current session finished.
+  atomic_store(&gHeapprofdInitHookInstalled, false);
+  return nullptr;
+}
+
+extern "C" void* MallocInitHeapprofdHook(size_t bytes) {
+  if (!atomic_exchange(&gHeapprofdInitHookInstalled, true)) {
+    pthread_mutex_lock(&gGlobalsMutateLock);
+    __libc_globals.mutate([](libc_globals* globals) {
+      auto old_dispatch = GetDefaultDispatchTable();
+      atomic_store(&globals->default_dispatch_table, nullptr);
+      if (GetDispatchTable() == old_dispatch) {
+        atomic_store(&globals->current_dispatch_table, nullptr);
+      }
+    });
+    pthread_mutex_unlock(&gGlobalsMutateLock);
+
+    pthread_t thread_id;
+    if (pthread_create(&thread_id, nullptr, InitHeapprofd, nullptr) != 0) {
+      error_log("%s: heapprofd: failed to pthread_create.", getprogname());
+    } else if (pthread_detach(thread_id) != 0) {
+      error_log("%s: heapprofd: failed to pthread_detach", getprogname());
+    }
+    if (pthread_setname_np(thread_id, "heapprofdinit") != 0) {
+      error_log("%s: heapprod: failed to pthread_setname_np", getprogname());
+    }
+  }
+  return Malloc(malloc)(bytes);
+}
+
+// Marks this process as a profileable zygote child.
+static bool HandleInitZygoteChildProfiling() {
+  atomic_store_explicit(&gMallocZygoteChildProfileable, true, memory_order_release);
+
+  // Conditionally start "from startup" profiling.
+  if (HeapprofdShouldLoad()) {
+    // Directly call the signal handler (will correctly guard against
+    // concurrent signal delivery).
+    MaybeInstallInitHeapprofdHook(kHeapprofdSignal);
+  }
+  return true;
+}
+
+static bool DispatchReset() {
+  if (!atomic_exchange(&gHeapprofdInitInProgress, true)) {
+    pthread_mutex_lock(&gGlobalsMutateLock);
+    __libc_globals.mutate([](libc_globals* globals) {
+      auto old_dispatch = GetDefaultDispatchTable();
+      atomic_store(&globals->default_dispatch_table, nullptr);
+      if (GetDispatchTable() == old_dispatch) {
+        atomic_store(&globals->current_dispatch_table, nullptr);
+      }
+    });
+    pthread_mutex_unlock(&gGlobalsMutateLock);
+    atomic_store(&gHeapprofdInitInProgress, false);
+    return true;
+  }
+  errno = EAGAIN;
+  return false;
+}
+
+bool HeapprofdMallopt(int opcode, void* arg, size_t arg_size) {
+  if (opcode == M_INIT_ZYGOTE_CHILD_PROFILING) {
+    if (arg != nullptr || arg_size != 0) {
+      errno = EINVAL;
+      return false;
+    }
+    return HandleInitZygoteChildProfiling();
+  }
+  if (opcode == M_RESET_HOOKS) {
+    if (arg != nullptr || arg_size != 0) {
+      errno = EINVAL;
+      return false;
+    }
+    return DispatchReset();
+  }
+  errno = ENOTSUP;
+  return false;
+}
diff --git a/libc/arch-mips/bionic/libgcc_compat.c b/libc/bionic/malloc_heapprofd.h
similarity index 75%
copy from libc/arch-mips/bionic/libgcc_compat.c
copy to libc/bionic/malloc_heapprofd.h
index 1a0f566..9e846b6 100644
--- a/libc/arch-mips/bionic/libgcc_compat.c
+++ b/libc/bionic/malloc_heapprofd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,16 +26,22 @@
  * SUCH DAMAGE.
  */
 
-extern char __divdi3;
-extern char __moddi3;
-extern char __popcountsi2;
-extern char __udivdi3;
-extern char __umoddi3;
+#pragma once
 
-void* __bionic_libgcc_compat_symbols[] = {
-    &__divdi3,
-    &__moddi3,
-    &__popcountsi2,
-    &__udivdi3,
-    &__umoddi3,
-};
+#include <stdint.h>
+
+#include <private/bionic_globals.h>
+
+bool HeapprofdShouldLoad();
+
+void HeapprofdInstallHooksAtInit(libc_globals* globals);
+
+void HeapprofdInstallSignalHandler();
+
+void HeapprofdInstallErrorSignalHandler();
+
+void HeapprofdMaskSignal();
+
+void HeapprofdUnmaskSignal();
+
+bool HeapprofdMallopt(int optcode, void* arg, size_t arg_size);
diff --git a/libc/bionic/malloc_info.cpp b/libc/bionic/malloc_info.cpp
deleted file mode 100644
index 9c8a4bf..0000000
--- a/libc/bionic/malloc_info.cpp
+++ /dev/null
@@ -1,94 +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.
- */
-
-#include "malloc_info.h"
-
-#include <errno.h>
-#include "private/bionic_macros.h"
-
-class __LIBC_HIDDEN__ Elem {
-public:
-  // name must be valid throughout lifetime of the object.
-  explicit Elem(FILE* fp, const char* name,
-                const char* attr_fmt = nullptr, ...) {
-    this->fp = fp;
-    this->name = name;
-
-    fprintf(fp, "<%s", name);
-    if (attr_fmt != nullptr) {
-      va_list args;
-      va_start(args, attr_fmt);
-      fputc(' ', fp);
-      vfprintf(fp, attr_fmt, args);
-      va_end(args);
-    }
-    fputc('>', fp);
-  }
-
-  ~Elem() noexcept {
-    fprintf(fp, "</%s>", name);
-  }
-
-  void contents(const char* fmt, ...) {
-      va_list args;
-      va_start(args, fmt);
-      vfprintf(fp, fmt, args);
-      va_end(args);
-  }
-
-private:
-  FILE* fp;
-  const char* name;
-
-  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(Elem);
-};
-
-int malloc_info(int options, FILE* fp) {
-  if (options != 0) {
-    errno = EINVAL;
-    return -1;
-  }
-
-  Elem root(fp, "malloc", "version=\"jemalloc-1\"");
-
-  // Dump all of the large allocations in the arenas.
-  for (size_t i = 0; i < __mallinfo_narenas(); i++) {
-    struct mallinfo mi = __mallinfo_arena_info(i);
-    if (mi.hblkhd != 0) {
-      Elem arena_elem(fp, "heap", "nr=\"%d\"", i);
-      {
-        Elem(fp, "allocated-large").contents("%zu", mi.ordblks);
-        Elem(fp, "allocated-huge").contents("%zu", mi.uordblks);
-        Elem(fp, "allocated-bins").contents("%zu", mi.fsmblks);
-
-        size_t total = 0;
-        for (size_t j = 0; j < __mallinfo_nbins(); j++) {
-          struct mallinfo mi = __mallinfo_bin_info(i, j);
-          if (mi.ordblks != 0) {
-            Elem bin_elem(fp, "bin", "nr=\"%d\"", j);
-            Elem(fp, "allocated").contents("%zu", mi.ordblks);
-            Elem(fp, "nmalloc").contents("%zu", mi.uordblks);
-            Elem(fp, "ndalloc").contents("%zu", mi.fordblks);
-            total += mi.ordblks;
-          }
-        }
-        Elem(fp, "bins-total").contents("%zu", total);
-      }
-    }
-  }
-
-  return 0;
-}
diff --git a/libc/bionic/malloc_limit.cpp b/libc/bionic/malloc_limit.cpp
new file mode 100644
index 0000000..69a8f89
--- /dev/null
+++ b/libc/bionic/malloc_limit.cpp
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2019 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 <inttypes.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <private/bionic_malloc_dispatch.h>
+
+#if __has_feature(hwaddress_sanitizer)
+#include <sanitizer/allocator_interface.h>
+#endif
+
+#include "malloc_common.h"
+#include "malloc_common_dynamic.h"
+#include "malloc_heapprofd.h"
+#include "malloc_limit.h"
+
+__BEGIN_DECLS
+static void* LimitCalloc(size_t n_elements, size_t elem_size);
+static void LimitFree(void* mem);
+static void* LimitMalloc(size_t bytes);
+static void* LimitMemalign(size_t alignment, size_t bytes);
+static int LimitPosixMemalign(void** memptr, size_t alignment, size_t size);
+static void* LimitRealloc(void* old_mem, size_t bytes);
+static void* LimitAlignedAlloc(size_t alignment, size_t size);
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+static void* LimitPvalloc(size_t bytes);
+static void* LimitValloc(size_t bytes);
+#endif
+
+// Pass through functions.
+static size_t LimitUsableSize(const void* mem);
+static struct mallinfo LimitMallinfo();
+static int LimitIterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*), void* arg);
+static void LimitMallocDisable();
+static void LimitMallocEnable();
+static int LimitMallocInfo(int options, FILE* fp);
+static int LimitMallopt(int param, int value);
+__END_DECLS
+
+static constexpr MallocDispatch __limit_dispatch
+  __attribute__((unused)) = {
+    LimitCalloc,
+    LimitFree,
+    LimitMallinfo,
+    LimitMalloc,
+    LimitUsableSize,
+    LimitMemalign,
+    LimitPosixMemalign,
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+    LimitPvalloc,
+#endif
+    LimitRealloc,
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+    LimitValloc,
+#endif
+    LimitIterate,
+    LimitMallocDisable,
+    LimitMallocEnable,
+    LimitMallopt,
+    LimitAlignedAlloc,
+    LimitMallocInfo,
+  };
+
+static _Atomic uint64_t gAllocated;
+static uint64_t gAllocLimit;
+
+static inline bool CheckLimit(size_t bytes) {
+  uint64_t total;
+  if (__predict_false(__builtin_add_overflow(
+                          atomic_load_explicit(&gAllocated, memory_order_relaxed), bytes, &total) ||
+                      total > gAllocLimit)) {
+    return false;
+  }
+  return true;
+}
+
+static inline void* IncrementLimit(void* mem) {
+  if (__predict_false(mem == nullptr)) {
+    return nullptr;
+  }
+  atomic_fetch_add(&gAllocated, LimitUsableSize(mem));
+  return mem;
+}
+
+void* LimitCalloc(size_t n_elements, size_t elem_size) {
+  size_t total;
+  if (__builtin_add_overflow(n_elements, elem_size, &total) || !CheckLimit(total)) {
+    warning_log("malloc_limit: calloc(%zu, %zu) exceeds limit %" PRId64, n_elements, elem_size,
+                gAllocLimit);
+    return nullptr;
+  }
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return IncrementLimit(dispatch_table->calloc(n_elements, elem_size));
+  }
+  return IncrementLimit(Malloc(calloc)(n_elements, elem_size));
+}
+
+void LimitFree(void* mem) {
+  atomic_fetch_sub(&gAllocated, LimitUsableSize(mem));
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->free(mem);
+  }
+  return Malloc(free)(mem);
+}
+
+void* LimitMalloc(size_t bytes) {
+  if (!CheckLimit(bytes)) {
+    warning_log("malloc_limit: malloc(%zu) exceeds limit %" PRId64, bytes, gAllocLimit);
+    return nullptr;
+  }
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return IncrementLimit(dispatch_table->malloc(bytes));
+  }
+  return IncrementLimit(Malloc(malloc)(bytes));
+}
+
+static void* LimitMemalign(size_t alignment, size_t bytes) {
+  if (!CheckLimit(bytes)) {
+    warning_log("malloc_limit: memalign(%zu, %zu) exceeds limit %" PRId64, alignment, bytes,
+                gAllocLimit);
+    return nullptr;
+  }
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return IncrementLimit(dispatch_table->memalign(alignment, bytes));
+  }
+  return IncrementLimit(Malloc(memalign)(alignment, bytes));
+}
+
+static int LimitPosixMemalign(void** memptr, size_t alignment, size_t size) {
+  if (!CheckLimit(size)) {
+    warning_log("malloc_limit: posix_memalign(%zu, %zu) exceeds limit %" PRId64, alignment, size,
+                gAllocLimit);
+    return ENOMEM;
+  }
+  int retval;
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    retval = dispatch_table->posix_memalign(memptr, alignment, size);
+  } else {
+    retval = Malloc(posix_memalign)(memptr, alignment, size);
+  }
+  if (__predict_false(retval != 0)) {
+    return retval;
+  }
+  IncrementLimit(*memptr);
+  return 0;
+}
+
+static void* LimitAlignedAlloc(size_t alignment, size_t size) {
+  if (!CheckLimit(size)) {
+    warning_log("malloc_limit: aligned_alloc(%zu, %zu) exceeds limit %" PRId64, alignment, size,
+                gAllocLimit);
+    return nullptr;
+  }
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return IncrementLimit(dispatch_table->aligned_alloc(alignment, size));
+  }
+  return IncrementLimit(Malloc(aligned_alloc)(alignment, size));
+}
+
+static void* LimitRealloc(void* old_mem, size_t bytes) {
+  size_t old_usable_size = LimitUsableSize(old_mem);
+  void* new_ptr;
+  // Need to check the size only if the allocation will increase in size.
+  if (bytes > old_usable_size && !CheckLimit(bytes - old_usable_size)) {
+    warning_log("malloc_limit: realloc(%p, %zu) exceeds limit %" PRId64, old_mem, bytes,
+                gAllocLimit);
+    // Free the old pointer.
+    LimitFree(old_mem);
+    return nullptr;
+  }
+
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    new_ptr = dispatch_table->realloc(old_mem, bytes);
+  } else {
+    new_ptr = Malloc(realloc)(old_mem, bytes);
+  }
+
+  if (__predict_false(new_ptr == nullptr)) {
+    // This acts as if the pointer was freed.
+    atomic_fetch_sub(&gAllocated, old_usable_size);
+    return nullptr;
+  }
+
+  size_t new_usable_size = LimitUsableSize(new_ptr);
+  // Assumes that most allocations increase in size, rather than shrink.
+  if (__predict_false(old_usable_size > new_usable_size)) {
+    atomic_fetch_sub(&gAllocated, old_usable_size - new_usable_size);
+  } else {
+    atomic_fetch_add(&gAllocated, new_usable_size - old_usable_size);
+  }
+  return new_ptr;
+}
+
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+static void* LimitPvalloc(size_t bytes) {
+  if (!CheckLimit(bytes)) {
+    warning_log("malloc_limit: pvalloc(%zu) exceeds limit %" PRId64, bytes, gAllocLimit);
+    return nullptr;
+  }
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return IncrementLimit(dispatch_table->pvalloc(bytes));
+  }
+  return IncrementLimit(Malloc(pvalloc)(bytes));
+}
+
+static void* LimitValloc(size_t bytes) {
+  if (!CheckLimit(bytes)) {
+    warning_log("malloc_limit: valloc(%zu) exceeds limit %" PRId64, bytes, gAllocLimit);
+    return nullptr;
+  }
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return IncrementLimit(dispatch_table->valloc(bytes));
+  }
+  return IncrementLimit(Malloc(valloc)(bytes));
+}
+#endif
+
+#if defined(LIBC_STATIC)
+static bool EnableLimitDispatchTable() {
+  // This is the only valid way to modify the dispatch tables for a
+  // static executable so no locks are necessary.
+  __libc_globals.mutate([](libc_globals* globals) {
+    atomic_store(&globals->current_dispatch_table, &__limit_dispatch);
+  });
+  return true;
+}
+#else
+static bool EnableLimitDispatchTable() {
+  HeapprofdMaskSignal();
+  pthread_mutex_lock(&gGlobalsMutateLock);
+  // All other code that calls mutate will grab the gGlobalsMutateLock.
+  // However, there is one case where the lock cannot be acquired, in the
+  // signal handler that enables heapprofd. In order to avoid having two
+  // threads calling mutate at the same time, use an atomic variable to
+  // verify that only this function or the signal handler are calling mutate.
+  // If this function is called at the same time as the signal handler is
+  // being called, allow up to five ms for the signal handler to complete
+  // before failing.
+  bool enabled = false;
+  size_t num_tries = 10;
+  while (true) {
+    if (!atomic_exchange(&gGlobalsMutating, true)) {
+      __libc_globals.mutate([](libc_globals* globals) {
+        atomic_store(&globals->current_dispatch_table, &__limit_dispatch);
+      });
+      atomic_store(&gGlobalsMutating, false);
+      enabled = true;
+      break;
+    }
+    if (--num_tries == 0) {
+      break;
+    }
+    usleep(1000);
+  }
+  pthread_mutex_unlock(&gGlobalsMutateLock);
+  HeapprofdUnmaskSignal();
+  if (enabled) {
+    info_log("malloc_limit: Allocation limit enabled, max size %" PRId64 " bytes\n", gAllocLimit);
+  } else {
+    error_log("malloc_limit: Failed to enable allocation limit.");
+  }
+  return enabled;
+}
+#endif
+
+bool LimitEnable(void* arg, size_t arg_size) {
+  if (arg == nullptr || arg_size != sizeof(size_t)) {
+    errno = EINVAL;
+    return false;
+  }
+
+  static _Atomic bool limit_enabled;
+  if (atomic_exchange(&limit_enabled, true)) {
+    // The limit can only be enabled once.
+    error_log("malloc_limit: The allocation limit has already been set, it can only be set once.");
+    return false;
+  }
+
+  gAllocLimit = *reinterpret_cast<size_t*>(arg);
+#if __has_feature(hwaddress_sanitizer)
+  size_t current_allocated = __sanitizer_get_current_allocated_bytes();
+#else
+  size_t current_allocated;
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    current_allocated = dispatch_table->mallinfo().uordblks;
+  } else {
+    current_allocated = Malloc(mallinfo)().uordblks;
+  }
+#endif
+  atomic_store(&gAllocated, current_allocated);
+
+  return EnableLimitDispatchTable();
+}
+
+static size_t LimitUsableSize(const void* mem) {
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->malloc_usable_size(mem);
+  }
+  return Malloc(malloc_usable_size)(mem);
+}
+
+static struct mallinfo LimitMallinfo() {
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->mallinfo();
+  }
+  return Malloc(mallinfo)();
+}
+
+static int LimitIterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*), void* arg) {
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->iterate(base, size, callback, arg);
+  }
+  return Malloc(iterate)(base, size, callback, arg);
+}
+
+static void LimitMallocDisable() {
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    dispatch_table->malloc_disable();
+  } else {
+    Malloc(malloc_disable)();
+  }
+}
+
+static void LimitMallocEnable() {
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    dispatch_table->malloc_enable();
+  } else {
+    Malloc(malloc_enable)();
+  }
+}
+
+static int LimitMallocInfo(int options, FILE* fp) {
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->malloc_info(options, fp);
+  }
+  return Malloc(malloc_info)(options, fp);
+}
+
+static int LimitMallopt(int param, int value) {
+  auto dispatch_table = GetDefaultDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    return dispatch_table->mallopt(param, value);
+  }
+  return Malloc(mallopt)(param, value);
+}
diff --git a/libc/arch-mips/bionic/libgcc_compat.c b/libc/bionic/malloc_limit.h
similarity index 81%
copy from libc/arch-mips/bionic/libgcc_compat.c
copy to libc/bionic/malloc_limit.h
index 1a0f566..282598f 100644
--- a/libc/arch-mips/bionic/libgcc_compat.c
+++ b/libc/bionic/malloc_limit.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,16 +26,9 @@
  * SUCH DAMAGE.
  */
 
-extern char __divdi3;
-extern char __moddi3;
-extern char __popcountsi2;
-extern char __udivdi3;
-extern char __umoddi3;
+#pragma once
 
-void* __bionic_libgcc_compat_symbols[] = {
-    &__divdi3,
-    &__moddi3,
-    &__popcountsi2,
-    &__udivdi3,
-    &__umoddi3,
-};
+#include <stdint.h>
+
+// Function prototypes.
+bool LimitEnable(void* arg, size_t arg_size);
diff --git a/libc/bionic/pthread_detach.cpp b/libc/bionic/pthread_detach.cpp
index c2e4127..6b22039 100644
--- a/libc/bionic/pthread_detach.cpp
+++ b/libc/bionic/pthread_detach.cpp
@@ -34,7 +34,7 @@
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
 int pthread_detach(pthread_t t) {
-  pthread_internal_t* thread = __pthread_internal_find(t);
+  pthread_internal_t* thread = __pthread_internal_find(t, "pthread_detach");
   if (thread == nullptr) {
     return ESRCH;
   }
diff --git a/libc/bionic/pthread_getcpuclockid.cpp b/libc/bionic/pthread_getcpuclockid.cpp
index f641e4c..0b35998 100644
--- a/libc/bionic/pthread_getcpuclockid.cpp
+++ b/libc/bionic/pthread_getcpuclockid.cpp
@@ -31,7 +31,7 @@
 #include "pthread_internal.h"
 
 int pthread_getcpuclockid(pthread_t t, clockid_t* clockid) {
-  pid_t tid = pthread_gettid_np(t);
+  pid_t tid = __pthread_internal_gettid(t, "pthread_getcpuclockid");
   if (tid == -1) return ESRCH;
 
   // The tid is stored in the top bits, but negated.
diff --git a/libc/bionic/pthread_getschedparam.cpp b/libc/bionic/pthread_getschedparam.cpp
index cc1ece8..ed1853b 100644
--- a/libc/bionic/pthread_getschedparam.cpp
+++ b/libc/bionic/pthread_getschedparam.cpp
@@ -34,7 +34,7 @@
 int pthread_getschedparam(pthread_t t, int* policy, sched_param* param) {
   ErrnoRestorer errno_restorer;
 
-  pid_t tid = pthread_gettid_np(t);
+  pid_t tid = __pthread_internal_gettid(t, "pthread_getschedparam");
   if (tid == -1) return ESRCH;
 
   if (sched_getparam(tid, param) == -1) return errno;
diff --git a/libc/bionic/pthread_gettid_np.cpp b/libc/bionic/pthread_gettid_np.cpp
index 1beddc9..d14900b 100644
--- a/libc/bionic/pthread_gettid_np.cpp
+++ b/libc/bionic/pthread_gettid_np.cpp
@@ -31,6 +31,5 @@
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
 pid_t pthread_gettid_np(pthread_t t) {
-  pthread_internal_t* thread = __pthread_internal_find(t);
-  return thread ? thread->tid : -1;
+  return __pthread_internal_gettid(t, "pthread_gettid_np");
 }
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 46fa630..6fddefe 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -80,7 +80,12 @@
   __pthread_internal_free(thread);
 }
 
-pthread_internal_t* __pthread_internal_find(pthread_t thread_id) {
+pid_t __pthread_internal_gettid(pthread_t thread_id, const char* caller) {
+  pthread_internal_t* thread = __pthread_internal_find(thread_id, caller);
+  return thread ? thread->tid : -1;
+}
+
+pthread_internal_t* __pthread_internal_find(pthread_t thread_id, const char* caller) {
   pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(thread_id);
 
   // Check if we're looking for ourselves before acquiring the lock.
@@ -103,9 +108,9 @@
       // addresses might sometimes contain threads or things that look enough like
       // threads for us to do some real damage by continuing.
       // TODO: try getting rid of this when Treble lets us keep vendor blobs on an old API level.
-      async_safe_format_log(ANDROID_LOG_WARN, "libc", "invalid pthread_t (0) passed to libc");
+      async_safe_format_log(ANDROID_LOG_WARN, "libc", "invalid pthread_t (0) passed to %s", caller);
     } else {
-      async_safe_fatal("invalid pthread_t %p passed to libc", thread);
+      async_safe_fatal("invalid pthread_t %p passed to %s", thread, caller);
     }
   }
   return nullptr;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index cbcdadf..a1e0c45 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -163,10 +163,11 @@
 __LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
 __LIBC_HIDDEN__ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size);
 
-__LIBC_HIDDEN__ pthread_t           __pthread_internal_add(pthread_internal_t* thread);
-__LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id);
-__LIBC_HIDDEN__ void                __pthread_internal_remove(pthread_internal_t* thread);
-__LIBC_HIDDEN__ void                __pthread_internal_remove_and_free(pthread_internal_t* thread);
+__LIBC_HIDDEN__ pthread_t __pthread_internal_add(pthread_internal_t* thread);
+__LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id, const char* caller);
+__LIBC_HIDDEN__ pid_t __pthread_internal_gettid(pthread_t pthread_id, const char* caller);
+__LIBC_HIDDEN__ void __pthread_internal_remove(pthread_internal_t* thread);
+__LIBC_HIDDEN__ void __pthread_internal_remove_and_free(pthread_internal_t* thread);
 
 static inline __always_inline bionic_tcb* __get_bionic_tcb() {
   return reinterpret_cast<bionic_tcb*>(&__get_tls()[MIN_TLS_SLOT]);
diff --git a/libc/bionic/pthread_join.cpp b/libc/bionic/pthread_join.cpp
index 8e4ca59..e230fab 100644
--- a/libc/bionic/pthread_join.cpp
+++ b/libc/bionic/pthread_join.cpp
@@ -40,7 +40,7 @@
     return EDEADLK;
   }
 
-  pthread_internal_t* thread = __pthread_internal_find(t);
+  pthread_internal_t* thread = __pthread_internal_find(t, "pthread_join");
   if (thread == nullptr) {
     return ESRCH;
   }
diff --git a/libc/bionic/pthread_kill.cpp b/libc/bionic/pthread_kill.cpp
index 1531574..8b38f4c 100644
--- a/libc/bionic/pthread_kill.cpp
+++ b/libc/bionic/pthread_kill.cpp
@@ -35,7 +35,7 @@
 int pthread_kill(pthread_t t, int sig) {
   ErrnoRestorer errno_restorer;
 
-  pid_t tid = pthread_gettid_np(t);
+  pid_t tid = __pthread_internal_gettid(t, "pthread_kill");
 
   // tid gets reset to 0 on thread exit by CLONE_CHILD_CLEARTID.
   if (tid == 0 || tid == -1) return ESRCH;
diff --git a/libc/bionic/pthread_setname_np.cpp b/libc/bionic/pthread_setname_np.cpp
index f582d53..f673983 100644
--- a/libc/bionic/pthread_setname_np.cpp
+++ b/libc/bionic/pthread_setname_np.cpp
@@ -42,9 +42,10 @@
 // This value is not exported by kernel headers.
 #define MAX_TASK_COMM_LEN 16
 
-static int __open_task_comm_fd(pthread_t t, int flags) {
+static int __open_task_comm_fd(pthread_t t, int flags, const char* caller) {
   char comm_name[64];
-  snprintf(comm_name, sizeof(comm_name), "/proc/self/task/%d/comm", pthread_gettid_np(t));
+  snprintf(comm_name, sizeof(comm_name), "/proc/self/task/%d/comm",
+           __pthread_internal_gettid(t, caller));
   return open(comm_name, O_CLOEXEC | flags);
 }
 
@@ -59,7 +60,7 @@
   }
 
   // We have to get another thread's name.
-  int fd = __open_task_comm_fd(t, O_RDONLY);
+  int fd = __open_task_comm_fd(t, O_RDONLY, "pthread_getname_np");
   if (fd == -1) return errno;
 
   ssize_t n = TEMP_FAILURE_RETRY(read(fd, buf, buf_size));
@@ -91,7 +92,7 @@
   }
 
   // We have to set another thread's name.
-  int fd = __open_task_comm_fd(t, O_WRONLY);
+  int fd = __open_task_comm_fd(t, O_WRONLY, "pthread_setname_np");
   if (fd == -1) return errno;
 
   ssize_t n = TEMP_FAILURE_RETRY(write(fd, thread_name, thread_name_len));
diff --git a/libc/bionic/pthread_setschedparam.cpp b/libc/bionic/pthread_setschedparam.cpp
index 10826d1..8a02728 100644
--- a/libc/bionic/pthread_setschedparam.cpp
+++ b/libc/bionic/pthread_setschedparam.cpp
@@ -31,11 +31,12 @@
 #include <sched.h>
 
 #include "private/ErrnoRestorer.h"
+#include "pthread_internal.h"
 
 int pthread_setschedparam(pthread_t t, int policy, const sched_param* param) {
   ErrnoRestorer errno_restorer;
 
-  pid_t tid = pthread_gettid_np(t);
+  pid_t tid = __pthread_internal_gettid(t, "pthread_setschedparam");
   if (tid == -1) return ESRCH;
 
   return (sched_setscheduler(tid, policy, param) == -1) ? errno : 0;
@@ -44,7 +45,7 @@
 int pthread_setschedprio(pthread_t t, int priority) {
   ErrnoRestorer errno_restorer;
 
-  pid_t tid = pthread_gettid_np(t);
+  pid_t tid = __pthread_internal_gettid(t, "pthread_setschedprio");
   if (tid == -1) return ESRCH;
 
   sched_param param = { .sched_priority = priority };
diff --git a/libc/bionic/pthread_sigqueue.cpp b/libc/bionic/pthread_sigqueue.cpp
index 34bda38..5d13ed5 100644
--- a/libc/bionic/pthread_sigqueue.cpp
+++ b/libc/bionic/pthread_sigqueue.cpp
@@ -38,7 +38,7 @@
 int pthread_sigqueue(pthread_t t, int sig, const union sigval value) {
   ErrnoRestorer errno_restorer;
 
-  pid_t tid = pthread_gettid_np(t);
+  pid_t tid = __pthread_internal_gettid(t, "pthread_sigqueue");
   if (tid == -1) return ESRCH;
 
   siginfo_t siginfo;
diff --git a/libc/bionic/strsignal.cpp b/libc/bionic/strsignal.cpp
index 5637431..05d3498 100644
--- a/libc/bionic/strsignal.cpp
+++ b/libc/bionic/strsignal.cpp
@@ -37,7 +37,7 @@
 };
 
 const char* const sys_signame[NSIG] = {
-#define __BIONIC_SIGDEF(signal_number, unused) [ signal_number ] = #signal_number + 3,
+#define __BIONIC_SIGDEF(signal_number, unused) [ signal_number ] = &(#signal_number)[3],
 #include "private/bionic_sigdefs.h"
 };
 
diff --git a/libc/bionic/system_property_set.cpp b/libc/bionic/system_property_set.cpp
index bc3ba76..c508db1 100644
--- a/libc/bionic/system_property_set.cpp
+++ b/libc/bionic/system_property_set.cpp
@@ -42,6 +42,7 @@
 #include <unistd.h>
 
 #include <async_safe/log.h>
+#include <async_safe/CHECK.h>
 
 #include "private/bionic_defs.h"
 #include "private/bionic_macros.h"
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index e78be39..f0b731c 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -114,6 +114,29 @@
    */
   ANDROID_DLEXT_USE_NAMESPACE = 0x200,
 
+  /**
+   * Instructs dlopen to apply `ANDROID_DLEXT_RESERVED_ADDRESS`,
+   * `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`, `ANDROID_DLEXT_WRITE_RELRO` and
+   * `ANDROID_DLEXT_USE_RELRO` to any libraries loaded as dependencies of the
+   * main library as well.
+   *
+   * This means that if the main library depends on one or more not-already-loaded libraries, they
+   * will be loaded consecutively into the region starting at `reserved_addr`, and `reserved_size`
+   * must be large enough to contain all of the libraries. The libraries will be loaded in the
+   * deterministic order constructed from the DT_NEEDED entries, rather than the more secure random
+   * order used by default.
+   *
+   * Each library's GNU RELRO sections will be written out to `relro_fd` in the same order they were
+   * loaded. This will mean that the resulting file is dependent on which of the libraries were
+   * already loaded, as only the newly loaded libraries will be included, not any already-loaded
+   * dependencies. The caller should ensure that the set of libraries newly loaded is consistent
+   * for this to be effective.
+   *
+   * This is mainly useful for the system WebView implementation.
+   */
+  ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE = 0x400,
+
+
   /** Mask of valid bits. */
   ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
                                         ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
@@ -122,7 +145,8 @@
                                         ANDROID_DLEXT_USE_LIBRARY_FD |
                                         ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
                                         ANDROID_DLEXT_FORCE_LOAD |
-                                        ANDROID_DLEXT_USE_NAMESPACE,
+                                        ANDROID_DLEXT_USE_NAMESPACE |
+                                        ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE,
 };
 
 struct android_namespace_t;
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index ea7689c..d71e6d4 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -128,21 +128,21 @@
 /*
  * Create an owner tag with the specified type and least significant 56 bits of tag.
  */
-uint64_t android_fdsan_create_owner_tag(enum android_fdsan_owner_type type, uint64_t tag) __INTRODUCED_IN_FUTURE __attribute__((__weak__));
+uint64_t android_fdsan_create_owner_tag(enum android_fdsan_owner_type type, uint64_t tag) __INTRODUCED_IN(29) __attribute__((__weak__));
 
 /*
  * Exchange a file descriptor's tag.
  *
  * Logs and aborts if the fd's tag does not match expected_tag.
  */
-void android_fdsan_exchange_owner_tag(int fd, uint64_t expected_tag, uint64_t new_tag) __INTRODUCED_IN_FUTURE __attribute__((__weak__));
+void android_fdsan_exchange_owner_tag(int fd, uint64_t expected_tag, uint64_t new_tag) __INTRODUCED_IN(29) __attribute__((__weak__));
 
 /*
  * Close a file descriptor with a tag, and resets the tag to 0.
  *
  * Logs and aborts if the tag is incorrect.
  */
-int android_fdsan_close_with_tag(int fd, uint64_t tag) __INTRODUCED_IN_FUTURE __attribute__((__weak__));
+int android_fdsan_close_with_tag(int fd, uint64_t tag) __INTRODUCED_IN(29) __attribute__((__weak__));
 
 /*
  * Get a file descriptor's current owner tag.
@@ -180,7 +180,7 @@
 /*
  * Get the error level.
  */
-enum android_fdsan_error_level android_fdsan_get_error_level() __INTRODUCED_IN_FUTURE __attribute__((__weak__));
+enum android_fdsan_error_level android_fdsan_get_error_level() __INTRODUCED_IN(29) __attribute__((__weak__));
 
 /*
  * Set the error level and return the previous state.
@@ -195,6 +195,6 @@
  * value, and so should probably only be called in single-threaded contexts
  * (e.g. postfork).
  */
-enum android_fdsan_error_level android_fdsan_set_error_level(enum android_fdsan_error_level new_level) __INTRODUCED_IN_FUTURE __attribute__((__weak__));
+enum android_fdsan_error_level android_fdsan_set_error_level(enum android_fdsan_error_level new_level) __INTRODUCED_IN(29) __attribute__((__weak__));
 
 __END_DECLS
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index 01fa348..d60957f 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" #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)))
diff --git a/libc/include/resolv.h b/libc/include/resolv.h
index 1518475..6318d00 100644
--- a/libc/include/resolv.h
+++ b/libc/include/resolv.h
@@ -60,7 +60,7 @@
 int res_search(const char* __name, int __class, int __type, u_char* __answer, int __answer_size);
 
 #define res_randomid __res_randomid
-u_int __res_randomid(void) __INTRODUCED_IN_FUTURE;
+u_int __res_randomid(void) __INTRODUCED_IN(29);
 
 __END_DECLS
 
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 96a77a7..d5b8619 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -154,7 +154,7 @@
  *
  * Returns the number of samples written to `__averages` (at most 3), and returns -1 on failure.
  */
-int getloadavg(double __averages[], int __n) __INTRODUCED_IN_FUTURE;
+int getloadavg(double __averages[], int __n) __INTRODUCED_IN(29);
 
 /* BSD compatibility. */
 const char* getprogname(void) __INTRODUCED_IN(21);
diff --git a/libc/include/time.h b/libc/include/time.h
index ea41fda..48c5efc 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -109,7 +109,7 @@
 time_t timegm(struct tm* __tm) __INTRODUCED_IN(12);
 
 #define TIME_UTC 1
-int timespec_get(struct timespec* __ts, int __base) __INTRODUCED_IN_FUTURE;
+int timespec_get(struct timespec* __ts, int __base) __INTRODUCED_IN(29);
 
 __END_DECLS
 
diff --git a/libc/kernel/uapi/asm-arm64/asm/hwcap.h b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
index 8f50b1d..44853a4 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -47,4 +47,7 @@
 #define HWCAP_ILRCPC (1 << 26)
 #define HWCAP_FLAGM (1 << 27)
 #define HWCAP_SSBS (1 << 28)
+#define HWCAP_SB (1 << 29)
+#define HWCAP_PACA (1 << 30)
+#define HWCAP_PACG (1UL << 31)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/ptrace.h b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
index e1cfb48..15fde29 100644
--- a/libc/kernel/uapi/asm-arm64/asm/ptrace.h
+++ b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
@@ -20,7 +20,7 @@
 #define _UAPI__ASM_PTRACE_H
 #include <linux/types.h>
 #include <asm/hwcap.h>
-#include <asm/sigcontext.h>
+#include <asm/sve_context.h>
 #define PSR_MODE_EL0t 0x00000000
 #define PSR_MODE_EL1t 0x00000004
 #define PSR_MODE_EL1h 0x00000005
@@ -81,26 +81,29 @@
 #define SVE_PT_REGS_SVE SVE_PT_REGS_MASK
 #define SVE_PT_VL_INHERIT (PR_SVE_VL_INHERIT >> 16)
 #define SVE_PT_VL_ONEXEC (PR_SVE_SET_VL_ONEXEC >> 16)
-#define SVE_PT_REGS_OFFSET ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_PT_REGS_OFFSET ((sizeof(struct user_sve_header) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
 #define SVE_PT_FPSIMD_OFFSET SVE_PT_REGS_OFFSET
 #define SVE_PT_FPSIMD_SIZE(vq,flags) (sizeof(struct user_fpsimd_state))
-#define SVE_PT_SVE_ZREG_SIZE(vq) SVE_SIG_ZREG_SIZE(vq)
-#define SVE_PT_SVE_PREG_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
-#define SVE_PT_SVE_FFR_SIZE(vq) SVE_SIG_FFR_SIZE(vq)
+#define SVE_PT_SVE_ZREG_SIZE(vq) __SVE_ZREG_SIZE(vq)
+#define SVE_PT_SVE_PREG_SIZE(vq) __SVE_PREG_SIZE(vq)
+#define SVE_PT_SVE_FFR_SIZE(vq) __SVE_FFR_SIZE(vq)
 #define SVE_PT_SVE_FPSR_SIZE sizeof(__u32)
 #define SVE_PT_SVE_FPCR_SIZE sizeof(__u32)
-#define __SVE_SIG_TO_PT(offset) ((offset) - SVE_SIG_REGS_OFFSET + SVE_PT_REGS_OFFSET)
 #define SVE_PT_SVE_OFFSET SVE_PT_REGS_OFFSET
-#define SVE_PT_SVE_ZREGS_OFFSET __SVE_SIG_TO_PT(SVE_SIG_ZREGS_OFFSET)
-#define SVE_PT_SVE_ZREG_OFFSET(vq,n) __SVE_SIG_TO_PT(SVE_SIG_ZREG_OFFSET(vq, n))
-#define SVE_PT_SVE_ZREGS_SIZE(vq) (SVE_PT_SVE_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)
-#define SVE_PT_SVE_PREGS_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_PREGS_OFFSET(vq))
-#define SVE_PT_SVE_PREG_OFFSET(vq,n) __SVE_SIG_TO_PT(SVE_SIG_PREG_OFFSET(vq, n))
-#define SVE_PT_SVE_PREGS_SIZE(vq) (SVE_PT_SVE_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_PT_SVE_PREGS_OFFSET(vq))
-#define SVE_PT_SVE_FFR_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_FFR_OFFSET(vq))
-#define SVE_PT_SVE_FPSR_OFFSET(vq) ((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_PT_SVE_ZREGS_OFFSET (SVE_PT_REGS_OFFSET + __SVE_ZREGS_OFFSET)
+#define SVE_PT_SVE_ZREG_OFFSET(vq,n) (SVE_PT_REGS_OFFSET + __SVE_ZREG_OFFSET(vq, n))
+#define SVE_PT_SVE_ZREGS_SIZE(vq) (SVE_PT_SVE_ZREG_OFFSET(vq, __SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)
+#define SVE_PT_SVE_PREGS_OFFSET(vq) (SVE_PT_REGS_OFFSET + __SVE_PREGS_OFFSET(vq))
+#define SVE_PT_SVE_PREG_OFFSET(vq,n) (SVE_PT_REGS_OFFSET + __SVE_PREG_OFFSET(vq, n))
+#define SVE_PT_SVE_PREGS_SIZE(vq) (SVE_PT_SVE_PREG_OFFSET(vq, __SVE_NUM_PREGS) - SVE_PT_SVE_PREGS_OFFSET(vq))
+#define SVE_PT_SVE_FFR_OFFSET(vq) (SVE_PT_REGS_OFFSET + __SVE_FFR_OFFSET(vq))
+#define SVE_PT_SVE_FPSR_OFFSET(vq) ((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
 #define SVE_PT_SVE_FPCR_OFFSET(vq) (SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE)
-#define SVE_PT_SVE_SIZE(vq,flags) ((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE - SVE_PT_SVE_OFFSET + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_PT_SVE_SIZE(vq,flags) ((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE - SVE_PT_SVE_OFFSET + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
 #define SVE_PT_SIZE(vq,flags) (((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ? SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
+struct user_pac_mask {
+  __u64 data_mask;
+  __u64 insn_mask;
+};
 #endif
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
index b0617de..518079d 100644
--- a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
+++ b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
@@ -58,27 +58,28 @@
   __u16 __reserved[3];
 };
 #endif
-#define SVE_VQ_BYTES 16
-#define SVE_VQ_MIN 1
-#define SVE_VQ_MAX 512
-#define SVE_VL_MIN (SVE_VQ_MIN * SVE_VQ_BYTES)
-#define SVE_VL_MAX (SVE_VQ_MAX * SVE_VQ_BYTES)
-#define SVE_NUM_ZREGS 32
-#define SVE_NUM_PREGS 16
-#define sve_vl_valid(vl) ((vl) % SVE_VQ_BYTES == 0 && (vl) >= SVE_VL_MIN && (vl) <= SVE_VL_MAX)
-#define sve_vq_from_vl(vl) ((vl) / SVE_VQ_BYTES)
-#define sve_vl_from_vq(vq) ((vq) * SVE_VQ_BYTES)
-#define SVE_SIG_ZREG_SIZE(vq) ((__u32) (vq) * SVE_VQ_BYTES)
-#define SVE_SIG_PREG_SIZE(vq) ((__u32) (vq) * (SVE_VQ_BYTES / 8))
-#define SVE_SIG_FFR_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
-#define SVE_SIG_REGS_OFFSET ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
-#define SVE_SIG_ZREGS_OFFSET SVE_SIG_REGS_OFFSET
-#define SVE_SIG_ZREG_OFFSET(vq,n) (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREG_SIZE(vq) * (n))
-#define SVE_SIG_ZREGS_SIZE(vq) (SVE_SIG_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_SIG_ZREGS_OFFSET)
-#define SVE_SIG_PREGS_OFFSET(vq) (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREGS_SIZE(vq))
-#define SVE_SIG_PREG_OFFSET(vq,n) (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREG_SIZE(vq) * (n))
-#define SVE_SIG_PREGS_SIZE(vq) (SVE_SIG_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_SIG_PREGS_OFFSET(vq))
-#define SVE_SIG_FFR_OFFSET(vq) (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREGS_SIZE(vq))
-#define SVE_SIG_REGS_SIZE(vq) (SVE_SIG_FFR_OFFSET(vq) + SVE_SIG_FFR_SIZE(vq) - SVE_SIG_REGS_OFFSET)
+#include <asm/sve_context.h>
+#define SVE_VQ_BYTES __SVE_VQ_BYTES
+#define SVE_VQ_MIN __SVE_VQ_MIN
+#define SVE_VQ_MAX __SVE_VQ_MAX
+#define SVE_VL_MIN __SVE_VL_MIN
+#define SVE_VL_MAX __SVE_VL_MAX
+#define SVE_NUM_ZREGS __SVE_NUM_ZREGS
+#define SVE_NUM_PREGS __SVE_NUM_PREGS
+#define sve_vl_valid(vl) __sve_vl_valid(vl)
+#define sve_vq_from_vl(vl) __sve_vq_from_vl(vl)
+#define sve_vl_from_vq(vq) __sve_vl_from_vq(vq)
+#define SVE_SIG_ZREG_SIZE(vq) __SVE_ZREG_SIZE(vq)
+#define SVE_SIG_PREG_SIZE(vq) __SVE_PREG_SIZE(vq)
+#define SVE_SIG_FFR_SIZE(vq) __SVE_FFR_SIZE(vq)
+#define SVE_SIG_REGS_OFFSET ((sizeof(struct sve_context) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
+#define SVE_SIG_ZREGS_OFFSET (SVE_SIG_REGS_OFFSET + __SVE_ZREGS_OFFSET)
+#define SVE_SIG_ZREG_OFFSET(vq,n) (SVE_SIG_REGS_OFFSET + __SVE_ZREG_OFFSET(vq, n))
+#define SVE_SIG_ZREGS_SIZE(vq) __SVE_ZREGS_SIZE(vq)
+#define SVE_SIG_PREGS_OFFSET(vq) (SVE_SIG_REGS_OFFSET + __SVE_PREGS_OFFSET(vq))
+#define SVE_SIG_PREG_OFFSET(vq,n) (SVE_SIG_REGS_OFFSET + __SVE_PREG_OFFSET(vq, n))
+#define SVE_SIG_PREGS_SIZE(vq) __SVE_PREGS_SIZE(vq)
+#define SVE_SIG_FFR_OFFSET(vq) (SVE_SIG_REGS_OFFSET + __SVE_FFR_OFFSET(vq))
+#define SVE_SIG_REGS_SIZE(vq) (__SVE_FFR_OFFSET(vq) + __SVE_FFR_SIZE(vq))
 #define SVE_SIG_CONTEXT_SIZE(vq) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/sve_context.h b/libc/kernel/uapi/asm-arm64/asm/sve_context.h
new file mode 100644
index 0000000..ff0063e
--- /dev/null
+++ b/libc/kernel/uapi/asm-arm64/asm/sve_context.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI__ASM_SVE_CONTEXT_H
+#define _UAPI__ASM_SVE_CONTEXT_H
+#include <linux/types.h>
+#define __SVE_VQ_BYTES 16
+#define __SVE_VQ_MIN 1
+#define __SVE_VQ_MAX 512
+#define __SVE_VL_MIN (__SVE_VQ_MIN * __SVE_VQ_BYTES)
+#define __SVE_VL_MAX (__SVE_VQ_MAX * __SVE_VQ_BYTES)
+#define __SVE_NUM_ZREGS 32
+#define __SVE_NUM_PREGS 16
+#define __sve_vl_valid(vl) ((vl) % __SVE_VQ_BYTES == 0 && (vl) >= __SVE_VL_MIN && (vl) <= __SVE_VL_MAX)
+#define __sve_vq_from_vl(vl) ((vl) / __SVE_VQ_BYTES)
+#define __sve_vl_from_vq(vq) ((vq) * __SVE_VQ_BYTES)
+#define __SVE_ZREG_SIZE(vq) ((__u32) (vq) * __SVE_VQ_BYTES)
+#define __SVE_PREG_SIZE(vq) ((__u32) (vq) * (__SVE_VQ_BYTES / 8))
+#define __SVE_FFR_SIZE(vq) __SVE_PREG_SIZE(vq)
+#define __SVE_ZREGS_OFFSET 0
+#define __SVE_ZREG_OFFSET(vq,n) (__SVE_ZREGS_OFFSET + __SVE_ZREG_SIZE(vq) * (n))
+#define __SVE_ZREGS_SIZE(vq) (__SVE_ZREG_OFFSET(vq, __SVE_NUM_ZREGS) - __SVE_ZREGS_OFFSET)
+#define __SVE_PREGS_OFFSET(vq) (__SVE_ZREGS_OFFSET + __SVE_ZREGS_SIZE(vq))
+#define __SVE_PREG_OFFSET(vq,n) (__SVE_PREGS_OFFSET(vq) + __SVE_PREG_SIZE(vq) * (n))
+#define __SVE_PREGS_SIZE(vq) (__SVE_PREG_OFFSET(vq, __SVE_NUM_PREGS) - __SVE_PREGS_OFFSET(vq))
+#define __SVE_FFR_OFFSET(vq) (__SVE_PREGS_OFFSET(vq) + __SVE_PREGS_SIZE(vq))
+#endif
diff --git a/libc/kernel/uapi/asm-generic/unistd.h b/libc/kernel/uapi/asm-generic/unistd.h
index fddf1d0..4113881 100644
--- a/libc/kernel/uapi/asm-generic/unistd.h
+++ b/libc/kernel/uapi/asm-generic/unistd.h
@@ -321,8 +321,9 @@
 #define __NR_statx 291
 #define __NR_io_pgetevents 292
 #define __NR_rseq 293
+#define __NR_kexec_file_load 294
 #undef __NR_syscalls
-#define __NR_syscalls 294
+#define __NR_syscalls 295
 #if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
 #define __NR_fcntl __NR3264_fcntl
 #define __NR_statfs __NR3264_statfs
diff --git a/libc/kernel/uapi/asm-mips/asm/inst.h b/libc/kernel/uapi/asm-mips/asm/inst.h
index 61fa3d6..090a40b 100644
--- a/libc/kernel/uapi/asm-mips/asm/inst.h
+++ b/libc/kernel/uapi/asm-mips/asm/inst.h
@@ -549,8 +549,9 @@
   mm_ext_op = 0x02c,
   mm_pool32axf_op = 0x03c,
   mm_srl32_op = 0x040,
+  mm_srlv32_op = 0x050,
   mm_sra_op = 0x080,
-  mm_srlv32_op = 0x090,
+  mm_srav_op = 0x090,
   mm_rotr_op = 0x0c0,
   mm_lwxs_op = 0x118,
   mm_addu32_op = 0x150,
diff --git a/libc/kernel/uapi/asm-mips/asm/sgidefs.h b/libc/kernel/uapi/asm-mips/asm/sgidefs.h
index 040459b..92750de 100644
--- a/libc/kernel/uapi/asm-mips/asm/sgidefs.h
+++ b/libc/kernel/uapi/asm-mips/asm/sgidefs.h
@@ -18,9 +18,6 @@
  ****************************************************************************/
 #ifndef __ASM_SGIDEFS_H
 #define __ASM_SGIDEFS_H
-#ifndef __linux__
-#error Use a Linux compiler or give up .
-#endif
 #define _MIPS_ISA_MIPS1 1
 #define _MIPS_ISA_MIPS2 2
 #define _MIPS_ISA_MIPS3 3
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd.h b/libc/kernel/uapi/asm-mips/asm/unistd.h
index e4dee2b..65f3614 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd.h
@@ -21,1048 +21,14 @@
 #include <asm/sgidefs.h>
 #if _MIPS_SIM == _MIPS_SIM_ABI32
 #define __NR_Linux 4000
-#define __NR_syscall (__NR_Linux + 0)
-#define __NR_exit (__NR_Linux + 1)
-#define __NR_fork (__NR_Linux + 2)
-#define __NR_read (__NR_Linux + 3)
-#define __NR_write (__NR_Linux + 4)
-#define __NR_open (__NR_Linux + 5)
-#define __NR_close (__NR_Linux + 6)
-#define __NR_waitpid (__NR_Linux + 7)
-#define __NR_creat (__NR_Linux + 8)
-#define __NR_link (__NR_Linux + 9)
-#define __NR_unlink (__NR_Linux + 10)
-#define __NR_execve (__NR_Linux + 11)
-#define __NR_chdir (__NR_Linux + 12)
-#define __NR_time (__NR_Linux + 13)
-#define __NR_mknod (__NR_Linux + 14)
-#define __NR_chmod (__NR_Linux + 15)
-#define __NR_lchown (__NR_Linux + 16)
-#define __NR_break (__NR_Linux + 17)
-#define __NR_unused18 (__NR_Linux + 18)
-#define __NR_lseek (__NR_Linux + 19)
-#define __NR_getpid (__NR_Linux + 20)
-#define __NR_mount (__NR_Linux + 21)
-#define __NR_umount (__NR_Linux + 22)
-#define __NR_setuid (__NR_Linux + 23)
-#define __NR_getuid (__NR_Linux + 24)
-#define __NR_stime (__NR_Linux + 25)
-#define __NR_ptrace (__NR_Linux + 26)
-#define __NR_alarm (__NR_Linux + 27)
-#define __NR_unused28 (__NR_Linux + 28)
-#define __NR_pause (__NR_Linux + 29)
-#define __NR_utime (__NR_Linux + 30)
-#define __NR_stty (__NR_Linux + 31)
-#define __NR_gtty (__NR_Linux + 32)
-#define __NR_access (__NR_Linux + 33)
-#define __NR_nice (__NR_Linux + 34)
-#define __NR_ftime (__NR_Linux + 35)
-#define __NR_sync (__NR_Linux + 36)
-#define __NR_kill (__NR_Linux + 37)
-#define __NR_rename (__NR_Linux + 38)
-#define __NR_mkdir (__NR_Linux + 39)
-#define __NR_rmdir (__NR_Linux + 40)
-#define __NR_dup (__NR_Linux + 41)
-#define __NR_pipe (__NR_Linux + 42)
-#define __NR_times (__NR_Linux + 43)
-#define __NR_prof (__NR_Linux + 44)
-#define __NR_brk (__NR_Linux + 45)
-#define __NR_setgid (__NR_Linux + 46)
-#define __NR_getgid (__NR_Linux + 47)
-#define __NR_signal (__NR_Linux + 48)
-#define __NR_geteuid (__NR_Linux + 49)
-#define __NR_getegid (__NR_Linux + 50)
-#define __NR_acct (__NR_Linux + 51)
-#define __NR_umount2 (__NR_Linux + 52)
-#define __NR_lock (__NR_Linux + 53)
-#define __NR_ioctl (__NR_Linux + 54)
-#define __NR_fcntl (__NR_Linux + 55)
-#define __NR_mpx (__NR_Linux + 56)
-#define __NR_setpgid (__NR_Linux + 57)
-#define __NR_ulimit (__NR_Linux + 58)
-#define __NR_unused59 (__NR_Linux + 59)
-#define __NR_umask (__NR_Linux + 60)
-#define __NR_chroot (__NR_Linux + 61)
-#define __NR_ustat (__NR_Linux + 62)
-#define __NR_dup2 (__NR_Linux + 63)
-#define __NR_getppid (__NR_Linux + 64)
-#define __NR_getpgrp (__NR_Linux + 65)
-#define __NR_setsid (__NR_Linux + 66)
-#define __NR_sigaction (__NR_Linux + 67)
-#define __NR_sgetmask (__NR_Linux + 68)
-#define __NR_ssetmask (__NR_Linux + 69)
-#define __NR_setreuid (__NR_Linux + 70)
-#define __NR_setregid (__NR_Linux + 71)
-#define __NR_sigsuspend (__NR_Linux + 72)
-#define __NR_sigpending (__NR_Linux + 73)
-#define __NR_sethostname (__NR_Linux + 74)
-#define __NR_setrlimit (__NR_Linux + 75)
-#define __NR_getrlimit (__NR_Linux + 76)
-#define __NR_getrusage (__NR_Linux + 77)
-#define __NR_gettimeofday (__NR_Linux + 78)
-#define __NR_settimeofday (__NR_Linux + 79)
-#define __NR_getgroups (__NR_Linux + 80)
-#define __NR_setgroups (__NR_Linux + 81)
-#define __NR_reserved82 (__NR_Linux + 82)
-#define __NR_symlink (__NR_Linux + 83)
-#define __NR_unused84 (__NR_Linux + 84)
-#define __NR_readlink (__NR_Linux + 85)
-#define __NR_uselib (__NR_Linux + 86)
-#define __NR_swapon (__NR_Linux + 87)
-#define __NR_reboot (__NR_Linux + 88)
-#define __NR_readdir (__NR_Linux + 89)
-#define __NR_mmap (__NR_Linux + 90)
-#define __NR_munmap (__NR_Linux + 91)
-#define __NR_truncate (__NR_Linux + 92)
-#define __NR_ftruncate (__NR_Linux + 93)
-#define __NR_fchmod (__NR_Linux + 94)
-#define __NR_fchown (__NR_Linux + 95)
-#define __NR_getpriority (__NR_Linux + 96)
-#define __NR_setpriority (__NR_Linux + 97)
-#define __NR_profil (__NR_Linux + 98)
-#define __NR_statfs (__NR_Linux + 99)
-#define __NR_fstatfs (__NR_Linux + 100)
-#define __NR_ioperm (__NR_Linux + 101)
-#define __NR_socketcall (__NR_Linux + 102)
-#define __NR_syslog (__NR_Linux + 103)
-#define __NR_setitimer (__NR_Linux + 104)
-#define __NR_getitimer (__NR_Linux + 105)
-#define __NR_stat (__NR_Linux + 106)
-#define __NR_lstat (__NR_Linux + 107)
-#define __NR_fstat (__NR_Linux + 108)
-#define __NR_unused109 (__NR_Linux + 109)
-#define __NR_iopl (__NR_Linux + 110)
-#define __NR_vhangup (__NR_Linux + 111)
-#define __NR_idle (__NR_Linux + 112)
-#define __NR_vm86 (__NR_Linux + 113)
-#define __NR_wait4 (__NR_Linux + 114)
-#define __NR_swapoff (__NR_Linux + 115)
-#define __NR_sysinfo (__NR_Linux + 116)
-#define __NR_ipc (__NR_Linux + 117)
-#define __NR_fsync (__NR_Linux + 118)
-#define __NR_sigreturn (__NR_Linux + 119)
-#define __NR_clone (__NR_Linux + 120)
-#define __NR_setdomainname (__NR_Linux + 121)
-#define __NR_uname (__NR_Linux + 122)
-#define __NR_modify_ldt (__NR_Linux + 123)
-#define __NR_adjtimex (__NR_Linux + 124)
-#define __NR_mprotect (__NR_Linux + 125)
-#define __NR_sigprocmask (__NR_Linux + 126)
-#define __NR_create_module (__NR_Linux + 127)
-#define __NR_init_module (__NR_Linux + 128)
-#define __NR_delete_module (__NR_Linux + 129)
-#define __NR_get_kernel_syms (__NR_Linux + 130)
-#define __NR_quotactl (__NR_Linux + 131)
-#define __NR_getpgid (__NR_Linux + 132)
-#define __NR_fchdir (__NR_Linux + 133)
-#define __NR_bdflush (__NR_Linux + 134)
-#define __NR_sysfs (__NR_Linux + 135)
-#define __NR_personality (__NR_Linux + 136)
-#define __NR_afs_syscall (__NR_Linux + 137)
-#define __NR_setfsuid (__NR_Linux + 138)
-#define __NR_setfsgid (__NR_Linux + 139)
-#define __NR__llseek (__NR_Linux + 140)
-#define __NR_getdents (__NR_Linux + 141)
-#define __NR__newselect (__NR_Linux + 142)
-#define __NR_flock (__NR_Linux + 143)
-#define __NR_msync (__NR_Linux + 144)
-#define __NR_readv (__NR_Linux + 145)
-#define __NR_writev (__NR_Linux + 146)
-#define __NR_cacheflush (__NR_Linux + 147)
-#define __NR_cachectl (__NR_Linux + 148)
-#define __NR_sysmips (__NR_Linux + 149)
-#define __NR_unused150 (__NR_Linux + 150)
-#define __NR_getsid (__NR_Linux + 151)
-#define __NR_fdatasync (__NR_Linux + 152)
-#define __NR__sysctl (__NR_Linux + 153)
-#define __NR_mlock (__NR_Linux + 154)
-#define __NR_munlock (__NR_Linux + 155)
-#define __NR_mlockall (__NR_Linux + 156)
-#define __NR_munlockall (__NR_Linux + 157)
-#define __NR_sched_setparam (__NR_Linux + 158)
-#define __NR_sched_getparam (__NR_Linux + 159)
-#define __NR_sched_setscheduler (__NR_Linux + 160)
-#define __NR_sched_getscheduler (__NR_Linux + 161)
-#define __NR_sched_yield (__NR_Linux + 162)
-#define __NR_sched_get_priority_max (__NR_Linux + 163)
-#define __NR_sched_get_priority_min (__NR_Linux + 164)
-#define __NR_sched_rr_get_interval (__NR_Linux + 165)
-#define __NR_nanosleep (__NR_Linux + 166)
-#define __NR_mremap (__NR_Linux + 167)
-#define __NR_accept (__NR_Linux + 168)
-#define __NR_bind (__NR_Linux + 169)
-#define __NR_connect (__NR_Linux + 170)
-#define __NR_getpeername (__NR_Linux + 171)
-#define __NR_getsockname (__NR_Linux + 172)
-#define __NR_getsockopt (__NR_Linux + 173)
-#define __NR_listen (__NR_Linux + 174)
-#define __NR_recv (__NR_Linux + 175)
-#define __NR_recvfrom (__NR_Linux + 176)
-#define __NR_recvmsg (__NR_Linux + 177)
-#define __NR_send (__NR_Linux + 178)
-#define __NR_sendmsg (__NR_Linux + 179)
-#define __NR_sendto (__NR_Linux + 180)
-#define __NR_setsockopt (__NR_Linux + 181)
-#define __NR_shutdown (__NR_Linux + 182)
-#define __NR_socket (__NR_Linux + 183)
-#define __NR_socketpair (__NR_Linux + 184)
-#define __NR_setresuid (__NR_Linux + 185)
-#define __NR_getresuid (__NR_Linux + 186)
-#define __NR_query_module (__NR_Linux + 187)
-#define __NR_poll (__NR_Linux + 188)
-#define __NR_nfsservctl (__NR_Linux + 189)
-#define __NR_setresgid (__NR_Linux + 190)
-#define __NR_getresgid (__NR_Linux + 191)
-#define __NR_prctl (__NR_Linux + 192)
-#define __NR_rt_sigreturn (__NR_Linux + 193)
-#define __NR_rt_sigaction (__NR_Linux + 194)
-#define __NR_rt_sigprocmask (__NR_Linux + 195)
-#define __NR_rt_sigpending (__NR_Linux + 196)
-#define __NR_rt_sigtimedwait (__NR_Linux + 197)
-#define __NR_rt_sigqueueinfo (__NR_Linux + 198)
-#define __NR_rt_sigsuspend (__NR_Linux + 199)
-#define __NR_pread64 (__NR_Linux + 200)
-#define __NR_pwrite64 (__NR_Linux + 201)
-#define __NR_chown (__NR_Linux + 202)
-#define __NR_getcwd (__NR_Linux + 203)
-#define __NR_capget (__NR_Linux + 204)
-#define __NR_capset (__NR_Linux + 205)
-#define __NR_sigaltstack (__NR_Linux + 206)
-#define __NR_sendfile (__NR_Linux + 207)
-#define __NR_getpmsg (__NR_Linux + 208)
-#define __NR_putpmsg (__NR_Linux + 209)
-#define __NR_mmap2 (__NR_Linux + 210)
-#define __NR_truncate64 (__NR_Linux + 211)
-#define __NR_ftruncate64 (__NR_Linux + 212)
-#define __NR_stat64 (__NR_Linux + 213)
-#define __NR_lstat64 (__NR_Linux + 214)
-#define __NR_fstat64 (__NR_Linux + 215)
-#define __NR_pivot_root (__NR_Linux + 216)
-#define __NR_mincore (__NR_Linux + 217)
-#define __NR_madvise (__NR_Linux + 218)
-#define __NR_getdents64 (__NR_Linux + 219)
-#define __NR_fcntl64 (__NR_Linux + 220)
-#define __NR_reserved221 (__NR_Linux + 221)
-#define __NR_gettid (__NR_Linux + 222)
-#define __NR_readahead (__NR_Linux + 223)
-#define __NR_setxattr (__NR_Linux + 224)
-#define __NR_lsetxattr (__NR_Linux + 225)
-#define __NR_fsetxattr (__NR_Linux + 226)
-#define __NR_getxattr (__NR_Linux + 227)
-#define __NR_lgetxattr (__NR_Linux + 228)
-#define __NR_fgetxattr (__NR_Linux + 229)
-#define __NR_listxattr (__NR_Linux + 230)
-#define __NR_llistxattr (__NR_Linux + 231)
-#define __NR_flistxattr (__NR_Linux + 232)
-#define __NR_removexattr (__NR_Linux + 233)
-#define __NR_lremovexattr (__NR_Linux + 234)
-#define __NR_fremovexattr (__NR_Linux + 235)
-#define __NR_tkill (__NR_Linux + 236)
-#define __NR_sendfile64 (__NR_Linux + 237)
-#define __NR_futex (__NR_Linux + 238)
-#define __NR_sched_setaffinity (__NR_Linux + 239)
-#define __NR_sched_getaffinity (__NR_Linux + 240)
-#define __NR_io_setup (__NR_Linux + 241)
-#define __NR_io_destroy (__NR_Linux + 242)
-#define __NR_io_getevents (__NR_Linux + 243)
-#define __NR_io_submit (__NR_Linux + 244)
-#define __NR_io_cancel (__NR_Linux + 245)
-#define __NR_exit_group (__NR_Linux + 246)
-#define __NR_lookup_dcookie (__NR_Linux + 247)
-#define __NR_epoll_create (__NR_Linux + 248)
-#define __NR_epoll_ctl (__NR_Linux + 249)
-#define __NR_epoll_wait (__NR_Linux + 250)
-#define __NR_remap_file_pages (__NR_Linux + 251)
-#define __NR_set_tid_address (__NR_Linux + 252)
-#define __NR_restart_syscall (__NR_Linux + 253)
-#define __NR_fadvise64 (__NR_Linux + 254)
-#define __NR_statfs64 (__NR_Linux + 255)
-#define __NR_fstatfs64 (__NR_Linux + 256)
-#define __NR_timer_create (__NR_Linux + 257)
-#define __NR_timer_settime (__NR_Linux + 258)
-#define __NR_timer_gettime (__NR_Linux + 259)
-#define __NR_timer_getoverrun (__NR_Linux + 260)
-#define __NR_timer_delete (__NR_Linux + 261)
-#define __NR_clock_settime (__NR_Linux + 262)
-#define __NR_clock_gettime (__NR_Linux + 263)
-#define __NR_clock_getres (__NR_Linux + 264)
-#define __NR_clock_nanosleep (__NR_Linux + 265)
-#define __NR_tgkill (__NR_Linux + 266)
-#define __NR_utimes (__NR_Linux + 267)
-#define __NR_mbind (__NR_Linux + 268)
-#define __NR_get_mempolicy (__NR_Linux + 269)
-#define __NR_set_mempolicy (__NR_Linux + 270)
-#define __NR_mq_open (__NR_Linux + 271)
-#define __NR_mq_unlink (__NR_Linux + 272)
-#define __NR_mq_timedsend (__NR_Linux + 273)
-#define __NR_mq_timedreceive (__NR_Linux + 274)
-#define __NR_mq_notify (__NR_Linux + 275)
-#define __NR_mq_getsetattr (__NR_Linux + 276)
-#define __NR_vserver (__NR_Linux + 277)
-#define __NR_waitid (__NR_Linux + 278)
-#define __NR_add_key (__NR_Linux + 280)
-#define __NR_request_key (__NR_Linux + 281)
-#define __NR_keyctl (__NR_Linux + 282)
-#define __NR_set_thread_area (__NR_Linux + 283)
-#define __NR_inotify_init (__NR_Linux + 284)
-#define __NR_inotify_add_watch (__NR_Linux + 285)
-#define __NR_inotify_rm_watch (__NR_Linux + 286)
-#define __NR_migrate_pages (__NR_Linux + 287)
-#define __NR_openat (__NR_Linux + 288)
-#define __NR_mkdirat (__NR_Linux + 289)
-#define __NR_mknodat (__NR_Linux + 290)
-#define __NR_fchownat (__NR_Linux + 291)
-#define __NR_futimesat (__NR_Linux + 292)
-#define __NR_fstatat64 (__NR_Linux + 293)
-#define __NR_unlinkat (__NR_Linux + 294)
-#define __NR_renameat (__NR_Linux + 295)
-#define __NR_linkat (__NR_Linux + 296)
-#define __NR_symlinkat (__NR_Linux + 297)
-#define __NR_readlinkat (__NR_Linux + 298)
-#define __NR_fchmodat (__NR_Linux + 299)
-#define __NR_faccessat (__NR_Linux + 300)
-#define __NR_pselect6 (__NR_Linux + 301)
-#define __NR_ppoll (__NR_Linux + 302)
-#define __NR_unshare (__NR_Linux + 303)
-#define __NR_splice (__NR_Linux + 304)
-#define __NR_sync_file_range (__NR_Linux + 305)
-#define __NR_tee (__NR_Linux + 306)
-#define __NR_vmsplice (__NR_Linux + 307)
-#define __NR_move_pages (__NR_Linux + 308)
-#define __NR_set_robust_list (__NR_Linux + 309)
-#define __NR_get_robust_list (__NR_Linux + 310)
-#define __NR_kexec_load (__NR_Linux + 311)
-#define __NR_getcpu (__NR_Linux + 312)
-#define __NR_epoll_pwait (__NR_Linux + 313)
-#define __NR_ioprio_set (__NR_Linux + 314)
-#define __NR_ioprio_get (__NR_Linux + 315)
-#define __NR_utimensat (__NR_Linux + 316)
-#define __NR_signalfd (__NR_Linux + 317)
-#define __NR_timerfd (__NR_Linux + 318)
-#define __NR_eventfd (__NR_Linux + 319)
-#define __NR_fallocate (__NR_Linux + 320)
-#define __NR_timerfd_create (__NR_Linux + 321)
-#define __NR_timerfd_gettime (__NR_Linux + 322)
-#define __NR_timerfd_settime (__NR_Linux + 323)
-#define __NR_signalfd4 (__NR_Linux + 324)
-#define __NR_eventfd2 (__NR_Linux + 325)
-#define __NR_epoll_create1 (__NR_Linux + 326)
-#define __NR_dup3 (__NR_Linux + 327)
-#define __NR_pipe2 (__NR_Linux + 328)
-#define __NR_inotify_init1 (__NR_Linux + 329)
-#define __NR_preadv (__NR_Linux + 330)
-#define __NR_pwritev (__NR_Linux + 331)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332)
-#define __NR_perf_event_open (__NR_Linux + 333)
-#define __NR_accept4 (__NR_Linux + 334)
-#define __NR_recvmmsg (__NR_Linux + 335)
-#define __NR_fanotify_init (__NR_Linux + 336)
-#define __NR_fanotify_mark (__NR_Linux + 337)
-#define __NR_prlimit64 (__NR_Linux + 338)
-#define __NR_name_to_handle_at (__NR_Linux + 339)
-#define __NR_open_by_handle_at (__NR_Linux + 340)
-#define __NR_clock_adjtime (__NR_Linux + 341)
-#define __NR_syncfs (__NR_Linux + 342)
-#define __NR_sendmmsg (__NR_Linux + 343)
-#define __NR_setns (__NR_Linux + 344)
-#define __NR_process_vm_readv (__NR_Linux + 345)
-#define __NR_process_vm_writev (__NR_Linux + 346)
-#define __NR_kcmp (__NR_Linux + 347)
-#define __NR_finit_module (__NR_Linux + 348)
-#define __NR_sched_setattr (__NR_Linux + 349)
-#define __NR_sched_getattr (__NR_Linux + 350)
-#define __NR_renameat2 (__NR_Linux + 351)
-#define __NR_seccomp (__NR_Linux + 352)
-#define __NR_getrandom (__NR_Linux + 353)
-#define __NR_memfd_create (__NR_Linux + 354)
-#define __NR_bpf (__NR_Linux + 355)
-#define __NR_execveat (__NR_Linux + 356)
-#define __NR_userfaultfd (__NR_Linux + 357)
-#define __NR_membarrier (__NR_Linux + 358)
-#define __NR_mlock2 (__NR_Linux + 359)
-#define __NR_copy_file_range (__NR_Linux + 360)
-#define __NR_preadv2 (__NR_Linux + 361)
-#define __NR_pwritev2 (__NR_Linux + 362)
-#define __NR_pkey_mprotect (__NR_Linux + 363)
-#define __NR_pkey_alloc (__NR_Linux + 364)
-#define __NR_pkey_free (__NR_Linux + 365)
-#define __NR_statx (__NR_Linux + 366)
-#define __NR_rseq (__NR_Linux + 367)
-#define __NR_io_pgetevents (__NR_Linux + 368)
-#define __NR_Linux_syscalls 368
+#include <asm/unistd_o32.h>
 #endif
-#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 368
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 #define __NR_Linux 5000
-#define __NR_read (__NR_Linux + 0)
-#define __NR_write (__NR_Linux + 1)
-#define __NR_open (__NR_Linux + 2)
-#define __NR_close (__NR_Linux + 3)
-#define __NR_stat (__NR_Linux + 4)
-#define __NR_fstat (__NR_Linux + 5)
-#define __NR_lstat (__NR_Linux + 6)
-#define __NR_poll (__NR_Linux + 7)
-#define __NR_lseek (__NR_Linux + 8)
-#define __NR_mmap (__NR_Linux + 9)
-#define __NR_mprotect (__NR_Linux + 10)
-#define __NR_munmap (__NR_Linux + 11)
-#define __NR_brk (__NR_Linux + 12)
-#define __NR_rt_sigaction (__NR_Linux + 13)
-#define __NR_rt_sigprocmask (__NR_Linux + 14)
-#define __NR_ioctl (__NR_Linux + 15)
-#define __NR_pread64 (__NR_Linux + 16)
-#define __NR_pwrite64 (__NR_Linux + 17)
-#define __NR_readv (__NR_Linux + 18)
-#define __NR_writev (__NR_Linux + 19)
-#define __NR_access (__NR_Linux + 20)
-#define __NR_pipe (__NR_Linux + 21)
-#define __NR__newselect (__NR_Linux + 22)
-#define __NR_sched_yield (__NR_Linux + 23)
-#define __NR_mremap (__NR_Linux + 24)
-#define __NR_msync (__NR_Linux + 25)
-#define __NR_mincore (__NR_Linux + 26)
-#define __NR_madvise (__NR_Linux + 27)
-#define __NR_shmget (__NR_Linux + 28)
-#define __NR_shmat (__NR_Linux + 29)
-#define __NR_shmctl (__NR_Linux + 30)
-#define __NR_dup (__NR_Linux + 31)
-#define __NR_dup2 (__NR_Linux + 32)
-#define __NR_pause (__NR_Linux + 33)
-#define __NR_nanosleep (__NR_Linux + 34)
-#define __NR_getitimer (__NR_Linux + 35)
-#define __NR_setitimer (__NR_Linux + 36)
-#define __NR_alarm (__NR_Linux + 37)
-#define __NR_getpid (__NR_Linux + 38)
-#define __NR_sendfile (__NR_Linux + 39)
-#define __NR_socket (__NR_Linux + 40)
-#define __NR_connect (__NR_Linux + 41)
-#define __NR_accept (__NR_Linux + 42)
-#define __NR_sendto (__NR_Linux + 43)
-#define __NR_recvfrom (__NR_Linux + 44)
-#define __NR_sendmsg (__NR_Linux + 45)
-#define __NR_recvmsg (__NR_Linux + 46)
-#define __NR_shutdown (__NR_Linux + 47)
-#define __NR_bind (__NR_Linux + 48)
-#define __NR_listen (__NR_Linux + 49)
-#define __NR_getsockname (__NR_Linux + 50)
-#define __NR_getpeername (__NR_Linux + 51)
-#define __NR_socketpair (__NR_Linux + 52)
-#define __NR_setsockopt (__NR_Linux + 53)
-#define __NR_getsockopt (__NR_Linux + 54)
-#define __NR_clone (__NR_Linux + 55)
-#define __NR_fork (__NR_Linux + 56)
-#define __NR_execve (__NR_Linux + 57)
-#define __NR_exit (__NR_Linux + 58)
-#define __NR_wait4 (__NR_Linux + 59)
-#define __NR_kill (__NR_Linux + 60)
-#define __NR_uname (__NR_Linux + 61)
-#define __NR_semget (__NR_Linux + 62)
-#define __NR_semop (__NR_Linux + 63)
-#define __NR_semctl (__NR_Linux + 64)
-#define __NR_shmdt (__NR_Linux + 65)
-#define __NR_msgget (__NR_Linux + 66)
-#define __NR_msgsnd (__NR_Linux + 67)
-#define __NR_msgrcv (__NR_Linux + 68)
-#define __NR_msgctl (__NR_Linux + 69)
-#define __NR_fcntl (__NR_Linux + 70)
-#define __NR_flock (__NR_Linux + 71)
-#define __NR_fsync (__NR_Linux + 72)
-#define __NR_fdatasync (__NR_Linux + 73)
-#define __NR_truncate (__NR_Linux + 74)
-#define __NR_ftruncate (__NR_Linux + 75)
-#define __NR_getdents (__NR_Linux + 76)
-#define __NR_getcwd (__NR_Linux + 77)
-#define __NR_chdir (__NR_Linux + 78)
-#define __NR_fchdir (__NR_Linux + 79)
-#define __NR_rename (__NR_Linux + 80)
-#define __NR_mkdir (__NR_Linux + 81)
-#define __NR_rmdir (__NR_Linux + 82)
-#define __NR_creat (__NR_Linux + 83)
-#define __NR_link (__NR_Linux + 84)
-#define __NR_unlink (__NR_Linux + 85)
-#define __NR_symlink (__NR_Linux + 86)
-#define __NR_readlink (__NR_Linux + 87)
-#define __NR_chmod (__NR_Linux + 88)
-#define __NR_fchmod (__NR_Linux + 89)
-#define __NR_chown (__NR_Linux + 90)
-#define __NR_fchown (__NR_Linux + 91)
-#define __NR_lchown (__NR_Linux + 92)
-#define __NR_umask (__NR_Linux + 93)
-#define __NR_gettimeofday (__NR_Linux + 94)
-#define __NR_getrlimit (__NR_Linux + 95)
-#define __NR_getrusage (__NR_Linux + 96)
-#define __NR_sysinfo (__NR_Linux + 97)
-#define __NR_times (__NR_Linux + 98)
-#define __NR_ptrace (__NR_Linux + 99)
-#define __NR_getuid (__NR_Linux + 100)
-#define __NR_syslog (__NR_Linux + 101)
-#define __NR_getgid (__NR_Linux + 102)
-#define __NR_setuid (__NR_Linux + 103)
-#define __NR_setgid (__NR_Linux + 104)
-#define __NR_geteuid (__NR_Linux + 105)
-#define __NR_getegid (__NR_Linux + 106)
-#define __NR_setpgid (__NR_Linux + 107)
-#define __NR_getppid (__NR_Linux + 108)
-#define __NR_getpgrp (__NR_Linux + 109)
-#define __NR_setsid (__NR_Linux + 110)
-#define __NR_setreuid (__NR_Linux + 111)
-#define __NR_setregid (__NR_Linux + 112)
-#define __NR_getgroups (__NR_Linux + 113)
-#define __NR_setgroups (__NR_Linux + 114)
-#define __NR_setresuid (__NR_Linux + 115)
-#define __NR_getresuid (__NR_Linux + 116)
-#define __NR_setresgid (__NR_Linux + 117)
-#define __NR_getresgid (__NR_Linux + 118)
-#define __NR_getpgid (__NR_Linux + 119)
-#define __NR_setfsuid (__NR_Linux + 120)
-#define __NR_setfsgid (__NR_Linux + 121)
-#define __NR_getsid (__NR_Linux + 122)
-#define __NR_capget (__NR_Linux + 123)
-#define __NR_capset (__NR_Linux + 124)
-#define __NR_rt_sigpending (__NR_Linux + 125)
-#define __NR_rt_sigtimedwait (__NR_Linux + 126)
-#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
-#define __NR_rt_sigsuspend (__NR_Linux + 128)
-#define __NR_sigaltstack (__NR_Linux + 129)
-#define __NR_utime (__NR_Linux + 130)
-#define __NR_mknod (__NR_Linux + 131)
-#define __NR_personality (__NR_Linux + 132)
-#define __NR_ustat (__NR_Linux + 133)
-#define __NR_statfs (__NR_Linux + 134)
-#define __NR_fstatfs (__NR_Linux + 135)
-#define __NR_sysfs (__NR_Linux + 136)
-#define __NR_getpriority (__NR_Linux + 137)
-#define __NR_setpriority (__NR_Linux + 138)
-#define __NR_sched_setparam (__NR_Linux + 139)
-#define __NR_sched_getparam (__NR_Linux + 140)
-#define __NR_sched_setscheduler (__NR_Linux + 141)
-#define __NR_sched_getscheduler (__NR_Linux + 142)
-#define __NR_sched_get_priority_max (__NR_Linux + 143)
-#define __NR_sched_get_priority_min (__NR_Linux + 144)
-#define __NR_sched_rr_get_interval (__NR_Linux + 145)
-#define __NR_mlock (__NR_Linux + 146)
-#define __NR_munlock (__NR_Linux + 147)
-#define __NR_mlockall (__NR_Linux + 148)
-#define __NR_munlockall (__NR_Linux + 149)
-#define __NR_vhangup (__NR_Linux + 150)
-#define __NR_pivot_root (__NR_Linux + 151)
-#define __NR__sysctl (__NR_Linux + 152)
-#define __NR_prctl (__NR_Linux + 153)
-#define __NR_adjtimex (__NR_Linux + 154)
-#define __NR_setrlimit (__NR_Linux + 155)
-#define __NR_chroot (__NR_Linux + 156)
-#define __NR_sync (__NR_Linux + 157)
-#define __NR_acct (__NR_Linux + 158)
-#define __NR_settimeofday (__NR_Linux + 159)
-#define __NR_mount (__NR_Linux + 160)
-#define __NR_umount2 (__NR_Linux + 161)
-#define __NR_swapon (__NR_Linux + 162)
-#define __NR_swapoff (__NR_Linux + 163)
-#define __NR_reboot (__NR_Linux + 164)
-#define __NR_sethostname (__NR_Linux + 165)
-#define __NR_setdomainname (__NR_Linux + 166)
-#define __NR_create_module (__NR_Linux + 167)
-#define __NR_init_module (__NR_Linux + 168)
-#define __NR_delete_module (__NR_Linux + 169)
-#define __NR_get_kernel_syms (__NR_Linux + 170)
-#define __NR_query_module (__NR_Linux + 171)
-#define __NR_quotactl (__NR_Linux + 172)
-#define __NR_nfsservctl (__NR_Linux + 173)
-#define __NR_getpmsg (__NR_Linux + 174)
-#define __NR_putpmsg (__NR_Linux + 175)
-#define __NR_afs_syscall (__NR_Linux + 176)
-#define __NR_reserved177 (__NR_Linux + 177)
-#define __NR_gettid (__NR_Linux + 178)
-#define __NR_readahead (__NR_Linux + 179)
-#define __NR_setxattr (__NR_Linux + 180)
-#define __NR_lsetxattr (__NR_Linux + 181)
-#define __NR_fsetxattr (__NR_Linux + 182)
-#define __NR_getxattr (__NR_Linux + 183)
-#define __NR_lgetxattr (__NR_Linux + 184)
-#define __NR_fgetxattr (__NR_Linux + 185)
-#define __NR_listxattr (__NR_Linux + 186)
-#define __NR_llistxattr (__NR_Linux + 187)
-#define __NR_flistxattr (__NR_Linux + 188)
-#define __NR_removexattr (__NR_Linux + 189)
-#define __NR_lremovexattr (__NR_Linux + 190)
-#define __NR_fremovexattr (__NR_Linux + 191)
-#define __NR_tkill (__NR_Linux + 192)
-#define __NR_reserved193 (__NR_Linux + 193)
-#define __NR_futex (__NR_Linux + 194)
-#define __NR_sched_setaffinity (__NR_Linux + 195)
-#define __NR_sched_getaffinity (__NR_Linux + 196)
-#define __NR_cacheflush (__NR_Linux + 197)
-#define __NR_cachectl (__NR_Linux + 198)
-#define __NR_sysmips (__NR_Linux + 199)
-#define __NR_io_setup (__NR_Linux + 200)
-#define __NR_io_destroy (__NR_Linux + 201)
-#define __NR_io_getevents (__NR_Linux + 202)
-#define __NR_io_submit (__NR_Linux + 203)
-#define __NR_io_cancel (__NR_Linux + 204)
-#define __NR_exit_group (__NR_Linux + 205)
-#define __NR_lookup_dcookie (__NR_Linux + 206)
-#define __NR_epoll_create (__NR_Linux + 207)
-#define __NR_epoll_ctl (__NR_Linux + 208)
-#define __NR_epoll_wait (__NR_Linux + 209)
-#define __NR_remap_file_pages (__NR_Linux + 210)
-#define __NR_rt_sigreturn (__NR_Linux + 211)
-#define __NR_set_tid_address (__NR_Linux + 212)
-#define __NR_restart_syscall (__NR_Linux + 213)
-#define __NR_semtimedop (__NR_Linux + 214)
-#define __NR_fadvise64 (__NR_Linux + 215)
-#define __NR_timer_create (__NR_Linux + 216)
-#define __NR_timer_settime (__NR_Linux + 217)
-#define __NR_timer_gettime (__NR_Linux + 218)
-#define __NR_timer_getoverrun (__NR_Linux + 219)
-#define __NR_timer_delete (__NR_Linux + 220)
-#define __NR_clock_settime (__NR_Linux + 221)
-#define __NR_clock_gettime (__NR_Linux + 222)
-#define __NR_clock_getres (__NR_Linux + 223)
-#define __NR_clock_nanosleep (__NR_Linux + 224)
-#define __NR_tgkill (__NR_Linux + 225)
-#define __NR_utimes (__NR_Linux + 226)
-#define __NR_mbind (__NR_Linux + 227)
-#define __NR_get_mempolicy (__NR_Linux + 228)
-#define __NR_set_mempolicy (__NR_Linux + 229)
-#define __NR_mq_open (__NR_Linux + 230)
-#define __NR_mq_unlink (__NR_Linux + 231)
-#define __NR_mq_timedsend (__NR_Linux + 232)
-#define __NR_mq_timedreceive (__NR_Linux + 233)
-#define __NR_mq_notify (__NR_Linux + 234)
-#define __NR_mq_getsetattr (__NR_Linux + 235)
-#define __NR_vserver (__NR_Linux + 236)
-#define __NR_waitid (__NR_Linux + 237)
-#define __NR_add_key (__NR_Linux + 239)
-#define __NR_request_key (__NR_Linux + 240)
-#define __NR_keyctl (__NR_Linux + 241)
-#define __NR_set_thread_area (__NR_Linux + 242)
-#define __NR_inotify_init (__NR_Linux + 243)
-#define __NR_inotify_add_watch (__NR_Linux + 244)
-#define __NR_inotify_rm_watch (__NR_Linux + 245)
-#define __NR_migrate_pages (__NR_Linux + 246)
-#define __NR_openat (__NR_Linux + 247)
-#define __NR_mkdirat (__NR_Linux + 248)
-#define __NR_mknodat (__NR_Linux + 249)
-#define __NR_fchownat (__NR_Linux + 250)
-#define __NR_futimesat (__NR_Linux + 251)
-#define __NR_newfstatat (__NR_Linux + 252)
-#define __NR_unlinkat (__NR_Linux + 253)
-#define __NR_renameat (__NR_Linux + 254)
-#define __NR_linkat (__NR_Linux + 255)
-#define __NR_symlinkat (__NR_Linux + 256)
-#define __NR_readlinkat (__NR_Linux + 257)
-#define __NR_fchmodat (__NR_Linux + 258)
-#define __NR_faccessat (__NR_Linux + 259)
-#define __NR_pselect6 (__NR_Linux + 260)
-#define __NR_ppoll (__NR_Linux + 261)
-#define __NR_unshare (__NR_Linux + 262)
-#define __NR_splice (__NR_Linux + 263)
-#define __NR_sync_file_range (__NR_Linux + 264)
-#define __NR_tee (__NR_Linux + 265)
-#define __NR_vmsplice (__NR_Linux + 266)
-#define __NR_move_pages (__NR_Linux + 267)
-#define __NR_set_robust_list (__NR_Linux + 268)
-#define __NR_get_robust_list (__NR_Linux + 269)
-#define __NR_kexec_load (__NR_Linux + 270)
-#define __NR_getcpu (__NR_Linux + 271)
-#define __NR_epoll_pwait (__NR_Linux + 272)
-#define __NR_ioprio_set (__NR_Linux + 273)
-#define __NR_ioprio_get (__NR_Linux + 274)
-#define __NR_utimensat (__NR_Linux + 275)
-#define __NR_signalfd (__NR_Linux + 276)
-#define __NR_timerfd (__NR_Linux + 277)
-#define __NR_eventfd (__NR_Linux + 278)
-#define __NR_fallocate (__NR_Linux + 279)
-#define __NR_timerfd_create (__NR_Linux + 280)
-#define __NR_timerfd_gettime (__NR_Linux + 281)
-#define __NR_timerfd_settime (__NR_Linux + 282)
-#define __NR_signalfd4 (__NR_Linux + 283)
-#define __NR_eventfd2 (__NR_Linux + 284)
-#define __NR_epoll_create1 (__NR_Linux + 285)
-#define __NR_dup3 (__NR_Linux + 286)
-#define __NR_pipe2 (__NR_Linux + 287)
-#define __NR_inotify_init1 (__NR_Linux + 288)
-#define __NR_preadv (__NR_Linux + 289)
-#define __NR_pwritev (__NR_Linux + 290)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291)
-#define __NR_perf_event_open (__NR_Linux + 292)
-#define __NR_accept4 (__NR_Linux + 293)
-#define __NR_recvmmsg (__NR_Linux + 294)
-#define __NR_fanotify_init (__NR_Linux + 295)
-#define __NR_fanotify_mark (__NR_Linux + 296)
-#define __NR_prlimit64 (__NR_Linux + 297)
-#define __NR_name_to_handle_at (__NR_Linux + 298)
-#define __NR_open_by_handle_at (__NR_Linux + 299)
-#define __NR_clock_adjtime (__NR_Linux + 300)
-#define __NR_syncfs (__NR_Linux + 301)
-#define __NR_sendmmsg (__NR_Linux + 302)
-#define __NR_setns (__NR_Linux + 303)
-#define __NR_process_vm_readv (__NR_Linux + 304)
-#define __NR_process_vm_writev (__NR_Linux + 305)
-#define __NR_kcmp (__NR_Linux + 306)
-#define __NR_finit_module (__NR_Linux + 307)
-#define __NR_getdents64 (__NR_Linux + 308)
-#define __NR_sched_setattr (__NR_Linux + 309)
-#define __NR_sched_getattr (__NR_Linux + 310)
-#define __NR_renameat2 (__NR_Linux + 311)
-#define __NR_seccomp (__NR_Linux + 312)
-#define __NR_getrandom (__NR_Linux + 313)
-#define __NR_memfd_create (__NR_Linux + 314)
-#define __NR_bpf (__NR_Linux + 315)
-#define __NR_execveat (__NR_Linux + 316)
-#define __NR_userfaultfd (__NR_Linux + 317)
-#define __NR_membarrier (__NR_Linux + 318)
-#define __NR_mlock2 (__NR_Linux + 319)
-#define __NR_copy_file_range (__NR_Linux + 320)
-#define __NR_preadv2 (__NR_Linux + 321)
-#define __NR_pwritev2 (__NR_Linux + 322)
-#define __NR_pkey_mprotect (__NR_Linux + 323)
-#define __NR_pkey_alloc (__NR_Linux + 324)
-#define __NR_pkey_free (__NR_Linux + 325)
-#define __NR_statx (__NR_Linux + 326)
-#define __NR_rseq (__NR_Linux + 327)
-#define __NR_io_pgetevents (__NR_Linux + 328)
-#define __NR_Linux_syscalls 328
+#include <asm/unistd_n64.h>
 #endif
-#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 328
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 #define __NR_Linux 6000
-#define __NR_read (__NR_Linux + 0)
-#define __NR_write (__NR_Linux + 1)
-#define __NR_open (__NR_Linux + 2)
-#define __NR_close (__NR_Linux + 3)
-#define __NR_stat (__NR_Linux + 4)
-#define __NR_fstat (__NR_Linux + 5)
-#define __NR_lstat (__NR_Linux + 6)
-#define __NR_poll (__NR_Linux + 7)
-#define __NR_lseek (__NR_Linux + 8)
-#define __NR_mmap (__NR_Linux + 9)
-#define __NR_mprotect (__NR_Linux + 10)
-#define __NR_munmap (__NR_Linux + 11)
-#define __NR_brk (__NR_Linux + 12)
-#define __NR_rt_sigaction (__NR_Linux + 13)
-#define __NR_rt_sigprocmask (__NR_Linux + 14)
-#define __NR_ioctl (__NR_Linux + 15)
-#define __NR_pread64 (__NR_Linux + 16)
-#define __NR_pwrite64 (__NR_Linux + 17)
-#define __NR_readv (__NR_Linux + 18)
-#define __NR_writev (__NR_Linux + 19)
-#define __NR_access (__NR_Linux + 20)
-#define __NR_pipe (__NR_Linux + 21)
-#define __NR__newselect (__NR_Linux + 22)
-#define __NR_sched_yield (__NR_Linux + 23)
-#define __NR_mremap (__NR_Linux + 24)
-#define __NR_msync (__NR_Linux + 25)
-#define __NR_mincore (__NR_Linux + 26)
-#define __NR_madvise (__NR_Linux + 27)
-#define __NR_shmget (__NR_Linux + 28)
-#define __NR_shmat (__NR_Linux + 29)
-#define __NR_shmctl (__NR_Linux + 30)
-#define __NR_dup (__NR_Linux + 31)
-#define __NR_dup2 (__NR_Linux + 32)
-#define __NR_pause (__NR_Linux + 33)
-#define __NR_nanosleep (__NR_Linux + 34)
-#define __NR_getitimer (__NR_Linux + 35)
-#define __NR_setitimer (__NR_Linux + 36)
-#define __NR_alarm (__NR_Linux + 37)
-#define __NR_getpid (__NR_Linux + 38)
-#define __NR_sendfile (__NR_Linux + 39)
-#define __NR_socket (__NR_Linux + 40)
-#define __NR_connect (__NR_Linux + 41)
-#define __NR_accept (__NR_Linux + 42)
-#define __NR_sendto (__NR_Linux + 43)
-#define __NR_recvfrom (__NR_Linux + 44)
-#define __NR_sendmsg (__NR_Linux + 45)
-#define __NR_recvmsg (__NR_Linux + 46)
-#define __NR_shutdown (__NR_Linux + 47)
-#define __NR_bind (__NR_Linux + 48)
-#define __NR_listen (__NR_Linux + 49)
-#define __NR_getsockname (__NR_Linux + 50)
-#define __NR_getpeername (__NR_Linux + 51)
-#define __NR_socketpair (__NR_Linux + 52)
-#define __NR_setsockopt (__NR_Linux + 53)
-#define __NR_getsockopt (__NR_Linux + 54)
-#define __NR_clone (__NR_Linux + 55)
-#define __NR_fork (__NR_Linux + 56)
-#define __NR_execve (__NR_Linux + 57)
-#define __NR_exit (__NR_Linux + 58)
-#define __NR_wait4 (__NR_Linux + 59)
-#define __NR_kill (__NR_Linux + 60)
-#define __NR_uname (__NR_Linux + 61)
-#define __NR_semget (__NR_Linux + 62)
-#define __NR_semop (__NR_Linux + 63)
-#define __NR_semctl (__NR_Linux + 64)
-#define __NR_shmdt (__NR_Linux + 65)
-#define __NR_msgget (__NR_Linux + 66)
-#define __NR_msgsnd (__NR_Linux + 67)
-#define __NR_msgrcv (__NR_Linux + 68)
-#define __NR_msgctl (__NR_Linux + 69)
-#define __NR_fcntl (__NR_Linux + 70)
-#define __NR_flock (__NR_Linux + 71)
-#define __NR_fsync (__NR_Linux + 72)
-#define __NR_fdatasync (__NR_Linux + 73)
-#define __NR_truncate (__NR_Linux + 74)
-#define __NR_ftruncate (__NR_Linux + 75)
-#define __NR_getdents (__NR_Linux + 76)
-#define __NR_getcwd (__NR_Linux + 77)
-#define __NR_chdir (__NR_Linux + 78)
-#define __NR_fchdir (__NR_Linux + 79)
-#define __NR_rename (__NR_Linux + 80)
-#define __NR_mkdir (__NR_Linux + 81)
-#define __NR_rmdir (__NR_Linux + 82)
-#define __NR_creat (__NR_Linux + 83)
-#define __NR_link (__NR_Linux + 84)
-#define __NR_unlink (__NR_Linux + 85)
-#define __NR_symlink (__NR_Linux + 86)
-#define __NR_readlink (__NR_Linux + 87)
-#define __NR_chmod (__NR_Linux + 88)
-#define __NR_fchmod (__NR_Linux + 89)
-#define __NR_chown (__NR_Linux + 90)
-#define __NR_fchown (__NR_Linux + 91)
-#define __NR_lchown (__NR_Linux + 92)
-#define __NR_umask (__NR_Linux + 93)
-#define __NR_gettimeofday (__NR_Linux + 94)
-#define __NR_getrlimit (__NR_Linux + 95)
-#define __NR_getrusage (__NR_Linux + 96)
-#define __NR_sysinfo (__NR_Linux + 97)
-#define __NR_times (__NR_Linux + 98)
-#define __NR_ptrace (__NR_Linux + 99)
-#define __NR_getuid (__NR_Linux + 100)
-#define __NR_syslog (__NR_Linux + 101)
-#define __NR_getgid (__NR_Linux + 102)
-#define __NR_setuid (__NR_Linux + 103)
-#define __NR_setgid (__NR_Linux + 104)
-#define __NR_geteuid (__NR_Linux + 105)
-#define __NR_getegid (__NR_Linux + 106)
-#define __NR_setpgid (__NR_Linux + 107)
-#define __NR_getppid (__NR_Linux + 108)
-#define __NR_getpgrp (__NR_Linux + 109)
-#define __NR_setsid (__NR_Linux + 110)
-#define __NR_setreuid (__NR_Linux + 111)
-#define __NR_setregid (__NR_Linux + 112)
-#define __NR_getgroups (__NR_Linux + 113)
-#define __NR_setgroups (__NR_Linux + 114)
-#define __NR_setresuid (__NR_Linux + 115)
-#define __NR_getresuid (__NR_Linux + 116)
-#define __NR_setresgid (__NR_Linux + 117)
-#define __NR_getresgid (__NR_Linux + 118)
-#define __NR_getpgid (__NR_Linux + 119)
-#define __NR_setfsuid (__NR_Linux + 120)
-#define __NR_setfsgid (__NR_Linux + 121)
-#define __NR_getsid (__NR_Linux + 122)
-#define __NR_capget (__NR_Linux + 123)
-#define __NR_capset (__NR_Linux + 124)
-#define __NR_rt_sigpending (__NR_Linux + 125)
-#define __NR_rt_sigtimedwait (__NR_Linux + 126)
-#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
-#define __NR_rt_sigsuspend (__NR_Linux + 128)
-#define __NR_sigaltstack (__NR_Linux + 129)
-#define __NR_utime (__NR_Linux + 130)
-#define __NR_mknod (__NR_Linux + 131)
-#define __NR_personality (__NR_Linux + 132)
-#define __NR_ustat (__NR_Linux + 133)
-#define __NR_statfs (__NR_Linux + 134)
-#define __NR_fstatfs (__NR_Linux + 135)
-#define __NR_sysfs (__NR_Linux + 136)
-#define __NR_getpriority (__NR_Linux + 137)
-#define __NR_setpriority (__NR_Linux + 138)
-#define __NR_sched_setparam (__NR_Linux + 139)
-#define __NR_sched_getparam (__NR_Linux + 140)
-#define __NR_sched_setscheduler (__NR_Linux + 141)
-#define __NR_sched_getscheduler (__NR_Linux + 142)
-#define __NR_sched_get_priority_max (__NR_Linux + 143)
-#define __NR_sched_get_priority_min (__NR_Linux + 144)
-#define __NR_sched_rr_get_interval (__NR_Linux + 145)
-#define __NR_mlock (__NR_Linux + 146)
-#define __NR_munlock (__NR_Linux + 147)
-#define __NR_mlockall (__NR_Linux + 148)
-#define __NR_munlockall (__NR_Linux + 149)
-#define __NR_vhangup (__NR_Linux + 150)
-#define __NR_pivot_root (__NR_Linux + 151)
-#define __NR__sysctl (__NR_Linux + 152)
-#define __NR_prctl (__NR_Linux + 153)
-#define __NR_adjtimex (__NR_Linux + 154)
-#define __NR_setrlimit (__NR_Linux + 155)
-#define __NR_chroot (__NR_Linux + 156)
-#define __NR_sync (__NR_Linux + 157)
-#define __NR_acct (__NR_Linux + 158)
-#define __NR_settimeofday (__NR_Linux + 159)
-#define __NR_mount (__NR_Linux + 160)
-#define __NR_umount2 (__NR_Linux + 161)
-#define __NR_swapon (__NR_Linux + 162)
-#define __NR_swapoff (__NR_Linux + 163)
-#define __NR_reboot (__NR_Linux + 164)
-#define __NR_sethostname (__NR_Linux + 165)
-#define __NR_setdomainname (__NR_Linux + 166)
-#define __NR_create_module (__NR_Linux + 167)
-#define __NR_init_module (__NR_Linux + 168)
-#define __NR_delete_module (__NR_Linux + 169)
-#define __NR_get_kernel_syms (__NR_Linux + 170)
-#define __NR_query_module (__NR_Linux + 171)
-#define __NR_quotactl (__NR_Linux + 172)
-#define __NR_nfsservctl (__NR_Linux + 173)
-#define __NR_getpmsg (__NR_Linux + 174)
-#define __NR_putpmsg (__NR_Linux + 175)
-#define __NR_afs_syscall (__NR_Linux + 176)
-#define __NR_reserved177 (__NR_Linux + 177)
-#define __NR_gettid (__NR_Linux + 178)
-#define __NR_readahead (__NR_Linux + 179)
-#define __NR_setxattr (__NR_Linux + 180)
-#define __NR_lsetxattr (__NR_Linux + 181)
-#define __NR_fsetxattr (__NR_Linux + 182)
-#define __NR_getxattr (__NR_Linux + 183)
-#define __NR_lgetxattr (__NR_Linux + 184)
-#define __NR_fgetxattr (__NR_Linux + 185)
-#define __NR_listxattr (__NR_Linux + 186)
-#define __NR_llistxattr (__NR_Linux + 187)
-#define __NR_flistxattr (__NR_Linux + 188)
-#define __NR_removexattr (__NR_Linux + 189)
-#define __NR_lremovexattr (__NR_Linux + 190)
-#define __NR_fremovexattr (__NR_Linux + 191)
-#define __NR_tkill (__NR_Linux + 192)
-#define __NR_reserved193 (__NR_Linux + 193)
-#define __NR_futex (__NR_Linux + 194)
-#define __NR_sched_setaffinity (__NR_Linux + 195)
-#define __NR_sched_getaffinity (__NR_Linux + 196)
-#define __NR_cacheflush (__NR_Linux + 197)
-#define __NR_cachectl (__NR_Linux + 198)
-#define __NR_sysmips (__NR_Linux + 199)
-#define __NR_io_setup (__NR_Linux + 200)
-#define __NR_io_destroy (__NR_Linux + 201)
-#define __NR_io_getevents (__NR_Linux + 202)
-#define __NR_io_submit (__NR_Linux + 203)
-#define __NR_io_cancel (__NR_Linux + 204)
-#define __NR_exit_group (__NR_Linux + 205)
-#define __NR_lookup_dcookie (__NR_Linux + 206)
-#define __NR_epoll_create (__NR_Linux + 207)
-#define __NR_epoll_ctl (__NR_Linux + 208)
-#define __NR_epoll_wait (__NR_Linux + 209)
-#define __NR_remap_file_pages (__NR_Linux + 210)
-#define __NR_rt_sigreturn (__NR_Linux + 211)
-#define __NR_fcntl64 (__NR_Linux + 212)
-#define __NR_set_tid_address (__NR_Linux + 213)
-#define __NR_restart_syscall (__NR_Linux + 214)
-#define __NR_semtimedop (__NR_Linux + 215)
-#define __NR_fadvise64 (__NR_Linux + 216)
-#define __NR_statfs64 (__NR_Linux + 217)
-#define __NR_fstatfs64 (__NR_Linux + 218)
-#define __NR_sendfile64 (__NR_Linux + 219)
-#define __NR_timer_create (__NR_Linux + 220)
-#define __NR_timer_settime (__NR_Linux + 221)
-#define __NR_timer_gettime (__NR_Linux + 222)
-#define __NR_timer_getoverrun (__NR_Linux + 223)
-#define __NR_timer_delete (__NR_Linux + 224)
-#define __NR_clock_settime (__NR_Linux + 225)
-#define __NR_clock_gettime (__NR_Linux + 226)
-#define __NR_clock_getres (__NR_Linux + 227)
-#define __NR_clock_nanosleep (__NR_Linux + 228)
-#define __NR_tgkill (__NR_Linux + 229)
-#define __NR_utimes (__NR_Linux + 230)
-#define __NR_mbind (__NR_Linux + 231)
-#define __NR_get_mempolicy (__NR_Linux + 232)
-#define __NR_set_mempolicy (__NR_Linux + 233)
-#define __NR_mq_open (__NR_Linux + 234)
-#define __NR_mq_unlink (__NR_Linux + 235)
-#define __NR_mq_timedsend (__NR_Linux + 236)
-#define __NR_mq_timedreceive (__NR_Linux + 237)
-#define __NR_mq_notify (__NR_Linux + 238)
-#define __NR_mq_getsetattr (__NR_Linux + 239)
-#define __NR_vserver (__NR_Linux + 240)
-#define __NR_waitid (__NR_Linux + 241)
-#define __NR_add_key (__NR_Linux + 243)
-#define __NR_request_key (__NR_Linux + 244)
-#define __NR_keyctl (__NR_Linux + 245)
-#define __NR_set_thread_area (__NR_Linux + 246)
-#define __NR_inotify_init (__NR_Linux + 247)
-#define __NR_inotify_add_watch (__NR_Linux + 248)
-#define __NR_inotify_rm_watch (__NR_Linux + 249)
-#define __NR_migrate_pages (__NR_Linux + 250)
-#define __NR_openat (__NR_Linux + 251)
-#define __NR_mkdirat (__NR_Linux + 252)
-#define __NR_mknodat (__NR_Linux + 253)
-#define __NR_fchownat (__NR_Linux + 254)
-#define __NR_futimesat (__NR_Linux + 255)
-#define __NR_newfstatat (__NR_Linux + 256)
-#define __NR_unlinkat (__NR_Linux + 257)
-#define __NR_renameat (__NR_Linux + 258)
-#define __NR_linkat (__NR_Linux + 259)
-#define __NR_symlinkat (__NR_Linux + 260)
-#define __NR_readlinkat (__NR_Linux + 261)
-#define __NR_fchmodat (__NR_Linux + 262)
-#define __NR_faccessat (__NR_Linux + 263)
-#define __NR_pselect6 (__NR_Linux + 264)
-#define __NR_ppoll (__NR_Linux + 265)
-#define __NR_unshare (__NR_Linux + 266)
-#define __NR_splice (__NR_Linux + 267)
-#define __NR_sync_file_range (__NR_Linux + 268)
-#define __NR_tee (__NR_Linux + 269)
-#define __NR_vmsplice (__NR_Linux + 270)
-#define __NR_move_pages (__NR_Linux + 271)
-#define __NR_set_robust_list (__NR_Linux + 272)
-#define __NR_get_robust_list (__NR_Linux + 273)
-#define __NR_kexec_load (__NR_Linux + 274)
-#define __NR_getcpu (__NR_Linux + 275)
-#define __NR_epoll_pwait (__NR_Linux + 276)
-#define __NR_ioprio_set (__NR_Linux + 277)
-#define __NR_ioprio_get (__NR_Linux + 278)
-#define __NR_utimensat (__NR_Linux + 279)
-#define __NR_signalfd (__NR_Linux + 280)
-#define __NR_timerfd (__NR_Linux + 281)
-#define __NR_eventfd (__NR_Linux + 282)
-#define __NR_fallocate (__NR_Linux + 283)
-#define __NR_timerfd_create (__NR_Linux + 284)
-#define __NR_timerfd_gettime (__NR_Linux + 285)
-#define __NR_timerfd_settime (__NR_Linux + 286)
-#define __NR_signalfd4 (__NR_Linux + 287)
-#define __NR_eventfd2 (__NR_Linux + 288)
-#define __NR_epoll_create1 (__NR_Linux + 289)
-#define __NR_dup3 (__NR_Linux + 290)
-#define __NR_pipe2 (__NR_Linux + 291)
-#define __NR_inotify_init1 (__NR_Linux + 292)
-#define __NR_preadv (__NR_Linux + 293)
-#define __NR_pwritev (__NR_Linux + 294)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295)
-#define __NR_perf_event_open (__NR_Linux + 296)
-#define __NR_accept4 (__NR_Linux + 297)
-#define __NR_recvmmsg (__NR_Linux + 298)
-#define __NR_getdents64 (__NR_Linux + 299)
-#define __NR_fanotify_init (__NR_Linux + 300)
-#define __NR_fanotify_mark (__NR_Linux + 301)
-#define __NR_prlimit64 (__NR_Linux + 302)
-#define __NR_name_to_handle_at (__NR_Linux + 303)
-#define __NR_open_by_handle_at (__NR_Linux + 304)
-#define __NR_clock_adjtime (__NR_Linux + 305)
-#define __NR_syncfs (__NR_Linux + 306)
-#define __NR_sendmmsg (__NR_Linux + 307)
-#define __NR_setns (__NR_Linux + 308)
-#define __NR_process_vm_readv (__NR_Linux + 309)
-#define __NR_process_vm_writev (__NR_Linux + 310)
-#define __NR_kcmp (__NR_Linux + 311)
-#define __NR_finit_module (__NR_Linux + 312)
-#define __NR_sched_setattr (__NR_Linux + 313)
-#define __NR_sched_getattr (__NR_Linux + 314)
-#define __NR_renameat2 (__NR_Linux + 315)
-#define __NR_seccomp (__NR_Linux + 316)
-#define __NR_getrandom (__NR_Linux + 317)
-#define __NR_memfd_create (__NR_Linux + 318)
-#define __NR_bpf (__NR_Linux + 319)
-#define __NR_execveat (__NR_Linux + 320)
-#define __NR_userfaultfd (__NR_Linux + 321)
-#define __NR_membarrier (__NR_Linux + 322)
-#define __NR_mlock2 (__NR_Linux + 323)
-#define __NR_copy_file_range (__NR_Linux + 324)
-#define __NR_preadv2 (__NR_Linux + 325)
-#define __NR_pwritev2 (__NR_Linux + 326)
-#define __NR_pkey_mprotect (__NR_Linux + 327)
-#define __NR_pkey_alloc (__NR_Linux + 328)
-#define __NR_pkey_free (__NR_Linux + 329)
-#define __NR_statx (__NR_Linux + 330)
-#define __NR_rseq (__NR_Linux + 331)
-#define __NR_io_pgetevents (__NR_Linux + 332)
-#define __NR_Linux_syscalls 332
+#include <asm/unistd_n32.h>
 #endif
-#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 332
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_n32.h b/libc/kernel/uapi/asm-mips/asm/unistd_n32.h
new file mode 100644
index 0000000..a72d9d2
--- /dev/null
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_n32.h
@@ -0,0 +1,353 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_MIPS_UNISTD_N32_H
+#define _UAPI_ASM_MIPS_UNISTD_N32_H
+#define __NR_read (__NR_Linux + 0)
+#define __NR_write (__NR_Linux + 1)
+#define __NR_open (__NR_Linux + 2)
+#define __NR_close (__NR_Linux + 3)
+#define __NR_stat (__NR_Linux + 4)
+#define __NR_fstat (__NR_Linux + 5)
+#define __NR_lstat (__NR_Linux + 6)
+#define __NR_poll (__NR_Linux + 7)
+#define __NR_lseek (__NR_Linux + 8)
+#define __NR_mmap (__NR_Linux + 9)
+#define __NR_mprotect (__NR_Linux + 10)
+#define __NR_munmap (__NR_Linux + 11)
+#define __NR_brk (__NR_Linux + 12)
+#define __NR_rt_sigaction (__NR_Linux + 13)
+#define __NR_rt_sigprocmask (__NR_Linux + 14)
+#define __NR_ioctl (__NR_Linux + 15)
+#define __NR_pread64 (__NR_Linux + 16)
+#define __NR_pwrite64 (__NR_Linux + 17)
+#define __NR_readv (__NR_Linux + 18)
+#define __NR_writev (__NR_Linux + 19)
+#define __NR_access (__NR_Linux + 20)
+#define __NR_pipe (__NR_Linux + 21)
+#define __NR__newselect (__NR_Linux + 22)
+#define __NR_sched_yield (__NR_Linux + 23)
+#define __NR_mremap (__NR_Linux + 24)
+#define __NR_msync (__NR_Linux + 25)
+#define __NR_mincore (__NR_Linux + 26)
+#define __NR_madvise (__NR_Linux + 27)
+#define __NR_shmget (__NR_Linux + 28)
+#define __NR_shmat (__NR_Linux + 29)
+#define __NR_shmctl (__NR_Linux + 30)
+#define __NR_dup (__NR_Linux + 31)
+#define __NR_dup2 (__NR_Linux + 32)
+#define __NR_pause (__NR_Linux + 33)
+#define __NR_nanosleep (__NR_Linux + 34)
+#define __NR_getitimer (__NR_Linux + 35)
+#define __NR_setitimer (__NR_Linux + 36)
+#define __NR_alarm (__NR_Linux + 37)
+#define __NR_getpid (__NR_Linux + 38)
+#define __NR_sendfile (__NR_Linux + 39)
+#define __NR_socket (__NR_Linux + 40)
+#define __NR_connect (__NR_Linux + 41)
+#define __NR_accept (__NR_Linux + 42)
+#define __NR_sendto (__NR_Linux + 43)
+#define __NR_recvfrom (__NR_Linux + 44)
+#define __NR_sendmsg (__NR_Linux + 45)
+#define __NR_recvmsg (__NR_Linux + 46)
+#define __NR_shutdown (__NR_Linux + 47)
+#define __NR_bind (__NR_Linux + 48)
+#define __NR_listen (__NR_Linux + 49)
+#define __NR_getsockname (__NR_Linux + 50)
+#define __NR_getpeername (__NR_Linux + 51)
+#define __NR_socketpair (__NR_Linux + 52)
+#define __NR_setsockopt (__NR_Linux + 53)
+#define __NR_getsockopt (__NR_Linux + 54)
+#define __NR_clone (__NR_Linux + 55)
+#define __NR_fork (__NR_Linux + 56)
+#define __NR_execve (__NR_Linux + 57)
+#define __NR_exit (__NR_Linux + 58)
+#define __NR_wait4 (__NR_Linux + 59)
+#define __NR_kill (__NR_Linux + 60)
+#define __NR_uname (__NR_Linux + 61)
+#define __NR_semget (__NR_Linux + 62)
+#define __NR_semop (__NR_Linux + 63)
+#define __NR_semctl (__NR_Linux + 64)
+#define __NR_shmdt (__NR_Linux + 65)
+#define __NR_msgget (__NR_Linux + 66)
+#define __NR_msgsnd (__NR_Linux + 67)
+#define __NR_msgrcv (__NR_Linux + 68)
+#define __NR_msgctl (__NR_Linux + 69)
+#define __NR_fcntl (__NR_Linux + 70)
+#define __NR_flock (__NR_Linux + 71)
+#define __NR_fsync (__NR_Linux + 72)
+#define __NR_fdatasync (__NR_Linux + 73)
+#define __NR_truncate (__NR_Linux + 74)
+#define __NR_ftruncate (__NR_Linux + 75)
+#define __NR_getdents (__NR_Linux + 76)
+#define __NR_getcwd (__NR_Linux + 77)
+#define __NR_chdir (__NR_Linux + 78)
+#define __NR_fchdir (__NR_Linux + 79)
+#define __NR_rename (__NR_Linux + 80)
+#define __NR_mkdir (__NR_Linux + 81)
+#define __NR_rmdir (__NR_Linux + 82)
+#define __NR_creat (__NR_Linux + 83)
+#define __NR_link (__NR_Linux + 84)
+#define __NR_unlink (__NR_Linux + 85)
+#define __NR_symlink (__NR_Linux + 86)
+#define __NR_readlink (__NR_Linux + 87)
+#define __NR_chmod (__NR_Linux + 88)
+#define __NR_fchmod (__NR_Linux + 89)
+#define __NR_chown (__NR_Linux + 90)
+#define __NR_fchown (__NR_Linux + 91)
+#define __NR_lchown (__NR_Linux + 92)
+#define __NR_umask (__NR_Linux + 93)
+#define __NR_gettimeofday (__NR_Linux + 94)
+#define __NR_getrlimit (__NR_Linux + 95)
+#define __NR_getrusage (__NR_Linux + 96)
+#define __NR_sysinfo (__NR_Linux + 97)
+#define __NR_times (__NR_Linux + 98)
+#define __NR_ptrace (__NR_Linux + 99)
+#define __NR_getuid (__NR_Linux + 100)
+#define __NR_syslog (__NR_Linux + 101)
+#define __NR_getgid (__NR_Linux + 102)
+#define __NR_setuid (__NR_Linux + 103)
+#define __NR_setgid (__NR_Linux + 104)
+#define __NR_geteuid (__NR_Linux + 105)
+#define __NR_getegid (__NR_Linux + 106)
+#define __NR_setpgid (__NR_Linux + 107)
+#define __NR_getppid (__NR_Linux + 108)
+#define __NR_getpgrp (__NR_Linux + 109)
+#define __NR_setsid (__NR_Linux + 110)
+#define __NR_setreuid (__NR_Linux + 111)
+#define __NR_setregid (__NR_Linux + 112)
+#define __NR_getgroups (__NR_Linux + 113)
+#define __NR_setgroups (__NR_Linux + 114)
+#define __NR_setresuid (__NR_Linux + 115)
+#define __NR_getresuid (__NR_Linux + 116)
+#define __NR_setresgid (__NR_Linux + 117)
+#define __NR_getresgid (__NR_Linux + 118)
+#define __NR_getpgid (__NR_Linux + 119)
+#define __NR_setfsuid (__NR_Linux + 120)
+#define __NR_setfsgid (__NR_Linux + 121)
+#define __NR_getsid (__NR_Linux + 122)
+#define __NR_capget (__NR_Linux + 123)
+#define __NR_capset (__NR_Linux + 124)
+#define __NR_rt_sigpending (__NR_Linux + 125)
+#define __NR_rt_sigtimedwait (__NR_Linux + 126)
+#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
+#define __NR_rt_sigsuspend (__NR_Linux + 128)
+#define __NR_sigaltstack (__NR_Linux + 129)
+#define __NR_utime (__NR_Linux + 130)
+#define __NR_mknod (__NR_Linux + 131)
+#define __NR_personality (__NR_Linux + 132)
+#define __NR_ustat (__NR_Linux + 133)
+#define __NR_statfs (__NR_Linux + 134)
+#define __NR_fstatfs (__NR_Linux + 135)
+#define __NR_sysfs (__NR_Linux + 136)
+#define __NR_getpriority (__NR_Linux + 137)
+#define __NR_setpriority (__NR_Linux + 138)
+#define __NR_sched_setparam (__NR_Linux + 139)
+#define __NR_sched_getparam (__NR_Linux + 140)
+#define __NR_sched_setscheduler (__NR_Linux + 141)
+#define __NR_sched_getscheduler (__NR_Linux + 142)
+#define __NR_sched_get_priority_max (__NR_Linux + 143)
+#define __NR_sched_get_priority_min (__NR_Linux + 144)
+#define __NR_sched_rr_get_interval (__NR_Linux + 145)
+#define __NR_mlock (__NR_Linux + 146)
+#define __NR_munlock (__NR_Linux + 147)
+#define __NR_mlockall (__NR_Linux + 148)
+#define __NR_munlockall (__NR_Linux + 149)
+#define __NR_vhangup (__NR_Linux + 150)
+#define __NR_pivot_root (__NR_Linux + 151)
+#define __NR__sysctl (__NR_Linux + 152)
+#define __NR_prctl (__NR_Linux + 153)
+#define __NR_adjtimex (__NR_Linux + 154)
+#define __NR_setrlimit (__NR_Linux + 155)
+#define __NR_chroot (__NR_Linux + 156)
+#define __NR_sync (__NR_Linux + 157)
+#define __NR_acct (__NR_Linux + 158)
+#define __NR_settimeofday (__NR_Linux + 159)
+#define __NR_mount (__NR_Linux + 160)
+#define __NR_umount2 (__NR_Linux + 161)
+#define __NR_swapon (__NR_Linux + 162)
+#define __NR_swapoff (__NR_Linux + 163)
+#define __NR_reboot (__NR_Linux + 164)
+#define __NR_sethostname (__NR_Linux + 165)
+#define __NR_setdomainname (__NR_Linux + 166)
+#define __NR_create_module (__NR_Linux + 167)
+#define __NR_init_module (__NR_Linux + 168)
+#define __NR_delete_module (__NR_Linux + 169)
+#define __NR_get_kernel_syms (__NR_Linux + 170)
+#define __NR_query_module (__NR_Linux + 171)
+#define __NR_quotactl (__NR_Linux + 172)
+#define __NR_nfsservctl (__NR_Linux + 173)
+#define __NR_getpmsg (__NR_Linux + 174)
+#define __NR_putpmsg (__NR_Linux + 175)
+#define __NR_afs_syscall (__NR_Linux + 176)
+#define __NR_reserved177 (__NR_Linux + 177)
+#define __NR_gettid (__NR_Linux + 178)
+#define __NR_readahead (__NR_Linux + 179)
+#define __NR_setxattr (__NR_Linux + 180)
+#define __NR_lsetxattr (__NR_Linux + 181)
+#define __NR_fsetxattr (__NR_Linux + 182)
+#define __NR_getxattr (__NR_Linux + 183)
+#define __NR_lgetxattr (__NR_Linux + 184)
+#define __NR_fgetxattr (__NR_Linux + 185)
+#define __NR_listxattr (__NR_Linux + 186)
+#define __NR_llistxattr (__NR_Linux + 187)
+#define __NR_flistxattr (__NR_Linux + 188)
+#define __NR_removexattr (__NR_Linux + 189)
+#define __NR_lremovexattr (__NR_Linux + 190)
+#define __NR_fremovexattr (__NR_Linux + 191)
+#define __NR_tkill (__NR_Linux + 192)
+#define __NR_reserved193 (__NR_Linux + 193)
+#define __NR_futex (__NR_Linux + 194)
+#define __NR_sched_setaffinity (__NR_Linux + 195)
+#define __NR_sched_getaffinity (__NR_Linux + 196)
+#define __NR_cacheflush (__NR_Linux + 197)
+#define __NR_cachectl (__NR_Linux + 198)
+#define __NR_sysmips (__NR_Linux + 199)
+#define __NR_io_setup (__NR_Linux + 200)
+#define __NR_io_destroy (__NR_Linux + 201)
+#define __NR_io_getevents (__NR_Linux + 202)
+#define __NR_io_submit (__NR_Linux + 203)
+#define __NR_io_cancel (__NR_Linux + 204)
+#define __NR_exit_group (__NR_Linux + 205)
+#define __NR_lookup_dcookie (__NR_Linux + 206)
+#define __NR_epoll_create (__NR_Linux + 207)
+#define __NR_epoll_ctl (__NR_Linux + 208)
+#define __NR_epoll_wait (__NR_Linux + 209)
+#define __NR_remap_file_pages (__NR_Linux + 210)
+#define __NR_rt_sigreturn (__NR_Linux + 211)
+#define __NR_fcntl64 (__NR_Linux + 212)
+#define __NR_set_tid_address (__NR_Linux + 213)
+#define __NR_restart_syscall (__NR_Linux + 214)
+#define __NR_semtimedop (__NR_Linux + 215)
+#define __NR_fadvise64 (__NR_Linux + 216)
+#define __NR_statfs64 (__NR_Linux + 217)
+#define __NR_fstatfs64 (__NR_Linux + 218)
+#define __NR_sendfile64 (__NR_Linux + 219)
+#define __NR_timer_create (__NR_Linux + 220)
+#define __NR_timer_settime (__NR_Linux + 221)
+#define __NR_timer_gettime (__NR_Linux + 222)
+#define __NR_timer_getoverrun (__NR_Linux + 223)
+#define __NR_timer_delete (__NR_Linux + 224)
+#define __NR_clock_settime (__NR_Linux + 225)
+#define __NR_clock_gettime (__NR_Linux + 226)
+#define __NR_clock_getres (__NR_Linux + 227)
+#define __NR_clock_nanosleep (__NR_Linux + 228)
+#define __NR_tgkill (__NR_Linux + 229)
+#define __NR_utimes (__NR_Linux + 230)
+#define __NR_mbind (__NR_Linux + 231)
+#define __NR_get_mempolicy (__NR_Linux + 232)
+#define __NR_set_mempolicy (__NR_Linux + 233)
+#define __NR_mq_open (__NR_Linux + 234)
+#define __NR_mq_unlink (__NR_Linux + 235)
+#define __NR_mq_timedsend (__NR_Linux + 236)
+#define __NR_mq_timedreceive (__NR_Linux + 237)
+#define __NR_mq_notify (__NR_Linux + 238)
+#define __NR_mq_getsetattr (__NR_Linux + 239)
+#define __NR_vserver (__NR_Linux + 240)
+#define __NR_waitid (__NR_Linux + 241)
+#define __NR_add_key (__NR_Linux + 243)
+#define __NR_request_key (__NR_Linux + 244)
+#define __NR_keyctl (__NR_Linux + 245)
+#define __NR_set_thread_area (__NR_Linux + 246)
+#define __NR_inotify_init (__NR_Linux + 247)
+#define __NR_inotify_add_watch (__NR_Linux + 248)
+#define __NR_inotify_rm_watch (__NR_Linux + 249)
+#define __NR_migrate_pages (__NR_Linux + 250)
+#define __NR_openat (__NR_Linux + 251)
+#define __NR_mkdirat (__NR_Linux + 252)
+#define __NR_mknodat (__NR_Linux + 253)
+#define __NR_fchownat (__NR_Linux + 254)
+#define __NR_futimesat (__NR_Linux + 255)
+#define __NR_newfstatat (__NR_Linux + 256)
+#define __NR_unlinkat (__NR_Linux + 257)
+#define __NR_renameat (__NR_Linux + 258)
+#define __NR_linkat (__NR_Linux + 259)
+#define __NR_symlinkat (__NR_Linux + 260)
+#define __NR_readlinkat (__NR_Linux + 261)
+#define __NR_fchmodat (__NR_Linux + 262)
+#define __NR_faccessat (__NR_Linux + 263)
+#define __NR_pselect6 (__NR_Linux + 264)
+#define __NR_ppoll (__NR_Linux + 265)
+#define __NR_unshare (__NR_Linux + 266)
+#define __NR_splice (__NR_Linux + 267)
+#define __NR_sync_file_range (__NR_Linux + 268)
+#define __NR_tee (__NR_Linux + 269)
+#define __NR_vmsplice (__NR_Linux + 270)
+#define __NR_move_pages (__NR_Linux + 271)
+#define __NR_set_robust_list (__NR_Linux + 272)
+#define __NR_get_robust_list (__NR_Linux + 273)
+#define __NR_kexec_load (__NR_Linux + 274)
+#define __NR_getcpu (__NR_Linux + 275)
+#define __NR_epoll_pwait (__NR_Linux + 276)
+#define __NR_ioprio_set (__NR_Linux + 277)
+#define __NR_ioprio_get (__NR_Linux + 278)
+#define __NR_utimensat (__NR_Linux + 279)
+#define __NR_signalfd (__NR_Linux + 280)
+#define __NR_timerfd (__NR_Linux + 281)
+#define __NR_eventfd (__NR_Linux + 282)
+#define __NR_fallocate (__NR_Linux + 283)
+#define __NR_timerfd_create (__NR_Linux + 284)
+#define __NR_timerfd_gettime (__NR_Linux + 285)
+#define __NR_timerfd_settime (__NR_Linux + 286)
+#define __NR_signalfd4 (__NR_Linux + 287)
+#define __NR_eventfd2 (__NR_Linux + 288)
+#define __NR_epoll_create1 (__NR_Linux + 289)
+#define __NR_dup3 (__NR_Linux + 290)
+#define __NR_pipe2 (__NR_Linux + 291)
+#define __NR_inotify_init1 (__NR_Linux + 292)
+#define __NR_preadv (__NR_Linux + 293)
+#define __NR_pwritev (__NR_Linux + 294)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295)
+#define __NR_perf_event_open (__NR_Linux + 296)
+#define __NR_accept4 (__NR_Linux + 297)
+#define __NR_recvmmsg (__NR_Linux + 298)
+#define __NR_getdents64 (__NR_Linux + 299)
+#define __NR_fanotify_init (__NR_Linux + 300)
+#define __NR_fanotify_mark (__NR_Linux + 301)
+#define __NR_prlimit64 (__NR_Linux + 302)
+#define __NR_name_to_handle_at (__NR_Linux + 303)
+#define __NR_open_by_handle_at (__NR_Linux + 304)
+#define __NR_clock_adjtime (__NR_Linux + 305)
+#define __NR_syncfs (__NR_Linux + 306)
+#define __NR_sendmmsg (__NR_Linux + 307)
+#define __NR_setns (__NR_Linux + 308)
+#define __NR_process_vm_readv (__NR_Linux + 309)
+#define __NR_process_vm_writev (__NR_Linux + 310)
+#define __NR_kcmp (__NR_Linux + 311)
+#define __NR_finit_module (__NR_Linux + 312)
+#define __NR_sched_setattr (__NR_Linux + 313)
+#define __NR_sched_getattr (__NR_Linux + 314)
+#define __NR_renameat2 (__NR_Linux + 315)
+#define __NR_seccomp (__NR_Linux + 316)
+#define __NR_getrandom (__NR_Linux + 317)
+#define __NR_memfd_create (__NR_Linux + 318)
+#define __NR_bpf (__NR_Linux + 319)
+#define __NR_execveat (__NR_Linux + 320)
+#define __NR_userfaultfd (__NR_Linux + 321)
+#define __NR_membarrier (__NR_Linux + 322)
+#define __NR_mlock2 (__NR_Linux + 323)
+#define __NR_copy_file_range (__NR_Linux + 324)
+#define __NR_preadv2 (__NR_Linux + 325)
+#define __NR_pwritev2 (__NR_Linux + 326)
+#define __NR_pkey_mprotect (__NR_Linux + 327)
+#define __NR_pkey_alloc (__NR_Linux + 328)
+#define __NR_pkey_free (__NR_Linux + 329)
+#define __NR_statx (__NR_Linux + 330)
+#define __NR_rseq (__NR_Linux + 331)
+#define __NR_io_pgetevents (__NR_Linux + 332)
+#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_n64.h b/libc/kernel/uapi/asm-mips/asm/unistd_n64.h
new file mode 100644
index 0000000..5ea908a
--- /dev/null
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_n64.h
@@ -0,0 +1,349 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_MIPS_UNISTD_N64_H
+#define _UAPI_ASM_MIPS_UNISTD_N64_H
+#define __NR_read (__NR_Linux + 0)
+#define __NR_write (__NR_Linux + 1)
+#define __NR_open (__NR_Linux + 2)
+#define __NR_close (__NR_Linux + 3)
+#define __NR_stat (__NR_Linux + 4)
+#define __NR_fstat (__NR_Linux + 5)
+#define __NR_lstat (__NR_Linux + 6)
+#define __NR_poll (__NR_Linux + 7)
+#define __NR_lseek (__NR_Linux + 8)
+#define __NR_mmap (__NR_Linux + 9)
+#define __NR_mprotect (__NR_Linux + 10)
+#define __NR_munmap (__NR_Linux + 11)
+#define __NR_brk (__NR_Linux + 12)
+#define __NR_rt_sigaction (__NR_Linux + 13)
+#define __NR_rt_sigprocmask (__NR_Linux + 14)
+#define __NR_ioctl (__NR_Linux + 15)
+#define __NR_pread64 (__NR_Linux + 16)
+#define __NR_pwrite64 (__NR_Linux + 17)
+#define __NR_readv (__NR_Linux + 18)
+#define __NR_writev (__NR_Linux + 19)
+#define __NR_access (__NR_Linux + 20)
+#define __NR_pipe (__NR_Linux + 21)
+#define __NR__newselect (__NR_Linux + 22)
+#define __NR_sched_yield (__NR_Linux + 23)
+#define __NR_mremap (__NR_Linux + 24)
+#define __NR_msync (__NR_Linux + 25)
+#define __NR_mincore (__NR_Linux + 26)
+#define __NR_madvise (__NR_Linux + 27)
+#define __NR_shmget (__NR_Linux + 28)
+#define __NR_shmat (__NR_Linux + 29)
+#define __NR_shmctl (__NR_Linux + 30)
+#define __NR_dup (__NR_Linux + 31)
+#define __NR_dup2 (__NR_Linux + 32)
+#define __NR_pause (__NR_Linux + 33)
+#define __NR_nanosleep (__NR_Linux + 34)
+#define __NR_getitimer (__NR_Linux + 35)
+#define __NR_setitimer (__NR_Linux + 36)
+#define __NR_alarm (__NR_Linux + 37)
+#define __NR_getpid (__NR_Linux + 38)
+#define __NR_sendfile (__NR_Linux + 39)
+#define __NR_socket (__NR_Linux + 40)
+#define __NR_connect (__NR_Linux + 41)
+#define __NR_accept (__NR_Linux + 42)
+#define __NR_sendto (__NR_Linux + 43)
+#define __NR_recvfrom (__NR_Linux + 44)
+#define __NR_sendmsg (__NR_Linux + 45)
+#define __NR_recvmsg (__NR_Linux + 46)
+#define __NR_shutdown (__NR_Linux + 47)
+#define __NR_bind (__NR_Linux + 48)
+#define __NR_listen (__NR_Linux + 49)
+#define __NR_getsockname (__NR_Linux + 50)
+#define __NR_getpeername (__NR_Linux + 51)
+#define __NR_socketpair (__NR_Linux + 52)
+#define __NR_setsockopt (__NR_Linux + 53)
+#define __NR_getsockopt (__NR_Linux + 54)
+#define __NR_clone (__NR_Linux + 55)
+#define __NR_fork (__NR_Linux + 56)
+#define __NR_execve (__NR_Linux + 57)
+#define __NR_exit (__NR_Linux + 58)
+#define __NR_wait4 (__NR_Linux + 59)
+#define __NR_kill (__NR_Linux + 60)
+#define __NR_uname (__NR_Linux + 61)
+#define __NR_semget (__NR_Linux + 62)
+#define __NR_semop (__NR_Linux + 63)
+#define __NR_semctl (__NR_Linux + 64)
+#define __NR_shmdt (__NR_Linux + 65)
+#define __NR_msgget (__NR_Linux + 66)
+#define __NR_msgsnd (__NR_Linux + 67)
+#define __NR_msgrcv (__NR_Linux + 68)
+#define __NR_msgctl (__NR_Linux + 69)
+#define __NR_fcntl (__NR_Linux + 70)
+#define __NR_flock (__NR_Linux + 71)
+#define __NR_fsync (__NR_Linux + 72)
+#define __NR_fdatasync (__NR_Linux + 73)
+#define __NR_truncate (__NR_Linux + 74)
+#define __NR_ftruncate (__NR_Linux + 75)
+#define __NR_getdents (__NR_Linux + 76)
+#define __NR_getcwd (__NR_Linux + 77)
+#define __NR_chdir (__NR_Linux + 78)
+#define __NR_fchdir (__NR_Linux + 79)
+#define __NR_rename (__NR_Linux + 80)
+#define __NR_mkdir (__NR_Linux + 81)
+#define __NR_rmdir (__NR_Linux + 82)
+#define __NR_creat (__NR_Linux + 83)
+#define __NR_link (__NR_Linux + 84)
+#define __NR_unlink (__NR_Linux + 85)
+#define __NR_symlink (__NR_Linux + 86)
+#define __NR_readlink (__NR_Linux + 87)
+#define __NR_chmod (__NR_Linux + 88)
+#define __NR_fchmod (__NR_Linux + 89)
+#define __NR_chown (__NR_Linux + 90)
+#define __NR_fchown (__NR_Linux + 91)
+#define __NR_lchown (__NR_Linux + 92)
+#define __NR_umask (__NR_Linux + 93)
+#define __NR_gettimeofday (__NR_Linux + 94)
+#define __NR_getrlimit (__NR_Linux + 95)
+#define __NR_getrusage (__NR_Linux + 96)
+#define __NR_sysinfo (__NR_Linux + 97)
+#define __NR_times (__NR_Linux + 98)
+#define __NR_ptrace (__NR_Linux + 99)
+#define __NR_getuid (__NR_Linux + 100)
+#define __NR_syslog (__NR_Linux + 101)
+#define __NR_getgid (__NR_Linux + 102)
+#define __NR_setuid (__NR_Linux + 103)
+#define __NR_setgid (__NR_Linux + 104)
+#define __NR_geteuid (__NR_Linux + 105)
+#define __NR_getegid (__NR_Linux + 106)
+#define __NR_setpgid (__NR_Linux + 107)
+#define __NR_getppid (__NR_Linux + 108)
+#define __NR_getpgrp (__NR_Linux + 109)
+#define __NR_setsid (__NR_Linux + 110)
+#define __NR_setreuid (__NR_Linux + 111)
+#define __NR_setregid (__NR_Linux + 112)
+#define __NR_getgroups (__NR_Linux + 113)
+#define __NR_setgroups (__NR_Linux + 114)
+#define __NR_setresuid (__NR_Linux + 115)
+#define __NR_getresuid (__NR_Linux + 116)
+#define __NR_setresgid (__NR_Linux + 117)
+#define __NR_getresgid (__NR_Linux + 118)
+#define __NR_getpgid (__NR_Linux + 119)
+#define __NR_setfsuid (__NR_Linux + 120)
+#define __NR_setfsgid (__NR_Linux + 121)
+#define __NR_getsid (__NR_Linux + 122)
+#define __NR_capget (__NR_Linux + 123)
+#define __NR_capset (__NR_Linux + 124)
+#define __NR_rt_sigpending (__NR_Linux + 125)
+#define __NR_rt_sigtimedwait (__NR_Linux + 126)
+#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
+#define __NR_rt_sigsuspend (__NR_Linux + 128)
+#define __NR_sigaltstack (__NR_Linux + 129)
+#define __NR_utime (__NR_Linux + 130)
+#define __NR_mknod (__NR_Linux + 131)
+#define __NR_personality (__NR_Linux + 132)
+#define __NR_ustat (__NR_Linux + 133)
+#define __NR_statfs (__NR_Linux + 134)
+#define __NR_fstatfs (__NR_Linux + 135)
+#define __NR_sysfs (__NR_Linux + 136)
+#define __NR_getpriority (__NR_Linux + 137)
+#define __NR_setpriority (__NR_Linux + 138)
+#define __NR_sched_setparam (__NR_Linux + 139)
+#define __NR_sched_getparam (__NR_Linux + 140)
+#define __NR_sched_setscheduler (__NR_Linux + 141)
+#define __NR_sched_getscheduler (__NR_Linux + 142)
+#define __NR_sched_get_priority_max (__NR_Linux + 143)
+#define __NR_sched_get_priority_min (__NR_Linux + 144)
+#define __NR_sched_rr_get_interval (__NR_Linux + 145)
+#define __NR_mlock (__NR_Linux + 146)
+#define __NR_munlock (__NR_Linux + 147)
+#define __NR_mlockall (__NR_Linux + 148)
+#define __NR_munlockall (__NR_Linux + 149)
+#define __NR_vhangup (__NR_Linux + 150)
+#define __NR_pivot_root (__NR_Linux + 151)
+#define __NR__sysctl (__NR_Linux + 152)
+#define __NR_prctl (__NR_Linux + 153)
+#define __NR_adjtimex (__NR_Linux + 154)
+#define __NR_setrlimit (__NR_Linux + 155)
+#define __NR_chroot (__NR_Linux + 156)
+#define __NR_sync (__NR_Linux + 157)
+#define __NR_acct (__NR_Linux + 158)
+#define __NR_settimeofday (__NR_Linux + 159)
+#define __NR_mount (__NR_Linux + 160)
+#define __NR_umount2 (__NR_Linux + 161)
+#define __NR_swapon (__NR_Linux + 162)
+#define __NR_swapoff (__NR_Linux + 163)
+#define __NR_reboot (__NR_Linux + 164)
+#define __NR_sethostname (__NR_Linux + 165)
+#define __NR_setdomainname (__NR_Linux + 166)
+#define __NR_create_module (__NR_Linux + 167)
+#define __NR_init_module (__NR_Linux + 168)
+#define __NR_delete_module (__NR_Linux + 169)
+#define __NR_get_kernel_syms (__NR_Linux + 170)
+#define __NR_query_module (__NR_Linux + 171)
+#define __NR_quotactl (__NR_Linux + 172)
+#define __NR_nfsservctl (__NR_Linux + 173)
+#define __NR_getpmsg (__NR_Linux + 174)
+#define __NR_putpmsg (__NR_Linux + 175)
+#define __NR_afs_syscall (__NR_Linux + 176)
+#define __NR_reserved177 (__NR_Linux + 177)
+#define __NR_gettid (__NR_Linux + 178)
+#define __NR_readahead (__NR_Linux + 179)
+#define __NR_setxattr (__NR_Linux + 180)
+#define __NR_lsetxattr (__NR_Linux + 181)
+#define __NR_fsetxattr (__NR_Linux + 182)
+#define __NR_getxattr (__NR_Linux + 183)
+#define __NR_lgetxattr (__NR_Linux + 184)
+#define __NR_fgetxattr (__NR_Linux + 185)
+#define __NR_listxattr (__NR_Linux + 186)
+#define __NR_llistxattr (__NR_Linux + 187)
+#define __NR_flistxattr (__NR_Linux + 188)
+#define __NR_removexattr (__NR_Linux + 189)
+#define __NR_lremovexattr (__NR_Linux + 190)
+#define __NR_fremovexattr (__NR_Linux + 191)
+#define __NR_tkill (__NR_Linux + 192)
+#define __NR_reserved193 (__NR_Linux + 193)
+#define __NR_futex (__NR_Linux + 194)
+#define __NR_sched_setaffinity (__NR_Linux + 195)
+#define __NR_sched_getaffinity (__NR_Linux + 196)
+#define __NR_cacheflush (__NR_Linux + 197)
+#define __NR_cachectl (__NR_Linux + 198)
+#define __NR_sysmips (__NR_Linux + 199)
+#define __NR_io_setup (__NR_Linux + 200)
+#define __NR_io_destroy (__NR_Linux + 201)
+#define __NR_io_getevents (__NR_Linux + 202)
+#define __NR_io_submit (__NR_Linux + 203)
+#define __NR_io_cancel (__NR_Linux + 204)
+#define __NR_exit_group (__NR_Linux + 205)
+#define __NR_lookup_dcookie (__NR_Linux + 206)
+#define __NR_epoll_create (__NR_Linux + 207)
+#define __NR_epoll_ctl (__NR_Linux + 208)
+#define __NR_epoll_wait (__NR_Linux + 209)
+#define __NR_remap_file_pages (__NR_Linux + 210)
+#define __NR_rt_sigreturn (__NR_Linux + 211)
+#define __NR_set_tid_address (__NR_Linux + 212)
+#define __NR_restart_syscall (__NR_Linux + 213)
+#define __NR_semtimedop (__NR_Linux + 214)
+#define __NR_fadvise64 (__NR_Linux + 215)
+#define __NR_timer_create (__NR_Linux + 216)
+#define __NR_timer_settime (__NR_Linux + 217)
+#define __NR_timer_gettime (__NR_Linux + 218)
+#define __NR_timer_getoverrun (__NR_Linux + 219)
+#define __NR_timer_delete (__NR_Linux + 220)
+#define __NR_clock_settime (__NR_Linux + 221)
+#define __NR_clock_gettime (__NR_Linux + 222)
+#define __NR_clock_getres (__NR_Linux + 223)
+#define __NR_clock_nanosleep (__NR_Linux + 224)
+#define __NR_tgkill (__NR_Linux + 225)
+#define __NR_utimes (__NR_Linux + 226)
+#define __NR_mbind (__NR_Linux + 227)
+#define __NR_get_mempolicy (__NR_Linux + 228)
+#define __NR_set_mempolicy (__NR_Linux + 229)
+#define __NR_mq_open (__NR_Linux + 230)
+#define __NR_mq_unlink (__NR_Linux + 231)
+#define __NR_mq_timedsend (__NR_Linux + 232)
+#define __NR_mq_timedreceive (__NR_Linux + 233)
+#define __NR_mq_notify (__NR_Linux + 234)
+#define __NR_mq_getsetattr (__NR_Linux + 235)
+#define __NR_vserver (__NR_Linux + 236)
+#define __NR_waitid (__NR_Linux + 237)
+#define __NR_add_key (__NR_Linux + 239)
+#define __NR_request_key (__NR_Linux + 240)
+#define __NR_keyctl (__NR_Linux + 241)
+#define __NR_set_thread_area (__NR_Linux + 242)
+#define __NR_inotify_init (__NR_Linux + 243)
+#define __NR_inotify_add_watch (__NR_Linux + 244)
+#define __NR_inotify_rm_watch (__NR_Linux + 245)
+#define __NR_migrate_pages (__NR_Linux + 246)
+#define __NR_openat (__NR_Linux + 247)
+#define __NR_mkdirat (__NR_Linux + 248)
+#define __NR_mknodat (__NR_Linux + 249)
+#define __NR_fchownat (__NR_Linux + 250)
+#define __NR_futimesat (__NR_Linux + 251)
+#define __NR_newfstatat (__NR_Linux + 252)
+#define __NR_unlinkat (__NR_Linux + 253)
+#define __NR_renameat (__NR_Linux + 254)
+#define __NR_linkat (__NR_Linux + 255)
+#define __NR_symlinkat (__NR_Linux + 256)
+#define __NR_readlinkat (__NR_Linux + 257)
+#define __NR_fchmodat (__NR_Linux + 258)
+#define __NR_faccessat (__NR_Linux + 259)
+#define __NR_pselect6 (__NR_Linux + 260)
+#define __NR_ppoll (__NR_Linux + 261)
+#define __NR_unshare (__NR_Linux + 262)
+#define __NR_splice (__NR_Linux + 263)
+#define __NR_sync_file_range (__NR_Linux + 264)
+#define __NR_tee (__NR_Linux + 265)
+#define __NR_vmsplice (__NR_Linux + 266)
+#define __NR_move_pages (__NR_Linux + 267)
+#define __NR_set_robust_list (__NR_Linux + 268)
+#define __NR_get_robust_list (__NR_Linux + 269)
+#define __NR_kexec_load (__NR_Linux + 270)
+#define __NR_getcpu (__NR_Linux + 271)
+#define __NR_epoll_pwait (__NR_Linux + 272)
+#define __NR_ioprio_set (__NR_Linux + 273)
+#define __NR_ioprio_get (__NR_Linux + 274)
+#define __NR_utimensat (__NR_Linux + 275)
+#define __NR_signalfd (__NR_Linux + 276)
+#define __NR_timerfd (__NR_Linux + 277)
+#define __NR_eventfd (__NR_Linux + 278)
+#define __NR_fallocate (__NR_Linux + 279)
+#define __NR_timerfd_create (__NR_Linux + 280)
+#define __NR_timerfd_gettime (__NR_Linux + 281)
+#define __NR_timerfd_settime (__NR_Linux + 282)
+#define __NR_signalfd4 (__NR_Linux + 283)
+#define __NR_eventfd2 (__NR_Linux + 284)
+#define __NR_epoll_create1 (__NR_Linux + 285)
+#define __NR_dup3 (__NR_Linux + 286)
+#define __NR_pipe2 (__NR_Linux + 287)
+#define __NR_inotify_init1 (__NR_Linux + 288)
+#define __NR_preadv (__NR_Linux + 289)
+#define __NR_pwritev (__NR_Linux + 290)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291)
+#define __NR_perf_event_open (__NR_Linux + 292)
+#define __NR_accept4 (__NR_Linux + 293)
+#define __NR_recvmmsg (__NR_Linux + 294)
+#define __NR_fanotify_init (__NR_Linux + 295)
+#define __NR_fanotify_mark (__NR_Linux + 296)
+#define __NR_prlimit64 (__NR_Linux + 297)
+#define __NR_name_to_handle_at (__NR_Linux + 298)
+#define __NR_open_by_handle_at (__NR_Linux + 299)
+#define __NR_clock_adjtime (__NR_Linux + 300)
+#define __NR_syncfs (__NR_Linux + 301)
+#define __NR_sendmmsg (__NR_Linux + 302)
+#define __NR_setns (__NR_Linux + 303)
+#define __NR_process_vm_readv (__NR_Linux + 304)
+#define __NR_process_vm_writev (__NR_Linux + 305)
+#define __NR_kcmp (__NR_Linux + 306)
+#define __NR_finit_module (__NR_Linux + 307)
+#define __NR_getdents64 (__NR_Linux + 308)
+#define __NR_sched_setattr (__NR_Linux + 309)
+#define __NR_sched_getattr (__NR_Linux + 310)
+#define __NR_renameat2 (__NR_Linux + 311)
+#define __NR_seccomp (__NR_Linux + 312)
+#define __NR_getrandom (__NR_Linux + 313)
+#define __NR_memfd_create (__NR_Linux + 314)
+#define __NR_bpf (__NR_Linux + 315)
+#define __NR_execveat (__NR_Linux + 316)
+#define __NR_userfaultfd (__NR_Linux + 317)
+#define __NR_membarrier (__NR_Linux + 318)
+#define __NR_mlock2 (__NR_Linux + 319)
+#define __NR_copy_file_range (__NR_Linux + 320)
+#define __NR_preadv2 (__NR_Linux + 321)
+#define __NR_pwritev2 (__NR_Linux + 322)
+#define __NR_pkey_mprotect (__NR_Linux + 323)
+#define __NR_pkey_alloc (__NR_Linux + 324)
+#define __NR_pkey_free (__NR_Linux + 325)
+#define __NR_statx (__NR_Linux + 326)
+#define __NR_rseq (__NR_Linux + 327)
+#define __NR_io_pgetevents (__NR_Linux + 328)
+#endif
diff --git a/libc/kernel/uapi/asm-generic/shmparam.h b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h
similarity index 86%
rename from libc/kernel/uapi/asm-generic/shmparam.h
rename to libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h
index d3f1453..2b74f63 100644
--- a/libc/kernel/uapi/asm-generic/shmparam.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h
@@ -16,7 +16,8 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef __ASM_GENERIC_SHMPARAM_H
-#define __ASM_GENERIC_SHMPARAM_H
-#define SHMLBA PAGE_SIZE
+#ifndef _UAPI_ASM_MIPS_UNISTD_NR_N32_H
+#define _UAPI_ASM_MIPS_UNISTD_NR_N32_H
+#define __NR_N32_Linux 6000
+#define __NR_N32_Linux_syscalls 333
 #endif
diff --git a/libc/kernel/uapi/asm-generic/shmparam.h b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h
similarity index 86%
copy from libc/kernel/uapi/asm-generic/shmparam.h
copy to libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h
index d3f1453..22300b2 100644
--- a/libc/kernel/uapi/asm-generic/shmparam.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h
@@ -16,7 +16,8 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef __ASM_GENERIC_SHMPARAM_H
-#define __ASM_GENERIC_SHMPARAM_H
-#define SHMLBA PAGE_SIZE
+#ifndef _UAPI_ASM_MIPS_UNISTD_NR_N64_H
+#define _UAPI_ASM_MIPS_UNISTD_NR_N64_H
+#define __NR_64_Linux 5000
+#define __NR_64_Linux_syscalls 329
 #endif
diff --git a/libc/kernel/uapi/asm-generic/shmparam.h b/libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h
similarity index 86%
copy from libc/kernel/uapi/asm-generic/shmparam.h
copy to libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h
index d3f1453..02cbd21 100644
--- a/libc/kernel/uapi/asm-generic/shmparam.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h
@@ -16,7 +16,8 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef __ASM_GENERIC_SHMPARAM_H
-#define __ASM_GENERIC_SHMPARAM_H
-#define SHMLBA PAGE_SIZE
+#ifndef _UAPI_ASM_MIPS_UNISTD_NR_O32_H
+#define _UAPI_ASM_MIPS_UNISTD_NR_O32_H
+#define __NR_O32_Linux 4000
+#define __NR_O32_Linux_syscalls 369
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_o32.h b/libc/kernel/uapi/asm-mips/asm/unistd_o32.h
new file mode 100644
index 0000000..bc248dd
--- /dev/null
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_o32.h
@@ -0,0 +1,389 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_MIPS_UNISTD_O32_H
+#define _UAPI_ASM_MIPS_UNISTD_O32_H
+#define __NR_syscall (__NR_Linux + 0)
+#define __NR_exit (__NR_Linux + 1)
+#define __NR_fork (__NR_Linux + 2)
+#define __NR_read (__NR_Linux + 3)
+#define __NR_write (__NR_Linux + 4)
+#define __NR_open (__NR_Linux + 5)
+#define __NR_close (__NR_Linux + 6)
+#define __NR_waitpid (__NR_Linux + 7)
+#define __NR_creat (__NR_Linux + 8)
+#define __NR_link (__NR_Linux + 9)
+#define __NR_unlink (__NR_Linux + 10)
+#define __NR_execve (__NR_Linux + 11)
+#define __NR_chdir (__NR_Linux + 12)
+#define __NR_time (__NR_Linux + 13)
+#define __NR_mknod (__NR_Linux + 14)
+#define __NR_chmod (__NR_Linux + 15)
+#define __NR_lchown (__NR_Linux + 16)
+#define __NR_break (__NR_Linux + 17)
+#define __NR_unused18 (__NR_Linux + 18)
+#define __NR_lseek (__NR_Linux + 19)
+#define __NR_getpid (__NR_Linux + 20)
+#define __NR_mount (__NR_Linux + 21)
+#define __NR_umount (__NR_Linux + 22)
+#define __NR_setuid (__NR_Linux + 23)
+#define __NR_getuid (__NR_Linux + 24)
+#define __NR_stime (__NR_Linux + 25)
+#define __NR_ptrace (__NR_Linux + 26)
+#define __NR_alarm (__NR_Linux + 27)
+#define __NR_unused28 (__NR_Linux + 28)
+#define __NR_pause (__NR_Linux + 29)
+#define __NR_utime (__NR_Linux + 30)
+#define __NR_stty (__NR_Linux + 31)
+#define __NR_gtty (__NR_Linux + 32)
+#define __NR_access (__NR_Linux + 33)
+#define __NR_nice (__NR_Linux + 34)
+#define __NR_ftime (__NR_Linux + 35)
+#define __NR_sync (__NR_Linux + 36)
+#define __NR_kill (__NR_Linux + 37)
+#define __NR_rename (__NR_Linux + 38)
+#define __NR_mkdir (__NR_Linux + 39)
+#define __NR_rmdir (__NR_Linux + 40)
+#define __NR_dup (__NR_Linux + 41)
+#define __NR_pipe (__NR_Linux + 42)
+#define __NR_times (__NR_Linux + 43)
+#define __NR_prof (__NR_Linux + 44)
+#define __NR_brk (__NR_Linux + 45)
+#define __NR_setgid (__NR_Linux + 46)
+#define __NR_getgid (__NR_Linux + 47)
+#define __NR_signal (__NR_Linux + 48)
+#define __NR_geteuid (__NR_Linux + 49)
+#define __NR_getegid (__NR_Linux + 50)
+#define __NR_acct (__NR_Linux + 51)
+#define __NR_umount2 (__NR_Linux + 52)
+#define __NR_lock (__NR_Linux + 53)
+#define __NR_ioctl (__NR_Linux + 54)
+#define __NR_fcntl (__NR_Linux + 55)
+#define __NR_mpx (__NR_Linux + 56)
+#define __NR_setpgid (__NR_Linux + 57)
+#define __NR_ulimit (__NR_Linux + 58)
+#define __NR_unused59 (__NR_Linux + 59)
+#define __NR_umask (__NR_Linux + 60)
+#define __NR_chroot (__NR_Linux + 61)
+#define __NR_ustat (__NR_Linux + 62)
+#define __NR_dup2 (__NR_Linux + 63)
+#define __NR_getppid (__NR_Linux + 64)
+#define __NR_getpgrp (__NR_Linux + 65)
+#define __NR_setsid (__NR_Linux + 66)
+#define __NR_sigaction (__NR_Linux + 67)
+#define __NR_sgetmask (__NR_Linux + 68)
+#define __NR_ssetmask (__NR_Linux + 69)
+#define __NR_setreuid (__NR_Linux + 70)
+#define __NR_setregid (__NR_Linux + 71)
+#define __NR_sigsuspend (__NR_Linux + 72)
+#define __NR_sigpending (__NR_Linux + 73)
+#define __NR_sethostname (__NR_Linux + 74)
+#define __NR_setrlimit (__NR_Linux + 75)
+#define __NR_getrlimit (__NR_Linux + 76)
+#define __NR_getrusage (__NR_Linux + 77)
+#define __NR_gettimeofday (__NR_Linux + 78)
+#define __NR_settimeofday (__NR_Linux + 79)
+#define __NR_getgroups (__NR_Linux + 80)
+#define __NR_setgroups (__NR_Linux + 81)
+#define __NR_reserved82 (__NR_Linux + 82)
+#define __NR_symlink (__NR_Linux + 83)
+#define __NR_unused84 (__NR_Linux + 84)
+#define __NR_readlink (__NR_Linux + 85)
+#define __NR_uselib (__NR_Linux + 86)
+#define __NR_swapon (__NR_Linux + 87)
+#define __NR_reboot (__NR_Linux + 88)
+#define __NR_readdir (__NR_Linux + 89)
+#define __NR_mmap (__NR_Linux + 90)
+#define __NR_munmap (__NR_Linux + 91)
+#define __NR_truncate (__NR_Linux + 92)
+#define __NR_ftruncate (__NR_Linux + 93)
+#define __NR_fchmod (__NR_Linux + 94)
+#define __NR_fchown (__NR_Linux + 95)
+#define __NR_getpriority (__NR_Linux + 96)
+#define __NR_setpriority (__NR_Linux + 97)
+#define __NR_profil (__NR_Linux + 98)
+#define __NR_statfs (__NR_Linux + 99)
+#define __NR_fstatfs (__NR_Linux + 100)
+#define __NR_ioperm (__NR_Linux + 101)
+#define __NR_socketcall (__NR_Linux + 102)
+#define __NR_syslog (__NR_Linux + 103)
+#define __NR_setitimer (__NR_Linux + 104)
+#define __NR_getitimer (__NR_Linux + 105)
+#define __NR_stat (__NR_Linux + 106)
+#define __NR_lstat (__NR_Linux + 107)
+#define __NR_fstat (__NR_Linux + 108)
+#define __NR_unused109 (__NR_Linux + 109)
+#define __NR_iopl (__NR_Linux + 110)
+#define __NR_vhangup (__NR_Linux + 111)
+#define __NR_idle (__NR_Linux + 112)
+#define __NR_vm86 (__NR_Linux + 113)
+#define __NR_wait4 (__NR_Linux + 114)
+#define __NR_swapoff (__NR_Linux + 115)
+#define __NR_sysinfo (__NR_Linux + 116)
+#define __NR_ipc (__NR_Linux + 117)
+#define __NR_fsync (__NR_Linux + 118)
+#define __NR_sigreturn (__NR_Linux + 119)
+#define __NR_clone (__NR_Linux + 120)
+#define __NR_setdomainname (__NR_Linux + 121)
+#define __NR_uname (__NR_Linux + 122)
+#define __NR_modify_ldt (__NR_Linux + 123)
+#define __NR_adjtimex (__NR_Linux + 124)
+#define __NR_mprotect (__NR_Linux + 125)
+#define __NR_sigprocmask (__NR_Linux + 126)
+#define __NR_create_module (__NR_Linux + 127)
+#define __NR_init_module (__NR_Linux + 128)
+#define __NR_delete_module (__NR_Linux + 129)
+#define __NR_get_kernel_syms (__NR_Linux + 130)
+#define __NR_quotactl (__NR_Linux + 131)
+#define __NR_getpgid (__NR_Linux + 132)
+#define __NR_fchdir (__NR_Linux + 133)
+#define __NR_bdflush (__NR_Linux + 134)
+#define __NR_sysfs (__NR_Linux + 135)
+#define __NR_personality (__NR_Linux + 136)
+#define __NR_afs_syscall (__NR_Linux + 137)
+#define __NR_setfsuid (__NR_Linux + 138)
+#define __NR_setfsgid (__NR_Linux + 139)
+#define __NR__llseek (__NR_Linux + 140)
+#define __NR_getdents (__NR_Linux + 141)
+#define __NR__newselect (__NR_Linux + 142)
+#define __NR_flock (__NR_Linux + 143)
+#define __NR_msync (__NR_Linux + 144)
+#define __NR_readv (__NR_Linux + 145)
+#define __NR_writev (__NR_Linux + 146)
+#define __NR_cacheflush (__NR_Linux + 147)
+#define __NR_cachectl (__NR_Linux + 148)
+#define __NR_sysmips (__NR_Linux + 149)
+#define __NR_unused150 (__NR_Linux + 150)
+#define __NR_getsid (__NR_Linux + 151)
+#define __NR_fdatasync (__NR_Linux + 152)
+#define __NR__sysctl (__NR_Linux + 153)
+#define __NR_mlock (__NR_Linux + 154)
+#define __NR_munlock (__NR_Linux + 155)
+#define __NR_mlockall (__NR_Linux + 156)
+#define __NR_munlockall (__NR_Linux + 157)
+#define __NR_sched_setparam (__NR_Linux + 158)
+#define __NR_sched_getparam (__NR_Linux + 159)
+#define __NR_sched_setscheduler (__NR_Linux + 160)
+#define __NR_sched_getscheduler (__NR_Linux + 161)
+#define __NR_sched_yield (__NR_Linux + 162)
+#define __NR_sched_get_priority_max (__NR_Linux + 163)
+#define __NR_sched_get_priority_min (__NR_Linux + 164)
+#define __NR_sched_rr_get_interval (__NR_Linux + 165)
+#define __NR_nanosleep (__NR_Linux + 166)
+#define __NR_mremap (__NR_Linux + 167)
+#define __NR_accept (__NR_Linux + 168)
+#define __NR_bind (__NR_Linux + 169)
+#define __NR_connect (__NR_Linux + 170)
+#define __NR_getpeername (__NR_Linux + 171)
+#define __NR_getsockname (__NR_Linux + 172)
+#define __NR_getsockopt (__NR_Linux + 173)
+#define __NR_listen (__NR_Linux + 174)
+#define __NR_recv (__NR_Linux + 175)
+#define __NR_recvfrom (__NR_Linux + 176)
+#define __NR_recvmsg (__NR_Linux + 177)
+#define __NR_send (__NR_Linux + 178)
+#define __NR_sendmsg (__NR_Linux + 179)
+#define __NR_sendto (__NR_Linux + 180)
+#define __NR_setsockopt (__NR_Linux + 181)
+#define __NR_shutdown (__NR_Linux + 182)
+#define __NR_socket (__NR_Linux + 183)
+#define __NR_socketpair (__NR_Linux + 184)
+#define __NR_setresuid (__NR_Linux + 185)
+#define __NR_getresuid (__NR_Linux + 186)
+#define __NR_query_module (__NR_Linux + 187)
+#define __NR_poll (__NR_Linux + 188)
+#define __NR_nfsservctl (__NR_Linux + 189)
+#define __NR_setresgid (__NR_Linux + 190)
+#define __NR_getresgid (__NR_Linux + 191)
+#define __NR_prctl (__NR_Linux + 192)
+#define __NR_rt_sigreturn (__NR_Linux + 193)
+#define __NR_rt_sigaction (__NR_Linux + 194)
+#define __NR_rt_sigprocmask (__NR_Linux + 195)
+#define __NR_rt_sigpending (__NR_Linux + 196)
+#define __NR_rt_sigtimedwait (__NR_Linux + 197)
+#define __NR_rt_sigqueueinfo (__NR_Linux + 198)
+#define __NR_rt_sigsuspend (__NR_Linux + 199)
+#define __NR_pread64 (__NR_Linux + 200)
+#define __NR_pwrite64 (__NR_Linux + 201)
+#define __NR_chown (__NR_Linux + 202)
+#define __NR_getcwd (__NR_Linux + 203)
+#define __NR_capget (__NR_Linux + 204)
+#define __NR_capset (__NR_Linux + 205)
+#define __NR_sigaltstack (__NR_Linux + 206)
+#define __NR_sendfile (__NR_Linux + 207)
+#define __NR_getpmsg (__NR_Linux + 208)
+#define __NR_putpmsg (__NR_Linux + 209)
+#define __NR_mmap2 (__NR_Linux + 210)
+#define __NR_truncate64 (__NR_Linux + 211)
+#define __NR_ftruncate64 (__NR_Linux + 212)
+#define __NR_stat64 (__NR_Linux + 213)
+#define __NR_lstat64 (__NR_Linux + 214)
+#define __NR_fstat64 (__NR_Linux + 215)
+#define __NR_pivot_root (__NR_Linux + 216)
+#define __NR_mincore (__NR_Linux + 217)
+#define __NR_madvise (__NR_Linux + 218)
+#define __NR_getdents64 (__NR_Linux + 219)
+#define __NR_fcntl64 (__NR_Linux + 220)
+#define __NR_reserved221 (__NR_Linux + 221)
+#define __NR_gettid (__NR_Linux + 222)
+#define __NR_readahead (__NR_Linux + 223)
+#define __NR_setxattr (__NR_Linux + 224)
+#define __NR_lsetxattr (__NR_Linux + 225)
+#define __NR_fsetxattr (__NR_Linux + 226)
+#define __NR_getxattr (__NR_Linux + 227)
+#define __NR_lgetxattr (__NR_Linux + 228)
+#define __NR_fgetxattr (__NR_Linux + 229)
+#define __NR_listxattr (__NR_Linux + 230)
+#define __NR_llistxattr (__NR_Linux + 231)
+#define __NR_flistxattr (__NR_Linux + 232)
+#define __NR_removexattr (__NR_Linux + 233)
+#define __NR_lremovexattr (__NR_Linux + 234)
+#define __NR_fremovexattr (__NR_Linux + 235)
+#define __NR_tkill (__NR_Linux + 236)
+#define __NR_sendfile64 (__NR_Linux + 237)
+#define __NR_futex (__NR_Linux + 238)
+#define __NR_sched_setaffinity (__NR_Linux + 239)
+#define __NR_sched_getaffinity (__NR_Linux + 240)
+#define __NR_io_setup (__NR_Linux + 241)
+#define __NR_io_destroy (__NR_Linux + 242)
+#define __NR_io_getevents (__NR_Linux + 243)
+#define __NR_io_submit (__NR_Linux + 244)
+#define __NR_io_cancel (__NR_Linux + 245)
+#define __NR_exit_group (__NR_Linux + 246)
+#define __NR_lookup_dcookie (__NR_Linux + 247)
+#define __NR_epoll_create (__NR_Linux + 248)
+#define __NR_epoll_ctl (__NR_Linux + 249)
+#define __NR_epoll_wait (__NR_Linux + 250)
+#define __NR_remap_file_pages (__NR_Linux + 251)
+#define __NR_set_tid_address (__NR_Linux + 252)
+#define __NR_restart_syscall (__NR_Linux + 253)
+#define __NR_fadvise64 (__NR_Linux + 254)
+#define __NR_statfs64 (__NR_Linux + 255)
+#define __NR_fstatfs64 (__NR_Linux + 256)
+#define __NR_timer_create (__NR_Linux + 257)
+#define __NR_timer_settime (__NR_Linux + 258)
+#define __NR_timer_gettime (__NR_Linux + 259)
+#define __NR_timer_getoverrun (__NR_Linux + 260)
+#define __NR_timer_delete (__NR_Linux + 261)
+#define __NR_clock_settime (__NR_Linux + 262)
+#define __NR_clock_gettime (__NR_Linux + 263)
+#define __NR_clock_getres (__NR_Linux + 264)
+#define __NR_clock_nanosleep (__NR_Linux + 265)
+#define __NR_tgkill (__NR_Linux + 266)
+#define __NR_utimes (__NR_Linux + 267)
+#define __NR_mbind (__NR_Linux + 268)
+#define __NR_get_mempolicy (__NR_Linux + 269)
+#define __NR_set_mempolicy (__NR_Linux + 270)
+#define __NR_mq_open (__NR_Linux + 271)
+#define __NR_mq_unlink (__NR_Linux + 272)
+#define __NR_mq_timedsend (__NR_Linux + 273)
+#define __NR_mq_timedreceive (__NR_Linux + 274)
+#define __NR_mq_notify (__NR_Linux + 275)
+#define __NR_mq_getsetattr (__NR_Linux + 276)
+#define __NR_vserver (__NR_Linux + 277)
+#define __NR_waitid (__NR_Linux + 278)
+#define __NR_add_key (__NR_Linux + 280)
+#define __NR_request_key (__NR_Linux + 281)
+#define __NR_keyctl (__NR_Linux + 282)
+#define __NR_set_thread_area (__NR_Linux + 283)
+#define __NR_inotify_init (__NR_Linux + 284)
+#define __NR_inotify_add_watch (__NR_Linux + 285)
+#define __NR_inotify_rm_watch (__NR_Linux + 286)
+#define __NR_migrate_pages (__NR_Linux + 287)
+#define __NR_openat (__NR_Linux + 288)
+#define __NR_mkdirat (__NR_Linux + 289)
+#define __NR_mknodat (__NR_Linux + 290)
+#define __NR_fchownat (__NR_Linux + 291)
+#define __NR_futimesat (__NR_Linux + 292)
+#define __NR_fstatat64 (__NR_Linux + 293)
+#define __NR_unlinkat (__NR_Linux + 294)
+#define __NR_renameat (__NR_Linux + 295)
+#define __NR_linkat (__NR_Linux + 296)
+#define __NR_symlinkat (__NR_Linux + 297)
+#define __NR_readlinkat (__NR_Linux + 298)
+#define __NR_fchmodat (__NR_Linux + 299)
+#define __NR_faccessat (__NR_Linux + 300)
+#define __NR_pselect6 (__NR_Linux + 301)
+#define __NR_ppoll (__NR_Linux + 302)
+#define __NR_unshare (__NR_Linux + 303)
+#define __NR_splice (__NR_Linux + 304)
+#define __NR_sync_file_range (__NR_Linux + 305)
+#define __NR_tee (__NR_Linux + 306)
+#define __NR_vmsplice (__NR_Linux + 307)
+#define __NR_move_pages (__NR_Linux + 308)
+#define __NR_set_robust_list (__NR_Linux + 309)
+#define __NR_get_robust_list (__NR_Linux + 310)
+#define __NR_kexec_load (__NR_Linux + 311)
+#define __NR_getcpu (__NR_Linux + 312)
+#define __NR_epoll_pwait (__NR_Linux + 313)
+#define __NR_ioprio_set (__NR_Linux + 314)
+#define __NR_ioprio_get (__NR_Linux + 315)
+#define __NR_utimensat (__NR_Linux + 316)
+#define __NR_signalfd (__NR_Linux + 317)
+#define __NR_timerfd (__NR_Linux + 318)
+#define __NR_eventfd (__NR_Linux + 319)
+#define __NR_fallocate (__NR_Linux + 320)
+#define __NR_timerfd_create (__NR_Linux + 321)
+#define __NR_timerfd_gettime (__NR_Linux + 322)
+#define __NR_timerfd_settime (__NR_Linux + 323)
+#define __NR_signalfd4 (__NR_Linux + 324)
+#define __NR_eventfd2 (__NR_Linux + 325)
+#define __NR_epoll_create1 (__NR_Linux + 326)
+#define __NR_dup3 (__NR_Linux + 327)
+#define __NR_pipe2 (__NR_Linux + 328)
+#define __NR_inotify_init1 (__NR_Linux + 329)
+#define __NR_preadv (__NR_Linux + 330)
+#define __NR_pwritev (__NR_Linux + 331)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332)
+#define __NR_perf_event_open (__NR_Linux + 333)
+#define __NR_accept4 (__NR_Linux + 334)
+#define __NR_recvmmsg (__NR_Linux + 335)
+#define __NR_fanotify_init (__NR_Linux + 336)
+#define __NR_fanotify_mark (__NR_Linux + 337)
+#define __NR_prlimit64 (__NR_Linux + 338)
+#define __NR_name_to_handle_at (__NR_Linux + 339)
+#define __NR_open_by_handle_at (__NR_Linux + 340)
+#define __NR_clock_adjtime (__NR_Linux + 341)
+#define __NR_syncfs (__NR_Linux + 342)
+#define __NR_sendmmsg (__NR_Linux + 343)
+#define __NR_setns (__NR_Linux + 344)
+#define __NR_process_vm_readv (__NR_Linux + 345)
+#define __NR_process_vm_writev (__NR_Linux + 346)
+#define __NR_kcmp (__NR_Linux + 347)
+#define __NR_finit_module (__NR_Linux + 348)
+#define __NR_sched_setattr (__NR_Linux + 349)
+#define __NR_sched_getattr (__NR_Linux + 350)
+#define __NR_renameat2 (__NR_Linux + 351)
+#define __NR_seccomp (__NR_Linux + 352)
+#define __NR_getrandom (__NR_Linux + 353)
+#define __NR_memfd_create (__NR_Linux + 354)
+#define __NR_bpf (__NR_Linux + 355)
+#define __NR_execveat (__NR_Linux + 356)
+#define __NR_userfaultfd (__NR_Linux + 357)
+#define __NR_membarrier (__NR_Linux + 358)
+#define __NR_mlock2 (__NR_Linux + 359)
+#define __NR_copy_file_range (__NR_Linux + 360)
+#define __NR_preadv2 (__NR_Linux + 361)
+#define __NR_pwritev2 (__NR_Linux + 362)
+#define __NR_pkey_mprotect (__NR_Linux + 363)
+#define __NR_pkey_alloc (__NR_Linux + 364)
+#define __NR_pkey_free (__NR_Linux + 365)
+#define __NR_statx (__NR_Linux + 366)
+#define __NR_rseq (__NR_Linux + 367)
+#define __NR_io_pgetevents (__NR_Linux + 368)
+#endif
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 8d65fd4..baa2e44 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -195,6 +195,12 @@
 #define AMDGPU_TILING_NUM_BANKS_MASK 0x3
 #define AMDGPU_TILING_SWIZZLE_MODE_SHIFT 0
 #define AMDGPU_TILING_SWIZZLE_MODE_MASK 0x1f
+#define AMDGPU_TILING_DCC_OFFSET_256B_SHIFT 5
+#define AMDGPU_TILING_DCC_OFFSET_256B_MASK 0xFFFFFF
+#define AMDGPU_TILING_DCC_PITCH_MAX_SHIFT 29
+#define AMDGPU_TILING_DCC_PITCH_MAX_MASK 0x3FFF
+#define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT 43
+#define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK 0x1
 #define AMDGPU_TILING_SET(field,value) (((__u64) (value) & AMDGPU_TILING_ ##field ##_MASK) << AMDGPU_TILING_ ##field ##_SHIFT)
 #define AMDGPU_TILING_GET(value,field) (((__u64) (value) >> AMDGPU_TILING_ ##field ##_SHIFT) & AMDGPU_TILING_ ##field ##_MASK)
 #define AMDGPU_GEM_METADATA_OP_SET_METADATA 1
diff --git a/libc/kernel/uapi/drm/drm_fourcc.h b/libc/kernel/uapi/drm/drm_fourcc.h
index df89cd1..d95bda0 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -75,6 +75,11 @@
 #define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y')
 #define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y')
 #define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V')
+#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V')
+#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0')
+#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0')
+#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2')
+#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2')
 #define DRM_FORMAT_XRGB8888_A8 fourcc_code('X', 'R', 'A', '8')
 #define DRM_FORMAT_XBGR8888_A8 fourcc_code('X', 'B', 'A', '8')
 #define DRM_FORMAT_RGBX8888_A8 fourcc_code('R', 'X', 'A', '8')
diff --git a/libc/kernel/uapi/drm/drm_mode.h b/libc/kernel/uapi/drm/drm_mode.h
index dff9f34..1944c9c 100644
--- a/libc/kernel/uapi/drm/drm_mode.h
+++ b/libc/kernel/uapi/drm/drm_mode.h
@@ -463,6 +463,12 @@
 struct drm_mode_revoke_lease {
   __u32 lessee_id;
 };
+struct drm_mode_rect {
+  __s32 x1;
+  __s32 y1;
+  __s32 x2;
+  __s32 y2;
+};
 #ifdef __cplusplus
 }
 #endif
diff --git a/libc/kernel/uapi/drm/i915_drm.h b/libc/kernel/uapi/drm/i915_drm.h
index 89fa529..b3fd9fd 100644
--- a/libc/kernel/uapi/drm/i915_drm.h
+++ b/libc/kernel/uapi/drm/i915_drm.h
@@ -281,6 +281,9 @@
 typedef struct drm_i915_irq_wait {
   int irq_seq;
 } drm_i915_irq_wait_t;
+#define I915_GEM_PPGTT_NONE 0
+#define I915_GEM_PPGTT_ALIASING 1
+#define I915_GEM_PPGTT_FULL 2
 #define I915_PARAM_IRQ_ACTIVE 1
 #define I915_PARAM_ALLOW_BATCHBUFFER 2
 #define I915_PARAM_LAST_DISPATCH 3
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index df8119f..f6bee3e 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -57,12 +57,16 @@
   __u32 flags;
   __u32 handle;
 };
-#define MSM_INFO_IOVA 0x01
-#define MSM_INFO_FLAGS (MSM_INFO_IOVA)
+#define MSM_INFO_GET_OFFSET 0x00
+#define MSM_INFO_GET_IOVA 0x01
+#define MSM_INFO_SET_NAME 0x02
+#define MSM_INFO_GET_NAME 0x03
 struct drm_msm_gem_info {
   __u32 handle;
-  __u32 flags;
-  __u64 offset;
+  __u32 info;
+  __u64 value;
+  __u32 len;
+  __u32 pad;
 };
 #define MSM_PREP_READ 0x01
 #define MSM_PREP_WRITE 0x02
@@ -97,7 +101,8 @@
 };
 #define MSM_SUBMIT_BO_READ 0x0001
 #define MSM_SUBMIT_BO_WRITE 0x0002
-#define MSM_SUBMIT_BO_FLAGS (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE)
+#define MSM_SUBMIT_BO_DUMP 0x0004
+#define MSM_SUBMIT_BO_FLAGS (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE | MSM_SUBMIT_BO_DUMP)
 struct drm_msm_gem_submit_bo {
   __u32 flags;
   __u32 handle;
diff --git a/libc/kernel/uapi/drm/v3d_drm.h b/libc/kernel/uapi/drm/v3d_drm.h
index 8865911..985f327 100644
--- a/libc/kernel/uapi/drm/v3d_drm.h
+++ b/libc/kernel/uapi/drm/v3d_drm.h
@@ -28,12 +28,14 @@
 #define DRM_V3D_MMAP_BO 0x03
 #define DRM_V3D_GET_PARAM 0x04
 #define DRM_V3D_GET_BO_OFFSET 0x05
+#define DRM_V3D_SUBMIT_TFU 0x06
 #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
 #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
 #define DRM_IOCTL_V3D_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_CREATE_BO, struct drm_v3d_create_bo)
 #define DRM_IOCTL_V3D_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
 #define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
 #define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
+#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
 struct drm_v3d_submit_cl {
   __u32 bcl_start;
   __u32 bcl_end;
@@ -73,6 +75,7 @@
   DRM_V3D_PARAM_V3D_CORE0_IDENT0,
   DRM_V3D_PARAM_V3D_CORE0_IDENT1,
   DRM_V3D_PARAM_V3D_CORE0_IDENT2,
+  DRM_V3D_PARAM_SUPPORTS_TFU,
 };
 struct drm_v3d_get_param {
   __u32 param;
@@ -83,6 +86,19 @@
   __u32 handle;
   __u32 offset;
 };
+struct drm_v3d_submit_tfu {
+  __u32 icfg;
+  __u32 iia;
+  __u32 iis;
+  __u32 ica;
+  __u32 iua;
+  __u32 ioa;
+  __u32 ios;
+  __u32 coef[4];
+  __u32 bo_handles[4];
+  __u32 in_sync;
+  __u32 out_sync;
+};
 #ifdef __cplusplus
 }
 #endif
diff --git a/libc/kernel/uapi/drm/virtgpu_drm.h b/libc/kernel/uapi/drm/virtgpu_drm.h
index 84986e4..bc4aad4 100644
--- a/libc/kernel/uapi/drm/virtgpu_drm.h
+++ b/libc/kernel/uapi/drm/virtgpu_drm.h
@@ -31,6 +31,9 @@
 #define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07
 #define DRM_VIRTGPU_WAIT 0x08
 #define DRM_VIRTGPU_GET_CAPS 0x09
+#define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01
+#define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02
+#define VIRTGPU_EXECBUF_FLAGS (VIRTGPU_EXECBUF_FENCE_FD_IN | VIRTGPU_EXECBUF_FENCE_FD_OUT | 0)
 struct drm_virtgpu_map {
   __u64 offset;
   __u32 handle;
@@ -42,7 +45,7 @@
   __u64 command;
   __u64 bo_handles;
   __u32 num_bo_handles;
-  __u32 pad;
+  __s32 fence_fd;
 };
 #define VIRTGPU_PARAM_3D_FEATURES 1
 #define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2
@@ -105,7 +108,7 @@
   __u32 pad;
 };
 #define DRM_IOCTL_VIRTGPU_MAP DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map)
-#define DRM_IOCTL_VIRTGPU_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER, struct drm_virtgpu_execbuffer)
+#define DRM_IOCTL_VIRTGPU_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER, struct drm_virtgpu_execbuffer)
 #define DRM_IOCTL_VIRTGPU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM, struct drm_virtgpu_getparam)
 #define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE, struct drm_virtgpu_resource_create)
 #define DRM_IOCTL_VIRTGPU_RESOURCE_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, struct drm_virtgpu_resource_info)
diff --git a/libc/kernel/uapi/asm-generic/shmparam.h b/libc/kernel/uapi/linux/android/binderfs.h
similarity index 74%
copy from libc/kernel/uapi/asm-generic/shmparam.h
copy to libc/kernel/uapi/linux/android/binderfs.h
index d3f1453..d58c333 100644
--- a/libc/kernel/uapi/asm-generic/shmparam.h
+++ b/libc/kernel/uapi/linux/android/binderfs.h
@@ -16,7 +16,16 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef __ASM_GENERIC_SHMPARAM_H
-#define __ASM_GENERIC_SHMPARAM_H
-#define SHMLBA PAGE_SIZE
+#ifndef _UAPI_LINUX_BINDERFS_H
+#define _UAPI_LINUX_BINDERFS_H
+#include <linux/android/binder.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#define BINDERFS_MAX_NAME 255
+struct binderfs_device {
+  char name[BINDERFS_MAX_NAME + 1];
+  __u32 major;
+  __u32 minor;
+};
+#define BINDER_CTL_ADD _IOWR('b', 1, struct binderfs_device)
 #endif
diff --git a/libc/kernel/uapi/linux/audit.h b/libc/kernel/uapi/linux/audit.h
index 235a0e7..0698fc8 100644
--- a/libc/kernel/uapi/linux/audit.h
+++ b/libc/kernel/uapi/linux/audit.h
@@ -265,6 +265,7 @@
 #define AUDIT_ARCH_ARM (EM_ARM | __AUDIT_ARCH_LE)
 #define AUDIT_ARCH_ARMEB (EM_ARM)
 #define AUDIT_ARCH_CRIS (EM_CRIS | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_CSKY (EM_CSKY | __AUDIT_ARCH_LE)
 #define AUDIT_ARCH_FRV (EM_FRV)
 #define AUDIT_ARCH_I386 (EM_386 | __AUDIT_ARCH_LE)
 #define AUDIT_ARCH_IA64 (EM_IA_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
@@ -283,6 +284,8 @@
 #define AUDIT_ARCH_PPC (EM_PPC)
 #define AUDIT_ARCH_PPC64 (EM_PPC64 | __AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_PPC64LE (EM_PPC64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_RISCV32 (EM_RISCV | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_RISCV64 (EM_RISCV | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
 #define AUDIT_ARCH_S390 (EM_S390)
 #define AUDIT_ARCH_S390X (EM_S390 | __AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_SH (EM_SH)
@@ -295,6 +298,7 @@
 #define AUDIT_ARCH_TILEGX32 (EM_TILEGX | __AUDIT_ARCH_LE)
 #define AUDIT_ARCH_TILEPRO (EM_TILEPRO | __AUDIT_ARCH_LE)
 #define AUDIT_ARCH_X86_64 (EM_X86_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_XTENSA (EM_XTENSA)
 #define AUDIT_PERM_EXEC 1
 #define AUDIT_PERM_WRITE 2
 #define AUDIT_PERM_READ 4
diff --git a/libc/kernel/uapi/linux/auto_fs.h b/libc/kernel/uapi/linux/auto_fs.h
index 0264b86..9a9dd65 100644
--- a/libc/kernel/uapi/linux/auto_fs.h
+++ b/libc/kernel/uapi/linux/auto_fs.h
@@ -24,7 +24,7 @@
 #define AUTOFS_PROTO_VERSION 5
 #define AUTOFS_MIN_PROTO_VERSION 3
 #define AUTOFS_MAX_PROTO_VERSION 5
-#define AUTOFS_PROTO_SUBVERSION 3
+#define AUTOFS_PROTO_SUBVERSION 4
 #if defined(__ia64__) || defined(__alpha__)
 typedef unsigned long autofs_wqt_t;
 #else
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index d70a409..894b9f7 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -169,6 +169,7 @@
 #define BPF_F_ALLOW_OVERRIDE (1U << 0)
 #define BPF_F_ALLOW_MULTI (1U << 1)
 #define BPF_F_STRICT_ALIGNMENT (1U << 0)
+#define BPF_F_ANY_ALIGNMENT (1U << 1)
 #define BPF_PSEUDO_MAP_FD 1
 #define BPF_PSEUDO_CALL 1
 #define BPF_ANY 0
@@ -177,11 +178,12 @@
 #define BPF_F_NO_PREALLOC (1U << 0)
 #define BPF_F_NO_COMMON_LRU (1U << 1)
 #define BPF_F_NUMA_NODE (1U << 2)
-#define BPF_F_QUERY_EFFECTIVE (1U << 0)
 #define BPF_OBJ_NAME_LEN 16U
 #define BPF_F_RDONLY (1U << 3)
 #define BPF_F_WRONLY (1U << 4)
 #define BPF_F_STACK_BUILD_ID (1U << 5)
+#define BPF_F_ZERO_SEED (1U << 6)
+#define BPF_F_QUERY_EFFECTIVE (1U << 0)
 enum bpf_stack_build_id_status {
   BPF_STACK_BUILD_ID_EMPTY = 0,
   BPF_STACK_BUILD_ID_VALID = 1,
@@ -233,6 +235,13 @@
     char prog_name[BPF_OBJ_NAME_LEN];
     __u32 prog_ifindex;
     __u32 expected_attach_type;
+    __u32 prog_btf_fd;
+    __u32 func_info_rec_size;
+    __aligned_u64 func_info;
+    __u32 func_info_cnt;
+    __u32 line_info_rec_size;
+    __aligned_u64 line_info;
+    __u32 line_info_cnt;
   };
   struct {
     __aligned_u64 pathname;
@@ -301,7 +310,7 @@
     __u64 probe_addr;
   } task_fd_query;
 } __attribute__((aligned(8)));
-#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind), FN(xdp_adjust_tail), FN(skb_get_xfrm_state), FN(get_stack), FN(skb_load_bytes_relative), FN(fib_lookup), FN(sock_hash_update), FN(msg_redirect_hash), FN(sk_redirect_hash), FN(lwt_push_encap), FN(lwt_seg6_store_bytes), FN(lwt_seg6_adjust_srh), FN(lwt_seg6_action), FN(rc_repeat), FN(rc_keydown), FN(skb_cgroup_id), FN(get_current_cgroup_id), FN(get_local_storage), FN(sk_select_reuseport), FN(skb_ancestor_cgroup_id), FN(sk_lookup_tcp), FN(sk_lookup_udp), FN(sk_release), FN(map_push_elem), FN(map_pop_elem), FN(map_peek_elem), FN(msg_push_data),
+#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind), FN(xdp_adjust_tail), FN(skb_get_xfrm_state), FN(get_stack), FN(skb_load_bytes_relative), FN(fib_lookup), FN(sock_hash_update), FN(msg_redirect_hash), FN(sk_redirect_hash), FN(lwt_push_encap), FN(lwt_seg6_store_bytes), FN(lwt_seg6_adjust_srh), FN(lwt_seg6_action), FN(rc_repeat), FN(rc_keydown), FN(skb_cgroup_id), FN(get_current_cgroup_id), FN(get_local_storage), FN(sk_select_reuseport), FN(skb_ancestor_cgroup_id), FN(sk_lookup_tcp), FN(sk_lookup_udp), FN(sk_release), FN(map_push_elem), FN(map_pop_elem), FN(map_peek_elem), FN(msg_push_data), FN(msg_pop_data), FN(rc_pointer_rel),
 #define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
 enum bpf_func_id {
   __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -368,6 +377,8 @@
   __u32 local_port;
   __u32 data_meta;
   __bpf_md_ptr(struct bpf_flow_keys *, flow_keys);
+  __u64 tstamp;
+  __u32 wire_len;
 };
 struct bpf_tunnel_key {
   __u32 tunnel_id;
@@ -451,6 +462,7 @@
   __u32 local_ip6[4];
   __u32 remote_port;
   __u32 local_port;
+  __u32 size;
 };
 struct sk_reuseport_md {
   __bpf_md_ptr(void *, data);
@@ -483,6 +495,18 @@
   __u32 nr_jited_func_lens;
   __aligned_u64 jited_ksyms;
   __aligned_u64 jited_func_lens;
+  __u32 btf_id;
+  __u32 func_info_rec_size;
+  __aligned_u64 func_info;
+  __u32 nr_func_info;
+  __u32 nr_line_info;
+  __aligned_u64 line_info;
+  __aligned_u64 jited_line_info;
+  __u32 nr_jited_line_info;
+  __u32 line_info_rec_size;
+  __u32 jited_line_info_rec_size;
+  __u32 nr_prog_tags;
+  __aligned_u64 prog_tags;
 } __attribute__((aligned(8)));
 struct bpf_map_info {
   __u32 type;
@@ -678,4 +702,16 @@
     };
   };
 };
+struct bpf_func_info {
+  __u32 insn_off;
+  __u32 type_id;
+};
+#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10)
+#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col) & 0x3ff)
+struct bpf_line_info {
+  __u32 insn_off;
+  __u32 file_name_off;
+  __u32 line_off;
+  __u32 line_col;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/btf.h b/libc/kernel/uapi/linux/btf.h
index 33dde5a..6e13631 100644
--- a/libc/kernel/uapi/linux/btf.h
+++ b/libc/kernel/uapi/linux/btf.h
@@ -44,6 +44,7 @@
 };
 #define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
 #define BTF_INFO_VLEN(info) ((info) & 0xffff)
+#define BTF_INFO_KFLAG(info) ((info) >> 31)
 #define BTF_KIND_UNKN 0
 #define BTF_KIND_INT 1
 #define BTF_KIND_PTR 2
@@ -56,8 +57,10 @@
 #define BTF_KIND_VOLATILE 9
 #define BTF_KIND_CONST 10
 #define BTF_KIND_RESTRICT 11
-#define BTF_KIND_MAX 11
-#define NR_BTF_KINDS 12
+#define BTF_KIND_FUNC 12
+#define BTF_KIND_FUNC_PROTO 13
+#define BTF_KIND_MAX 13
+#define NR_BTF_KINDS 14
 #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
 #define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
 #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
@@ -78,4 +81,10 @@
   __u32 type;
   __u32 offset;
 };
+#define BTF_MEMBER_BITFIELD_SIZE(val) ((val) >> 24)
+#define BTF_MEMBER_BIT_OFFSET(val) ((val) & 0xffffff)
+struct btf_param {
+  __u32 name_off;
+  __u32 type;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/btrfs.h b/libc/kernel/uapi/linux/btrfs.h
index 2bb79d8..0dae543 100644
--- a/libc/kernel/uapi/linux/btrfs.h
+++ b/libc/kernel/uapi/linux/btrfs.h
@@ -173,6 +173,7 @@
 #define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7)
 #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8)
 #define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9)
+#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10)
 struct btrfs_ioctl_feature_flags {
   __u64 compat_flags;
   __u64 compat_ro_flags;
diff --git a/libc/kernel/uapi/linux/btrfs_tree.h b/libc/kernel/uapi/linux/btrfs_tree.h
index 6a461ec..0618f66 100644
--- a/libc/kernel/uapi/linux/btrfs_tree.h
+++ b/libc/kernel/uapi/linux/btrfs_tree.h
@@ -166,6 +166,7 @@
 #define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33)
 #define BTRFS_SUPER_FLAG_METADUMP_V2 (1ULL << 34)
 #define BTRFS_SUPER_FLAG_CHANGING_FSID (1ULL << 35)
+#define BTRFS_SUPER_FLAG_CHANGING_FSID_V2 (1ULL << 36)
 struct btrfs_extent_item {
   __le64 refs;
   __le64 generation;
diff --git a/libc/kernel/uapi/linux/cryptouser.h b/libc/kernel/uapi/linux/cryptouser.h
index 816fb05..b32db64 100644
--- a/libc/kernel/uapi/linux/cryptouser.h
+++ b/libc/kernel/uapi/linux/cryptouser.h
@@ -65,45 +65,62 @@
   __u32 cru_refcnt;
   __u32 cru_flags;
 };
-struct crypto_stat {
+struct crypto_stat_aead {
   char type[CRYPTO_MAX_NAME];
-  union {
-    __u32 stat_encrypt_cnt;
-    __u32 stat_compress_cnt;
-    __u32 stat_generate_cnt;
-    __u32 stat_hash_cnt;
-    __u32 stat_setsecret_cnt;
-  };
-  union {
-    __u64 stat_encrypt_tlen;
-    __u64 stat_compress_tlen;
-    __u64 stat_generate_tlen;
-    __u64 stat_hash_tlen;
-  };
-  union {
-    __u32 stat_akcipher_err_cnt;
-    __u32 stat_cipher_err_cnt;
-    __u32 stat_compress_err_cnt;
-    __u32 stat_aead_err_cnt;
-    __u32 stat_hash_err_cnt;
-    __u32 stat_rng_err_cnt;
-    __u32 stat_kpp_err_cnt;
-  };
-  union {
-    __u32 stat_decrypt_cnt;
-    __u32 stat_decompress_cnt;
-    __u32 stat_seed_cnt;
-    __u32 stat_generate_public_key_cnt;
-  };
-  union {
-    __u64 stat_decrypt_tlen;
-    __u64 stat_decompress_tlen;
-  };
-  union {
-    __u32 stat_verify_cnt;
-    __u32 stat_compute_shared_secret_cnt;
-  };
-  __u32 stat_sign_cnt;
+  __u64 stat_encrypt_cnt;
+  __u64 stat_encrypt_tlen;
+  __u64 stat_decrypt_cnt;
+  __u64 stat_decrypt_tlen;
+  __u64 stat_err_cnt;
+};
+struct crypto_stat_akcipher {
+  char type[CRYPTO_MAX_NAME];
+  __u64 stat_encrypt_cnt;
+  __u64 stat_encrypt_tlen;
+  __u64 stat_decrypt_cnt;
+  __u64 stat_decrypt_tlen;
+  __u64 stat_verify_cnt;
+  __u64 stat_sign_cnt;
+  __u64 stat_err_cnt;
+};
+struct crypto_stat_cipher {
+  char type[CRYPTO_MAX_NAME];
+  __u64 stat_encrypt_cnt;
+  __u64 stat_encrypt_tlen;
+  __u64 stat_decrypt_cnt;
+  __u64 stat_decrypt_tlen;
+  __u64 stat_err_cnt;
+};
+struct crypto_stat_compress {
+  char type[CRYPTO_MAX_NAME];
+  __u64 stat_compress_cnt;
+  __u64 stat_compress_tlen;
+  __u64 stat_decompress_cnt;
+  __u64 stat_decompress_tlen;
+  __u64 stat_err_cnt;
+};
+struct crypto_stat_hash {
+  char type[CRYPTO_MAX_NAME];
+  __u64 stat_hash_cnt;
+  __u64 stat_hash_tlen;
+  __u64 stat_err_cnt;
+};
+struct crypto_stat_kpp {
+  char type[CRYPTO_MAX_NAME];
+  __u64 stat_setsecret_cnt;
+  __u64 stat_generate_public_key_cnt;
+  __u64 stat_compute_shared_secret_cnt;
+  __u64 stat_err_cnt;
+};
+struct crypto_stat_rng {
+  char type[CRYPTO_MAX_NAME];
+  __u64 stat_generate_cnt;
+  __u64 stat_generate_tlen;
+  __u64 stat_seed_cnt;
+  __u64 stat_err_cnt;
+};
+struct crypto_stat_larval {
+  char type[CRYPTO_MAX_NAME];
 };
 struct crypto_report_larval {
   char type[CRYPTO_MAX_NAME];
diff --git a/libc/kernel/uapi/linux/devlink.h b/libc/kernel/uapi/linux/devlink.h
index ead40ad..7c55a0a 100644
--- a/libc/kernel/uapi/linux/devlink.h
+++ b/libc/kernel/uapi/linux/devlink.h
@@ -115,6 +115,10 @@
   __DEVLINK_PARAM_CMODE_MAX,
   DEVLINK_PARAM_CMODE_MAX = __DEVLINK_PARAM_CMODE_MAX - 1
 };
+enum devlink_param_fw_load_policy_value {
+  DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER,
+  DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH,
+};
 enum devlink_attr {
   DEVLINK_ATTR_UNSPEC,
   DEVLINK_ATTR_BUS_NAME,
diff --git a/libc/kernel/uapi/linux/elf-em.h b/libc/kernel/uapi/linux/elf-em.h
index 5b54e18..99835ae 100644
--- a/libc/kernel/uapi/linux/elf-em.h
+++ b/libc/kernel/uapi/linux/elf-em.h
@@ -45,6 +45,7 @@
 #define EM_M32R 88
 #define EM_MN10300 89
 #define EM_OPENRISC 92
+#define EM_XTENSA 94
 #define EM_BLACKFIN 106
 #define EM_ALTERA_NIOS2 113
 #define EM_TI_C6000 140
@@ -54,6 +55,7 @@
 #define EM_TILEGX 191
 #define EM_RISCV 243
 #define EM_BPF 247
+#define EM_CSKY 252
 #define EM_FRV 0x5441
 #define EM_ALPHA 0x9026
 #define EM_CYGNUS_M32R 0x9041
diff --git a/libc/kernel/uapi/linux/elf.h b/libc/kernel/uapi/linux/elf.h
index 1f69e1b..9845bd3 100644
--- a/libc/kernel/uapi/linux/elf.h
+++ b/libc/kernel/uapi/linux/elf.h
@@ -355,10 +355,12 @@
 #define NT_ARM_HW_WATCH 0x403
 #define NT_ARM_SYSTEM_CALL 0x404
 #define NT_ARM_SVE 0x405
+#define NT_ARM_PAC_MASK 0x406
 #define NT_ARC_V2 0x600
 #define NT_VMCOREDD 0x700
 #define NT_MIPS_DSP 0x800
 #define NT_MIPS_FP_MODE 0x801
+#define NT_MIPS_MSA 0x802
 typedef struct elf32_note {
   Elf32_Word n_namesz;
   Elf32_Word n_descsz;
diff --git a/libc/kernel/uapi/linux/fanotify.h b/libc/kernel/uapi/linux/fanotify.h
index 00a1871..4c33fde 100644
--- a/libc/kernel/uapi/linux/fanotify.h
+++ b/libc/kernel/uapi/linux/fanotify.h
@@ -24,9 +24,11 @@
 #define FAN_CLOSE_WRITE 0x00000008
 #define FAN_CLOSE_NOWRITE 0x00000010
 #define FAN_OPEN 0x00000020
+#define FAN_OPEN_EXEC 0x00001000
 #define FAN_Q_OVERFLOW 0x00004000
 #define FAN_OPEN_PERM 0x00010000
 #define FAN_ACCESS_PERM 0x00020000
+#define FAN_OPEN_EXEC_PERM 0x00040000
 #define FAN_ONDIR 0x40000000
 #define FAN_EVENT_ON_CHILD 0x08000000
 #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE)
diff --git a/libc/kernel/uapi/linux/fb.h b/libc/kernel/uapi/linux/fb.h
index 9f6b139..38da042 100644
--- a/libc/kernel/uapi/linux/fb.h
+++ b/libc/kernel/uapi/linux/fb.h
@@ -320,4 +320,6 @@
   struct fbcurpos hot;
   struct fb_image image;
 };
+#define FB_BACKLIGHT_LEVELS 128
+#define FB_BACKLIGHT_MAX 0xFF
 #endif
diff --git a/libc/kernel/uapi/linux/fs.h b/libc/kernel/uapi/linux/fs.h
index 5c237d8..84dc010 100644
--- a/libc/kernel/uapi/linux/fs.h
+++ b/libc/kernel/uapi/linux/fs.h
@@ -21,6 +21,7 @@
 #include <linux/limits.h>
 #include <linux/ioctl.h>
 #include <linux/types.h>
+#include <linux/mount.h>
 #undef NR_OPEN
 #define INR_OPEN_CUR 1024
 #define INR_OPEN_MAX 4096
@@ -74,40 +75,6 @@
   long dummy[5];
 };
 #define NR_FILE 8192
-#define MS_RDONLY 1
-#define MS_NOSUID 2
-#define MS_NODEV 4
-#define MS_NOEXEC 8
-#define MS_SYNCHRONOUS 16
-#define MS_REMOUNT 32
-#define MS_MANDLOCK 64
-#define MS_DIRSYNC 128
-#define MS_NOATIME 1024
-#define MS_NODIRATIME 2048
-#define MS_BIND 4096
-#define MS_MOVE 8192
-#define MS_REC 16384
-#define MS_VERBOSE 32768
-#define MS_SILENT 32768
-#define MS_POSIXACL (1 << 16)
-#define MS_UNBINDABLE (1 << 17)
-#define MS_PRIVATE (1 << 18)
-#define MS_SLAVE (1 << 19)
-#define MS_SHARED (1 << 20)
-#define MS_RELATIME (1 << 21)
-#define MS_KERNMOUNT (1 << 22)
-#define MS_I_VERSION (1 << 23)
-#define MS_STRICTATIME (1 << 24)
-#define MS_LAZYTIME (1 << 25)
-#define MS_SUBMOUNT (1 << 26)
-#define MS_NOREMOTELOCK (1 << 27)
-#define MS_NOSEC (1 << 28)
-#define MS_BORN (1 << 29)
-#define MS_ACTIVE (1 << 30)
-#define MS_NOUSER (1 << 31)
-#define MS_RMT_MASK (MS_RDONLY | MS_SYNCHRONOUS | MS_MANDLOCK | MS_I_VERSION | MS_LAZYTIME)
-#define MS_MGC_VAL 0xC0ED0000
-#define MS_MGC_MSK 0xffff0000
 struct fsxattr {
   __u32 fsx_xflags;
   __u32 fsx_extsize;
@@ -190,7 +157,8 @@
 #define FS_POLICY_FLAGS_PAD_16 0x02
 #define FS_POLICY_FLAGS_PAD_32 0x03
 #define FS_POLICY_FLAGS_PAD_MASK 0x03
-#define FS_POLICY_FLAGS_VALID 0x03
+#define FS_POLICY_FLAG_DIRECT_KEY 0x04
+#define FS_POLICY_FLAGS_VALID 0x07
 #define FS_ENCRYPTION_MODE_INVALID 0
 #define FS_ENCRYPTION_MODE_AES_256_XTS 1
 #define FS_ENCRYPTION_MODE_AES_256_GCM 2
@@ -200,6 +168,7 @@
 #define FS_ENCRYPTION_MODE_AES_128_CTS 6
 #define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7
 #define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8
+#define FS_ENCRYPTION_MODE_ADIANTUM 9
 struct fscrypt_policy {
   __u8 version;
   __u8 contents_encryption_mode;
diff --git a/libc/kernel/uapi/linux/hash_info.h b/libc/kernel/uapi/linux/hash_info.h
index 898e46f..824b71a 100644
--- a/libc/kernel/uapi/linux/hash_info.h
+++ b/libc/kernel/uapi/linux/hash_info.h
@@ -37,6 +37,8 @@
   HASH_ALGO_TGR_160,
   HASH_ALGO_TGR_192,
   HASH_ALGO_SM3_256,
+  HASH_ALGO_STREEBOG_256,
+  HASH_ALGO_STREEBOG_512,
   HASH_ALGO__LAST
 };
 #endif
diff --git a/libc/kernel/uapi/linux/if_bridge.h b/libc/kernel/uapi/linux/if_bridge.h
index 7e6a72f..31683c1 100644
--- a/libc/kernel/uapi/linux/if_bridge.h
+++ b/libc/kernel/uapi/linux/if_bridge.h
@@ -237,4 +237,12 @@
   __u64 mcast_bytes[BR_MCAST_DIR_SIZE];
   __u64 mcast_packets[BR_MCAST_DIR_SIZE];
 };
+enum br_boolopt_id {
+  BR_BOOLOPT_NO_LL_LEARN,
+  BR_BOOLOPT_MAX
+};
+struct br_boolopt_multi {
+  __u32 optval;
+  __u32 optmask;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index 2c80d3d..416c48b 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -221,6 +221,7 @@
   IFLA_BR_MCAST_IGMP_VERSION,
   IFLA_BR_MCAST_MLD_VERSION,
   IFLA_BR_VLAN_STATS_PER_PORT,
+  IFLA_BR_MULTI_BOOLOPT,
   __IFLA_BR_MAX,
 };
 #define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
@@ -426,6 +427,7 @@
   IFLA_VXLAN_LABEL,
   IFLA_VXLAN_GPE,
   IFLA_VXLAN_TTL_INHERIT,
+  IFLA_VXLAN_DF,
   __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -433,6 +435,13 @@
   __be16 low;
   __be16 high;
 };
+enum ifla_vxlan_df {
+  VXLAN_DF_UNSET = 0,
+  VXLAN_DF_SET,
+  VXLAN_DF_INHERIT,
+  __VXLAN_DF_END,
+  VXLAN_DF_MAX = __VXLAN_DF_END - 1,
+};
 enum {
   IFLA_GENEVE_UNSPEC,
   IFLA_GENEVE_ID,
@@ -447,9 +456,17 @@
   IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
   IFLA_GENEVE_LABEL,
   IFLA_GENEVE_TTL_INHERIT,
+  IFLA_GENEVE_DF,
   __IFLA_GENEVE_MAX
 };
 #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
+enum ifla_geneve_df {
+  GENEVE_DF_UNSET = 0,
+  GENEVE_DF_SET,
+  GENEVE_DF_INHERIT,
+  __GENEVE_DF_END,
+  GENEVE_DF_MAX = __GENEVE_DF_END - 1,
+};
 enum {
   IFLA_PPP_UNSPEC,
   IFLA_PPP_DEV_FD,
diff --git a/libc/kernel/uapi/linux/if_tun.h b/libc/kernel/uapi/linux/if_tun.h
index 6a3c75e..cb2d2d2 100644
--- a/libc/kernel/uapi/linux/if_tun.h
+++ b/libc/kernel/uapi/linux/if_tun.h
@@ -51,6 +51,7 @@
 #define TUNGETVNETBE _IOR('T', 223, int)
 #define TUNSETSTEERINGEBPF _IOR('T', 224, int)
 #define TUNSETFILTEREBPF _IOR('T', 225, int)
+#define TUNSETCARRIER _IOW('T', 226, int)
 #define IFF_TUN 0x0001
 #define IFF_TAP 0x0002
 #define IFF_NAPI 0x0010
diff --git a/libc/kernel/uapi/linux/in.h b/libc/kernel/uapi/linux/in.h
index 78bd72a..9ed00b4 100644
--- a/libc/kernel/uapi/linux/in.h
+++ b/libc/kernel/uapi/linux/in.h
@@ -201,7 +201,7 @@
 #define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
 #define IN_MULTICAST(a) IN_CLASSD(a)
 #define IN_MULTICAST_NET 0xe0000000
-#define IN_BADCLASS(a) (((long int) (a)) == (long int)0xffffffff)
+#define IN_BADCLASS(a) (((long int) (a)) == (long int) 0xffffffff)
 #define IN_EXPERIMENTAL(a) IN_BADCLASS((a))
 #define IN_CLASSE(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
 #define IN_CLASSE_NET 0xffffffff
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index 11e6d5b..1ca3cb0 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -623,6 +623,8 @@
 #define REL_WHEEL 0x08
 #define REL_MISC 0x09
 #define REL_RESERVED 0x0a
+#define REL_WHEEL_HI_RES 0x0b
+#define REL_HWHEEL_HI_RES 0x0c
 #define REL_MAX 0x0f
 #define REL_CNT (REL_MAX + 1)
 #define ABS_X 0x00
diff --git a/libc/kernel/uapi/linux/input.h b/libc/kernel/uapi/linux/input.h
index 0a4b563..f138f64 100644
--- a/libc/kernel/uapi/linux/input.h
+++ b/libc/kernel/uapi/linux/input.h
@@ -24,13 +24,17 @@
 #include <linux/types.h>
 #include "input-event-codes.h"
 struct input_event {
-#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL)
+#if __BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)
   struct timeval time;
 #define input_event_sec time.tv_sec
 #define input_event_usec time.tv_usec
 #else
   __kernel_ulong_t __sec;
+#if defined(__sparc__) && defined(__arch64__)
+  unsigned int __usec;
+#else
   __kernel_ulong_t __usec;
+#endif
 #define input_event_sec __sec
 #define input_event_usec __usec
 #endif
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index 525f672..5e20606 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -261,6 +261,20 @@
   __u32 n_devices;
   __u32 n_success;
 };
+struct kfd_ioctl_get_dmabuf_info_args {
+  __u64 size;
+  __u64 metadata_ptr;
+  __u32 metadata_size;
+  __u32 gpu_id;
+  __u32 flags;
+  __u32 dmabuf_fd;
+};
+struct kfd_ioctl_import_dmabuf_args {
+  __u64 va_addr;
+  __u64 handle;
+  __u32 gpu_id;
+  __u32 dmabuf_fd;
+};
 #define AMDKFD_IOCTL_BASE 'K'
 #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr)
 #define AMDKFD_IOR(nr,type) _IOR(AMDKFD_IOCTL_BASE, nr, type)
@@ -293,6 +307,8 @@
 #define AMDKFD_IOC_UNMAP_MEMORY_FROM_GPU AMDKFD_IOWR(0x19, struct kfd_ioctl_unmap_memory_from_gpu_args)
 #define AMDKFD_IOC_SET_CU_MASK AMDKFD_IOW(0x1A, struct kfd_ioctl_set_cu_mask_args)
 #define AMDKFD_IOC_GET_QUEUE_WAVE_STATE AMDKFD_IOWR(0x1B, struct kfd_ioctl_get_queue_wave_state_args)
+#define AMDKFD_IOC_GET_DMABUF_INFO AMDKFD_IOWR(0x1C, struct kfd_ioctl_get_dmabuf_info_args)
+#define AMDKFD_IOC_IMPORT_DMABUF AMDKFD_IOWR(0x1D, struct kfd_ioctl_import_dmabuf_args)
 #define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x1C
+#define AMDKFD_COMMAND_END 0x1E
 #endif
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index b70bcd9..8cfa34d 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -367,6 +367,15 @@
     __u64 padding2;
   };
 };
+struct kvm_clear_dirty_log {
+  __u32 slot;
+  __u32 num_pages;
+  __u64 first_page;
+  union {
+    void __user * dirty_bitmap;
+    __u64 padding2;
+  };
+};
 struct kvm_signal_mask {
   __u32 len;
   __u8 sigset[0];
@@ -759,6 +768,8 @@
 #define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163
 #define KVM_CAP_EXCEPTION_PAYLOAD 164
 #define KVM_CAP_ARM_VM_IPA_SIZE 165
+#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
+#define KVM_CAP_HYPERV_CPUID 167
 #ifdef KVM_CAP_IRQ_ROUTING
 struct kvm_irq_routing_irqchip {
   __u32 irqchip;
@@ -1070,6 +1081,8 @@
 #define KVM_HYPERV_EVENTFD _IOW(KVMIO, 0xbd, struct kvm_hyperv_eventfd)
 #define KVM_GET_NESTED_STATE _IOWR(KVMIO, 0xbe, struct kvm_nested_state)
 #define KVM_SET_NESTED_STATE _IOW(KVMIO, 0xbf, struct kvm_nested_state)
+#define KVM_CLEAR_DIRTY_LOG _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log)
+#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
 enum sev_cmd_id {
   KVM_SEV_INIT = 0,
   KVM_SEV_ES_INIT,
diff --git a/libc/kernel/uapi/linux/magic.h b/libc/kernel/uapi/linux/magic.h
index bf57a58..f3b337e 100644
--- a/libc/kernel/uapi/linux/magic.h
+++ b/libc/kernel/uapi/linux/magic.h
@@ -78,6 +78,7 @@
 #define DAXFS_MAGIC 0x64646178
 #define BINFMTFS_MAGIC 0x42494e4d
 #define DEVPTS_SUPER_MAGIC 0x1cd1
+#define BINDERFS_SUPER_MAGIC 0x6c6f6f70
 #define FUTEXFS_SUPER_MAGIC 0xBAD1DEA
 #define PIPEFS_MAGIC 0x50495045
 #define PROC_SUPER_MAGIC 0x9fa0
diff --git a/libc/kernel/uapi/linux/mount.h b/libc/kernel/uapi/linux/mount.h
new file mode 100644
index 0000000..54a4719
--- /dev/null
+++ b/libc/kernel/uapi/linux/mount.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_MOUNT_H
+#define _UAPI_LINUX_MOUNT_H
+#define MS_RDONLY 1
+#define MS_NOSUID 2
+#define MS_NODEV 4
+#define MS_NOEXEC 8
+#define MS_SYNCHRONOUS 16
+#define MS_REMOUNT 32
+#define MS_MANDLOCK 64
+#define MS_DIRSYNC 128
+#define MS_NOATIME 1024
+#define MS_NODIRATIME 2048
+#define MS_BIND 4096
+#define MS_MOVE 8192
+#define MS_REC 16384
+#define MS_VERBOSE 32768
+#define MS_SILENT 32768
+#define MS_POSIXACL (1 << 16)
+#define MS_UNBINDABLE (1 << 17)
+#define MS_PRIVATE (1 << 18)
+#define MS_SLAVE (1 << 19)
+#define MS_SHARED (1 << 20)
+#define MS_RELATIME (1 << 21)
+#define MS_KERNMOUNT (1 << 22)
+#define MS_I_VERSION (1 << 23)
+#define MS_STRICTATIME (1 << 24)
+#define MS_LAZYTIME (1 << 25)
+#define MS_SUBMOUNT (1 << 26)
+#define MS_NOREMOTELOCK (1 << 27)
+#define MS_NOSEC (1 << 28)
+#define MS_BORN (1 << 29)
+#define MS_ACTIVE (1 << 30)
+#define MS_NOUSER (1 << 31)
+#define MS_RMT_MASK (MS_RDONLY | MS_SYNCHRONOUS | MS_MANDLOCK | MS_I_VERSION | MS_LAZYTIME)
+#define MS_MGC_VAL 0xC0ED0000
+#define MS_MGC_MSK 0xffff0000
+#endif
diff --git a/libc/kernel/uapi/linux/msdos_fs.h b/libc/kernel/uapi/linux/msdos_fs.h
index 60ee22a..4b777db 100644
--- a/libc/kernel/uapi/linux/msdos_fs.h
+++ b/libc/kernel/uapi/linux/msdos_fs.h
@@ -57,12 +57,10 @@
 #define MSDOS_SLOTS 21
 #define MSDOS_DOT ".          "
 #define MSDOS_DOTDOT "..         "
-#define FAT_FIRST_ENT(s,x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x))
 #define FAT_START_ENT 2
 #define MAX_FAT12 0xFF4
 #define MAX_FAT16 0xFFF4
 #define MAX_FAT32 0x0FFFFFF6
-#define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12)
 #define BAD_FAT12 0xFF7
 #define BAD_FAT16 0xFFF7
 #define BAD_FAT32 0x0FFFFFF7
@@ -108,7 +106,7 @@
       __u8 state;
       __u8 signature;
       __u8 vol_id[4];
-      __u8 vol_label[11];
+      __u8 vol_label[MSDOS_NAME];
       __u8 fs_type[8];
     } fat16;
     struct {
@@ -123,7 +121,7 @@
       __u8 state;
       __u8 signature;
       __u8 vol_id[4];
-      __u8 vol_label[11];
+      __u8 vol_label[MSDOS_NAME];
       __u8 fs_type[8];
     } fat32;
   };
diff --git a/libc/kernel/uapi/linux/ncsi.h b/libc/kernel/uapi/linux/ncsi.h
index 23cdf1b..6334a8a 100644
--- a/libc/kernel/uapi/linux/ncsi.h
+++ b/libc/kernel/uapi/linux/ncsi.h
@@ -24,6 +24,8 @@
   NCSI_CMD_SET_INTERFACE,
   NCSI_CMD_CLEAR_INTERFACE,
   NCSI_CMD_SEND_CMD,
+  NCSI_CMD_SET_PACKAGE_MASK,
+  NCSI_CMD_SET_CHANNEL_MASK,
   __NCSI_CMD_AFTER_LAST,
   NCSI_CMD_MAX = __NCSI_CMD_AFTER_LAST - 1
 };
@@ -34,6 +36,9 @@
   NCSI_ATTR_PACKAGE_ID,
   NCSI_ATTR_CHANNEL_ID,
   NCSI_ATTR_DATA,
+  NCSI_ATTR_MULTI_FLAG,
+  NCSI_ATTR_PACKAGE_MASK,
+  NCSI_ATTR_CHANNEL_MASK,
   __NCSI_ATTR_AFTER_LAST,
   NCSI_ATTR_MAX = __NCSI_ATTR_AFTER_LAST - 1
 };
diff --git a/libc/kernel/uapi/linux/neighbour.h b/libc/kernel/uapi/linux/neighbour.h
index 6329211..4ce4736 100644
--- a/libc/kernel/uapi/linux/neighbour.h
+++ b/libc/kernel/uapi/linux/neighbour.h
@@ -42,6 +42,7 @@
   NDA_MASTER,
   NDA_LINK_NETNSID,
   NDA_SRC_VNI,
+  NDA_PROTOCOL,
   __NDA_MAX
 };
 #define NDA_MAX (__NDA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/net_namespace.h b/libc/kernel/uapi/linux/net_namespace.h
index b1d96f6..a54c9e1 100644
--- a/libc/kernel/uapi/linux/net_namespace.h
+++ b/libc/kernel/uapi/linux/net_namespace.h
@@ -24,6 +24,8 @@
   NETNSA_NSID,
   NETNSA_PID,
   NETNSA_FD,
+  NETNSA_TARGET_NSID,
+  NETNSA_CURRENT_NSID,
   __NETNSA_MAX,
 };
 #define NETNSA_MAX (__NETNSA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/netfilter.h b/libc/kernel/uapi/linux/netfilter.h
index 5538869..345b197 100644
--- a/libc/kernel/uapi/linux/netfilter.h
+++ b/libc/kernel/uapi/linux/netfilter.h
@@ -35,8 +35,6 @@
 #define NF_VERDICT_QBITS 16
 #define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE)
 #define NF_DROP_ERR(x) (((- x) << 16) | NF_DROP)
-#define NFC_UNKNOWN 0x4000
-#define NFC_ALTERED 0x8000
 #define NF_VERDICT_BITS 16
 enum nf_inet_hooks {
   NF_INET_PRE_ROUTING,
diff --git a/libc/kernel/uapi/linux/netfilter/ipset/ip_set.h b/libc/kernel/uapi/linux/netfilter/ipset/ip_set.h
index 17107b7..2c5aeeb 100644
--- a/libc/kernel/uapi/linux/netfilter/ipset/ip_set.h
+++ b/libc/kernel/uapi/linux/netfilter/ipset/ip_set.h
@@ -19,7 +19,8 @@
 #ifndef _UAPI_IP_SET_H
 #define _UAPI_IP_SET_H
 #include <linux/types.h>
-#define IPSET_PROTOCOL 6
+#define IPSET_PROTOCOL 7
+#define IPSET_PROTOCOL_MIN 6
 #define IPSET_MAXNAMELEN 32
 #define IPSET_MAX_COMMENT_SIZE 255
 enum ipset_cmd {
@@ -37,6 +38,8 @@
   IPSET_CMD_TEST,
   IPSET_CMD_HEADER,
   IPSET_CMD_TYPE,
+  IPSET_CMD_GET_BYNAME,
+  IPSET_CMD_GET_BYINDEX,
   IPSET_MSG_MAX,
   IPSET_CMD_RESTORE = IPSET_MSG_MAX,
   IPSET_CMD_HELP,
@@ -59,6 +62,7 @@
   IPSET_ATTR_LINENO,
   IPSET_ATTR_PROTOCOL_MIN,
   IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN,
+  IPSET_ATTR_INDEX,
   __IPSET_ATTR_CMD_MAX,
 };
 #define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
diff --git a/libc/kernel/uapi/linux/netfilter_decnet.h b/libc/kernel/uapi/linux/netfilter_decnet.h
index a9dcdd3..c9c16ca 100644
--- a/libc/kernel/uapi/linux/netfilter_decnet.h
+++ b/libc/kernel/uapi/linux/netfilter_decnet.h
@@ -20,10 +20,6 @@
 #define __LINUX_DECNET_NETFILTER_H
 #include <linux/netfilter.h>
 #include <limits.h>
-#define NFC_DN_SRC 0x0001
-#define NFC_DN_DST 0x0002
-#define NFC_DN_IF_IN 0x0004
-#define NFC_DN_IF_OUT 0x0008
 #define NF_DN_NUMHOOKS 7
 #define NF_DN_PRE_ROUTING 0
 #define NF_DN_LOCAL_IN 1
diff --git a/libc/kernel/uapi/linux/netfilter_ipv4.h b/libc/kernel/uapi/linux/netfilter_ipv4.h
index 7eed768..bb2a1d9 100644
--- a/libc/kernel/uapi/linux/netfilter_ipv4.h
+++ b/libc/kernel/uapi/linux/netfilter_ipv4.h
@@ -20,18 +20,6 @@
 #define _UAPI__LINUX_IP_NETFILTER_H
 #include <linux/netfilter.h>
 #include <limits.h>
-#define NFC_IP_SRC 0x0001
-#define NFC_IP_DST 0x0002
-#define NFC_IP_IF_IN 0x0004
-#define NFC_IP_IF_OUT 0x0008
-#define NFC_IP_TOS 0x0010
-#define NFC_IP_PROTO 0x0020
-#define NFC_IP_OPTIONS 0x0040
-#define NFC_IP_FRAG 0x0080
-#define NFC_IP_TCPFLAGS 0x0100
-#define NFC_IP_SRC_PT 0x0200
-#define NFC_IP_DST_PT 0x0400
-#define NFC_IP_PROTO_UNKNOWN 0x2000
 #define NF_IP_PRE_ROUTING 0
 #define NF_IP_LOCAL_IN 1
 #define NF_IP_FORWARD 2
diff --git a/libc/kernel/uapi/linux/netfilter_ipv6.h b/libc/kernel/uapi/linux/netfilter_ipv6.h
index 2054532..f454eb6 100644
--- a/libc/kernel/uapi/linux/netfilter_ipv6.h
+++ b/libc/kernel/uapi/linux/netfilter_ipv6.h
@@ -20,18 +20,6 @@
 #define _UAPI__LINUX_IP6_NETFILTER_H
 #include <linux/netfilter.h>
 #include <limits.h>
-#define NFC_IP6_SRC 0x0001
-#define NFC_IP6_DST 0x0002
-#define NFC_IP6_IF_IN 0x0004
-#define NFC_IP6_IF_OUT 0x0008
-#define NFC_IP6_TOS 0x0010
-#define NFC_IP6_PROTO 0x0020
-#define NFC_IP6_OPTIONS 0x0040
-#define NFC_IP6_FRAG 0x0080
-#define NFC_IP6_TCPFLAGS 0x0100
-#define NFC_IP6_SRC_PT 0x0200
-#define NFC_IP6_DST_PT 0x0400
-#define NFC_IP6_PROTO_UNKNOWN 0x2000
 #define NF_IP6_PRE_ROUTING 0
 #define NF_IP6_LOCAL_IN 1
 #define NF_IP6_FORWARD 2
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index 471e65f..29a7b66 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -164,6 +164,10 @@
   NL80211_CMD_STA_OPMODE_CHANGED,
   NL80211_CMD_CONTROL_PORT_FRAME,
   NL80211_CMD_GET_FTM_RESPONDER_STATS,
+  NL80211_CMD_PEER_MEASUREMENT_START,
+  NL80211_CMD_PEER_MEASUREMENT_RESULT,
+  NL80211_CMD_PEER_MEASUREMENT_COMPLETE,
+  NL80211_CMD_NOTIFY_RADAR,
   __NL80211_CMD_AFTER_LAST,
   NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
 };
@@ -452,6 +456,8 @@
   NL80211_ATTR_HE_CAPABILITY,
   NL80211_ATTR_FTM_RESPONDER,
   NL80211_ATTR_FTM_RESPONDER_STATS,
+  NL80211_ATTR_TIMEOUT,
+  NL80211_ATTR_PEER_MEASUREMENTS,
   __NL80211_ATTR_AFTER_LAST,
   NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
   NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -621,6 +627,7 @@
   NL80211_STA_INFO_ACK_SIGNAL_AVG,
   NL80211_STA_INFO_RX_MPDUS,
   NL80211_STA_INFO_FCS_ERROR_COUNT,
+  NL80211_STA_INFO_CONNECTED_TO_GATE,
   __NL80211_STA_INFO_AFTER_LAST,
   NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
 };
@@ -878,6 +885,7 @@
   NL80211_MESHCONF_POWER_MODE,
   NL80211_MESHCONF_AWAKE_WINDOW,
   NL80211_MESHCONF_PLINK_TIMEOUT,
+  NL80211_MESHCONF_CONNECTED_TO_GATE,
   __NL80211_MESHCONF_ATTR_AFTER_LAST,
   NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1
 };
@@ -1480,4 +1488,122 @@
   __NL80211_FTM_STATS_AFTER_LAST,
   NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1
 };
+enum nl80211_preamble {
+  NL80211_PREAMBLE_LEGACY,
+  NL80211_PREAMBLE_HT,
+  NL80211_PREAMBLE_VHT,
+  NL80211_PREAMBLE_DMG,
+};
+enum nl80211_peer_measurement_type {
+  NL80211_PMSR_TYPE_INVALID,
+  NL80211_PMSR_TYPE_FTM,
+  NUM_NL80211_PMSR_TYPES,
+  NL80211_PMSR_TYPE_MAX = NUM_NL80211_PMSR_TYPES - 1
+};
+enum nl80211_peer_measurement_status {
+  NL80211_PMSR_STATUS_SUCCESS,
+  NL80211_PMSR_STATUS_REFUSED,
+  NL80211_PMSR_STATUS_TIMEOUT,
+  NL80211_PMSR_STATUS_FAILURE,
+};
+enum nl80211_peer_measurement_req {
+  __NL80211_PMSR_REQ_ATTR_INVALID,
+  NL80211_PMSR_REQ_ATTR_DATA,
+  NL80211_PMSR_REQ_ATTR_GET_AP_TSF,
+  NUM_NL80211_PMSR_REQ_ATTRS,
+  NL80211_PMSR_REQ_ATTR_MAX = NUM_NL80211_PMSR_REQ_ATTRS - 1
+};
+enum nl80211_peer_measurement_resp {
+  __NL80211_PMSR_RESP_ATTR_INVALID,
+  NL80211_PMSR_RESP_ATTR_DATA,
+  NL80211_PMSR_RESP_ATTR_STATUS,
+  NL80211_PMSR_RESP_ATTR_HOST_TIME,
+  NL80211_PMSR_RESP_ATTR_AP_TSF,
+  NL80211_PMSR_RESP_ATTR_FINAL,
+  NL80211_PMSR_RESP_ATTR_PAD,
+  NUM_NL80211_PMSR_RESP_ATTRS,
+  NL80211_PMSR_RESP_ATTR_MAX = NUM_NL80211_PMSR_RESP_ATTRS - 1
+};
+enum nl80211_peer_measurement_peer_attrs {
+  __NL80211_PMSR_PEER_ATTR_INVALID,
+  NL80211_PMSR_PEER_ATTR_ADDR,
+  NL80211_PMSR_PEER_ATTR_CHAN,
+  NL80211_PMSR_PEER_ATTR_REQ,
+  NL80211_PMSR_PEER_ATTR_RESP,
+  NUM_NL80211_PMSR_PEER_ATTRS,
+  NL80211_PMSR_PEER_ATTR_MAX = NUM_NL80211_PMSR_PEER_ATTRS - 1,
+};
+enum nl80211_peer_measurement_attrs {
+  __NL80211_PMSR_ATTR_INVALID,
+  NL80211_PMSR_ATTR_MAX_PEERS,
+  NL80211_PMSR_ATTR_REPORT_AP_TSF,
+  NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR,
+  NL80211_PMSR_ATTR_TYPE_CAPA,
+  NL80211_PMSR_ATTR_PEERS,
+  NUM_NL80211_PMSR_ATTR,
+  NL80211_PMSR_ATTR_MAX = NUM_NL80211_PMSR_ATTR - 1
+};
+enum nl80211_peer_measurement_ftm_capa {
+  __NL80211_PMSR_FTM_CAPA_ATTR_INVALID,
+  NL80211_PMSR_FTM_CAPA_ATTR_ASAP,
+  NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP,
+  NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI,
+  NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC,
+  NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
+  NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
+  NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
+  NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
+  NUM_NL80211_PMSR_FTM_CAPA_ATTR,
+  NL80211_PMSR_FTM_CAPA_ATTR_MAX = NUM_NL80211_PMSR_FTM_CAPA_ATTR - 1
+};
+enum nl80211_peer_measurement_ftm_req {
+  __NL80211_PMSR_FTM_REQ_ATTR_INVALID,
+  NL80211_PMSR_FTM_REQ_ATTR_ASAP,
+  NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE,
+  NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP,
+  NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD,
+  NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION,
+  NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST,
+  NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES,
+  NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI,
+  NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC,
+  NUM_NL80211_PMSR_FTM_REQ_ATTR,
+  NL80211_PMSR_FTM_REQ_ATTR_MAX = NUM_NL80211_PMSR_FTM_REQ_ATTR - 1
+};
+enum nl80211_peer_measurement_ftm_failure_reasons {
+  NL80211_PMSR_FTM_FAILURE_UNSPECIFIED,
+  NL80211_PMSR_FTM_FAILURE_NO_RESPONSE,
+  NL80211_PMSR_FTM_FAILURE_REJECTED,
+  NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL,
+  NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE,
+  NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP,
+  NL80211_PMSR_FTM_FAILURE_PEER_BUSY,
+  NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS,
+};
+enum nl80211_peer_measurement_ftm_resp {
+  __NL80211_PMSR_FTM_RESP_ATTR_INVALID,
+  NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
+  NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX,
+  NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS,
+  NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES,
+  NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME,
+  NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP,
+  NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION,
+  NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST,
+  NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG,
+  NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD,
+  NL80211_PMSR_FTM_RESP_ATTR_TX_RATE,
+  NL80211_PMSR_FTM_RESP_ATTR_RX_RATE,
+  NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG,
+  NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE,
+  NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD,
+  NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG,
+  NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE,
+  NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD,
+  NL80211_PMSR_FTM_RESP_ATTR_LCI,
+  NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC,
+  NL80211_PMSR_FTM_RESP_ATTR_PAD,
+  NUM_NL80211_PMSR_FTM_RESP_ATTR,
+  NL80211_PMSR_FTM_RESP_ATTR_MAX = NUM_NL80211_PMSR_FTM_RESP_ATTR - 1
+};
 #endif
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index ac80a0a..2018f0b 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -389,6 +389,10 @@
   TCA_FLOWER_KEY_ENC_OPTS,
   TCA_FLOWER_KEY_ENC_OPTS_MASK,
   TCA_FLOWER_IN_HW_COUNT,
+  TCA_FLOWER_KEY_PORT_SRC_MIN,
+  TCA_FLOWER_KEY_PORT_SRC_MAX,
+  TCA_FLOWER_KEY_PORT_DST_MIN,
+  TCA_FLOWER_KEY_PORT_DST_MAX,
   __TCA_FLOWER_MAX,
 };
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
@@ -410,6 +414,7 @@
   TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
   TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
 };
+#define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0)
 enum {
   TCA_MATCHALL_UNSPEC,
   TCA_MATCHALL_CLASSID,
diff --git a/libc/kernel/uapi/linux/pkt_sched.h b/libc/kernel/uapi/linux/pkt_sched.h
index e7d4942..dc0cd2f 100644
--- a/libc/kernel/uapi/linux/pkt_sched.h
+++ b/libc/kernel/uapi/linux/pkt_sched.h
@@ -195,9 +195,33 @@
   TCA_GRED_DPS,
   TCA_GRED_MAX_P,
   TCA_GRED_LIMIT,
+  TCA_GRED_VQ_LIST,
   __TCA_GRED_MAX,
 };
 #define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
+enum {
+  TCA_GRED_VQ_ENTRY_UNSPEC,
+  TCA_GRED_VQ_ENTRY,
+  __TCA_GRED_VQ_ENTRY_MAX,
+};
+#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1)
+enum {
+  TCA_GRED_VQ_UNSPEC,
+  TCA_GRED_VQ_PAD,
+  TCA_GRED_VQ_DP,
+  TCA_GRED_VQ_STAT_BYTES,
+  TCA_GRED_VQ_STAT_PACKETS,
+  TCA_GRED_VQ_STAT_BACKLOG,
+  TCA_GRED_VQ_STAT_PROB_DROP,
+  TCA_GRED_VQ_STAT_PROB_MARK,
+  TCA_GRED_VQ_STAT_FORCED_DROP,
+  TCA_GRED_VQ_STAT_FORCED_MARK,
+  TCA_GRED_VQ_STAT_PDROP,
+  TCA_GRED_VQ_STAT_OTHER,
+  TCA_GRED_VQ_FLAGS,
+  __TCA_GRED_VQ_MAX
+};
+#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1)
 struct tc_gred_qopt {
   __u32 limit;
   __u32 qth_min;
@@ -639,6 +663,7 @@
   TCA_FQ_FLOW_REFILL_DELAY,
   TCA_FQ_ORPHAN_MASK,
   TCA_FQ_LOW_RATE_THRESHOLD,
+  TCA_FQ_CE_THRESHOLD,
   __TCA_FQ_MAX
 };
 #define TCA_FQ_MAX (__TCA_FQ_MAX - 1)
@@ -655,6 +680,7 @@
   __u32 inactive_flows;
   __u32 throttled_flows;
   __u32 unthrottle_latency_ns;
+  __u64 ce_mark;
 };
 enum {
   TCA_HHF_UNSPEC,
diff --git a/libc/kernel/uapi/linux/prctl.h b/libc/kernel/uapi/linux/prctl.h
index 44a088d..5031e8d 100644
--- a/libc/kernel/uapi/linux/prctl.h
+++ b/libc/kernel/uapi/linux/prctl.h
@@ -143,4 +143,10 @@
 #define PR_SPEC_ENABLE (1UL << 1)
 #define PR_SPEC_DISABLE (1UL << 2)
 #define PR_SPEC_FORCE_DISABLE (1UL << 3)
+#define PR_PAC_RESET_KEYS 54
+#define PR_PAC_APIAKEY (1UL << 0)
+#define PR_PAC_APIBKEY (1UL << 1)
+#define PR_PAC_APDAKEY (1UL << 2)
+#define PR_PAC_APDBKEY (1UL << 3)
+#define PR_PAC_APGAKEY (1UL << 4)
 #endif
diff --git a/libc/kernel/uapi/linux/ptp_clock.h b/libc/kernel/uapi/linux/ptp_clock.h
index f32dcf0..bef3fe2 100644
--- a/libc/kernel/uapi/linux/ptp_clock.h
+++ b/libc/kernel/uapi/linux/ptp_clock.h
@@ -56,6 +56,11 @@
   unsigned int rsv[3];
   struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
 };
+struct ptp_sys_offset_extended {
+  unsigned int n_samples;
+  unsigned int rsv[3];
+  struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
+};
 struct ptp_sys_offset_precise {
   struct ptp_clock_time device;
   struct ptp_clock_time sys_realtime;
@@ -84,6 +89,7 @@
 #define PTP_PIN_GETFUNC _IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
 #define PTP_PIN_SETFUNC _IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
 #define PTP_SYS_OFFSET_PRECISE _IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
+#define PTP_SYS_OFFSET_EXTENDED _IOWR(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
 struct ptp_extts_event {
   struct ptp_clock_time t;
   unsigned int index;
diff --git a/libc/kernel/uapi/linux/sctp.h b/libc/kernel/uapi/linux/sctp.h
index dc07d78..66fde70 100644
--- a/libc/kernel/uapi/linux/sctp.h
+++ b/libc/kernel/uapi/linux/sctp.h
@@ -83,6 +83,7 @@
 #define SCTP_STREAM_SCHEDULER_VALUE 124
 #define SCTP_INTERLEAVING_SUPPORTED 125
 #define SCTP_SENDMSG_CONNECT 126
+#define SCTP_EVENT 127
 #define SCTP_PR_SCTP_NONE 0x0000
 #define SCTP_PR_SCTP_TTL 0x0010
 #define SCTP_PR_SCTP_RTX 0x0020
@@ -360,6 +361,8 @@
 };
 enum sctp_sn_type {
   SCTP_SN_TYPE_BASE = (1 << 15),
+  SCTP_DATA_IO_EVENT = SCTP_SN_TYPE_BASE,
+#define SCTP_DATA_IO_EVENT SCTP_DATA_IO_EVENT
   SCTP_ASSOC_CHANGE,
 #define SCTP_ASSOC_CHANGE SCTP_ASSOC_CHANGE
   SCTP_PEER_ADDR_CHANGE,
@@ -384,6 +387,8 @@
 #define SCTP_ASSOC_RESET_EVENT SCTP_ASSOC_RESET_EVENT
   SCTP_STREAM_CHANGE_EVENT,
 #define SCTP_STREAM_CHANGE_EVENT SCTP_STREAM_CHANGE_EVENT
+  SCTP_SN_TYPE_MAX = SCTP_STREAM_CHANGE_EVENT,
+#define SCTP_SN_TYPE_MAX SCTP_SN_TYPE_MAX
 };
 typedef enum sctp_sn_error {
   SCTP_FAILED_THRESHOLD,
@@ -655,6 +660,11 @@
   uint16_t sas_instrms;
   uint16_t sas_outstrms;
 };
+struct sctp_event {
+  sctp_assoc_t se_assoc_id;
+  uint16_t se_type;
+  uint8_t se_on;
+};
 enum sctp_sched_type {
   SCTP_SS_FCFS,
   SCTP_SS_DEFAULT = SCTP_SS_FCFS,
diff --git a/libc/kernel/uapi/linux/seccomp.h b/libc/kernel/uapi/linux/seccomp.h
index fe63789..a1e577d 100644
--- a/libc/kernel/uapi/linux/seccomp.h
+++ b/libc/kernel/uapi/linux/seccomp.h
@@ -26,14 +26,17 @@
 #define SECCOMP_SET_MODE_STRICT 0
 #define SECCOMP_SET_MODE_FILTER 1
 #define SECCOMP_GET_ACTION_AVAIL 2
+#define SECCOMP_GET_NOTIF_SIZES 3
 #define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
 #define SECCOMP_FILTER_FLAG_LOG (1UL << 1)
 #define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
+#define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3)
 #define SECCOMP_RET_KILL_PROCESS 0x80000000U
 #define SECCOMP_RET_KILL_THREAD 0x00000000U
 #define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD
 #define SECCOMP_RET_TRAP 0x00030000U
 #define SECCOMP_RET_ERRNO 0x00050000U
+#define SECCOMP_RET_USER_NOTIF 0x7fc00000U
 #define SECCOMP_RET_TRACE 0x7ff00000U
 #define SECCOMP_RET_LOG 0x7ffc0000U
 #define SECCOMP_RET_ALLOW 0x7fff0000U
@@ -46,4 +49,29 @@
   __u64 instruction_pointer;
   __u64 args[6];
 };
+struct seccomp_notif_sizes {
+  __u16 seccomp_notif;
+  __u16 seccomp_notif_resp;
+  __u16 seccomp_data;
+};
+struct seccomp_notif {
+  __u64 id;
+  __u32 pid;
+  __u32 flags;
+  struct seccomp_data data;
+};
+struct seccomp_notif_resp {
+  __u64 id;
+  __s64 val;
+  __s32 error;
+  __u32 flags;
+};
+#define SECCOMP_IOC_MAGIC '!'
+#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
+#define SECCOMP_IOR(nr,type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
+#define SECCOMP_IOW(nr,type) _IOW(SECCOMP_IOC_MAGIC, nr, type)
+#define SECCOMP_IOWR(nr,type) _IOWR(SECCOMP_IOC_MAGIC, nr, type)
+#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
+#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, struct seccomp_notif_resp)
+#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOR(2, __u64)
 #endif
diff --git a/libc/kernel/uapi/linux/serial_core.h b/libc/kernel/uapi/linux/serial_core.h
index f0f464b..b9af467 100644
--- a/libc/kernel/uapi/linux/serial_core.h
+++ b/libc/kernel/uapi/linux/serial_core.h
@@ -134,4 +134,5 @@
 #define PORT_PIC32 115
 #define PORT_MPS2UART 116
 #define PORT_MTK_BTIF 117
+#define PORT_RDA 118
 #endif
diff --git a/libc/kernel/uapi/linux/snmp.h b/libc/kernel/uapi/linux/snmp.h
index ae24f0f..75dea54 100644
--- a/libc/kernel/uapi/linux/snmp.h
+++ b/libc/kernel/uapi/linux/snmp.h
@@ -210,6 +210,7 @@
   LINUX_MIB_TCPREQQFULLDROP,
   LINUX_MIB_TCPRETRANSFAIL,
   LINUX_MIB_TCPRCVCOALESCE,
+  LINUX_MIB_TCPBACKLOGCOALESCE,
   LINUX_MIB_TCPOFOQUEUE,
   LINUX_MIB_TCPOFODROP,
   LINUX_MIB_TCPOFOMERGE,
diff --git a/libc/kernel/uapi/linux/sysctl.h b/libc/kernel/uapi/linux/sysctl.h
index 24d8362..ae0f44a 100644
--- a/libc/kernel/uapi/linux/sysctl.h
+++ b/libc/kernel/uapi/linux/sysctl.h
@@ -124,6 +124,7 @@
   KERN_NMI_WATCHDOG = 75,
   KERN_PANIC_ON_NMI = 76,
   KERN_PANIC_ON_WARN = 77,
+  KERN_PANIC_PRINT = 78,
 };
 enum {
   VM_UNUSED1 = 1,
diff --git a/libc/kernel/uapi/linux/tcp.h b/libc/kernel/uapi/linux/tcp.h
index d940f0f..ce3d735 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -207,6 +207,7 @@
   TCP_NLA_BYTES_RETRANS,
   TCP_NLA_DSACK_DUPS,
   TCP_NLA_REORD_SEEN,
+  TCP_NLA_SRTT,
 };
 #define TCP_MD5SIG_MAXKEYLEN 80
 #define TCP_MD5SIG_FLAG_PREFIX 1
diff --git a/libc/kernel/uapi/linux/udp.h b/libc/kernel/uapi/linux/udp.h
index 3cd286b..278cf6c 100644
--- a/libc/kernel/uapi/linux/udp.h
+++ b/libc/kernel/uapi/linux/udp.h
@@ -30,6 +30,7 @@
 #define UDP_NO_CHECK6_TX 101
 #define UDP_NO_CHECK6_RX 102
 #define UDP_SEGMENT 103
+#define UDP_GRO 104
 #define UDP_ENCAP_ESPINUDP_NON_IKE 1
 #define UDP_ENCAP_ESPINUDP 2
 #define UDP_ENCAP_L2TPINUDP 3
diff --git a/libc/kernel/uapi/linux/v4l2-common.h b/libc/kernel/uapi/linux/v4l2-common.h
index 779bda9..021be85 100644
--- a/libc/kernel/uapi/linux/v4l2-common.h
+++ b/libc/kernel/uapi/linux/v4l2-common.h
@@ -27,18 +27,9 @@
 #define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101
 #define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102
 #define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103
-#define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP
-#define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE
-#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL V4L2_SEL_TGT_CROP
-#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL V4L2_SEL_TGT_COMPOSE
-#define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS V4L2_SEL_TGT_CROP_BOUNDS
-#define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS V4L2_SEL_TGT_COMPOSE_BOUNDS
 #define V4L2_SEL_FLAG_GE (1 << 0)
 #define V4L2_SEL_FLAG_LE (1 << 1)
 #define V4L2_SEL_FLAG_KEEP_CONFIG (1 << 2)
-#define V4L2_SUBDEV_SEL_FLAG_SIZE_GE V4L2_SEL_FLAG_GE
-#define V4L2_SUBDEV_SEL_FLAG_SIZE_LE V4L2_SEL_FLAG_LE
-#define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG V4L2_SEL_FLAG_KEEP_CONFIG
 struct v4l2_edid {
   __u32 pad;
   __u32 start_block;
@@ -46,4 +37,13 @@
   __u32 reserved[5];
   __u8 * edid;
 };
+#define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP
+#define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE
+#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL V4L2_SEL_TGT_CROP
+#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL V4L2_SEL_TGT_COMPOSE
+#define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS V4L2_SEL_TGT_CROP_BOUNDS
+#define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS V4L2_SEL_TGT_COMPOSE_BOUNDS
+#define V4L2_SUBDEV_SEL_FLAG_SIZE_GE V4L2_SEL_FLAG_GE
+#define V4L2_SUBDEV_SEL_FLAG_SIZE_LE V4L2_SEL_FLAG_LE
+#define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG V4L2_SEL_FLAG_KEEP_CONFIG
 #endif
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 6b1ef1b..6ec3412 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,5 +16,5 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#define LINUX_VERSION_CODE 267265
+#define LINUX_VERSION_CODE 327680
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/libc/kernel/uapi/linux/vfio.h b/libc/kernel/uapi/linux/vfio.h
index d282a52..b947abc 100644
--- a/libc/kernel/uapi/linux/vfio.h
+++ b/libc/kernel/uapi/linux/vfio.h
@@ -114,7 +114,20 @@
 #define VFIO_DEVICE_GFX_LINK_STATE_UP 1
 #define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2
 };
+#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1)
+#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1)
 #define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
+#define VFIO_REGION_INFO_CAP_NVLINK2_SSATGT 4
+struct vfio_region_info_cap_nvlink2_ssatgt {
+  struct vfio_info_cap_header header;
+  __u64 tgt;
+};
+#define VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD 5
+struct vfio_region_info_cap_nvlink2_lnkspd {
+  struct vfio_info_cap_header header;
+  __u32 link_speed;
+  __u32 __pad;
+};
 struct vfio_irq_info {
   __u32 argsz;
   __u32 flags;
diff --git a/libc/kernel/uapi/linux/vhost.h b/libc/kernel/uapi/linux/vhost.h
index e802e02..9e87e6e 100644
--- a/libc/kernel/uapi/linux/vhost.h
+++ b/libc/kernel/uapi/linux/vhost.h
@@ -18,71 +18,9 @@
  ****************************************************************************/
 #ifndef _LINUX_VHOST_H
 #define _LINUX_VHOST_H
+#include <linux/vhost_types.h>
 #include <linux/types.h>
-#include <linux/compiler.h>
 #include <linux/ioctl.h>
-#include <linux/virtio_config.h>
-#include <linux/virtio_ring.h>
-struct vhost_vring_state {
-  unsigned int index;
-  unsigned int num;
-};
-struct vhost_vring_file {
-  unsigned int index;
-  int fd;
-};
-struct vhost_vring_addr {
-  unsigned int index;
-  unsigned int flags;
-#define VHOST_VRING_F_LOG 0
-  __u64 desc_user_addr;
-  __u64 used_user_addr;
-  __u64 avail_user_addr;
-  __u64 log_guest_addr;
-};
-struct vhost_iotlb_msg {
-  __u64 iova;
-  __u64 size;
-  __u64 uaddr;
-#define VHOST_ACCESS_RO 0x1
-#define VHOST_ACCESS_WO 0x2
-#define VHOST_ACCESS_RW 0x3
-  __u8 perm;
-#define VHOST_IOTLB_MISS 1
-#define VHOST_IOTLB_UPDATE 2
-#define VHOST_IOTLB_INVALIDATE 3
-#define VHOST_IOTLB_ACCESS_FAIL 4
-  __u8 type;
-};
-#define VHOST_IOTLB_MSG 0x1
-#define VHOST_IOTLB_MSG_V2 0x2
-struct vhost_msg {
-  int type;
-  union {
-    struct vhost_iotlb_msg iotlb;
-    __u8 padding[64];
-  };
-};
-struct vhost_msg_v2 {
-  __u32 type;
-  __u32 reserved;
-  union {
-    struct vhost_iotlb_msg iotlb;
-    __u8 padding[64];
-  };
-};
-struct vhost_memory_region {
-  __u64 guest_phys_addr;
-  __u64 memory_size;
-  __u64 userspace_addr;
-  __u64 flags_padding;
-};
-#define VHOST_PAGE_SIZE 0x1000
-struct vhost_memory {
-  __u32 nregions;
-  __u32 padding;
-  struct vhost_memory_region regions[0];
-};
 #define VHOST_VIRTIO 0xAF
 #define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
 #define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
@@ -108,15 +46,6 @@
 #define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64)
 #define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64)
 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
-#define VHOST_F_LOG_ALL 26
-#define VHOST_NET_F_VIRTIO_NET_HDR 27
-#define VHOST_SCSI_ABI_VERSION 1
-struct vhost_scsi_target {
-  int abi_version;
-  char vhost_wwpn[224];
-  unsigned short vhost_tpgt;
-  unsigned short reserved;
-};
 #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
 #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
 #define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
diff --git a/libc/kernel/uapi/linux/vhost_types.h b/libc/kernel/uapi/linux/vhost_types.h
new file mode 100644
index 0000000..646fcdc
--- /dev/null
+++ b/libc/kernel/uapi/linux/vhost_types.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_VHOST_TYPES_H
+#define _LINUX_VHOST_TYPES_H
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+struct vhost_vring_state {
+  unsigned int index;
+  unsigned int num;
+};
+struct vhost_vring_file {
+  unsigned int index;
+  int fd;
+};
+struct vhost_vring_addr {
+  unsigned int index;
+  unsigned int flags;
+#define VHOST_VRING_F_LOG 0
+  __u64 desc_user_addr;
+  __u64 used_user_addr;
+  __u64 avail_user_addr;
+  __u64 log_guest_addr;
+};
+struct vhost_iotlb_msg {
+  __u64 iova;
+  __u64 size;
+  __u64 uaddr;
+#define VHOST_ACCESS_RO 0x1
+#define VHOST_ACCESS_WO 0x2
+#define VHOST_ACCESS_RW 0x3
+  __u8 perm;
+#define VHOST_IOTLB_MISS 1
+#define VHOST_IOTLB_UPDATE 2
+#define VHOST_IOTLB_INVALIDATE 3
+#define VHOST_IOTLB_ACCESS_FAIL 4
+  __u8 type;
+};
+#define VHOST_IOTLB_MSG 0x1
+#define VHOST_IOTLB_MSG_V2 0x2
+struct vhost_msg {
+  int type;
+  union {
+    struct vhost_iotlb_msg iotlb;
+    __u8 padding[64];
+  };
+};
+struct vhost_msg_v2 {
+  __u32 type;
+  __u32 reserved;
+  union {
+    struct vhost_iotlb_msg iotlb;
+    __u8 padding[64];
+  };
+};
+struct vhost_memory_region {
+  __u64 guest_phys_addr;
+  __u64 memory_size;
+  __u64 userspace_addr;
+  __u64 flags_padding;
+};
+#define VHOST_PAGE_SIZE 0x1000
+struct vhost_memory {
+  __u32 nregions;
+  __u32 padding;
+  struct vhost_memory_region regions[0];
+};
+#define VHOST_SCSI_ABI_VERSION 1
+struct vhost_scsi_target {
+  int abi_version;
+  char vhost_wwpn[224];
+  unsigned short vhost_tpgt;
+  unsigned short reserved;
+};
+#define VHOST_F_LOG_ALL 26
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
+#endif
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index ef89b08..74e591d 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -58,6 +58,7 @@
   V4L2_BUF_TYPE_SDR_CAPTURE = 11,
   V4L2_BUF_TYPE_SDR_OUTPUT = 12,
   V4L2_BUF_TYPE_META_CAPTURE = 13,
+  V4L2_BUF_TYPE_META_OUTPUT = 14,
   V4L2_BUF_TYPE_PRIVATE = 0x80,
 };
 #define V4L2_TYPE_IS_MULTIPLANAR(type) ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
@@ -179,6 +180,7 @@
 #define V4L2_CAP_READWRITE 0x01000000
 #define V4L2_CAP_ASYNCIO 0x02000000
 #define V4L2_CAP_STREAMING 0x04000000
+#define V4L2_CAP_META_OUTPUT 0x08000000
 #define V4L2_CAP_TOUCH 0x10000000
 #define V4L2_CAP_DEVICE_CAPS 0x80000000
 struct v4l2_pix_format {
@@ -356,6 +358,7 @@
 #define V4L2_PIX_FMT_MT21C v4l2_fourcc('M', 'T', '2', '1')
 #define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I')
 #define V4L2_PIX_FMT_SUNXI_TILED_NV12 v4l2_fourcc('S', 'T', '1', '2')
+#define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4')
 #define V4L2_PIX_FMT_IPU3_SBGGR10 v4l2_fourcc('i', 'p', '3', 'b')
 #define V4L2_PIX_FMT_IPU3_SGBRG10 v4l2_fourcc('i', 'p', '3', 'g')
 #define V4L2_PIX_FMT_IPU3_SGRBG10 v4l2_fourcc('i', 'p', '3', 'G')
@@ -481,6 +484,7 @@
 #define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
 #define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2)
 #define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3)
+#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4)
 struct v4l2_plane {
   __u32 bytesused;
   __u32 length;
diff --git a/libc/kernel/uapi/linux/virtio_blk.h b/libc/kernel/uapi/linux/virtio_blk.h
index 2d53704..5197434 100644
--- a/libc/kernel/uapi/linux/virtio_blk.h
+++ b/libc/kernel/uapi/linux/virtio_blk.h
@@ -29,6 +29,8 @@
 #define VIRTIO_BLK_F_BLK_SIZE 6
 #define VIRTIO_BLK_F_TOPOLOGY 10
 #define VIRTIO_BLK_F_MQ 12
+#define VIRTIO_BLK_F_DISCARD 13
+#define VIRTIO_BLK_F_WRITE_ZEROES 14
 #ifndef VIRTIO_BLK_NO_LEGACY
 #define VIRTIO_BLK_F_BARRIER 0
 #define VIRTIO_BLK_F_SCSI 7
@@ -54,6 +56,13 @@
   __u8 wce;
   __u8 unused;
   __u16 num_queues;
+  __u32 max_discard_sectors;
+  __u32 max_discard_seg;
+  __u32 discard_sector_alignment;
+  __u32 max_write_zeroes_sectors;
+  __u32 max_write_zeroes_seg;
+  __u8 write_zeroes_may_unmap;
+  __u8 unused1[3];
 } __attribute__((packed));
 #define VIRTIO_BLK_T_IN 0
 #define VIRTIO_BLK_T_OUT 1
@@ -62,6 +71,8 @@
 #endif
 #define VIRTIO_BLK_T_FLUSH 4
 #define VIRTIO_BLK_T_GET_ID 8
+#define VIRTIO_BLK_T_DISCARD 11
+#define VIRTIO_BLK_T_WRITE_ZEROES 13
 #ifndef VIRTIO_BLK_NO_LEGACY
 #define VIRTIO_BLK_T_BARRIER 0x80000000
 #endif
@@ -70,6 +81,12 @@
   __virtio32 ioprio;
   __virtio64 sector;
 };
+#define VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP 0x00000001
+struct virtio_blk_discard_write_zeroes {
+  __le64 sector;
+  __le32 num_sectors;
+  __le32 flags;
+};
 #ifndef VIRTIO_BLK_NO_LEGACY
 struct virtio_scsi_inhdr {
   __virtio32 errors;
diff --git a/libc/kernel/uapi/linux/virtio_config.h b/libc/kernel/uapi/linux/virtio_config.h
index ddf5e4e..c9ec83f 100644
--- a/libc/kernel/uapi/linux/virtio_config.h
+++ b/libc/kernel/uapi/linux/virtio_config.h
@@ -33,5 +33,7 @@
 #endif
 #define VIRTIO_F_VERSION_1 32
 #define VIRTIO_F_IOMMU_PLATFORM 33
+#define VIRTIO_F_RING_PACKED 34
+#define VIRTIO_F_ORDER_PLATFORM 36
 #define VIRTIO_F_SR_IOV 37
 #endif
diff --git a/libc/kernel/uapi/linux/virtio_gpu.h b/libc/kernel/uapi/linux/virtio_gpu.h
index 60dbf71..0ac7495 100644
--- a/libc/kernel/uapi/linux/virtio_gpu.h
+++ b/libc/kernel/uapi/linux/virtio_gpu.h
@@ -20,6 +20,7 @@
 #define VIRTIO_GPU_HW_H
 #include <linux/types.h>
 #define VIRTIO_GPU_F_VIRGL 0
+#define VIRTIO_GPU_F_EDID 1
 enum virtio_gpu_ctrl_type {
   VIRTIO_GPU_UNDEFINED = 0,
   VIRTIO_GPU_CMD_GET_DISPLAY_INFO = 0x0100,
@@ -32,6 +33,7 @@
   VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
   VIRTIO_GPU_CMD_GET_CAPSET_INFO,
   VIRTIO_GPU_CMD_GET_CAPSET,
+  VIRTIO_GPU_CMD_GET_EDID,
   VIRTIO_GPU_CMD_CTX_CREATE = 0x0200,
   VIRTIO_GPU_CMD_CTX_DESTROY,
   VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE,
@@ -46,6 +48,7 @@
   VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
   VIRTIO_GPU_RESP_OK_CAPSET_INFO,
   VIRTIO_GPU_RESP_OK_CAPSET,
+  VIRTIO_GPU_RESP_OK_EDID,
   VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
   VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY,
   VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID,
@@ -207,6 +210,17 @@
   struct virtio_gpu_ctrl_hdr hdr;
   __u8 capset_data[];
 };
+struct virtio_gpu_cmd_get_edid {
+  struct virtio_gpu_ctrl_hdr hdr;
+  __le32 scanout;
+  __le32 padding;
+};
+struct virtio_gpu_resp_edid {
+  struct virtio_gpu_ctrl_hdr hdr;
+  __le32 size;
+  __le32 padding;
+  __u8 edid[1024];
+};
 #define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
 struct virtio_gpu_config {
   __u32 events_read;
diff --git a/libc/kernel/uapi/linux/virtio_ring.h b/libc/kernel/uapi/linux/virtio_ring.h
index e3af401..ba75940 100644
--- a/libc/kernel/uapi/linux/virtio_ring.h
+++ b/libc/kernel/uapi/linux/virtio_ring.h
@@ -24,8 +24,14 @@
 #define VRING_DESC_F_NEXT 1
 #define VRING_DESC_F_WRITE 2
 #define VRING_DESC_F_INDIRECT 4
+#define VRING_PACKED_DESC_F_AVAIL 7
+#define VRING_PACKED_DESC_F_USED 15
 #define VRING_USED_F_NO_NOTIFY 1
 #define VRING_AVAIL_F_NO_INTERRUPT 1
+#define VRING_PACKED_EVENT_FLAG_ENABLE 0x0
+#define VRING_PACKED_EVENT_FLAG_DISABLE 0x1
+#define VRING_PACKED_EVENT_FLAG_DESC 0x2
+#define VRING_PACKED_EVENT_F_WRAP_CTR 15
 #define VIRTIO_RING_F_INDIRECT_DESC 28
 #define VIRTIO_RING_F_EVENT_IDX 29
 struct vring_desc {
@@ -59,4 +65,14 @@
 #define VRING_DESC_ALIGN_SIZE 16
 #define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
 #define vring_avail_event(vr) (* (__virtio16 *) & (vr)->used->ring[(vr)->num])
+struct vring_packed_desc_event {
+  __le16 off_wrap;
+  __le16 flags;
+};
+struct vring_packed_desc {
+  __le64 addr;
+  __le32 len;
+  __le16 id;
+  __le16 flags;
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/hfi/hfi1_user.h b/libc/kernel/uapi/rdma/hfi/hfi1_user.h
index 9148ed5..e74d837 100644
--- a/libc/kernel/uapi/rdma/hfi/hfi1_user.h
+++ b/libc/kernel/uapi/rdma/hfi/hfi1_user.h
@@ -28,6 +28,7 @@
 #define HFI1_CAP_SDMA_AHG (1UL << 2)
 #define HFI1_CAP_EXTENDED_PSN (1UL << 3)
 #define HFI1_CAP_HDRSUPP (1UL << 4)
+#define HFI1_CAP_TID_RDMA (1UL << 5)
 #define HFI1_CAP_USE_SDMA_HEAD (1UL << 6)
 #define HFI1_CAP_MULTI_PKT_EGR (1UL << 7)
 #define HFI1_CAP_NODROP_RHQ_FULL (1UL << 8)
@@ -38,6 +39,7 @@
 #define HFI1_CAP_NO_INTEGRITY (1UL << 13)
 #define HFI1_CAP_PKEY_CHECK (1UL << 14)
 #define HFI1_CAP_STATIC_RATE_CTRL (1UL << 15)
+#define HFI1_CAP_OPFN (1UL << 16)
 #define HFI1_CAP_SDMA_HEAD_CHECK (1UL << 17)
 #define HFI1_CAP_EARLY_CREDIT_RETURN (1UL << 18)
 #define HFI1_RCVHDR_ENTSIZE_2 (1UL << 0)
diff --git a/libc/kernel/uapi/rdma/hns-abi.h b/libc/kernel/uapi/rdma/hns-abi.h
index 23bedf9..0bae0d4 100644
--- a/libc/kernel/uapi/rdma/hns-abi.h
+++ b/libc/kernel/uapi/rdma/hns-abi.h
@@ -27,6 +27,15 @@
   __aligned_u64 cqn;
   __aligned_u64 cap_flags;
 };
+struct hns_roce_ib_create_srq {
+  __aligned_u64 buf_addr;
+  __aligned_u64 db_addr;
+  __aligned_u64 que_addr;
+};
+struct hns_roce_ib_create_srq_resp {
+  __u32 srqn;
+  __u32 reserved;
+};
 struct hns_roce_ib_create_qp {
   __aligned_u64 buf_addr;
   __aligned_u64 db_addr;
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
index 69ded8e..ebf8b7c 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
@@ -44,6 +44,20 @@
   UVERBS_ATTR_UHW_IN = UVERBS_UDATA_DRIVER_DATA_FLAG,
   UVERBS_ATTR_UHW_OUT,
 };
+enum uverbs_methods_device {
+  UVERBS_METHOD_INVOKE_WRITE,
+  UVERBS_METHOD_INFO_HANDLES,
+  UVERBS_METHOD_QUERY_PORT,
+};
+enum uverbs_attrs_invoke_write_cmd_attr_ids {
+  UVERBS_ATTR_CORE_IN,
+  UVERBS_ATTR_CORE_OUT,
+  UVERBS_ATTR_WRITE_CMD,
+};
+enum uverbs_attrs_query_port_cmd_attr_ids {
+  UVERBS_ATTR_QUERY_PORT_PORT_NUM,
+  UVERBS_ATTR_QUERY_PORT_RESP,
+};
 enum uverbs_attrs_create_cq_cmd_attr_ids {
   UVERBS_ATTR_CREATE_CQ_HANDLE,
   UVERBS_ATTR_CREATE_CQ_CQE,
@@ -104,6 +118,17 @@
 };
 enum uverbs_methods_mr {
   UVERBS_METHOD_DM_MR_REG,
+  UVERBS_METHOD_MR_DESTROY,
+  UVERBS_METHOD_ADVISE_MR,
+};
+enum uverbs_attrs_mr_destroy_ids {
+  UVERBS_ATTR_DESTROY_MR_HANDLE,
+};
+enum uverbs_attrs_advise_mr_cmd_attr_ids {
+  UVERBS_ATTR_ADVISE_MR_PD_HANDLE,
+  UVERBS_ATTR_ADVISE_MR_ADVICE,
+  UVERBS_ATTR_ADVISE_MR_FLAGS,
+  UVERBS_ATTR_ADVISE_MR_SGE_LIST,
 };
 enum uverbs_attrs_create_counters_cmd_attr_ids {
   UVERBS_ATTR_CREATE_COUNTERS_HANDLE,
@@ -121,4 +146,45 @@
   UVERBS_METHOD_COUNTERS_DESTROY,
   UVERBS_METHOD_COUNTERS_READ,
 };
+enum uverbs_attrs_info_handles_id {
+  UVERBS_ATTR_INFO_OBJECT_ID,
+  UVERBS_ATTR_INFO_TOTAL_HANDLES,
+  UVERBS_ATTR_INFO_HANDLES_LIST,
+};
+enum uverbs_methods_pd {
+  UVERBS_METHOD_PD_DESTROY,
+};
+enum uverbs_attrs_pd_destroy_ids {
+  UVERBS_ATTR_DESTROY_PD_HANDLE,
+};
+enum uverbs_methods_mw {
+  UVERBS_METHOD_MW_DESTROY,
+};
+enum uverbs_attrs_mw_destroy_ids {
+  UVERBS_ATTR_DESTROY_MW_HANDLE,
+};
+enum uverbs_methods_xrcd {
+  UVERBS_METHOD_XRCD_DESTROY,
+};
+enum uverbs_attrs_xrcd_destroy_ids {
+  UVERBS_ATTR_DESTROY_XRCD_HANDLE,
+};
+enum uverbs_methods_ah {
+  UVERBS_METHOD_AH_DESTROY,
+};
+enum uverbs_attrs_ah_destroy_ids {
+  UVERBS_ATTR_DESTROY_AH_HANDLE,
+};
+enum uverbs_methods_rwq_ind_tbl {
+  UVERBS_METHOD_RWQ_IND_TBL_DESTROY,
+};
+enum uverbs_attrs_rwq_ind_tbl_destroy_ids {
+  UVERBS_ATTR_DESTROY_RWQ_IND_TBL_HANDLE,
+};
+enum uverbs_methods_flow {
+  UVERBS_METHOD_FLOW_DESTROY,
+};
+enum uverbs_attrs_flow_destroy_ids {
+  UVERBS_ATTR_DESTROY_FLOW_HANDLE,
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
index 8bea1cb..47a548e 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
@@ -19,6 +19,7 @@
 #ifndef IB_USER_IOCTL_VERBS_H
 #define IB_USER_IOCTL_VERBS_H
 #include <linux/types.h>
+#include <rdma/ib_user_verbs.h>
 #ifndef RDMA_UAPI_PTR
 #define RDMA_UAPI_PTR(_type,_name) __aligned_u64 _name
 #endif
@@ -112,4 +113,16 @@
 enum ib_uverbs_read_counters_flags {
   IB_UVERBS_READ_COUNTERS_PREFER_CACHED = 1 << 0,
 };
+enum ib_uverbs_advise_mr_advice {
+  IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH,
+  IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_WRITE,
+};
+enum ib_uverbs_advise_mr_flag {
+  IB_UVERBS_ADVISE_MR_FLAG_FLUSH = 1 << 0,
+};
+struct ib_uverbs_query_port_resp_ex {
+  struct ib_uverbs_query_port_resp legacy_resp;
+  __u16 port_cap_flags2;
+  __u8 reserved[6];
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/ib_user_verbs.h b/libc/kernel/uapi/rdma/ib_user_verbs.h
index 6ca4413..3154b7a 100644
--- a/libc/kernel/uapi/rdma/ib_user_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_verbs.h
@@ -21,7 +21,7 @@
 #include <linux/types.h>
 #define IB_USER_VERBS_ABI_VERSION 6
 #define IB_USER_VERBS_CMD_THRESHOLD 50
-enum {
+enum ib_uverbs_write_cmds {
   IB_USER_VERBS_CMD_GET_CONTEXT,
   IB_USER_VERBS_CMD_QUERY_DEVICE,
   IB_USER_VERBS_CMD_QUERY_PORT,
@@ -111,6 +111,7 @@
 struct ib_uverbs_get_context_resp {
   __u32 async_fd;
   __u32 num_comp_vectors;
+  __aligned_u64 driver_data[0];
 };
 struct ib_uverbs_query_device {
   __aligned_u64 response;
@@ -237,6 +238,7 @@
 };
 struct ib_uverbs_alloc_pd_resp {
   __u32 pd_handle;
+  __u32 driver_data[0];
 };
 struct ib_uverbs_dealloc_pd {
   __u32 pd_handle;
@@ -249,6 +251,7 @@
 };
 struct ib_uverbs_open_xrcd_resp {
   __u32 xrcd_handle;
+  __u32 driver_data[0];
 };
 struct ib_uverbs_close_xrcd {
   __u32 xrcd_handle;
@@ -266,6 +269,7 @@
   __u32 mr_handle;
   __u32 lkey;
   __u32 rkey;
+  __u32 driver_data[0];
 };
 struct ib_uverbs_rereg_mr {
   __aligned_u64 response;
@@ -276,10 +280,12 @@
   __aligned_u64 hca_va;
   __u32 pd_handle;
   __u32 access_flags;
+  __aligned_u64 driver_data[0];
 };
 struct ib_uverbs_rereg_mr_resp {
   __u32 lkey;
   __u32 rkey;
+  __aligned_u64 driver_data[0];
 };
 struct ib_uverbs_dereg_mr {
   __u32 mr_handle;
@@ -289,10 +295,12 @@
   __u32 pd_handle;
   __u8 mw_type;
   __u8 reserved[3];
+  __aligned_u64 driver_data[0];
 };
 struct ib_uverbs_alloc_mw_resp {
   __u32 mw_handle;
   __u32 rkey;
+  __aligned_u64 driver_data[0];
 };
 struct ib_uverbs_dealloc_mw {
   __u32 mw_handle;
@@ -328,6 +336,7 @@
 struct ib_uverbs_create_cq_resp {
   __u32 cq_handle;
   __u32 cqe;
+  __aligned_u64 driver_data[0];
 };
 struct ib_uverbs_ex_create_cq_resp {
   struct ib_uverbs_create_cq_resp base;
@@ -507,6 +516,7 @@
   __u32 max_recv_sge;
   __u32 max_inline_data;
   __u32 reserved;
+  __u32 driver_data[0];
 };
 struct ib_uverbs_ex_create_qp_resp {
   struct ib_uverbs_create_qp_resp base;
@@ -600,8 +610,6 @@
   __u32 rate_limit;
   __u32 reserved;
 };
-struct ib_uverbs_modify_qp_resp {
-};
 struct ib_uverbs_ex_modify_qp_resp {
   __u32 comp_mask;
   __u32 response_length;
@@ -709,9 +717,11 @@
   __u32 pd_handle;
   __u32 reserved;
   struct ib_uverbs_ah_attr attr;
+  __aligned_u64 driver_data[0];
 };
 struct ib_uverbs_create_ah_resp {
   __u32 ah_handle;
+  __u32 driver_data[0];
 };
 struct ib_uverbs_destroy_ah {
   __u32 ah_handle;
@@ -970,6 +980,7 @@
   __u32 max_wr;
   __u32 max_sge;
   __u32 srqn;
+  __u32 driver_data[0];
 };
 struct ib_uverbs_modify_srq {
   __u32 srq_handle;
diff --git a/libc/kernel/uapi/rdma/mlx5-abi.h b/libc/kernel/uapi/rdma/mlx5-abi.h
index 77e14f6..4c85c6c 100644
--- a/libc/kernel/uapi/rdma/mlx5-abi.h
+++ b/libc/kernel/uapi/rdma/mlx5-abi.h
@@ -31,6 +31,7 @@
   MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_UC = 1 << 6,
   MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC = 1 << 7,
   MLX5_QP_FLAG_ALLOW_SCATTER_CQE = 1 << 8,
+  MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE = 1 << 9,
 };
 enum {
   MLX5_SRQ_FLAG_SIGNATURE = 1 << 0,
@@ -162,6 +163,7 @@
 enum mlx5_ib_query_dev_resp_flags {
   MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP = 1 << 0,
   MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_PAD = 1 << 1,
+  MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE = 1 << 2,
 };
 enum mlx5_ib_tunnel_offloads {
   MLX5_IB_TUNNELED_OFFLOADS_VXLAN = 1 << 0,
diff --git a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
index 902816b..dcc3d85 100644
--- a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -120,6 +120,7 @@
   MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
   MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
   MLX5_IB_ATTR_CREATE_FLOW_TAG,
+  MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
 };
 enum mlx5_ib_destoy_flow_attrs {
   MLX5_IB_ATTR_DESTROY_FLOW_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
diff --git a/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h b/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
index 7b43e35..fc86778 100644
--- a/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
+++ b/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
@@ -47,6 +47,7 @@
   PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD,
   PVRDMA_WR_BIND_MW,
   PVRDMA_WR_REG_SIG_MR,
+  PVRDMA_WR_ERROR,
 };
 enum pvrdma_wc_status {
   PVRDMA_WC_SUCCESS,
diff --git a/libc/kernel/uapi/sound/firewire.h b/libc/kernel/uapi/sound/firewire.h
index 91289c0..67c010b 100644
--- a/libc/kernel/uapi/sound/firewire.h
+++ b/libc/kernel/uapi/sound/firewire.h
@@ -25,6 +25,7 @@
 #define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475
 #define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c
 #define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479
+#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d
 struct snd_firewire_event_common {
   unsigned int type;
 };
@@ -58,17 +59,28 @@
   unsigned int type;
   __u32 message;
 };
+struct snd_firewire_tascam_change {
+  unsigned int index;
+  __be32 before;
+  __be32 after;
+};
+struct snd_firewire_event_tascam_control {
+  unsigned int type;
+  struct snd_firewire_tascam_change changes[0];
+};
 union snd_firewire_event {
   struct snd_firewire_event_common common;
   struct snd_firewire_event_lock_status lock_status;
   struct snd_firewire_event_dice_notification dice_notification;
   struct snd_firewire_event_efw_response efw_response;
   struct snd_firewire_event_digi00x_message digi00x_message;
+  struct snd_firewire_event_tascam_control tascam_control;
   struct snd_firewire_event_motu_notification motu_notification;
 };
 #define SNDRV_FIREWIRE_IOCTL_GET_INFO _IOR('H', 0xf8, struct snd_firewire_get_info)
 #define SNDRV_FIREWIRE_IOCTL_LOCK _IO('H', 0xf9)
 #define SNDRV_FIREWIRE_IOCTL_UNLOCK _IO('H', 0xfa)
+#define SNDRV_FIREWIRE_IOCTL_TASCAM_STATE _IOR('H', 0xfb, struct snd_firewire_tascam_state)
 #define SNDRV_FIREWIRE_TYPE_DICE 1
 #define SNDRV_FIREWIRE_TYPE_FIREWORKS 2
 #define SNDRV_FIREWIRE_TYPE_BEBOB 3
@@ -83,4 +95,8 @@
   unsigned char guid[8];
   char device_name[16];
 };
+#define SNDRV_FIREWIRE_TASCAM_STATE_COUNT 64
+struct snd_firewire_tascam_state {
+  __be32 data[SNDRV_FIREWIRE_TASCAM_STATE_COUNT];
+};
 #endif
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 6a6ea7d..e094967 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1481,7 +1481,7 @@
     # Used by libandroid_net
     android_getaddrinfofornet; # apex
 
-    # Used by libandroid_runtime
+    # Used by libandroid_runtime and libmedia
     android_mallopt; # apex
     gMallocLeakZygoteChild; # apex
 } LIBC_P;
@@ -1500,8 +1500,12 @@
     __aeabi_cdcmpeq; # arm
     __aeabi_cdcmple; # arm
     __aeabi_cdrcmple; # arm
+    __aeabi_cfcmpeq; # arm
+    __aeabi_cfcmple; # arm
+    __aeabi_cfrcmple; # arm
     __aeabi_d2f; # arm
     __aeabi_d2iz; # arm
+    __aeabi_d2uiz; # arm
     __aeabi_dadd; # arm
     __aeabi_dcmpeq; # arm
     __aeabi_dcmpge; # arm
@@ -1517,6 +1521,11 @@
     __aeabi_f2iz; # arm
     __aeabi_f2uiz; # arm
     __aeabi_fadd; # arm
+    __aeabi_fcmpeq; # arm
+    __aeabi_fcmpge; # arm
+    __aeabi_fcmpgt; # arm
+    __aeabi_fcmple; # arm
+    __aeabi_fcmplt; # arm
     __aeabi_fcmpun; # arm
     __aeabi_fdiv; # arm
     __aeabi_fmul; # arm
@@ -1561,17 +1570,20 @@
     __ashldi3; # arm
     __ashrdi3; # arm
     __bionic_brk; # arm x86 mips
-    __bionic_libgcc_compat_symbols; # arm x86
+    __bionic_libcrt_compat_symbols; # arm x86
     __cmpdf2; # arm
+    __cmpsf2; # arm
     __divdf3; # arm
     __divdi3; # arm x86 mips
     __divsf3; # arm
     __divsi3; # arm
     __dso_handle; # arm
     __eqdf2; # arm
+    __eqsf2; # arm
     __extendsfdf2; # arm
     __fixdfsi; # arm
     __fixsfsi; # arm
+    __fixunsdfsi; # arm
     __fixunssfsi; # arm
     __floatdidf; # arm
     __floatdisf; # arm
@@ -1584,6 +1596,7 @@
     __futex_wait; # arm x86 mips
     __futex_wake; # arm x86 mips
     __gedf2; # arm
+    __gesf2; # arm
     __get_thread; # arm x86 mips
     __get_tls; # arm x86 mips
     __getdents64; # arm x86 mips
@@ -1608,13 +1621,17 @@
     __gnu_Unwind_Save_WMMXC; # arm
     __gnu_Unwind_Save_WMMXD; # arm
     __gtdf2; # arm
+    __gtsf2; # arm
     __ledf2; # arm
+    __lesf2; # arm
     __lshrdi3; # arm
     __ltdf2; # arm
+    __ltsf2; # arm
     __muldf3; # arm
     __muldi3; # arm
     __mulsf3; # arm
     __nedf2; # arm
+    __nesf2; # arm
     __open; # arm x86 mips
     __page_shift; # arm x86 mips
     __page_size; # arm x86 mips
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 0961a94..bcbd7da 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -123,6 +123,7 @@
     static_libs: [
         "libc_malloc_debug",
         "libdemangle",
+        "libtinyxml2",
     ],
 
     shared_libs: [
@@ -144,6 +145,8 @@
 cc_test {
     name: "malloc_debug_system_tests",
 
+    include_dirs: ["bionic/libc"],
+
     srcs: [
         "tests/malloc_debug_system_tests.cpp",
     ],
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index 638061b..6c7d8fa 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -266,12 +266,12 @@
   error_log("  hash_index %zu does not have matching frame data.", hash_index);
 }
 
-void PointerData::LogFreeError(const FreePointerInfoType& info, size_t usable_size) {
+void PointerData::LogFreeError(const FreePointerInfoType& info, size_t max_cmp_bytes) {
   error_log(LOG_DIVIDER);
   uint8_t* memory = reinterpret_cast<uint8_t*>(info.pointer);
   error_log("+++ ALLOCATION %p USED AFTER FREE", memory);
   uint8_t fill_free_value = g_debug->config().fill_free_value();
-  for (size_t i = 0; i < usable_size; i++) {
+  for (size_t i = 0; i < max_cmp_bytes; i++) {
     if (memory[i] != fill_free_value) {
       error_log("  allocation[%zu] = 0x%02x (expected 0x%02x)", i, memory[i], fill_free_value);
     }
@@ -314,11 +314,12 @@
   size_t bytes = (usable_size < g_debug->config().fill_on_free_bytes())
                      ? usable_size
                      : g_debug->config().fill_on_free_bytes();
+  size_t max_cmp_bytes = bytes;
   const uint8_t* memory = reinterpret_cast<const uint8_t*>(info.pointer);
   while (bytes > 0) {
     size_t bytes_to_cmp = (bytes < g_cmp_mem.size()) ? bytes : g_cmp_mem.size();
     if (memcmp(memory, g_cmp_mem.data(), bytes_to_cmp) != 0) {
-      LogFreeError(info, usable_size);
+      LogFreeError(info, max_cmp_bytes);
     }
     bytes -= bytes_to_cmp;
     memory = &memory[bytes_to_cmp];
@@ -491,6 +492,17 @@
   }
 }
 
+void PointerData::GetAllocList(std::vector<ListInfoType>* list) {
+  std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
+  std::lock_guard<std::mutex> frame_guard(frame_mutex_);
+
+  if (pointers_.empty()) {
+    return;
+  }
+
+  GetList(list, false);
+}
+
 void PointerData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size,
                           size_t* total_memory, size_t* backtrace_size) {
   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
@@ -589,9 +601,9 @@
 }
 
 void PointerData::PrepareFork() NO_THREAD_SAFETY_ANALYSIS {
+  free_pointer_mutex_.lock();
   pointer_mutex_.lock();
   frame_mutex_.lock();
-  free_pointer_mutex_.lock();
 }
 
 void PointerData::PostForkParent() NO_THREAD_SAFETY_ANALYSIS {
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 6955c9a..24ca748 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -132,9 +132,6 @@
   void PostForkParent();
   void PostForkChild();
 
-  static void GetList(std::vector<ListInfoType>* list, bool only_with_backtrace);
-  static void GetUniqueList(std::vector<ListInfoType>* list, bool only_with_backtrace);
-
   static size_t AddBacktrace(size_t num_frames);
   static void RemoveBacktrace(size_t hash_index);
 
@@ -151,6 +148,7 @@
   static void VerifyFreedPointer(const FreePointerInfoType& info);
   static void VerifyAllFreed();
 
+  static void GetAllocList(std::vector<ListInfoType>* list);
   static void LogLeaks();
   static void DumpLiveToFile(FILE* fp);
 
@@ -165,6 +163,9 @@
   static std::string GetHashString(uintptr_t* frames, size_t num_frames);
   static void LogBacktrace(size_t hash_index);
 
+  static void GetList(std::vector<ListInfoType>* list, bool only_with_backtrace);
+  static void GetUniqueList(std::vector<ListInfoType>* list, bool only_with_backtrace);
+
   size_t alloc_offset_ = 0;
   std::vector<uint8_t> cmp_mem_;
 
diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map
index 2f590d0..8ed37fa 100644
--- a/libc/malloc_debug/exported32.map
+++ b/libc/malloc_debug/exported32.map
@@ -14,6 +14,7 @@
     debug_malloc_backtrace;
     debug_malloc_disable;
     debug_malloc_enable;
+    debug_malloc_info;
     debug_malloc_usable_size;
     debug_mallopt;
     debug_memalign;
diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map
index 08d36a5..cdff88b 100644
--- a/libc/malloc_debug/exported64.map
+++ b/libc/malloc_debug/exported64.map
@@ -14,6 +14,7 @@
     debug_malloc_backtrace;
     debug_malloc_disable;
     debug_malloc_enable;
+    debug_malloc_info;
     debug_malloc_usable_size;
     debug_mallopt;
     debug_memalign;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 2e6afff..093bdee 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -29,6 +29,7 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <malloc.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/cdefs.h>
 #include <sys/param.h>
@@ -41,6 +42,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <private/bionic_malloc_dispatch.h>
+#include <private/MallocXmlElem.h>
 
 #include "Config.h"
 #include "DebugData.h"
@@ -85,6 +87,7 @@
 void* debug_calloc(size_t nmemb, size_t bytes);
 struct mallinfo debug_mallinfo();
 int debug_mallopt(int param, int value);
+int debug_malloc_info(int options, FILE* fp);
 int debug_posix_memalign(void** memptr, size_t alignment, size_t size);
 int debug_iterate(uintptr_t base, size_t size,
                   void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
@@ -725,11 +728,37 @@
   return g_dispatch->mallopt(param, value);
 }
 
+int debug_malloc_info(int options, FILE* fp) {
+  if (DebugCallsDisabled() || !g_debug->TrackPointers()) {
+    return g_dispatch->malloc_info(options, fp);
+  }
+
+  MallocXmlElem root(fp, "malloc", "version=\"debug-malloc-1\"");
+  std::vector<ListInfoType> list;
+  PointerData::GetAllocList(&list);
+
+  size_t alloc_num = 0;
+  for (size_t i = 0; i < list.size(); i++) {
+    MallocXmlElem alloc(fp, "allocation", "nr=\"%zu\"", alloc_num);
+
+    size_t total = 1;
+    size_t size = list[i].size;
+    while (i < list.size() - 1 && list[i + 1].size == size) {
+      i++;
+      total++;
+    }
+    MallocXmlElem(fp, "size").Contents("%zu", list[i].size);
+    MallocXmlElem(fp, "total").Contents("%zu", total);
+    alloc_num++;
+  }
+  return 0;
+}
+
 void* debug_aligned_alloc(size_t alignment, size_t size) {
   if (DebugCallsDisabled()) {
     return g_dispatch->aligned_alloc(alignment, size);
   }
-  if (!powerof2(alignment)) {
+  if (!powerof2(alignment) || (size % alignment) != 0) {
     errno = EINVAL;
     return nullptr;
   }
@@ -741,7 +770,7 @@
     return g_dispatch->posix_memalign(memptr, alignment, size);
   }
 
-  if (!powerof2(alignment)) {
+  if (alignment < sizeof(void*) || !powerof2(alignment)) {
     return EINVAL;
   }
   int saved_errno = errno;
diff --git a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
index ccefb25..4fcd04c 100644
--- a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
@@ -37,13 +37,15 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <android-base/stringprintf.h>
 #include <gtest/gtest.h>
-
 #include <log/log.h>
 
 #include <string>
 #include <vector>
 
+#include "private/bionic_malloc.h"
+
 static constexpr time_t kTimeoutSeconds = 5;
 
 static void Exec(const char* test_name, const char* debug_options, pid_t* pid) {
@@ -60,13 +62,15 @@
     ASSERT_NE(0, dup2(fds[1], STDERR_FILENO));
 
     std::vector<const char*> args;
-    args.push_back(testing::internal::GetArgvs()[0].c_str());
+    // Get a copy of this argument so it doesn't disappear on us.
+    std::string exec(testing::internal::GetArgvs()[0]);
+    args.push_back(exec.c_str());
     args.push_back("--gtest_also_run_disabled_tests");
     std::string filter_arg = std::string("--gtest_filter=") + test_name;
     args.push_back(filter_arg.c_str());
     args.push_back(nullptr);
     execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
-    exit(1);
+    exit(20);
   }
   ASSERT_NE(-1, *pid);
   close(fds[1]);
@@ -196,16 +200,217 @@
   ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}));
 }
 
-TEST(MallocTests, DISABLED_leak_memory) {
+static void SetAllocationLimit() {
+  // Set to a large value, this is only to enable the limit code and
+  // verify that malloc debug is still called properly.
+  size_t limit = 500 * 1024 * 1024;
+  ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
+}
+
+static void AlignedAlloc() {
+  void* ptr = aligned_alloc(64, 1152);
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 0, 1152);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_aligned_alloc) {
+  AlignedAlloc();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_aligned_alloc) {
+  SetAllocationLimit();
+  AlignedAlloc();
+}
+
+static void Calloc() {
+  void* ptr = calloc(1, 1123);
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 1, 1123);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_calloc) {
+  Calloc();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_calloc) {
+  SetAllocationLimit();
+  Calloc();
+}
+
+static void Malloc() {
   void* ptr = malloc(1123);
   ASSERT_TRUE(ptr != nullptr);
   memset(ptr, 0, 1123);
 }
 
-TEST(MallocDebugSystemTest, verify_leak) {
-  pid_t pid;
-  ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_leak_memory", "backtrace leak_track", &pid));
+TEST(MallocTests, DISABLED_leak_memory_malloc) {
+  Malloc();
+}
 
-  ASSERT_NO_FATAL_FAILURE(FindStrings(
-      pid, std::vector<const char*>{"malloc debug enabled", "leaked block of size 1123 at"}));
+TEST(MallocTests, DISABLED_leak_memory_limit_malloc) {
+  SetAllocationLimit();
+  Malloc();
+}
+
+static void Memalign() {
+  void* ptr = memalign(64, 1123);
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 0, 1123);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_memalign) {
+  Memalign();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_memalign) {
+  SetAllocationLimit();
+  Memalign();
+}
+
+static void PosixMemalign() {
+  void* ptr;
+  ASSERT_EQ(0, posix_memalign(&ptr, 64, 1123));
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 0, 1123);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_posix_memalign) {
+  PosixMemalign();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_posix_memalign) {
+  SetAllocationLimit();
+  PosixMemalign();
+}
+
+static void Reallocarray() {
+  void* ptr = reallocarray(nullptr, 1, 1123);
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 0, 1123);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_reallocarray) {
+  Reallocarray();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_reallocarray) {
+  SetAllocationLimit();
+  Reallocarray();
+}
+
+static void Realloc() {
+  void* ptr = realloc(nullptr, 1123);
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 0, 1123);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_realloc) {
+  Realloc();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_realloc) {
+  SetAllocationLimit();
+  Realloc();
+}
+
+#if !defined(__LP64__)
+extern "C" void* pvalloc(size_t);
+
+static void Pvalloc() {
+  void* ptr = pvalloc(1123);
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 0, 1123);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_pvalloc) {
+  Pvalloc();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_pvalloc) {
+  SetAllocationLimit();
+  Pvalloc();
+}
+
+extern "C" void* valloc(size_t);
+
+static void Valloc() {
+  void* ptr = valloc(1123);
+  ASSERT_TRUE(ptr != nullptr);
+  memset(ptr, 0, 1123);
+}
+
+TEST(MallocTests, DISABLED_leak_memory_valloc) {
+  Valloc();
+}
+
+TEST(MallocTests, DISABLED_leak_memory_limit_valloc) {
+  SetAllocationLimit();
+  Valloc();
+}
+#endif
+
+static void VerifyLeak(const char* test_prefix) {
+  struct FunctionInfo {
+    const char* name;
+    size_t size;
+  };
+  static FunctionInfo functions[] = {
+    {
+      "aligned_alloc",
+      1152,
+    },
+    {
+      "calloc",
+      1123,
+    },
+    {
+      "malloc",
+      1123,
+    },
+    {
+      "memalign",
+      1123,
+    },
+    {
+      "posix_memalign",
+      1123,
+    },
+    {
+      "reallocarray",
+      1123,
+    },
+    {
+      "realloc",
+      1123,
+    },
+#if !defined(__LP64__)
+    {
+      "pvalloc",
+      4096,
+    },
+    {
+      "valloc",
+      1123,
+    }
+#endif
+  };
+
+  for (size_t i = 0; i < sizeof(functions) / sizeof(FunctionInfo); i++) {
+    pid_t pid;
+    SCOPED_TRACE(testing::Message() << functions[i].name << " expected size " << functions[i].size);
+    std::string test = std::string("MallocTests.DISABLED_") + test_prefix + functions[i].name;
+    EXPECT_NO_FATAL_FAILURE(Exec(test.c_str(), "backtrace leak_track", &pid));
+
+    std::string expected_leak = android::base::StringPrintf("leaked block of size %zu at", functions[i].size);
+    EXPECT_NO_FATAL_FAILURE(FindStrings(
+        pid, std::vector<const char*>{"malloc debug enabled", expected_leak.c_str()}));
+  }
+}
+
+TEST(MallocDebugSystemTest, verify_leak) {
+  VerifyLeak("leak_memory_");
+}
+
+TEST(MallocDebugSystemTest, verify_leak_allocation_limit) {
+  VerifyLeak("leak_memory_limit_");
 }
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 44f9795..66955db 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -16,6 +16,7 @@
 
 #include <malloc.h>
 #include <signal.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/cdefs.h>
@@ -25,10 +26,13 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <memory>
 #include <thread>
 #include <vector>
 #include <utility>
 
+#include <tinyxml2.h>
+
 #include <gtest/gtest.h>
 
 #include <android-base/file.h>
@@ -62,6 +66,7 @@
 
 struct mallinfo debug_mallinfo();
 int debug_mallopt(int, int);
+int debug_malloc_info(int, FILE*);
 
 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
 void* debug_pvalloc(size_t);
@@ -136,6 +141,7 @@
   nullptr,
   mallopt,
   aligned_alloc,
+  malloc_info,
 };
 
 std::string ShowDiffs(uint8_t* a, uint8_t* b, size_t size) {
@@ -318,7 +324,7 @@
   ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
   debug_free(pointer);
 
-  pointer = debug_aligned_alloc(128, 15);
+  pointer = debug_aligned_alloc(16, 16);
   ASSERT_TRUE(pointer != nullptr);
   ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
   debug_free(pointer);
@@ -990,6 +996,35 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugTest, free_track_pointer_modified_after_free) {
+  Init("free_track=4 fill_on_free=2 free_track_backtrace_num_frames=0");
+
+  void* pointers[5];
+  for (size_t i = 0; i < sizeof(pointers) / sizeof(void*); i++) {
+    pointers[i] = debug_malloc(100);
+    ASSERT_TRUE(pointers[i] != nullptr);
+    memset(pointers[i], 0, 100);
+  }
+
+  debug_free(pointers[0]);
+
+  // overwrite the whole pointer, only expect errors on the fill bytes we check.
+  memset(pointers[0], 0x20, 100);
+
+  for (size_t i = 1; i < sizeof(pointers) / sizeof(void*); i++) {
+    debug_free(pointers[i]);
+  }
+
+  std::string expected_log(DIVIDER);
+  expected_log += android::base::StringPrintf("6 malloc_debug +++ ALLOCATION %p USED AFTER FREE\n",
+                                              pointers[0]);
+  expected_log += "6 malloc_debug   allocation[0] = 0x20 (expected 0xef)\n";
+  expected_log += "6 malloc_debug   allocation[1] = 0x20 (expected 0xef)\n";
+  expected_log += DIVIDER;
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
 TEST_F(MallocDebugTest, get_malloc_leak_info_invalid) {
   Init("fill");
 
@@ -2115,9 +2150,9 @@
   debug_free(pointer);
   expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
 
-  pointer = debug_aligned_alloc(32, 50);
+  pointer = debug_aligned_alloc(32, 64);
   ASSERT_TRUE(pointer != nullptr);
-  expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
+  expected += android::base::StringPrintf("%d: memalign %p 32 64\n", getpid(), pointer);
   debug_free(pointer);
   expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
 
@@ -2436,3 +2471,82 @@
   pointer[-get_tag_offset()] = tag_value;
 }
 
+TEST_F(MallocDebugTest, malloc_info_no_pointer_tracking) {
+  Init("fill");
+
+  char* buffer;
+  size_t size;
+  FILE* memstream = open_memstream(&buffer, &size);
+  ASSERT_TRUE(memstream != nullptr);
+  ASSERT_EQ(0, debug_malloc_info(0, memstream));
+  ASSERT_EQ(0, fclose(memstream));
+
+  tinyxml2::XMLDocument doc;
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buffer));
+  auto root = doc.FirstChildElement();
+  ASSERT_TRUE(root != nullptr);
+  ASSERT_STREQ("malloc", root->Name());
+  // Don't care what the underyling implementation says, just that it's
+  // not generated by debug malloc.
+  ASSERT_STRNE("debug-malloc-1", root->Attribute("version"));
+}
+
+TEST_F(MallocDebugTest, malloc_info_with_pointer_tracking) {
+  Init("verify_pointers");
+
+  std::unique_ptr<void, decltype(debug_free)*> ptr1(debug_malloc(1000), debug_free);
+  ASSERT_TRUE(ptr1.get() != nullptr);
+  std::unique_ptr<void, decltype(debug_free)*> ptr2(debug_malloc(1000), debug_free);
+  ASSERT_TRUE(ptr2.get() != nullptr);
+  std::unique_ptr<void, decltype(debug_free)*> ptr3(debug_malloc(500), debug_free);
+  ASSERT_TRUE(ptr3.get() != nullptr);
+  std::unique_ptr<void, decltype(debug_free)*> ptr4(debug_malloc(1200), debug_free);
+  ASSERT_TRUE(ptr4.get() != nullptr);
+
+  char* buffer;
+  size_t size;
+  FILE* memstream = open_memstream(&buffer, &size);
+  ASSERT_TRUE(memstream != nullptr);
+  ASSERT_EQ(0, debug_malloc_info(0, memstream));
+  ASSERT_EQ(0, fclose(memstream));
+
+  SCOPED_TRACE(testing::Message() << "Output:\n" << buffer);
+
+  tinyxml2::XMLDocument doc;
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buffer));
+  auto root = doc.FirstChildElement();
+  ASSERT_TRUE(root != nullptr);
+  ASSERT_STREQ("malloc", root->Name());
+  ASSERT_STREQ("debug-malloc-1", root->Attribute("version"));
+
+  auto alloc = root->FirstChildElement();
+  ASSERT_TRUE(alloc != nullptr);
+  ASSERT_STREQ("allocation", alloc->Name());
+  int val;
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->QueryIntAttribute("nr", &val));
+  ASSERT_EQ(0, val);
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->FirstChildElement("size")->QueryIntText(&val));
+  ASSERT_EQ(1200, val);
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->FirstChildElement("total")->QueryIntText(&val));
+  ASSERT_EQ(1, val);
+
+  alloc = alloc->NextSiblingElement();
+  ASSERT_TRUE(alloc != nullptr);
+  ASSERT_STREQ("allocation", alloc->Name());
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->QueryIntAttribute("nr", &val));
+  ASSERT_EQ(1, val);
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->FirstChildElement("size")->QueryIntText(&val));
+  ASSERT_EQ(1000, val);
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->FirstChildElement("total")->QueryIntText(&val));
+  ASSERT_EQ(2, val);
+
+  alloc = alloc->NextSiblingElement();
+  ASSERT_TRUE(alloc != nullptr);
+  ASSERT_STREQ("allocation", alloc->Name());
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->QueryIntAttribute("nr", &val));
+  ASSERT_EQ(2, val);
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->FirstChildElement("size")->QueryIntText(&val));
+  ASSERT_EQ(500, val);
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->FirstChildElement("total")->QueryIntText(&val));
+  ASSERT_EQ(1, val);
+}
diff --git a/libc/malloc_hooks/Android.bp b/libc/malloc_hooks/Android.bp
index d4b5a2a..d119f89 100644
--- a/libc/malloc_hooks/Android.bp
+++ b/libc/malloc_hooks/Android.bp
@@ -39,14 +39,6 @@
 // ==============================================================
 cc_test {
     name: "malloc_hooks_unit_tests",
-    multilib: {
-        lib32: {
-            suffix: "32",
-        },
-        lib64: {
-            suffix: "64",
-        },
-    },
 
     srcs: [
         "tests/malloc_hooks_tests.cpp",
diff --git a/libc/malloc_hooks/exported32.map b/libc/malloc_hooks/exported32.map
index bd3e547..293d9ac 100644
--- a/libc/malloc_hooks/exported32.map
+++ b/libc/malloc_hooks/exported32.map
@@ -13,6 +13,7 @@
     hooks_malloc_backtrace;
     hooks_malloc_disable;
     hooks_malloc_enable;
+    hooks_malloc_info;
     hooks_malloc_usable_size;
     hooks_mallopt;
     hooks_memalign;
diff --git a/libc/malloc_hooks/exported64.map b/libc/malloc_hooks/exported64.map
index 72465c4..340106b 100644
--- a/libc/malloc_hooks/exported64.map
+++ b/libc/malloc_hooks/exported64.map
@@ -13,6 +13,7 @@
     hooks_malloc_backtrace;
     hooks_malloc_disable;
     hooks_malloc_enable;
+    hooks_malloc_info;
     hooks_malloc_usable_size;
     hooks_mallopt;
     hooks_memalign;
diff --git a/libc/malloc_hooks/malloc_hooks.cpp b/libc/malloc_hooks/malloc_hooks.cpp
index f7bdd56..07b668f 100644
--- a/libc/malloc_hooks/malloc_hooks.cpp
+++ b/libc/malloc_hooks/malloc_hooks.cpp
@@ -29,6 +29,7 @@
 #include <errno.h>
 #include <malloc.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/param.h>
 #include <unistd.h>
@@ -57,6 +58,7 @@
 void hooks_free_malloc_leak_info(uint8_t* info);
 size_t hooks_malloc_usable_size(void* pointer);
 void* hooks_malloc(size_t size);
+int hooks_malloc_info(int options, FILE* fp);
 void hooks_free(void* pointer);
 void* hooks_memalign(size_t alignment, size_t bytes);
 void* hooks_aligned_alloc(size_t alignment, size_t bytes);
@@ -174,9 +176,13 @@
   return g_dispatch->mallopt(param, value);
 }
 
+int hooks_malloc_info(int options, FILE* fp) {
+  return g_dispatch->malloc_info(options, fp);
+}
+
 void* hooks_aligned_alloc(size_t alignment, size_t size) {
   if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
-    if (!powerof2(alignment)) {
+    if (!powerof2(alignment) || (size % alignment) != 0) {
       errno = EINVAL;
       return nullptr;
     }
@@ -191,7 +197,7 @@
 
 int hooks_posix_memalign(void** memptr, size_t alignment, size_t size) {
   if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
-    if (!powerof2(alignment)) {
+    if (alignment < sizeof(void*) || !powerof2(alignment)) {
       return EINVAL;
     }
     *memptr = __memalign_hook(alignment, size, __builtin_return_address(0));
diff --git a/libc/private/MallocXmlElem.h b/libc/private/MallocXmlElem.h
new file mode 100644
index 0000000..04d3eee
--- /dev/null
+++ b/libc/private/MallocXmlElem.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <private/bionic_macros.h>
+
+class MallocXmlElem {
+ public:
+  // Name must be valid throughout lifetime of the object.
+  explicit MallocXmlElem(FILE* fp, const char* name,
+                         const char* attr_fmt = nullptr, ...) : fp_(fp), name_(name) {
+    fprintf(fp, "<%s", name_);
+    if (attr_fmt != nullptr) {
+      va_list args;
+      va_start(args, attr_fmt);
+      fputc(' ', fp_);
+      vfprintf(fp_, attr_fmt, args);
+      va_end(args);
+    }
+    fputc('>', fp_);
+  }
+
+  ~MallocXmlElem() noexcept {
+    fprintf(fp_, "</%s>", name_);
+  }
+
+  void Contents(const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    vfprintf(fp_, fmt, args);
+    va_end(args);
+  }
+
+private:
+  FILE* fp_;
+  const char* name_;
+
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(MallocXmlElem);
+};
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 21a2a24..d73079e 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -29,6 +29,7 @@
 #ifndef _PRIVATE_BIONIC_GLOBALS_H
 #define _PRIVATE_BIONIC_GLOBALS_H
 
+#include <stdatomic.h>
 #include <sys/cdefs.h>
 #include <link.h>
 #include <pthread.h>
@@ -43,7 +44,21 @@
 struct libc_globals {
   vdso_entry vdso[VDSO_END];
   long setjmp_cookie;
-  MallocDispatch malloc_dispatch;
+
+  // In order to allow a complete switch between dispatch tables without
+  // the need for copying each function by function in the structure,
+  // use a single atomic pointer to switch.
+  // The current_dispatch_table pointer can only ever be set to a complete
+  // table. Any dispatch table that is pointed to by current_dispatch_table
+  // cannot be modified after that. If the pointer changes in the future,
+  // the old pointer must always stay valid.
+  // The malloc_dispatch_table is modified by malloc debug, malloc hooks,
+  // and heaprofd. Only one of these modes can be active at any given time.
+  _Atomic(const MallocDispatch*) current_dispatch_table;
+  // This pointer is only used by the allocation limit code when both a
+  // limit is enabled and some other hook is enabled at the same time.
+  _Atomic(const MallocDispatch*) default_dispatch_table;
+  MallocDispatch malloc_dispatch_table;
 };
 
 __LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals;
@@ -87,6 +102,7 @@
 
 #if defined(__i386__)
 __LIBC_HIDDEN__ extern void* __libc_sysinfo;
+__LIBC_HIDDEN__ void __libc_int0x80();
 __LIBC_HIDDEN__ void __libc_init_sysinfo();
 #endif
 
diff --git a/libc/private/bionic_malloc.h b/libc/private/bionic_malloc.h
index 5f4a75d..a1744aa 100644
--- a/libc/private/bionic_malloc.h
+++ b/libc/private/bionic_malloc.h
@@ -39,6 +39,12 @@
 #define M_INIT_ZYGOTE_CHILD_PROFILING M_INIT_ZYGOTE_CHILD_PROFILING
   M_RESET_HOOKS = 2,
 #define M_RESET_HOOKS M_RESET_HOOKS
+  // Set an upper bound on the total size in bytes of all allocations made
+  // using the memory allocation APIs.
+  //   arg = size_t*
+  //   arg_size = sizeof(size_t)
+  M_SET_ALLOCATION_LIMIT_BYTES = 3,
+#define M_SET_ALLOCATION_LIMIT_BYTES M_SET_ALLOCATION_LIMIT_BYTES
 };
 
 // Manipulates bionic-specific handling of memory allocation APIs such as
diff --git a/libc/private/bionic_malloc_dispatch.h b/libc/private/bionic_malloc_dispatch.h
index f15b72c..aea3a1c 100644
--- a/libc/private/bionic_malloc_dispatch.h
+++ b/libc/private/bionic_malloc_dispatch.h
@@ -31,7 +31,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include <stdatomic.h>
+#include <stdio.h>
 #include <private/bionic_config.h>
 
 // Entry in malloc dispatch table.
@@ -39,6 +39,7 @@
 typedef void (*MallocFree)(void*);
 typedef struct mallinfo (*MallocMallinfo)();
 typedef void* (*MallocMalloc)(size_t);
+typedef int (*MallocMallocInfo)(int, FILE*);
 typedef size_t (*MallocMallocUsableSize)(const void*);
 typedef void* (*MallocMemalign)(size_t, size_t);
 typedef int (*MallocPosixMemalign)(void**, size_t, size_t);
@@ -55,25 +56,26 @@
 #endif
 
 struct MallocDispatch {
-  _Atomic MallocCalloc calloc;
-  _Atomic MallocFree free;
-  _Atomic MallocMallinfo mallinfo;
-  _Atomic MallocMalloc malloc;
-  _Atomic MallocMallocUsableSize malloc_usable_size;
-  _Atomic MallocMemalign memalign;
-  _Atomic MallocPosixMemalign posix_memalign;
+  MallocCalloc calloc;
+  MallocFree free;
+  MallocMallinfo mallinfo;
+  MallocMalloc malloc;
+  MallocMallocUsableSize malloc_usable_size;
+  MallocMemalign memalign;
+  MallocPosixMemalign posix_memalign;
 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-  _Atomic MallocPvalloc pvalloc;
+  MallocPvalloc pvalloc;
 #endif
-  _Atomic MallocRealloc realloc;
+  MallocRealloc realloc;
 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-  _Atomic MallocValloc valloc;
+  MallocValloc valloc;
 #endif
-  _Atomic MallocIterate iterate;
-  _Atomic MallocMallocDisable malloc_disable;
-  _Atomic MallocMallocEnable malloc_enable;
-  _Atomic MallocMallopt mallopt;
-  _Atomic MallocAlignedAlloc aligned_alloc;
+  MallocIterate iterate;
+  MallocMallocDisable malloc_disable;
+  MallocMallocEnable malloc_enable;
+  MallocMallopt mallopt;
+  MallocAlignedAlloc aligned_alloc;
+  MallocMallocInfo malloc_info;
 } __attribute__((aligned(32)));
 
 #endif
diff --git a/libc/stdio/fmemopen.cpp b/libc/stdio/fmemopen.cpp
index 9d8c41f..6e333ba 100644
--- a/libc/stdio/fmemopen.cpp
+++ b/libc/stdio/fmemopen.cpp
@@ -149,7 +149,9 @@
   } else if (mode[0] == 'w') {
     ck->size = 0;
     ck->offset = 0;
-    ck->buf[0] = '\0';
+    if (capacity > 0) {
+      ck->buf[0] = '\0';
+    }
   }
 
   return fp;
diff --git a/libc/symbol_ordering b/libc/symbol_ordering
index b672b35..6fcc09e 100644
--- a/libc/symbol_ordering
+++ b/libc/symbol_ordering
@@ -3,11 +3,9 @@
 # symbols by size, we usually have less dirty pages at runtime, because small
 # symbols are grouped together.
 
-je_background_thread_enabled_state
-je_can_enable_background_thread
 _ZZ17__find_icu_symbolPKcE9found_icu
-_ZL28g_heapprofd_init_in_progress
-_ZL31g_heapprofd_init_hook_installed
+_ZL24gHeapprofdInitInProgress
+_ZL27gHeapprofdInitHookInstalled
 je_opt_abort
 je_opt_abort_conf
 je_opt_junk_alloc
@@ -19,7 +17,6 @@
 had_conf_error
 malloc_slow_flags
 je_opt_background_thread
-background_thread_enabled_at_fork
 ctl_initialized
 je_log_init_done
 mmap_flags
@@ -46,7 +43,6 @@
 optreset
 _rs_forked
 daylight
-_ZL17g_icudata_version
 gMallocLeakZygoteChild
 _ZL18netdClientInitOnce
 je_opt_narenas
@@ -71,8 +67,6 @@
 seed48.sseed
 ether_aton.addr
 je_background_thread_info
-je_max_background_threads
-je_n_background_threads
 je_malloc_message
 je_tcache_bin_info
 je_tcache_maxclass
@@ -93,7 +87,6 @@
 je_opt_muzzy_decay_ms
 dirty_decay_ms_default.0
 muzzy_decay_ms_default.0
-pthread_create_fptr
 b0
 ctl_arenas
 ctl_stats
@@ -175,7 +168,7 @@
 __res_randomid.__libc_mutex_random
 locallock
 g_atexit_lock
-_ZL11g_functions
+_ZL10gFunctions
 _ZL13vendor_passwd
 _ZL12vendor_group
 tm
diff --git a/libc/system_properties/Android.bp b/libc/system_properties/Android.bp
index f94cda9..911afb1 100644
--- a/libc/system_properties/Android.bp
+++ b/libc/system_properties/Android.bp
@@ -12,8 +12,8 @@
     whole_static_libs: [
         "libpropertyinfoparser",
     ],
-    static_libs: [
-        "libasync_safe",
+    header_libs: [
+        "libasync_safe_headers",
     ],
 
     include_dirs: [
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index d78a5e7..9a3b95e 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -584,8 +584,15 @@
                          "kernel/uapi/asm-arm/asm/unistd-eabi.h",
                          "kernel/uapi/asm-arm/asm/unistd-oabi.h",
                          "kernel/uapi/asm-mips/asm/unistd.h",
+                         "kernel/uapi/asm-mips/asm/unistd_n32.h",
+                         "kernel/uapi/asm-mips/asm/unistd_n64.h",
+                         "kernel/uapi/asm-mips/asm/unistd_nr_n32.h",
+                         "kernel/uapi/asm-mips/asm/unistd_nr_n64.h",
+                         "kernel/uapi/asm-mips/asm/unistd_nr_o32.h",
+                         "kernel/uapi/asm-mips/asm/unistd_o32.h",
                          "kernel/uapi/asm-x86/asm/unistd_32.h",
-                         "kernel/uapi/asm-x86/asm/unistd_64.h"]:
+                         "kernel/uapi/asm-x86/asm/unistd_64.h",
+                         "kernel/uapi/asm-x86/asm/unistd_x32.h"]:
           for line in open(os.path.join(bionic_libc_root, unistd_h)):
             m = re.search(pattern, line)
             if m:
diff --git a/libc/upstream-netbsd/common/lib/libc/stdlib/random.c b/libc/upstream-netbsd/common/lib/libc/stdlib/random.c
index e7503c7..0e6eac0 100644
--- a/libc/upstream-netbsd/common/lib/libc/stdlib/random.c
+++ b/libc/upstream-netbsd/common/lib/libc/stdlib/random.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: random.c,v 1.4 2014/06/12 20:59:46 christos Exp $	*/
+/*	$NetBSD: random.c,v 1.5 2016/02/08 05:27:24 dholland Exp $	*/
 
 /*
  * Copyright (c) 1983, 1993
@@ -35,7 +35,7 @@
 #if 0
 static char sccsid[] = "@(#)random.c	8.2 (Berkeley) 5/19/95";
 #else
-__RCSID("$NetBSD: random.c,v 1.4 2014/06/12 20:59:46 christos Exp $");
+__RCSID("$NetBSD: random.c,v 1.5 2016/02/08 05:27:24 dholland Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -92,7 +92,7 @@
  * state information, which will allow a degree seven polynomial.  (Note:
  * the zeroeth word of state information also has some other information
  * stored in it -- see setstate() for details).
- * 
+ *
  * The random number generation technique is a linear feedback shift register
  * approach, employing trinomials (since there are fewer terms to sum up that
  * way).  In this approach, the least significant bit of all the numbers in
@@ -318,12 +318,12 @@
  * the break values for the different R.N.G.'s, we choose the best (largest)
  * one we can and set things up for it.  srandom() is then called to
  * initialize the state information.
- * 
+ *
  * Note that on return from srandom(), we set state[-1] to be the type
  * multiplexed with the current value of the rear pointer; this is so
  * successive calls to initstate() won't lose this information and will be
  * able to restart with setstate().
- * 
+ *
  * Note: the first thing we do is save the current state, if any, just like
  * setstate() so that it doesn't matter when initstate is called.
  *
@@ -511,7 +511,7 @@
 {
 	static u_long randseed = 1;
 	long x, hi, lo, t;
- 
+
 	/*
 	 * Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1).
 	 * From "Random number generators: good ones are hard to find",
diff --git a/libc/upstream-netbsd/lib/libc/include/isc/dst.h b/libc/upstream-netbsd/lib/libc/include/isc/dst.h
index 5537e3d..a25cf01 100644
--- a/libc/upstream-netbsd/lib/libc/include/isc/dst.h
+++ b/libc/upstream-netbsd/lib/libc/include/isc/dst.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: dst.h,v 1.1.1.4 2009/04/12 16:35:44 christos Exp $	*/
+/*	$NetBSD: dst.h,v 1.2 2014/08/03 19:14:24 wiz Exp $	*/
 
 #ifndef DST_H
 #define DST_H
@@ -55,7 +55,7 @@
 #define	dst_write_key		__dst_write_key
 
 /* 
- * DST Crypto API defintions 
+ * DST Crypto API definitions 
  */
 void     dst_init(void);
 int      dst_check_algorithm(const int);
diff --git a/libc/upstream-netbsd/lib/libc/regex/regcomp.c b/libc/upstream-netbsd/lib/libc/regex/regcomp.c
index 6af9734..4a0d99a 100644
--- a/libc/upstream-netbsd/lib/libc/regex/regcomp.c
+++ b/libc/upstream-netbsd/lib/libc/regex/regcomp.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $	*/
+/*	$NetBSD: regcomp.c,v 1.38 2019/02/07 22:22:31 christos Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993, 1994
@@ -76,7 +76,7 @@
 #if 0
 static char sccsid[] = "@(#)regcomp.c	8.5 (Berkeley) 3/20/94";
 #else
-__RCSID("$NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $");
+__RCSID("$NetBSD: regcomp.c,v 1.38 2019/02/07 22:22:31 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -474,6 +474,8 @@
 		REQUIRE(!MORE() || !isdigit((unsigned char)PEEK()), REG_BADRPT);
 		/* FALLTHROUGH */
 	default:
+		if (p->error != 0)
+			return;
 		ordinary(p, c);
 		break;
 	}
@@ -692,6 +694,8 @@
 		REQUIRE(starordinary, REG_BADRPT);
 		/* FALLTHROUGH */
 	default:
+		if (p->error != 0)
+			return(0);
 		ordinary(p, c &~ BACKSL);
 		break;
 	}
@@ -1007,7 +1011,7 @@
 	}
 	len = p->next - sp;
 	for (cp = cnames; cp->name != NULL; cp++)
-		if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+		if (strncmp(cp->name, sp, len) == 0 && strlen(cp->name) == len)
 			return(cp->code);	/* known name */
 	if (len == 1)
 		return(*sp);	/* single character */
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/lldiv.c b/libc/upstream-netbsd/lib/libc/stdlib/lldiv.c
deleted file mode 100644
index 47104b3..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/lldiv.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*	$NetBSD: lldiv.c,v 1.4 2012/06/25 22:32:45 abs Exp $	*/
-
-/*
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "from: @(#)ldiv.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: lldiv.c,v 1.4 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include "namespace.h"
-#include <stdlib.h>		/* lldiv_t */
-
-#ifdef __weak_alias
-__weak_alias(lldiv, _lldiv)
-#endif
-
-/* LONGLONG */
-lldiv_t
-lldiv(long long int num, long long int denom)
-{
-	lldiv_t r;
-
-	/* see div.c for comments */
-
-	r.quot = num / denom;
-	r.rem = num % denom;
-	if (num >= 0 && r.rem < 0) {
-		r.quot++;
-		r.rem -= denom;
-	}
-	return (r);
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/div.c b/libc/upstream-openbsd/lib/libc/stdlib/div.c
similarity index 86%
rename from libc/upstream-netbsd/lib/libc/stdlib/div.c
rename to libc/upstream-openbsd/lib/libc/stdlib/div.c
index f3bd32f..beaa428 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/div.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/div.c
@@ -1,8 +1,7 @@
-/*	$NetBSD: div.c,v 1.8 2012/06/25 22:32:45 abs Exp $	*/
-
+/*	$OpenBSD: div.c,v 1.6 2015/09/13 08:31:47 guenther Exp $ */
 /*
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
@@ -32,15 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)div.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: div.c,v 1.8 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
 #include <stdlib.h>		/* div_t */
 
 div_t
@@ -79,3 +69,4 @@
 	}
 	return (r);
 }
+DEF_STRONG(div);
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/ldiv.c b/libc/upstream-openbsd/lib/libc/stdlib/ldiv.c
similarity index 81%
rename from libc/upstream-netbsd/lib/libc/stdlib/ldiv.c
rename to libc/upstream-openbsd/lib/libc/stdlib/ldiv.c
index 507c831..775065f 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/ldiv.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/ldiv.c
@@ -1,8 +1,7 @@
-/*	$NetBSD: ldiv.c,v 1.8 2012/06/25 22:32:45 abs Exp $	*/
-
+/*	$OpenBSD: ldiv.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
 /*
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
@@ -32,15 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)ldiv.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: ldiv.c,v 1.8 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
 #include <stdlib.h>		/* ldiv_t */
 
 ldiv_t
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/ldiv.c b/libc/upstream-openbsd/lib/libc/stdlib/lldiv.c
similarity index 78%
copy from libc/upstream-netbsd/lib/libc/stdlib/ldiv.c
copy to libc/upstream-openbsd/lib/libc/stdlib/lldiv.c
index 507c831..59c37b8 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/ldiv.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/lldiv.c
@@ -1,8 +1,7 @@
-/*	$NetBSD: ldiv.c,v 1.8 2012/06/25 22:32:45 abs Exp $	*/
-
+/*	$OpenBSD: lldiv.c,v 1.2 2016/08/14 23:18:03 guenther Exp $	*/
 /*
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
@@ -32,21 +31,12 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)ldiv.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: ldiv.c,v 1.8 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
+#include <stdlib.h>		/* lldiv_t */
 
-#include <stdlib.h>		/* ldiv_t */
-
-ldiv_t
-ldiv(long num, long denom)
+lldiv_t
+lldiv(long long num, long long denom)
 {
-	ldiv_t r;
+	lldiv_t r;
 
 	/* see div.c for comments */
 
@@ -58,3 +48,5 @@
 	}
 	return (r);
 }
+
+__weak_alias(qdiv, lldiv);
diff --git a/libc/upstream-netbsd/lib/libc/string/memccpy.c b/libc/upstream-openbsd/lib/libc/string/memccpy.c
similarity index 83%
rename from libc/upstream-netbsd/lib/libc/string/memccpy.c
rename to libc/upstream-openbsd/lib/libc/string/memccpy.c
index c086241..635061b 100644
--- a/libc/upstream-netbsd/lib/libc/string/memccpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/memccpy.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: memccpy.c,v 1.13 2012/06/25 22:32:46 abs Exp $	*/
+/*	$OpenBSD: memccpy.c,v 1.7 2015/08/31 02:53:57 guenther Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -29,25 +29,12 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)memccpy.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: memccpy.c,v 1.13 2012/06/25 22:32:46 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
 #include <string.h>
 
 void *
 memccpy(void *t, const void *f, int c, size_t n)
 {
 
-	_DIAGASSERT(t != 0);
-	_DIAGASSERT(f != 0);
-
 	if (n) {
 		unsigned char *tp = t;
 		const unsigned char *fp = f;
@@ -59,3 +46,4 @@
 	}
 	return (0);
 }
+DEF_WEAK(memccpy);
diff --git a/libc/upstream-netbsd/lib/libc/string/strcasestr.c b/libc/upstream-openbsd/lib/libc/string/strcasestr.c
similarity index 83%
rename from libc/upstream-netbsd/lib/libc/string/strcasestr.c
rename to libc/upstream-openbsd/lib/libc/string/strcasestr.c
index f8a9444..abb3e15 100644
--- a/libc/upstream-netbsd/lib/libc/string/strcasestr.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcasestr.c
@@ -1,4 +1,5 @@
-/*	$NetBSD: strcasestr.c,v 1.3 2005/11/29 03:12:00 christos Exp $	*/
+/*	$OpenBSD: strcasestr.c,v 1.4 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -32,13 +33,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: strcasestr.c,v 1.3 2005/11/29 03:12:00 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include "namespace.h"
-#include <assert.h>
 #include <ctype.h>
 #include <string.h>
 
@@ -51,11 +45,8 @@
 	char c, sc;
 	size_t len;
 
-	_DIAGASSERT(s != NULL);
-	_DIAGASSERT(find != NULL);
-
 	if ((c = *find++) != 0) {
-		c = tolower((unsigned char)c);
+		c = (char)tolower((unsigned char)c);
 		len = strlen(find);
 		do {
 			do {
@@ -65,5 +56,6 @@
 		} while (strncasecmp(s, find, len) != 0);
 		s--;
 	}
-	return __UNCONST(s);
+	return ((char *)s);
 }
+DEF_WEAK(strcasestr);
diff --git a/libc/upstream-netbsd/lib/libc/string/strcoll.c b/libc/upstream-openbsd/lib/libc/string/strcoll.c
similarity index 78%
rename from libc/upstream-netbsd/lib/libc/string/strcoll.c
rename to libc/upstream-openbsd/lib/libc/string/strcoll.c
index 77a0942..47a6ea4 100644
--- a/libc/upstream-netbsd/lib/libc/string/strcoll.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcoll.c
@@ -1,8 +1,7 @@
-/*	$NetBSD: strcoll.c,v 1.10 2012/06/25 22:32:46 abs Exp $	*/
-
+/*	$OpenBSD: strcoll.c,v 1.6 2015/08/31 02:53:57 guenther Exp $ */
 /*-
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
@@ -32,16 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)strcoll.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: strcoll.c,v 1.10 2012/06/25 22:32:46 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
 #include <string.h>
 
 /*
@@ -50,10 +39,7 @@
 int
 strcoll(const char *s1, const char *s2)
 {
-
-	_DIAGASSERT(s1 != NULL);
-	_DIAGASSERT(s2 != NULL);
-
 	/* LC_COLLATE is unimplemented, hence always "C" */
 	return (strcmp(s1, s2));
 }
+DEF_STRONG(strcoll);
diff --git a/libc/upstream-netbsd/lib/libc/string/strxfrm.c b/libc/upstream-openbsd/lib/libc/string/strxfrm.c
similarity index 73%
rename from libc/upstream-netbsd/lib/libc/string/strxfrm.c
rename to libc/upstream-openbsd/lib/libc/string/strxfrm.c
index 42c2a24..97df097 100644
--- a/libc/upstream-netbsd/lib/libc/string/strxfrm.c
+++ b/libc/upstream-openbsd/lib/libc/string/strxfrm.c
@@ -1,8 +1,7 @@
-/*	$NetBSD: strxfrm.c,v 1.12 2012/06/25 22:32:46 abs Exp $	*/
-
+/*	$OpenBSD: strxfrm.c,v 1.7 2015/08/31 02:53:57 guenther Exp $ */
 /*-
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
@@ -32,16 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)strxfrm.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: strxfrm.c,v 1.12 2012/06/25 22:32:46 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
 #include <string.h>
 
 /*
@@ -52,19 +41,12 @@
 size_t
 strxfrm(char *dst, const char *src, size_t n)
 {
-	size_t srclen, copysize;
-
-	_DIAGASSERT(src != NULL);
 
 	/*
 	 * Since locales are unimplemented, this is just a copy.
 	 */
-	srclen = strlen(src);
-	if (n != 0) {
-		_DIAGASSERT(dst != NULL);
-		copysize = srclen < n ? srclen : n - 1;
-		(void)memcpy(dst, src, copysize);
-		dst[copysize] = 0;
-	}
-	return (srclen);
+	if (n == 0)
+		return (strlen(src));
+	return (strlcpy(dst, src, n));
 }
+DEF_STRONG(strxfrm);
diff --git a/libdl/Android.bp b/libdl/Android.bp
index c17e72e..2e171d6 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -93,6 +93,9 @@
     nocrt: true,
     system_shared_libs: [],
 
+    // Opt out of native_coverage when opting out of system_shared_libs
+    native_coverage: false,
+
     // This is placeholder library the actual implementation is (currently)
     // provided by the linker.
     shared_libs: ["ld-android"],
@@ -105,7 +108,6 @@
         symbol_file: "libdl.map.txt",
         versions: ["10000"],
     },
-    required: ["libdl.mountpoint"],
 }
 
 ndk_library {
diff --git a/libm/Android.bp b/libm/Android.bp
index 079220b..8c32810 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -508,14 +508,10 @@
     },
     stl: "none",
 
-    // TODO(ivanlozano): Remove after b/118321713
-    xom: false,
-
     stubs: {
         symbol_file: "libm.map.txt",
         versions: ["10000"],
     },
-    required: ["libm.mountpoint"],
 }
 
 ndk_library {
diff --git a/libm/libm.map.txt b/libm/libm.map.txt
index 1f9a3f9..00ea7ee 100644
--- a/libm/libm.map.txt
+++ b/libm/libm.map.txt
@@ -301,58 +301,19 @@
     ___Unwind_RaiseException; # arm
     ___Unwind_Resume; # arm
     ___Unwind_Resume_or_Rethrow; # arm
-    __adddf3; # arm
-    __aeabi_cdcmpeq; # arm
-    __aeabi_cdcmple; # arm
-    __aeabi_cdrcmple; # arm
-    __aeabi_cfcmpeq; # arm
-    __aeabi_cfcmple; # arm
-    __aeabi_cfrcmple; # arm
     __aeabi_d2lz; # arm
-    __aeabi_d2uiz; # arm
     __aeabi_d2ulz; # arm
-    __aeabi_dadd; # arm
-    __aeabi_dcmpeq; # arm
-    __aeabi_dcmpge; # arm
-    __aeabi_dcmpgt; # arm
-    __aeabi_dcmple; # arm
-    __aeabi_dcmplt; # arm
-    __aeabi_ddiv; # arm
-    __aeabi_dmul; # arm
-    __aeabi_drsub; # arm
-    __aeabi_dsub; # arm
-    __aeabi_f2d; # arm
     __aeabi_f2lz; # arm
     __aeabi_f2ulz; # arm
-    __aeabi_fcmpeq; # arm
-    __aeabi_fcmpge; # arm
-    __aeabi_fcmpgt; # arm
-    __aeabi_fcmple; # arm
-    __aeabi_fcmplt; # arm
-    __aeabi_i2d; # arm
     __aeabi_l2d; # arm
-    __aeabi_ui2d; # arm
-    __aeabi_ul2d; # arm
     __aeabi_unwind_cpp_pr0; # arm
     __aeabi_unwind_cpp_pr1; # arm
     __aeabi_unwind_cpp_pr2; # arm
-    __cmpdf2; # arm
-    __cmpsf2; # arm
-    __divdf3; # arm
-    __eqdf2; # arm
-    __eqsf2; # arm
-    __extendsfdf2; # arm
     __fixdfdi; # arm mips
     __fixsfdi; # arm mips
     __fixunsdfdi; # arm mips
-    __fixunsdfsi; # arm
     __fixunssfdi; # arm mips
     __floatdidf; # arm
-    __floatsidf; # arm
-    __floatundidf; # arm
-    __floatunsidf; # arm
-    __gedf2; # arm
-    __gesf2; # arm
     __gnu_Unwind_Backtrace; # arm
     __gnu_unwind_execute; # arm
     __gnu_Unwind_ForcedUnwind; # arm
@@ -370,17 +331,7 @@
     __gnu_Unwind_Save_VFP_D_16_to_31; # arm
     __gnu_Unwind_Save_WMMXC; # arm
     __gnu_Unwind_Save_WMMXD; # arm
-    __gtdf2; # arm
-    __gtsf2; # arm
-    __ledf2; # arm
-    __lesf2; # arm
-    __ltdf2; # arm
-    __ltsf2; # arm
-    __muldf3; # arm
-    __nedf2; # arm
-    __nesf2; # arm
     __restore_core_regs; # arm
-    __subdf3; # arm
     _Unwind_Backtrace; # arm
     _Unwind_Complete; # arm
     _Unwind_DeleteException; # arm
diff --git a/libm/upstream-freebsd/lib/msun/ld128/e_powl.c b/libm/upstream-freebsd/lib/msun/ld128/e_powl.c
index 15a57dd..2f3ee55 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/e_powl.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/e_powl.c
@@ -32,7 +32,7 @@
  *	1. Compute and return log2(x) in two pieces:
  *		log2(x) = w1 + w2,
  *	   where w1 has 113-53 = 60 bit trailing zeros.
- *	2. Perform y*log2(x) = n+y' by simulating muti-precision
+ *	2. Perform y*log2(x) = n+y' by simulating multi-precision
  *	   arithmetic, where |y'|<=0.5.
  *	3. Return x**y = 2**n*exp(y'*log2)
  *
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/e_powl.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD: head/lib/msun/ld128/e_powl.c 342651 2018-12-31 15:43:06Z pfg $");
 
 #include <float.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h b/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h
index 5d78c4d..1ed79ae 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h
+++ b/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/ld128/e_rem_pio2l.h 336545 2018-07-20 12:42:24Z bde $");
 
 /* ld128 version of __ieee754_rem_pio2l(x,y)
  * 
@@ -74,14 +74,9 @@
 	if (ex < BIAS + 45 || ex == BIAS + 45 &&
 	    u.bits.manh < 0x921fb54442d1LL) {
 	    /* |x| ~< 2^45*(pi/2), medium size */
-	    /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
-	    fn = x*invpio2+0x1.8p112;
-	    fn = fn-0x1.8p112;
-#ifdef HAVE_EFFICIENT_I64RINT
+	    /* TODO: use only double precision for fn, as in expl(). */
+	    fn = rnintl(x * invpio2);
 	    n  = i64rint(fn);
-#else
-	    n  = fn;
-#endif
 	    r  = x-fn*pio2_1;
 	    w  = fn*pio2_1t;	/* 1st round good to 180 bit */
 	    {
diff --git a/libm/upstream-freebsd/lib/msun/ld128/k_expl.h b/libm/upstream-freebsd/lib/msun/ld128/k_expl.h
index 4c041e8..b80d00e 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/k_expl.h
+++ b/libm/upstream-freebsd/lib/msun/ld128/k_expl.h
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/k_expl.h 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD: head/lib/msun/ld128/k_expl.h 336545 2018-07-20 12:42:24Z bde $");
 
 /*
  * ld128 version of k_expl.h.  See ../ld80/s_expl.c for most comments.
@@ -244,16 +244,8 @@
 	int n, n2;
 
 	/* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */
-	/* Use a specialized rint() to get fn.  Assume round-to-nearest. */
-	/* XXX assume no extra precision for the additions, as for trig fns. */
-	/* XXX this set of comments is now quadruplicated. */
-	/* XXX but see ../src/e_exp.c for a fix using double_t. */
-	fn = (double)x * INV_L + 0x1.8p52 - 0x1.8p52;
-#if defined(HAVE_EFFICIENT_IRINT)
+	fn = rnint((double)x * INV_L);
 	n = irint(fn);
-#else
-	n = (int)fn;
-#endif
 	n2 = (unsigned)n % INTERVALS;
 	/* Depend on the sign bit being propagated: */
 	*kp = n >> LOG2_INTERVALS;
diff --git a/libm/upstream-freebsd/lib/msun/ld128/s_expl.c b/libm/upstream-freebsd/lib/msun/ld128/s_expl.c
index 53bc04a..f4c18be 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/s_expl.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/s_expl.c
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/s_expl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD: head/lib/msun/ld128/s_expl.c 336545 2018-07-20 12:42:24Z bde $");
 
 /*
  * ld128 version of s_expl.c.  See ../ld80/s_expl.c for most comments.
@@ -268,13 +268,8 @@
 	}
 
 	/* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */
-	/* Use a specialized rint() to get fn.  Assume round-to-nearest. */
-	fn = (double)x * INV_L + 0x1.8p52 - 0x1.8p52;
-#if defined(HAVE_EFFICIENT_IRINT)
+	fn = rnint((double)x * INV_L);
 	n = irint(fn);
-#else
-	n = (int)fn;
-#endif
 	n2 = (unsigned)n % INTERVALS;
 	k = n >> LOG2_INTERVALS;
 	r1 = x - fn * L1;
diff --git a/libm/upstream-freebsd/lib/msun/src/e_j0.c b/libm/upstream-freebsd/lib/msun/src/e_j0.c
index cfa71c2..6bca542 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_j0.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_j0.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_j0.c 336089 2018-07-08 16:26:13Z markj $");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_j0.c 343023 2019-01-14 15:48:35Z pfg $");
 
 /* __ieee754_j0(x), __ieee754_y0(x)
  * Bessel function of the first and second kinds of order zero.
@@ -80,7 +80,7 @@
 S03  =  5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */
 S04  =  1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
 
-static const double zero = 0.0;
+static const double zero = 0, qrtr = 0.25;
 
 double
 __ieee754_j0(double x)
@@ -97,7 +97,7 @@
 		c = cos(x);
 		ss = s-c;
 		cc = s+c;
-		if(ix<0x7fe00000) {  /* make sure x+x not overflow */
+		if(ix<0x7fe00000) {  /* Make sure x+x does not overflow. */
 		    z = -cos(x+x);
 		    if ((s*c)<zero) cc = z/ss;
 		    else 	    ss = z/cc;
@@ -123,9 +123,9 @@
 	r =  z*(R02+z*(R03+z*(R04+z*R05)));
 	s =  one+z*(S01+z*(S02+z*(S03+z*S04)));
 	if(ix < 0x3FF00000) {	/* |x| < 1.00 */
-	    return one + z*(-0.25+(r/s));
+	    return one + z*((r/s)-qrtr);
 	} else {
-	    u = 0.5*x;
+	    u = x/2;
 	    return((one+u)*(one-u)+z*(r/s));
 	}
 }
@@ -374,6 +374,7 @@
 static __inline double
 qzero(double x)
 {
+	static const double eighth = 0.125;
 	const double *p,*q;
 	double s,r,z;
 	int32_t ix;
@@ -386,5 +387,5 @@
 	z = one/(x*x);
 	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
 	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
-	return (-.125 + r/s)/x;
+	return (r/s-eighth)/x;
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/e_j0f.c b/libm/upstream-freebsd/lib/msun/src/e_j0f.c
index e53b218..714caac 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_j0f.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_j0f.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_j0f.c 283032 2015-05-17 16:27:06Z kargl $");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_j0f.c 343023 2019-01-14 15:48:35Z pfg $");
 
 /*
  * See e_j0.c for complete comments.
@@ -42,7 +42,7 @@
 S03  =  5.1354652442e-07, /* 0x3509daa6 */
 S04  =  1.1661400734e-09; /* 0x30a045e8 */
 
-static const float zero = 0.0;
+static const float zero = 0, qrtr = 0.25;
 
 float
 __ieee754_j0f(float x)
@@ -59,7 +59,7 @@
 		c = cosf(x);
 		ss = s-c;
 		cc = s+c;
-		if(ix<0x7f000000) {  /* make sure x+x not overflow */
+		if(ix<0x7f000000) {  /* Make sure x+x does not overflow. */
 		    z = -cosf(x+x);
 		    if ((s*c)<zero) cc = z/ss;
 		    else 	    ss = z/cc;
@@ -85,9 +85,9 @@
 	r =  z*(R02+z*(R03+z*(R04+z*R05)));
 	s =  one+z*(S01+z*(S02+z*(S03+z*S04)));
 	if(ix < 0x3F800000) {	/* |x| < 1.00 */
-	    return one + z*((float)-0.25+(r/s));
+	    return one + z*((r/s)-qrtr);
 	} else {
-	    u = (float)0.5*x;
+	    u = x/2;
 	    return((one+u)*(one-u)+z*(r/s));
 	}
 }
@@ -328,6 +328,7 @@
 static __inline float
 qzerof(float x)
 {
+	static const float eighth = 0.125;
 	const float *p,*q;
 	float s,r,z;
 	int32_t ix;
@@ -340,5 +341,5 @@
 	z = one/(x*x);
 	r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
 	s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
-	return (-(float).125 + r/s)/x;
+	return (r/s-eighth)/x;
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/e_pow.c b/libm/upstream-freebsd/lib/msun/src/e_pow.c
index 411dd52..b4f6a5a 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_pow.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_pow.c
@@ -10,7 +10,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_pow.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_pow.c 342851 2019-01-07 17:35:09Z pfg $");
 
 /* __ieee754_pow(x,y) return x**y
  *
@@ -133,7 +133,7 @@
 		k = (iy>>20)-0x3ff;	   /* exponent */
 		if(k>20) {
 		    j = ly>>(52-k);
-		    if((j<<(52-k))==ly) yisint = 2-(j&1);
+		    if(((u_int32_t)j<<(52-k))==ly) yisint = 2-(j&1);
 		} else if(ly==0) {
 		    j = iy>>(20-k);
 		    if((j<<(20-k))==iy) yisint = 2-(j&1);
diff --git a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c
index be2630b..3e62c2b 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2.c 336545 2018-07-20 12:42:24Z bde $");
 
 /* __ieee754_rem_pio2(x,y)
  * 
@@ -127,14 +127,8 @@
 	}
 	if(ix<0x413921fb) {	/* |x| ~< 2^20*(pi/2), medium size */
 medium:
-	    /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
-	    STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52);
-	    fn = fn-0x1.8p52;
-#ifdef HAVE_EFFICIENT_IRINT
+	    fn = rnint((double_t)x*invpio2);
 	    n  = irint(fn);
-#else
-	    n  = (int32_t)fn;
-#endif
 	    r  = x-fn*pio2_1;
 	    w  = fn*pio2_1t;	/* 1st round good to 85 bit */
 	    {
diff --git a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c
index f1ee7a0..2a89d27 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c
@@ -15,7 +15,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2f.c 336545 2018-07-20 12:42:24Z bde $");
 
 /* __ieee754_rem_pio2f(x,y)
  *
@@ -55,14 +55,8 @@
 	ix = hx&0x7fffffff;
     /* 33+53 bit pi is good enough for medium size */
 	if(ix<0x4dc90fdb) {		/* |x| ~< 2^28*(pi/2), medium size */
-	    /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
-	    STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52);
-	    fn = fn-0x1.8p52;
-#ifdef HAVE_EFFICIENT_IRINT
+	    fn = rnint((float_t)x*invpio2);
 	    n  = irint(fn);
-#else
-	    n  = (int32_t)fn;
-#endif
 	    r  = x-fn*pio2_1;
 	    w  = fn*pio2_1t;
 	    *y = r-w;
diff --git a/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c b/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c
index 81363d4..0869e03 100644
--- a/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c
+++ b/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/k_rem_pio2.c 298896 2016-05-01 19:37:33Z pfg $");
+__FBSDID("$FreeBSD: head/lib/msun/src/k_rem_pio2.c 342651 2018-12-31 15:43:06Z pfg $");
 
 /*
  * __kernel_rem_pio2(x,y,e0,nx,prec)
@@ -52,7 +52,7 @@
  *			64-bit  precision	2
  *			113-bit precision	3
  *		The actual value is the sum of them. Thus for 113-bit
- *		precison, one may have to do something like:
+ *		precision, one may have to do something like:
  *
  *		long double t,w,r_head, r_tail;
  *		t = (long double)y[2] + (long double)y[1];
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cbrt.c b/libm/upstream-freebsd/lib/msun/src/s_cbrt.c
index d75ad0b..268425e 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cbrt.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cbrt.c
@@ -13,8 +13,9 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cbrt.c 298896 2016-05-01 19:37:33Z pfg $");
+__FBSDID("$FreeBSD: head/lib/msun/src/s_cbrt.c 342563 2018-12-28 01:34:08Z jhibbits $");
 
+#include <float.h>
 #include "math.h"
 #include "math_private.h"
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cpow.c b/libm/upstream-freebsd/lib/msun/src/s_cpow.c
index 9be5c51..1cb99aa 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cpow.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cpow.c
@@ -44,11 +44,12 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cpow.c 336299 2018-07-15 00:23:10Z mmacy $");
+__FBSDID("$FreeBSD: head/lib/msun/src/s_cpow.c 336563 2018-07-20 18:27:30Z dim $");
 
 #include <complex.h>
 #include <float.h>
 #include <math.h>
+#include "math_private.h"
 
 double complex
 cpow(double complex a, double complex z)
@@ -60,7 +61,7 @@
 	y = cimag (z);
 	absa = cabs (a);
 	if (absa == 0.0) {
-		return (0.0 + 0.0 * I);
+		return (CMPLX(0.0, 0.0));
 	}
 	arga = carg (a);
 	r = pow (absa, x);
@@ -69,6 +70,6 @@
 		r = r * exp (-y * arga);
 		theta = theta + y * log (absa);
 	}
-	w = r * cos (theta) + (r * sin (theta)) * I;
+	w = CMPLX(r * cos (theta),  r * sin (theta));
 	return (w);
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cpowf.c b/libm/upstream-freebsd/lib/msun/src/s_cpowf.c
index 6e27f57..a2ef525 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cpowf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cpowf.c
@@ -44,10 +44,11 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cpowf.c 336299 2018-07-15 00:23:10Z mmacy $");
+__FBSDID("$FreeBSD: head/lib/msun/src/s_cpowf.c 336563 2018-07-20 18:27:30Z dim $");
 
 #include <complex.h>
 #include <math.h>
+#include "math_private.h"
 
 float complex
 cpowf(float complex a, float complex z)
@@ -59,7 +60,7 @@
 	y = cimagf(z);
 	absa = cabsf (a);
 	if (absa == 0.0f) {
-		return (0.0f + 0.0f * I);
+		return (CMPLXF(0.0f, 0.0f));
 	}
 	arga = cargf (a);
 	r = powf (absa, x);
@@ -68,6 +69,6 @@
 		r = r * expf (-y * arga);
 		theta = theta + y * logf (absa);
 	}
-	w = r * cosf (theta) + (r * sinf (theta)) * I;
+	w = CMPLXF(r * cosf (theta), r * sinf (theta));
 	return (w);
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cpowl.c b/libm/upstream-freebsd/lib/msun/src/s_cpowl.c
index fcb5c7f..f9c6373 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cpowl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cpowl.c
@@ -44,10 +44,11 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cpowl.c 336299 2018-07-15 00:23:10Z mmacy $");
+__FBSDID("$FreeBSD: head/lib/msun/src/s_cpowl.c 336563 2018-07-20 18:27:30Z dim $");
 
 #include <complex.h>
 #include <math.h>
+#include "math_private.h"
 
 long double complex
 cpowl(long double complex a, long double complex z)
@@ -59,7 +60,7 @@
 	y = cimagl(z);
 	absa = cabsl(a);
 	if (absa == 0.0L) {
-		return (0.0L + 0.0L * I);
+		return (CMPLXL(0.0L, 0.0L));
 	}
 	arga = cargl(a);
 	r = powl(absa, x);
@@ -68,6 +69,6 @@
 		r = r * expl(-y * arga);
 		theta = theta + y * logl(absa);
 	}
-	w = r * cosl(theta) + (r * sinl(theta)) * I;
+	w = CMPLXL(r * cosl(theta), r * sinl(theta));
 	return (w);
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cproj.c b/libm/upstream-freebsd/lib/msun/src/s_cproj.c
index 3083f2b..7677b5f 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cproj.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cproj.c
@@ -27,9 +27,10 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cproj.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD: head/lib/msun/src/s_cproj.c 342563 2018-12-28 01:34:08Z jhibbits $");
 
 #include <complex.h>
+#include <float.h>
 #include <math.h>
 
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/s_erf.c b/libm/upstream-freebsd/lib/msun/src/s_erf.c
index e1d63bc..3e39d80 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_erf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_erf.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/s_erf.c 342563 2018-12-28 01:34:08Z jhibbits $");
 
 /* double erf(double x)
  * double erfc(double x)
@@ -107,7 +107,7 @@
  *	   	erfc/erf(NaN) is NaN
  */
 
-
+#include <float.h>
 #include "math.h"
 #include "math_private.h"
 
diff --git a/linker/Android.bp b/linker/Android.bp
index fed921d..73328da 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -283,8 +283,6 @@
 
     name: "linker",
     symlinks: ["linker_asan"],
-    // The linker in the system partition is now only for bootstrapping
-    relative_install_path: "bootstrap",
     recovery_available: true,
     multilib: {
         lib32: {
@@ -296,6 +294,10 @@
         },
     },
     system_shared_libs: [],
+
+    // Opt out of native_coverage when opting out of system_shared_libs
+    native_coverage: false,
+
     target: {
         android: {
             static_libs: ["libdebuggerd_handler_fallback"],
@@ -303,7 +305,6 @@
     },
     compile_multilib: "both",
     xom: false,
-    required: ["linker.mountpoint"],
 }
 
 cc_library {
@@ -364,7 +365,46 @@
     nocrt: true,
     system_shared_libs: [],
 
+    // Opt out of native_coverage when opting out of system_shared_libs
+    native_coverage: false,
+
     sanitize: {
         never: true,
     },
 }
+
+cc_test {
+    name: "linker-unit-tests",
+
+    cflags: [
+        "-g",
+        "-Wall",
+        "-Wextra",
+        "-Wunused",
+        "-Werror",
+    ],
+
+    // We need to access Bionic private headers in the linker.
+    include_dirs: ["bionic/libc"],
+
+    srcs: [
+        // Tests.
+        "linker_block_allocator_test.cpp",
+        "linker_config_test.cpp",
+        "linked_list_test.cpp",
+        "linker_sleb128_test.cpp",
+        "linker_utils_test.cpp",
+
+        // Parts of the linker that we're testing.
+        "linker_block_allocator.cpp",
+        "linker_config.cpp",
+        "linker_test_globals.cpp",
+        "linker_utils.cpp",
+    ],
+
+    static_libs: [
+        "libasync_safe",
+        "libbase",
+        "liblog",
+    ],
+}
diff --git a/linker/Android.mk b/linker/Android.mk
deleted file mode 100644
index ea7451c..0000000
--- a/linker/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/linker/tests/linked_list_test.cpp b/linker/linked_list_test.cpp
similarity index 99%
rename from linker/tests/linked_list_test.cpp
rename to linker/linked_list_test.cpp
index 2b88ed0..71a7d09 100644
--- a/linker/tests/linked_list_test.cpp
+++ b/linker/linked_list_test.cpp
@@ -32,7 +32,7 @@
 
 #include <gtest/gtest.h>
 
-#include "../linked_list.h"
+#include "linked_list.h"
 
 namespace {
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index d0c740b..49c8f11 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -91,19 +91,21 @@
 static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
 
 #if defined(__LP64__)
-static const char* const kSystemLibDir     = "/system/lib64";
-static const char* const kOdmLibDir        = "/odm/lib64";
-static const char* const kVendorLibDir     = "/vendor/lib64";
-static const char* const kAsanSystemLibDir = "/data/asan/system/lib64";
-static const char* const kAsanOdmLibDir    = "/data/asan/odm/lib64";
-static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib64";
+static const char* const kSystemLibDir        = "/system/lib64";
+static const char* const kOdmLibDir           = "/odm/lib64";
+static const char* const kVendorLibDir        = "/vendor/lib64";
+static const char* const kAsanSystemLibDir    = "/data/asan/system/lib64";
+static const char* const kAsanOdmLibDir       = "/data/asan/odm/lib64";
+static const char* const kAsanVendorLibDir    = "/data/asan/vendor/lib64";
+static const char* const kRuntimeApexLibDir   = "/apex/com.android.runtime/lib64";
 #else
-static const char* const kSystemLibDir     = "/system/lib";
-static const char* const kOdmLibDir        = "/odm/lib";
-static const char* const kVendorLibDir     = "/vendor/lib";
-static const char* const kAsanSystemLibDir = "/data/asan/system/lib";
-static const char* const kAsanOdmLibDir    = "/data/asan/odm/lib";
-static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib";
+static const char* const kSystemLibDir        = "/system/lib";
+static const char* const kOdmLibDir           = "/odm/lib";
+static const char* const kVendorLibDir        = "/vendor/lib";
+static const char* const kAsanSystemLibDir    = "/data/asan/system/lib";
+static const char* const kAsanOdmLibDir       = "/data/asan/odm/lib";
+static const char* const kAsanVendorLibDir    = "/data/asan/vendor/lib";
+static const char* const kRuntimeApexLibDir   = "/apex/com.android.runtime/lib";
 #endif
 
 static const char* const kAsanLibDirPrefix = "/data/asan";
@@ -228,6 +230,44 @@
 }
 // END OF WORKAROUND
 
+// Workaround for dlopen(/system/lib(64)/<soname>) when .so is in /apex. http://b/121248172
+/**
+ * Translate /system path to /apex path if needed
+ * The workaround should work only when targetSdkVersion < Q.
+ *
+ * param out_name_to_apex pointing to /apex path
+ * return true if translation is needed
+ */
+static bool translateSystemPathToApexPath(const char* name, std::string* out_name_to_apex) {
+  static const char* const kSystemToRuntimeApexLibs[] = {
+    "libicuuc.so",
+    "libicui18n.so",
+  };
+  // New mapping for new apex should be added below
+
+  // Nothing to do if target sdk version is Q or above
+  if (get_application_target_sdk_version() >= __ANDROID_API_Q__) {
+    return false;
+  }
+
+  // If the path isn't /system/lib, there's nothing to do.
+  if (name == nullptr || dirname(name) != kSystemLibDir) {
+    return false;
+  }
+
+  const char* base_name = basename(name);
+
+  for (const char* soname : kSystemToRuntimeApexLibs) {
+    if (strcmp(base_name, soname) == 0) {
+      *out_name_to_apex = std::string(kRuntimeApexLibDir) + "/" + base_name;
+      return true;
+    }
+  }
+
+  return false;
+}
+// End Workaround for dlopen(/system/lib/<soname>) when .so is in /apex.
+
 static std::vector<std::string> g_ld_preload_names;
 
 static bool g_anonymous_namespace_initialized;
@@ -375,11 +415,9 @@
 //
 // Intended to be called by libc's __gnu_Unwind_Find_exidx().
 _Unwind_Ptr do_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
-  for (soinfo* si = solist_get_head(); si != 0; si = si->next) {
-    if ((pc >= si->base) && (pc < (si->base + si->size))) {
-        *pcount = si->ARM_exidx_count;
-        return reinterpret_cast<_Unwind_Ptr>(si->ARM_exidx);
-    }
+  if (soinfo* si = find_containing_library(reinterpret_cast<void*>(pc))) {
+    *pcount = si->ARM_exidx_count;
+    return reinterpret_cast<_Unwind_Ptr>(si->ARM_exidx);
   }
   *pcount = 0;
   return 0;
@@ -536,6 +574,10 @@
     allocator_.free(ptr);
   }
 
+  static void purge() {
+    allocator_.purge();
+  }
+
  private:
   static LinkerBlockAllocator allocator_;
 };
@@ -553,6 +595,10 @@
   static void free(T* ptr) {
     SizeBasedAllocator<sizeof(T)>::free(ptr);
   }
+
+  static void purge() {
+    SizeBasedAllocator<sizeof(T)>::purge();
+  }
 };
 
 class LoadTask {
@@ -650,9 +696,9 @@
     return elf_reader.Read(realpath, fd_, file_offset_, file_size);
   }
 
-  bool load() {
+  bool load(address_space_params* address_space) {
     ElfReader& elf_reader = get_elf_reader();
-    if (!elf_reader.Load(extinfo_)) {
+    if (!elf_reader.Load(address_space)) {
       return false;
     }
 
@@ -890,8 +936,18 @@
 soinfo* find_containing_library(const void* p) {
   ElfW(Addr) address = reinterpret_cast<ElfW(Addr)>(p);
   for (soinfo* si = solist_get_head(); si != nullptr; si = si->next) {
-    if (address >= si->base && address - si->base < si->size) {
-      return si;
+    if (address < si->base || address - si->base >= si->size) {
+      continue;
+    }
+    ElfW(Addr) vaddr = address - si->load_bias;
+    for (size_t i = 0; i != si->phnum; ++i) {
+      const ElfW(Phdr)* phdr = &si->phdr[i];
+      if (phdr->p_type != PT_LOAD) {
+        continue;
+      }
+      if (vaddr >= phdr->p_vaddr && vaddr < phdr->p_vaddr + phdr->p_memsz) {
+        return si;
+      }
     }
   }
   return nullptr;
@@ -1068,7 +1124,7 @@
                         ZipArchiveCache* zip_archive_cache,
                         const char* name, soinfo *needed_by,
                         off64_t* file_offset, std::string* realpath) {
-  TRACE("[ opening %s at namespace %s]", name, ns->get_name());
+  TRACE("[ opening %s from namespace %s ]", name, ns->get_name());
 
   // If the name contains a slash, we should attempt to open it directly and not search the paths.
   if (strchr(name, '/') != nullptr) {
@@ -1110,14 +1166,6 @@
     fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_default_library_paths(), realpath);
   }
 
-  // TODO(dimitry): workaround for http://b/26394120 (the grey-list)
-  if (fd == -1 && ns->is_greylist_enabled() && is_greylisted(ns, name, needed_by)) {
-    // try searching for it on default_namespace default_library_path
-    fd = open_library_on_paths(zip_archive_cache, name, file_offset,
-                               g_default_namespace.get_default_library_paths(), realpath);
-  }
-  // END OF WORKAROUND
-
   return fd;
 }
 
@@ -1217,6 +1265,9 @@
   const char* name = task->get_name();
   const android_dlextinfo* extinfo = task->get_extinfo();
 
+  LD_LOG(kLogDlopen, "load_library(ns=%s, task=%s, flags=0x%x, realpath=%s)", ns->get_name(), name,
+         rtld_flags, realpath.c_str());
+
   if ((file_offset % PAGE_SIZE) != 0) {
     DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
     return false;
@@ -1242,8 +1293,10 @@
   if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) {
     soinfo* si = nullptr;
     if (find_loaded_library_by_inode(ns, file_stat, file_offset, search_linked_namespaces, &si)) {
-      TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
-            "will return existing soinfo", name, si->get_realpath());
+      LD_LOG(kLogDlopen,
+             "load_library(ns=%s, task=%s): Already loaded under different name/path \"%s\" - "
+             "will return existing soinfo",
+             ns->get_name(), name, si->get_realpath());
       task->set_soinfo(si);
       return true;
     }
@@ -1344,6 +1397,8 @@
 #endif
 
   for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
+    LD_LOG(kLogDlopen, "load_library(ns=%s, task=%s): Adding DT_NEEDED task: %s",
+           ns->get_name(), task->get_name(), name);
     load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
   });
 
@@ -1459,17 +1514,24 @@
 
   if (!namespace_link.is_accessible(soname.c_str())) {
     // the library is not accessible via namespace_link
+    LD_LOG(kLogDlopen,
+           "find_library_in_linked_namespace(ns=%s, task=%s): Not accessible (soname=%s)",
+           ns->get_name(), task->get_name(), soname.c_str());
     return false;
   }
 
   // if library is already loaded - return it
   if (loaded) {
+    LD_LOG(kLogDlopen, "find_library_in_linked_namespace(ns=%s, task=%s): Already loaded",
+           ns->get_name(), task->get_name());
     task->set_soinfo(candidate);
     return true;
   }
 
   // returning true with empty soinfo means that the library is okay to be
   // loaded in the namespace but has not yet been loaded there before.
+  LD_LOG(kLogDlopen, "find_library_in_linked_namespace(ns=%s, task=%s): Ok to load", ns->get_name(),
+         task->get_name());
   task->set_soinfo(nullptr);
   return true;
 }
@@ -1483,26 +1545,47 @@
   soinfo* candidate;
 
   if (find_loaded_library_by_soname(ns, task->get_name(), search_linked_namespaces, &candidate)) {
+    LD_LOG(kLogDlopen,
+           "find_library_internal(ns=%s, task=%s): Already loaded (by soname): %s",
+           ns->get_name(), task->get_name(), candidate->get_realpath());
     task->set_soinfo(candidate);
     return true;
   }
 
   // Library might still be loaded, the accurate detection
   // of this fact is done by load_library.
-  TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]",
-      task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
+  TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder... ]",
+        task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
 
   if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags, search_linked_namespaces)) {
     return true;
   }
 
+  // TODO(dimitry): workaround for http://b/26394120 (the grey-list)
+  if (ns->is_greylist_enabled() && is_greylisted(ns, task->get_name(), task->get_needed_by())) {
+    // For the libs in the greylist, switch to the default namespace and then
+    // try the load again from there. The library could be loaded from the
+    // default namespace or from another namespace (e.g. runtime) that is linked
+    // from the default namespace.
+    LD_LOG(kLogDlopen,
+           "find_library_internal(ns=%s, task=%s): Greylisted library - trying namespace %s",
+           ns->get_name(), task->get_name(), g_default_namespace.get_name());
+    ns = &g_default_namespace;
+    if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags,
+                     search_linked_namespaces)) {
+      return true;
+    }
+  }
+  // END OF WORKAROUND
+
   if (search_linked_namespaces) {
     // if a library was not found - look into linked namespaces
     // preserve current dlerror in the case it fails.
     DlErrorRestorer dlerror_restorer;
+    LD_LOG(kLogDlopen, "find_library_internal(ns=%s, task=%s): Trying %zu linked namespaces",
+           ns->get_name(), task->get_name(), ns->linked_namespaces().size());
     for (auto& linked_namespace : ns->linked_namespaces()) {
-      if (find_library_in_linked_namespace(linked_namespace,
-                                           task)) {
+      if (find_library_in_linked_namespace(linked_namespace, task)) {
         if (task->get_soinfo() == nullptr) {
           // try to load the library - once namespace boundary is crossed
           // we need to load a library within separate load_group
@@ -1513,6 +1596,9 @@
           // Otherwise, the libs in the linked namespace won't get symbols from
           // the global group.
           if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) {
+            LD_LOG(
+                kLogDlopen, "find_library_internal(ns=%s, task=%s): Found in linked namespace %s",
+                ns->get_name(), task->get_name(), linked_namespace.linked_namespace()->get_name());
             return true;
           }
         } else {
@@ -1600,6 +1686,9 @@
     task->set_extinfo(is_dt_needed ? nullptr : extinfo);
     task->set_dt_needed(is_dt_needed);
 
+    LD_LOG(kLogDlopen, "find_libraries(ns=%s): task=%s, is_dt_needed=%d", ns->get_name(),
+           task->get_name(), is_dt_needed);
+
     // Note: start from the namespace that is stored in the LoadTask. This namespace
     // is different from the current namespace when the LoadTask is for a transitive
     // dependency and the lib that created the LoadTask is not found in the
@@ -1643,10 +1732,34 @@
       load_list.push_back(task);
     }
   }
-  shuffle(&load_list);
+  bool reserved_address_recursive = false;
+  if (extinfo) {
+    reserved_address_recursive = extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
+  }
+  if (!reserved_address_recursive) {
+    // Shuffle the load order in the normal case, but not if we are loading all
+    // the libraries to a reserved address range.
+    shuffle(&load_list);
+  }
+
+  // Set up address space parameters.
+  address_space_params extinfo_params, default_params;
+  size_t relro_fd_offset = 0;
+  if (extinfo) {
+    if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
+      extinfo_params.start_addr = extinfo->reserved_addr;
+      extinfo_params.reserved_size = extinfo->reserved_size;
+      extinfo_params.must_use_address = true;
+    } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
+      extinfo_params.start_addr = extinfo->reserved_addr;
+      extinfo_params.reserved_size = extinfo->reserved_size;
+    }
+  }
 
   for (auto&& task : load_list) {
-    if (!task->load()) {
+    address_space_params* address_space =
+        (reserved_address_recursive || !task->is_dt_needed()) ? &extinfo_params : &default_params;
+    if (!task->load(address_space)) {
       return false;
     }
   }
@@ -1756,7 +1869,7 @@
       // we should avoid linking them (because if they are not linked -> they
       // are in the local_group_roots and will be linked later).
       if (!si->is_linked() && si->get_primary_namespace() == local_group_ns) {
-        if (!si->link_image(global_group, local_group, extinfo) ||
+        if (!si->link_image(global_group, local_group, extinfo, &relro_fd_offset) ||
             !get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
           return false;
         }
@@ -2066,13 +2179,16 @@
   android_namespace_t* ns = get_caller_namespace(caller);
 
   LD_LOG(kLogDlopen,
-         "dlopen(name=\"%s\", flags=0x%x, extinfo=%s, caller=\"%s\", caller_ns=%s@%p) ...",
+         "dlopen(name=\"%s\", flags=0x%x, extinfo=%s, caller=\"%s\", caller_ns=%s@%p, targetSdkVersion=%i) ...",
          name,
          flags,
          android_dlextinfo_to_string(extinfo).c_str(),
          caller == nullptr ? "(null)" : caller->get_realpath(),
          ns == nullptr ? "(null)" : ns->get_name(),
-         ns);
+         ns,
+         get_application_target_sdk_version());
+
+  auto purge_guard = android::base::make_scope_guard([&]() { purge_unused_memory(); });
 
   auto failure_guard = android::base::make_scope_guard(
       [&]() { LD_LOG(kLogDlopen, "... dlopen failed: %s", linker_get_error_buffer()); });
@@ -2104,6 +2220,32 @@
     }
   }
 
+  // Workaround for dlopen(/system/lib/<soname>) when .so is in /apex. http://b/121248172
+  // The workaround works only when targetSdkVersion < Q.
+  std::string name_to_apex;
+  if (translateSystemPathToApexPath(name, &name_to_apex)) {
+    const char* new_name = name_to_apex.c_str();
+    LD_LOG(kLogDlopen, "dlopen considering translation from %s to APEX path %s",
+           name,
+           new_name);
+    // Some APEXs could be optionally disabled. Only translate the path
+    // when the old file is absent and the new file exists.
+    // TODO(b/124218500): Re-enable it once app compat issue is resolved
+    /*
+    if (file_exists(name)) {
+      LD_LOG(kLogDlopen, "dlopen %s exists, not translating", name);
+    } else
+    */
+    if (!file_exists(new_name)) {
+      LD_LOG(kLogDlopen, "dlopen %s does not exist, not translating",
+             new_name);
+    } else {
+      LD_LOG(kLogDlopen, "dlopen translation accepted: using %s", new_name);
+      name = new_name;
+    }
+  }
+  // End Workaround for dlopen(/system/lib/<soname>) when .so is in /apex.
+
   std::string asan_name_holder;
 
   const char* translated_name = name;
@@ -3018,7 +3160,7 @@
           }
         }
         break;
-#endif  // defined(R_GENERIC_TLSDESC)
+#endif  // defined(__aarch64__)
 
 #if defined(__aarch64__)
       case R_AARCH64_ABS64:
@@ -3190,11 +3332,14 @@
     }
   }
 
+#if defined(__aarch64__)
+  // Bionic currently only implements TLSDESC for arm64.
   for (const std::pair<TlsDescriptor*, size_t>& pair : deferred_tlsdesc_relocs) {
     TlsDescriptor* desc = pair.first;
     desc->func = tlsdesc_resolver_dynamic;
     desc->arg = reinterpret_cast<size_t>(&tlsdesc_args_[pair.second]);
   }
+#endif
 
   return true;
 }
@@ -3702,7 +3847,7 @@
 }
 
 bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
-                        const android_dlextinfo* extinfo) {
+                        const android_dlextinfo* extinfo, size_t* relro_fd_offset) {
   if (is_image_linked()) {
     // already linked.
     return true;
@@ -3849,7 +3994,7 @@
     }
   } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
     if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,
-                                 extinfo->relro_fd) < 0) {
+                                 extinfo->relro_fd, relro_fd_offset) < 0) {
       DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
              get_realpath(), strerror(errno));
       return false;
@@ -3965,6 +4110,7 @@
 
   std::string ld_config_file_path = get_ld_config_file_path(executable_path);
 
+  INFO("[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
   if (!Config::read_binary_config(ld_config_file_path.c_str(),
                                   executable_path,
                                   g_is_asan,
@@ -4069,3 +4215,17 @@
   }
   return it->second;
 }
+
+void purge_unused_memory() {
+  // For now, we only purge the memory used by LoadTask because we know those
+  // are temporary objects.
+  //
+  // Purging other LinkerBlockAllocator hardly yields much because they hold
+  // information about namespaces and opened libraries, which are not freed
+  // when the control leaves the linker.
+  //
+  // Purging BionicAllocator may give us a few dirty pages back, but those pages
+  // would be already zeroed out, so they compress easily in ZRAM.  Therefore,
+  // it is not worth munmap()'ing those pages.
+  TypeBasedAllocator<LoadTask>::purge();
+}
diff --git a/linker/linker.h b/linker/linker.h
index 91d3ddf..4c89ceb 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -186,3 +186,11 @@
 
 void increment_dso_handle_reference_counter(void* dso_handle);
 void decrement_dso_handle_reference_counter(void* dso_handle);
+
+void purge_unused_memory();
+
+struct address_space_params {
+  void* start_addr = nullptr;
+  size_t reserved_size = 0;
+  bool must_use_address = false;
+};
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index d72cad3..1e2f9a2 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -55,7 +55,8 @@
   : block_size_(
       round_up(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size, 16)),
     page_list_(nullptr),
-    free_block_list_(nullptr)
+    free_block_list_(nullptr),
+    allocated_(0)
 {}
 
 void* LinkerBlockAllocator::alloc() {
@@ -76,6 +77,8 @@
 
   memset(block_info, 0, block_size_);
 
+  ++allocated_;
+
   return block_info;
 }
 
@@ -104,6 +107,8 @@
   block_info->num_free_blocks = 1;
 
   free_block_list_ = block_info;
+
+  --allocated_;
 }
 
 void LinkerBlockAllocator::protect_all(int prot) {
@@ -129,7 +134,7 @@
 
   FreeBlockInfo* first_block = reinterpret_cast<FreeBlockInfo*>(page->bytes);
   first_block->next_block = free_block_list_;
-  first_block->num_free_blocks = (kAllocateSize - sizeof(LinkerBlockAllocatorPage*))/block_size_;
+  first_block->num_free_blocks = sizeof(page->bytes) / block_size_;
 
   free_block_list_ = first_block;
 
@@ -154,3 +159,18 @@
 
   abort();
 }
+
+void LinkerBlockAllocator::purge() {
+  if (allocated_) {
+    return;
+  }
+
+  LinkerBlockAllocatorPage* page = page_list_;
+  while (page) {
+    LinkerBlockAllocatorPage* next = page->next;
+    munmap(page, kAllocateSize);
+    page = next;
+  }
+  page_list_ = nullptr;
+  free_block_list_ = nullptr;
+}
diff --git a/linker/linker_block_allocator.h b/linker/linker_block_allocator.h
index 0c54b93..8ae4094 100644
--- a/linker/linker_block_allocator.h
+++ b/linker/linker_block_allocator.h
@@ -50,6 +50,9 @@
   void free(void* block);
   void protect_all(int prot);
 
+  // Purge all pages if all previously allocated blocks have been freed.
+  void purge();
+
  private:
   void create_new_page();
   LinkerBlockAllocatorPage* find_page(void* block);
@@ -57,6 +60,7 @@
   size_t block_size_;
   LinkerBlockAllocatorPage* page_list_;
   void* free_block_list_;
+  size_t allocated_;
 
   DISALLOW_COPY_AND_ASSIGN(LinkerBlockAllocator);
 };
diff --git a/linker/tests/linker_block_allocator_test.cpp b/linker/linker_block_allocator_test.cpp
similarity index 98%
rename from linker/tests/linker_block_allocator_test.cpp
rename to linker/linker_block_allocator_test.cpp
index d5eb97c..359eefb 100644
--- a/linker/tests/linker_block_allocator_test.cpp
+++ b/linker/linker_block_allocator_test.cpp
@@ -32,7 +32,7 @@
 
 #include <gtest/gtest.h>
 
-#include "../linker_block_allocator.h"
+#include "linker_block_allocator.h"
 
 #include <unistd.h>
 
@@ -145,4 +145,3 @@
   testing::FLAGS_gtest_death_test_style = "threadsafe";
   ASSERT_EXIT(protect_all(), testing::KilledBySignal(SIGSEGV), "trying to access protected page");
 }
-
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index 5a728d3..f7f9c41 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -80,7 +80,7 @@
         continue;
       }
 
-      if (line[0] == '[' && line[line.size() - 1] == ']') {
+      if (line[0] == '[' && line.back() == ']') {
         *name = line.substr(1, line.size() - 2);
         return kSection;
       }
@@ -269,6 +269,8 @@
     }
   }
 
+  INFO("[ Using config section \"%s\" ]", section_name.c_str());
+
   // skip everything until we meet a correct section
   while (true) {
     std::string name;
diff --git a/linker/tests/linker_config_test.cpp b/linker/linker_config_test.cpp
similarity index 99%
rename from linker/tests/linker_config_test.cpp
rename to linker/linker_config_test.cpp
index 14fd132..6a55bb2 100644
--- a/linker/tests/linker_config_test.cpp
+++ b/linker/linker_config_test.cpp
@@ -32,8 +32,8 @@
 
 #include <gtest/gtest.h>
 
-#include "../linker_config.h"
-#include "../linker_utils.h"
+#include "linker_config.h"
+#include "linker_utils.h"
 
 #include <unistd.h>
 
diff --git a/linker/linker_debug.h b/linker/linker_debug.h
index 862ea12..7a1cb3c 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -56,6 +56,7 @@
 #include <unistd.h>
 
 #include <async_safe/log.h>
+#include <async_safe/CHECK.h>
 
 __LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
 
diff --git a/linker/linker_logger.h b/linker/linker_logger.h
index f9fc38e..fedbc05 100644
--- a/linker/linker_logger.h
+++ b/linker/linker_logger.h
@@ -49,7 +49,7 @@
   LinkerLogger() : flags_(0) { }
 
   void ResetState();
-  void Log(const char* format, ...);
+  void Log(const char* format, ...) __printflike(2, 3);
 
   uint32_t IsEnabled(uint32_t type) {
     return flags_ & type;
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index b0c27dc..6c762a9 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -165,7 +165,7 @@
   si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
 
   si->prelink_image();
-  si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr);
+  si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr, nullptr);
   // prevents accidental unloads...
   si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_NODELETE);
   si->set_linked();
@@ -281,7 +281,8 @@
   if (!elf_reader.Read(result.path.c_str(), fd.get(), file_offset, result.file_stat.st_size)) {
     __linker_error("error: %s\n", linker_get_error_buffer());
   }
-  if (!elf_reader.Load(nullptr)) {
+  address_space_params address_space;
+  if (!elf_reader.Load(&address_space)) {
     __linker_error("error: %s\n", linker_get_error_buffer());
   }
 
@@ -352,6 +353,8 @@
   // a C-style string to last until the program exits.
   static std::string exe_path = exe_info.path;
 
+  INFO("[ Linking executable \"%s\" ]", exe_path.c_str());
+
   // Initialize the main exe's soinfo.
   soinfo* si = soinfo_alloc(&g_default_namespace,
                             exe_path.c_str(), &exe_info.file_stat,
@@ -448,7 +451,7 @@
                       &namespaces)) {
     __linker_cannot_link(g_argv[0]);
   } else if (needed_libraries_count == 0) {
-    if (!si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr)) {
+    if (!si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr, nullptr)) {
       __linker_cannot_link(g_argv[0]);
     }
     si->increment_ref_count();
@@ -503,6 +506,10 @@
   fflush(stdout);
 #endif
 
+  // We are about to hand control over to the executable loaded.  We don't want
+  // to leave dirty pages behind unnecessarily.
+  purge_unused_memory();
+
   ElfW(Addr) entry = exe_info.entry_point;
   TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry));
   return entry;
@@ -549,6 +556,24 @@
   async_safe_fatal("Could not find a PHDR: broken executable?");
 }
 
+// Detect an attempt to run the linker on itself. e.g.:
+//   /system/bin/linker64 /system/bin/linker64
+// Use priority-1 to run this constructor before other constructors.
+__attribute__((constructor(1))) static void detect_self_exec() {
+  // Normally, the linker initializes the auxv global before calling its
+  // constructors. If the linker loads itself, though, the first loader calls
+  // the second loader's constructors before calling __linker_init.
+  if (__libc_shared_globals()->auxv != nullptr) {
+    return;
+  }
+#if defined(__i386__)
+  // We don't have access to the auxv struct from here, so use the int 0x80
+  // fallback.
+  __libc_sysinfo = reinterpret_cast<void*>(__libc_int0x80);
+#endif
+  __linker_error("error: linker cannot load itself\n");
+}
+
 static ElfW(Addr) __attribute__((noinline))
 __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& linker_so);
 
@@ -571,18 +596,8 @@
   // another program), AT_BASE is 0.
   ElfW(Addr) linker_addr = getauxval(AT_BASE);
   if (linker_addr == 0) {
-    // Detect an attempt to run the linker on itself (e.g.
-    // `linker64 /system/bin/linker64`). If the kernel loaded this instance of
-    // the linker, then AT_ENTRY will refer to &_start. If it doesn't, then
-    // something else must have loaded this instance of the linker. It's
-    // simpler if we only allow one copy of the linker to be loaded at a time.
-    if (getauxval(AT_ENTRY) != reinterpret_cast<uintptr_t>(&_start)) {
-      // The first linker already relocated this one and set up TLS, so we don't
-      // need further libc initialization.
-      __linker_error("error: linker cannot load itself\n");
-    }
-    // Otherwise, the AT_PHDR and AT_PHNUM aux values describe this linker
-    // instance, so use the phdr to find the linker's base address.
+    // The AT_PHDR and AT_PHNUM aux values describe this linker instance, so use
+    // the phdr to find the linker's base address.
     ElfW(Addr) load_bias;
     get_elf_base_from_phdr(
       reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)), getauxval(AT_PHNUM),
@@ -611,7 +626,7 @@
   // 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 (!tmp_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, nullptr)) __linker_cannot_link(args.argv[0]);
 
   return __linker_init_post_relocation(args, tmp_linker_so);
 }
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 34ac606..1aaa17f 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -166,14 +166,12 @@
   return did_read_;
 }
 
-bool ElfReader::Load(const android_dlextinfo* extinfo) {
+bool ElfReader::Load(address_space_params* address_space) {
   CHECK(did_read_);
   if (did_load_) {
     return true;
   }
-  if (ReserveAddressSpace(extinfo) &&
-      LoadSegments() &&
-      FindPhdr()) {
+  if (ReserveAddressSpace(address_space) && LoadSegments() && FindPhdr()) {
     did_load_ = true;
   }
 
@@ -559,7 +557,7 @@
 // Reserve a virtual address range big enough to hold all loadable
 // segments of a program header table. This is done by creating a
 // private anonymous mmap() with PROT_NONE.
-bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
+bool ElfReader::ReserveAddressSpace(address_space_params* address_space) {
   ElfW(Addr) min_vaddr;
   load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
   if (load_size_ == 0) {
@@ -569,22 +567,11 @@
 
   uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
   void* start;
-  size_t reserved_size = 0;
-  bool reserved_hint = true;
 
-  if (extinfo != nullptr) {
-    if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
-      reserved_size = extinfo->reserved_size;
-      reserved_hint = false;
-    } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
-      reserved_size = extinfo->reserved_size;
-    }
-  }
-
-  if (load_size_ > reserved_size) {
-    if (!reserved_hint) {
+  if (load_size_ > address_space->reserved_size) {
+    if (address_space->must_use_address) {
       DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
-             reserved_size - load_size_, load_size_, name_.c_str());
+             load_size_ - address_space->reserved_size, load_size_, name_.c_str());
       return false;
     }
     start = ReserveAligned(load_size_, kLibraryAlignment);
@@ -593,8 +580,12 @@
       return false;
     }
   } else {
-    start = extinfo->reserved_addr;
+    start = address_space->start_addr;
     mapped_by_caller_ = true;
+
+    // Update the reserved address space to subtract the space used by this library.
+    address_space->start_addr = reinterpret_cast<uint8_t*>(address_space->start_addr) + load_size_;
+    address_space->reserved_size -= load_size_;
   }
 
   load_start_ = start;
@@ -887,13 +878,15 @@
  *   phdr_count  -> number of entries in tables
  *   load_bias   -> load bias
  *   fd          -> readable file descriptor to use
+ *   file_offset -> pointer to offset into file descriptor to use/update
  * Return:
  *   0 on error, -1 on failure (error code in errno).
  */
 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table,
                              size_t phdr_count,
                              ElfW(Addr) load_bias,
-                             int fd) {
+                             int fd,
+                             size_t* file_offset) {
   // Map the file at a temporary location so we can compare its contents.
   struct stat file_stat;
   if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
@@ -907,7 +900,6 @@
       return -1;
     }
   }
-  size_t file_offset = 0;
 
   // Iterate over the relro segments and compare/remap the pages.
   const ElfW(Phdr)* phdr = phdr_table;
@@ -921,12 +913,12 @@
     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
 
-    char* file_base = static_cast<char*>(temp_mapping) + file_offset;
+    char* file_base = static_cast<char*>(temp_mapping) + *file_offset;
     char* mem_base = reinterpret_cast<char*>(seg_page_start);
     size_t match_offset = 0;
     size_t size = seg_page_end - seg_page_start;
 
-    if (file_size - file_offset < size) {
+    if (file_size - *file_offset < size) {
       // File is too short to compare to this segment. The contents are likely
       // different as well (it's probably for a different library version) so
       // just don't bother checking.
@@ -950,7 +942,7 @@
       // Map over similar pages.
       if (mismatch_offset > match_offset) {
         void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset,
-                         PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, match_offset);
+                         PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, *file_offset + match_offset);
         if (map == MAP_FAILED) {
           munmap(temp_mapping, file_size);
           return -1;
@@ -961,7 +953,7 @@
     }
 
     // Add to the base file offset in case there are multiple relro segments.
-    file_offset += size;
+    *file_offset += size;
   }
   munmap(temp_mapping, file_size);
   return 0;
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 0eee089..9761bc8 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -43,7 +43,7 @@
   ElfReader();
 
   bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size);
-  bool Load(const android_dlextinfo* extinfo);
+  bool Load(address_space_params* address_space);
 
   const char* name() const { return name_.c_str(); }
   size_t phdr_count() const { return phdr_num_; }
@@ -62,7 +62,7 @@
   bool ReadProgramHeaders();
   bool ReadSectionHeaders();
   bool ReadDynamicSection();
-  bool ReserveAddressSpace(const android_dlextinfo* extinfo);
+  bool ReserveAddressSpace(address_space_params* address_space);
   bool LoadSegments();
   bool FindPhdr();
   bool CheckPhdr(ElfW(Addr));
@@ -122,7 +122,7 @@
                                    ElfW(Addr) load_bias, int fd);
 
 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
-                             ElfW(Addr) load_bias, int fd);
+                             ElfW(Addr) load_bias, int fd, size_t* file_offset);
 
 #if defined(__arm__)
 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
diff --git a/linker/tests/linker_sleb128_test.cpp b/linker/linker_sleb128_test.cpp
similarity index 98%
rename from linker/tests/linker_sleb128_test.cpp
rename to linker/linker_sleb128_test.cpp
index 551faf2..9e819c6 100644
--- a/linker/tests/linker_sleb128_test.cpp
+++ b/linker/linker_sleb128_test.cpp
@@ -32,7 +32,7 @@
 
 #include <gtest/gtest.h>
 
-#include "../linker_sleb128.h"
+#include "linker_sleb128.h"
 
 TEST(linker_sleb128, smoke) {
   std::vector<uint8_t> encoding;
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index dd9c6aa..80c51af 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -223,7 +223,7 @@
   void call_pre_init_constructors();
   bool prelink_image();
   bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
-                  const android_dlextinfo* extinfo);
+                  const android_dlextinfo* extinfo, size_t* relro_fd_offset);
   bool protect_relro();
 
   void add_child(soinfo* child);
diff --git a/linker/tests/linker_globals.cpp b/linker/linker_test_globals.cpp
similarity index 100%
rename from linker/tests/linker_globals.cpp
rename to linker/linker_test_globals.cpp
diff --git a/linker/linker_tls.cpp b/linker/linker_tls.cpp
index a3aa9bf..d2edbb3 100644
--- a/linker/linker_tls.cpp
+++ b/linker/linker_tls.cpp
@@ -30,6 +30,7 @@
 
 #include <vector>
 
+#include "async_safe/CHECK.h"
 #include "private/ScopedRWLock.h"
 #include "private/ScopedSignalBlocker.h"
 #include "private/bionic_defs.h"
diff --git a/linker/tests/linker_utils_test.cpp b/linker/linker_utils_test.cpp
similarity index 99%
rename from linker/tests/linker_utils_test.cpp
rename to linker/linker_utils_test.cpp
index e406af5..44907da 100644
--- a/linker/tests/linker_utils_test.cpp
+++ b/linker/linker_utils_test.cpp
@@ -32,7 +32,7 @@
 
 #include <gtest/gtest.h>
 
-#include "../linker_utils.h"
+#include "linker_utils.h"
 
 TEST(linker_utils, format_string) {
   std::vector<std::pair<std::string, std::string>> params = {{ "LIB", "lib32"}, { "SDKVER", "42"}};
diff --git a/linker/tests/Android.mk b/linker/tests/Android.mk
deleted file mode 100644
index 63e0555..0000000
--- a/linker/tests/Android.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# Copyright (C) 2012 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := linker-unit-tests
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../libc/
-
-LOCAL_SRC_FILES := \
-  linker_block_allocator_test.cpp \
-  linker_config_test.cpp \
-  linker_globals.cpp \
-  linked_list_test.cpp \
-  linker_sleb128_test.cpp \
-  linker_utils_test.cpp \
-  ../linker_block_allocator.cpp \
-  ../linker_config.cpp \
-  ../linker_utils.cpp \
-
-LOCAL_STATIC_LIBRARIES += libasync_safe libbase liblog
-
-include $(BUILD_NATIVE_TEST)
diff --git a/tests/Android.bp b/tests/Android.bp
index b374c27..ab11d47 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -40,7 +40,7 @@
     ],
     stl: "libc++",
     sanitize: {
-        never: true,
+        address: false,
     },
     bootstrap: true,
 }
@@ -95,6 +95,7 @@
         "grp_pwd_file_test.cpp",
         "iconv_test.cpp",
         "ifaddrs_test.cpp",
+        "ifunc_test.cpp",
         "inttypes_test.cpp",
         "iso646_test.c",
         "langinfo_test.cpp",
@@ -193,7 +194,6 @@
 
     include_dirs: [
         "bionic/libc",
-        "external/tinyxml2",
     ],
 
     target: {
@@ -385,6 +385,7 @@
             ],
             static_libs: [
                 "libmeminfo",
+                "libprocinfo",
                 "libziparchive",
                 "libLLVMObject",
                 "libLLVMBitReader",
@@ -506,7 +507,7 @@
 
     target: {
         android: {
-            shared_libs: ["libicuuc"],
+            shared_libs: ["libandroidicu"],
         },
     },
 
@@ -520,12 +521,14 @@
         "libtest_dt_runpath_b",
         "libtest_dt_runpath_c",
         "libtest_dt_runpath_x",
+        "libtest_dt_runpath_y",
         "libatest_simple_zip",
         "libcfi-test",
         "libcfi-test-bad",
         "libdlext_test_different_soname",
         "libdlext_test_fd",
         "libdlext_test_norelro",
+        "libdlext_test_recursive",
         "libdlext_test_runpath_zip_zipaligned",
         "libdlext_test",
         "libdlext_test_zip",
@@ -639,6 +642,8 @@
         "libnstest_ns_a_public1_internal",
         "libnstest_ns_b_public2",
         "libnstest_ns_b_public3",
+        "libsegment_gap_inner",
+        "libsegment_gap_outer",
         "ld_preload_test_helper",
         "ld_preload_test_helper_lib1",
         "ld_preload_test_helper_lib2",
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 266c7d7..04fc92d 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -35,8 +35,20 @@
     native_tests_var := TARGET_OUT_DATA_NATIVE_TESTS
   endif
 
-  LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)$(native_tests_var))/$($(module)_install_to_native_tests_dir)
-  LOCAL_MODULE_PATH_64 := $($(native_tests_var))/$($(module)_install_to_native_tests_dir)
+  ifneq ($($(module)_install_to_native_tests_dir_32),)
+    tests_dir_32 := $($(module)_install_to_native_tests_dir_32)
+  else
+    tests_dir_32 := $($(module)_install_to_native_tests_dir)
+  endif
+
+  ifneq ($($(module)_install_to_native_tests_dir_64),)
+    tests_dir_64 := $($(module)_install_to_native_tests_dir_64)
+  else
+    tests_dir_64 := $($(module)_install_to_native_tests_dir)
+  endif
+
+  LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)$(native_tests_var))/$(tests_dir_32)
+  LOCAL_MODULE_PATH_64 := $($(native_tests_var))/$(tests_dir_64)
 endif
 endif
 
diff --git a/tests/buffer_tests.cpp b/tests/buffer_tests.cpp
index 7563448..fb0b6d8 100644
--- a/tests/buffer_tests.cpp
+++ b/tests/buffer_tests.cpp
@@ -20,6 +20,7 @@
 
 #include <gtest/gtest.h>
 #include "buffer_tests.h"
+#include "utils.h"
 
 // For the comparison buffer tests, the maximum length to test for the
 // miscompare checks.
@@ -227,16 +228,11 @@
   }
 }
 
-// Malloc can return a tagged pointer, which is not accepted in mm system calls like mprotect.
-// Clear top 8 bits of the address on 64-bit platforms.
+// Malloc can return a tagged pointer, which is not accepted in mm system calls like mprotect
+// in the preliminary version of the syscall tagging support in the current Pixel 2 kernel.
+// Note: the final version of the kernel patchset may relax this requirement.
 static int MprotectHeap(void* addr, size_t len, int prot) {
-#if defined(__LP64__)
-  constexpr uintptr_t mask = (static_cast<uintptr_t>(1) << 56) - 1;
-  void* untagged_addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & mask);
-#else
-  void* untagged_addr = addr;
-#endif
-  return mprotect(untagged_addr, len, prot);
+  return mprotect(untag_address(addr), len, prot);
 }
 
 void RunSingleBufferAlignTest(
diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp
index 3bbddbb..f015b2c 100644
--- a/tests/complex_test.cpp
+++ b/tests/complex_test.cpp
@@ -27,7 +27,6 @@
 #define __INTRODUCED_IN(x)
 #define __INTRODUCED_IN_32(x)
 #define __INTRODUCED_IN_64(x)
-#define __INTRODUCED_IN_FUTURE
 #define __RENAME_LDBL(a,b,c)
 #endif
 
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index aea92b4..468ce3d 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -138,7 +138,7 @@
 
 TEST(dl, preinit_system_calls) {
 #if defined(__BIONIC__)
-  SKIP_WITH_HWASAN; // hwasan not initialized in preinit_array
+  SKIP_WITH_HWASAN; // hwasan not initialized in preinit_array, b/124007027
   std::string helper = GetTestlibRoot() +
       "/preinit_syscall_test_helper/preinit_syscall_test_helper";
   chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
@@ -150,6 +150,7 @@
 
 TEST(dl, preinit_getauxval) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // hwasan not initialized in preinit_array, b/124007027
   std::string helper = GetTestlibRoot() +
       "/preinit_getauxval_test_helper/preinit_getauxval_test_helper";
   chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index c9ecd2e..f5e0c9c 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -37,6 +37,7 @@
 #include <sys/wait.h>
 
 #include <meminfo/procmeminfo.h>
+#include <procinfo/process_map.h>
 #include <ziparchive/zip_archive.h>
 
 #include "gtest_globals.h"
@@ -59,6 +60,7 @@
 
 typedef int (*fn)(void);
 constexpr const char* kLibName = "libdlext_test.so";
+constexpr const char* kLibNameRecursive = "libdlext_test_recursive.so";
 constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
 constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
 constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
@@ -232,6 +234,12 @@
   dlclose(handle);
 }
 
+TEST(dlfcn, dlopen_from_nullptr_android_api_level) {
+  // Regression test for http://b/123972211. Testing dlopen(nullptr) when target sdk is P
+  android_set_application_target_sdk_version(__ANDROID_API_P__);
+  ASSERT_TRUE(dlopen(nullptr, RTLD_NOW) != nullptr);
+}
+
 TEST(dlfcn, dlopen_from_zip_absolute_path) {
   const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
   const std::string lib_path = GetTestlibRoot() + lib_zip_path;
@@ -332,6 +340,48 @@
   EXPECT_EQ(nullptr, handle_);
 }
 
+TEST_F(DlExtTest, ReservedRecursive) {
+  void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  ASSERT_TRUE(start != MAP_FAILED);
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
+  extinfo.reserved_addr = start;
+  extinfo.reserved_size = kLibSize;
+  handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
+  ASSERT_DL_NOTNULL(handle_);
+
+  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+  ASSERT_DL_NOTNULL(f);
+  EXPECT_GE(reinterpret_cast<void*>(f), start);
+  EXPECT_LT(reinterpret_cast<void*>(f),
+            reinterpret_cast<char*>(start) + kLibSize);
+  EXPECT_EQ(4, f());
+
+  f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
+  ASSERT_DL_NOTNULL(f);
+  EXPECT_GE(reinterpret_cast<void*>(f), start);
+  EXPECT_LT(reinterpret_cast<void*>(f),
+            reinterpret_cast<char*>(start) + kLibSize);
+  EXPECT_EQ(8, f());
+
+  uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
+  ASSERT_DL_NOTNULL(taxicab_number);
+  EXPECT_GE(reinterpret_cast<void*>(taxicab_number), start);
+  EXPECT_LT(reinterpret_cast<void*>(taxicab_number), reinterpret_cast<char*>(start) + kLibSize);
+  EXPECT_EQ(1729U, *taxicab_number);
+}
+
+TEST_F(DlExtTest, ReservedRecursiveTooSmall) {
+  void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  ASSERT_TRUE(start != MAP_FAILED);
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
+  extinfo.reserved_addr = start;
+  extinfo.reserved_size = PAGE_SIZE;
+  handle_ = android_dlopen_ext(kLibNameRecursive, RTLD_NOW, &extinfo);
+  EXPECT_EQ(nullptr, handle_);
+}
+
 TEST_F(DlExtTest, ReservedHint) {
   void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   ASSERT_TRUE(start != MAP_FAILED);
@@ -382,10 +432,14 @@
     DlExtTest::TearDown();
   }
 
-  void CreateRelroFile(const char* lib, const char* relro_file) {
+  void CreateRelroFile(const char* lib, const char* relro_file, bool recursive) {
     int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
     ASSERT_NOERROR(relro_fd);
 
+    if (recursive) {
+      extinfo_.flags |= ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
+    }
+
     pid_t pid = fork();
     if (pid == 0) {
       // child process
@@ -411,13 +465,19 @@
     extinfo_.relro_fd = relro_fd;
   }
 
-  void TryUsingRelro(const char* lib) {
+  void TryUsingRelro(const char* lib, bool recursive) {
     handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
     ASSERT_DL_NOTNULL(handle_);
     fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
     ASSERT_DL_NOTNULL(f);
     EXPECT_EQ(4, f());
 
+    if (recursive) {
+      fn f = reinterpret_cast<fn>(dlsym(handle_, "getBiggerRandomNumber"));
+      ASSERT_DL_NOTNULL(f);
+      EXPECT_EQ(8, f());
+    }
+
     uint32_t* taxicab_number =
             reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
     ASSERT_DL_NOTNULL(taxicab_number);
@@ -427,6 +487,8 @@
   void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
                                   size_t* pss_out);
 
+  std::string FindMappingName(void* ptr);
+
   android_dlextinfo extinfo_;
 };
 
@@ -434,8 +496,29 @@
   TemporaryFile tf; // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path));
-  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
+  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
+  void* relro_data = dlsym(handle_, "lots_of_relro");
+  ASSERT_DL_NOTNULL(relro_data);
+  EXPECT_EQ(tf.path, FindMappingName(relro_data));
+
+  // Use destructor of tf to close and unlink the file.
+  tf.fd = extinfo_.relro_fd;
+}
+
+TEST_F(DlExtRelroSharingTest, ChildWritesGoodDataRecursive) {
+  TemporaryFile tf; // Use tf to get an unique filename.
+  ASSERT_NOERROR(close(tf.fd));
+
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameRecursive, tf.path, true));
+  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameRecursive, true));
+  void* relro_data = dlsym(handle_, "lots_of_relro");
+  ASSERT_DL_NOTNULL(relro_data);
+  EXPECT_EQ(tf.path, FindMappingName(relro_data));
+  void* recursive_relro_data = dlsym(handle_, "lots_more_relro");
+  ASSERT_DL_NOTNULL(recursive_relro_data);
+  EXPECT_EQ(tf.path, FindMappingName(recursive_relro_data));
+
 
   // Use destructor of tf to close and unlink the file.
   tf.fd = extinfo_.relro_fd;
@@ -445,15 +528,15 @@
   TemporaryFile tf; // // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path));
-  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path, false));
+  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro, false));
 
   // Use destructor of tf to close and unlink the file.
   tf.fd = extinfo_.relro_fd;
 }
 
 TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
-  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
+  ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false));
 }
 
 TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
@@ -465,7 +548,7 @@
   TemporaryFile tf; // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path, false));
 
   int pipefd[2];
   ASSERT_NOERROR(pipe(pipefd));
@@ -580,6 +663,21 @@
   }
 }
 
+std::string DlExtRelroSharingTest::FindMappingName(void* ptr) {
+  uint64_t addr = reinterpret_cast<uint64_t>(ptr);
+  std::string found_name = "<not found>";
+
+  EXPECT_TRUE(android::procinfo::ReadMapFile(
+      "/proc/self/maps",
+      [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
+        if (addr >= start && addr < end) {
+          found_name = name;
+        }
+      }));
+
+  return found_name;
+}
+
 // Testing namespaces
 static const char* g_public_lib = "libnstest_public.so";
 
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 8a3b6f3..ff5b1a9 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -49,6 +49,12 @@
 #pragma clang diagnostic pop
 #endif //  defined(__ANDROID__) && (defined(__arm__) || defined(__i386__))
 
+// Declared manually because the macro definitions in <elf.h> conflict with LLVM headers.
+#ifdef __arm__
+typedef uintptr_t _Unwind_Ptr;
+extern "C" _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr, int*);
+#endif
+
 #define ASSERT_SUBSTR(needle, haystack) \
     ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
 
@@ -1732,4 +1738,28 @@
   ASSERT_TRUE(handle != nullptr) << dlerror();
 }
 
+TEST(dlfcn, segment_gap) {
+  void* handle = dlopen("libsegment_gap_outer.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+
+  auto get_inner = reinterpret_cast<void* (*)()>(dlsym(handle, "get_inner"));
+  void* inner = get_inner();
+  (void)inner;
+
+#if __arm__
+  int count;
+  _Unwind_Ptr outer_exidx = dl_unwind_find_exidx(reinterpret_cast<_Unwind_Ptr>(get_inner), &count);
+  _Unwind_Ptr inner_exidx = dl_unwind_find_exidx(reinterpret_cast<_Unwind_Ptr>(inner), &count);
+  EXPECT_NE(0u, outer_exidx);
+  EXPECT_NE(0u, inner_exidx);
+  EXPECT_NE(inner_exidx, outer_exidx);
+#endif
+
+  Dl_info info;
+  int rc = dladdr(inner, &info);
+  ASSERT_NE(rc, 0);
+
+  EXPECT_NE(nullptr, strstr(info.dli_fname, "libsegment_gap_inner.so"));
+}
+
 #endif
diff --git a/tests/elftls_dl_test.cpp b/tests/elftls_dl_test.cpp
index e908fb9..36bdc3b 100644
--- a/tests/elftls_dl_test.cpp
+++ b/tests/elftls_dl_test.cpp
@@ -32,6 +32,7 @@
 #include <thread>
 
 #include "gtest_globals.h"
+#include "private/__get_tls.h"
 #include "utils.h"
 
 #if defined(__BIONIC__)
@@ -114,11 +115,25 @@
   }).join();
 }
 
+extern "C" int* missing_weak_tls_addr();
+
+// The Bionic linker resolves a TPREL relocation to an unresolved weak TLS
+// symbol to 0, which is added to the thread pointer. N.B.: A TPREL relocation
+// in a static executable is resolved by the static linker instead, and static
+// linker behavior varies (especially with bfd and gold). See
+// https://bugs.llvm.org/show_bug.cgi?id=40570.
+TEST(elftls_dl, tprel_missing_weak) {
+  ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
+  std::thread([] {
+    ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
+  }).join();
+}
+
 // The behavior of accessing an unresolved weak TLS symbol using a dynamic TLS
 // relocation depends on which kind of implementation the target uses. With
 // TLSDESC, the result is NULL. With __tls_get_addr, the result is the
 // generation count (or maybe undefined behavior)? This test only tests TLSDESC.
-TEST(elftls_dl, missing_weak) {
+TEST(elftls_dl, tlsdesc_missing_weak) {
 #if defined(__aarch64__)
   void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
   ASSERT_NE(nullptr, lib);
diff --git a/tests/elftls_test.cpp b/tests/elftls_test.cpp
index 2d83d70..7c072b6 100644
--- a/tests/elftls_test.cpp
+++ b/tests/elftls_test.cpp
@@ -30,8 +30,6 @@
 
 #include <thread>
 
-#include "private/__get_tls.h"
-
 // Specify the LE access model explicitly. This file is compiled into the
 // bionic-unit-tests executable, but the compiler sees an -fpic object file
 // output into a static library, so it defaults to dynamic TLS accesses.
@@ -64,17 +62,9 @@
   }).join();
 }
 
-extern "C" int* missing_weak_tls_addr();
 extern "C" int bump_static_tls_var_1();
 extern "C" int bump_static_tls_var_2();
 
-TEST(elftls, tprel_missing_weak) {
-  ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
-  std::thread([] {
-    ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
-  }).join();
-}
-
 TEST(elftls, tprel_addend) {
   ASSERT_EQ(4, bump_static_tls_var_1());
   ASSERT_EQ(8, bump_static_tls_var_2());
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index 4b207b6..eb8fe2a 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -34,6 +34,7 @@
 #include <private/android_filesystem_config.h>
 
 #if defined(__BIONIC__)
+#include <android/api-level.h>
 #include <android-base/properties.h>
 #endif
 
@@ -247,11 +248,9 @@
   expect_range(AID_SHARED_GID_START, AID_SHARED_GID_END);
   expect_range(AID_ISOLATED_START, AID_ISOLATED_END);
 
-  // Upgrading devices launched before API level 28 may not comply with the below check.
-  // Due to the difficulty in changing uids after launch, it is waived for these devices.
-  // Also grant this check for device launched with 28(P) to give the vendor time to
-  // adopt the AID scheme.
-  if (android::base::GetIntProperty("ro.product.first_api_level", 0) <= 28) {
+  // TODO(73062966): We still don't have a good way to create vendor AIDs in the system or other
+  // non-vendor partitions, therefore we keep this check disabled.
+  if (android::base::GetIntProperty("ro.product.first_api_level", 0) <= __ANDROID_API_Q__) {
     return;
   }
 
diff --git a/libc/bionic/malloc_info.h b/tests/ifunc_test.cpp
similarity index 60%
rename from libc/bionic/malloc_info.h
rename to tests/ifunc_test.cpp
index 257fec1..7ab5899 100644
--- a/libc/bionic/malloc_info.h
+++ b/tests/ifunc_test.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
-#pragma once
+#include <gtest/gtest.h>
 
-#include <malloc.h>
-#include <sys/cdefs.h>
+int ret42() {
+  return 42;
+}
 
-__BEGIN_DECLS
+extern "C" void* resolver() {
+  return (void*)ret42;
+}
 
-__LIBC_HIDDEN__ size_t __mallinfo_narenas();
-__LIBC_HIDDEN__ size_t __mallinfo_nbins();
-__LIBC_HIDDEN__ struct mallinfo __mallinfo_arena_info(size_t);
-__LIBC_HIDDEN__ struct mallinfo __mallinfo_bin_info(size_t, size_t);
+int ifunc() __attribute__((ifunc("resolver")));
 
-__END_DECLS
+TEST(ifunc, function) {
+  ASSERT_EQ(42, ifunc());
+}
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index d58b6b8..422cd75 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -918,3 +918,18 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["exec_linker_helper_lib.cpp"],
 }
+
+cc_test_library {
+    name: "libsegment_gap_outer",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["segment_gap_outer.cpp"],
+    ldflags: ["-Wl,-T,bionic/tests/libs/segment_gap_outer.lds"],
+}
+
+cc_test_library {
+    name: "libsegment_gap_inner",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["segment_gap_inner.cpp"],
+}
diff --git a/tests/libs/Android.build.dlext_testzip.mk b/tests/libs/Android.build.dlext_testzip.mk
index 19fd64b..8775c29 100644
--- a/tests/libs/Android.build.dlext_testzip.mk
+++ b/tests/libs/Android.build.dlext_testzip.mk
@@ -59,21 +59,38 @@
 lib_b := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_b,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_b.so
 lib_c := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_c,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_c.so
 lib_x := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_x,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_x.so
+lib_y := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_y,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_y.so
 
 $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_D := $(lib_d)
 $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_A := $(lib_a)
 $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_B := $(lib_b)
 $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_C := $(lib_c)
 $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_X := $(lib_x)
-$(LOCAL_BUILT_MODULE) : $(lib_d) $(lib_a) $(lib_b) $(lib_c) $(lib_x) $(BIONIC_TESTS_ZIPALIGN)
+$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_Y := $(lib_y)
+ifeq ($(TARGET_IS_64_BIT),true)
+  ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
+    $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_OR_LIB64 := $(if $(LOCAL_2ND_ARCH_VAR_PREFIX),lib/$(TARGET_2ND_ARCH),lib64)
+  else
+    $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_OR_LIB64 := $(if $(LOCAL_2ND_ARCH_VAR_PREFIX),lib,lib64)
+  endif
+else
+  ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
+    $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_OR_LIB64 := $(if $(LOCAL_2ND_ARCH_VAR_PREFIX),lib/$(TARGET_2ND_ARCH),lib)
+  else
+    $(LOCAL_BUILT_MODULE) : PRIVATE_LIB_OR_LIB64 := lib
+  endif
+endif
+$(LOCAL_BUILT_MODULE) : $(lib_d) $(lib_a) $(lib_b) $(lib_c) $(lib_x) $(lib_y) $(BIONIC_TESTS_ZIPALIGN)
 	@echo "Aligning zip: $@"
 	$(hide) rm -rf $@.unaligned $@ $(dir $@)/zipdir && mkdir -p $(dir $@)/zipdir/libdir && \
-    mkdir -p $(dir $@)/zipdir/libdir/dt_runpath_a && mkdir -p $(dir $@)/zipdir/libdir/dt_runpath_b_c_x
+    mkdir -p $(dir $@)/zipdir/libdir/dt_runpath_a && mkdir -p $(dir $@)/zipdir/libdir/dt_runpath_b_c_x && \
+    mkdir -p $(dir $@)/zipdir/libdir/dt_runpath_y/$(PRIVATE_LIB_OR_LIB64)
 	$(hide) cp $(PRIVATE_LIB_D) $(dir $@)/zipdir/libdir
 	$(hide) cp $(PRIVATE_LIB_A) $(dir $@)/zipdir/libdir/dt_runpath_a
 	$(hide) cp $(PRIVATE_LIB_B) $(dir $@)/zipdir/libdir/dt_runpath_b_c_x
 	$(hide) cp $(PRIVATE_LIB_C) $(dir $@)/zipdir/libdir/dt_runpath_b_c_x
 	$(hide) cp $(PRIVATE_LIB_X) $(dir $@)/zipdir/libdir/dt_runpath_b_c_x
+	$(hide) cp $(PRIVATE_LIB_Y) $(dir $@)/zipdir/libdir/dt_runpath_y/$(PRIVATE_LIB_OR_LIB64)
 	$(hide) touch $(dir $@)/zipdir/empty_file.txt
 	$(hide) (cd $(dir $@)/zipdir && zip -qrD0 ../$(notdir $@).unaligned .)
 	$(hide) $(BIONIC_TESTS_ZIPALIGN) 4096 $@.unaligned $@
diff --git a/tests/libs/Android.build.dt_runpath.mk b/tests/libs/Android.build.dt_runpath.mk
index a3fcac5..b0d8e4b 100644
--- a/tests/libs/Android.build.dt_runpath.mk
+++ b/tests/libs/Android.build.dt_runpath.mk
@@ -21,11 +21,12 @@
 #
 # Dependencies
 #
-# libtest_dt_runpath_d.so                       runpath: ${ORIGIN}/dt_runpath_b_c_x
+# libtest_dt_runpath_d.so                       runpath: ${ORIGIN}/dt_runpath_b_c_x, ${ORIGIN}/dt_runpath_y/${LIB}
 # |-> dt_runpath_b_c_x/libtest_dt_runpath_b.so  runpath: ${ORIGIN}/../dt_runpath_a
 # |   |-> dt_runpath_a/libtest_dt_runpath_a.so
 # |-> dt_runpath_b_c_x/libtest_dt_runpath_c.so  runpath: ${ORIGIN}/invalid_dt_runpath
 # |   |-> libtest_dt_runpath_a.so (soname)
+# |-> dt_runpath_y/lib[64]/libtest_dt_runpath_y.so
 #
 # This one is used to test dlopen
 # dt_runpath_b_c_x/libtest_dt_runpath_x.so
@@ -61,12 +62,18 @@
 module := libtest_dt_runpath_c
 include $(LOCAL_PATH)/Android.build.testlib.mk
 
-# D depends on B and C with DT_RUNPATH.
+# D depends on B, C, and Y with DT_RUNPATH.
 libtest_dt_runpath_d_src_files := \
     dlopen_b.cpp
 
-libtest_dt_runpath_d_shared_libraries := libtest_dt_runpath_b libtest_dt_runpath_c
-libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x -Wl,--enable-new-dtags
+libtest_dt_runpath_d_shared_libraries := \
+    libtest_dt_runpath_b \
+    libtest_dt_runpath_c \
+    libtest_dt_runpath_y
+libtest_dt_runpath_d_ldflags := \
+    -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x \
+    -Wl,--rpath,\$${ORIGIN}/dt_runpath_y/\$${LIB} \
+    -Wl,--enable-new-dtags
 libtest_dt_runpath_d_ldlibs := -ldl
 module := libtest_dt_runpath_d
 include $(LOCAL_PATH)/Android.build.testlib.mk
@@ -77,8 +84,14 @@
 libtest_dt_runpath_d_zip_src_files := \
     dlopen_b.cpp
 
-libtest_dt_runpath_d_zip_shared_libraries := libtest_dt_runpath_b libtest_dt_runpath_c
-libtest_dt_runpath_d_zip_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x -Wl,--enable-new-dtags
+libtest_dt_runpath_d_zip_shared_libraries := \
+    libtest_dt_runpath_b \
+    libtest_dt_runpath_c \
+    libtest_dt_runpath_y
+libtest_dt_runpath_d_zip_ldflags := \
+    -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x \
+    -Wl,--rpath,\$${ORIGIN}/dt_runpath_y/\$${LIB} \
+    -Wl,--enable-new-dtags
 libtest_dt_runpath_d_zip_ldlibs := -ldl
 libtest_dt_runpath_d_zip_install_to_native_tests_dir := $(module)
 
@@ -96,3 +109,20 @@
 module := libtest_dt_runpath_x
 include $(LOCAL_PATH)/Android.build.testlib.mk
 
+# A leaf library in lib or lib64 directory
+libtest_dt_runpath_y_src_files := \
+    empty.cpp
+
+ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
+libtest_dt_runpath_y_install_to_native_tests_dir_32 := bionic-loader-test-libs/dt_runpath_y/lib/$(TARGET_2ND_ARCH)
+else
+libtest_dt_runpath_y_install_to_native_tests_dir_32 := bionic-loader-test-libs/dt_runpath_y/lib
+endif
+ifeq ($(TARGET_IS_64_BIT),true)
+libtest_dt_runpath_y_install_to_native_tests_dir_64 := bionic-loader-test-libs/dt_runpath_y/lib64
+else
+libtest_dt_runpath_y_install_to_native_tests_dir_64 := bionic-loader-test-libs/dt_runpath_y/lib
+endif
+
+module := libtest_dt_runpath_y
+include $(LOCAL_PATH)/Android.build.testlib.mk
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index 5bd028d..c40277d 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -49,6 +49,21 @@
 include $(LOCAL_PATH)/Android.build.testlib.mk
 
 # -----------------------------------------------------------------------------
+# Library used by dlext tests - recursive use of RELRO sharing
+# -----------------------------------------------------------------------------
+libdlext_test_recursive_src_files := \
+    dlext_test_recursive_library.cpp \
+
+libdlext_test_recursive_ldflags := \
+    -Wl,-z,relro \
+
+libdlext_test_recursive_shared_libraries := libdlext_test
+
+module := libdlext_test_recursive
+module_tag := optional
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
 # Library used by dlext tests - different name non-default location
 # -----------------------------------------------------------------------------
 module := libdlext_test_fd
diff --git a/tests/libs/dlext_test_recursive_library.cpp b/tests/libs/dlext_test_recursive_library.cpp
new file mode 100644
index 0000000..b37bd70
--- /dev/null
+++ b/tests/libs/dlext_test_recursive_library.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+extern "C" int getRandomNumber();
+
+class B {
+public:
+  virtual int getBiggerRandomNumber() {
+    // Call to the other library.
+    return getRandomNumber() * 2;
+  }
+
+  virtual ~B() {}
+};
+
+B b;
+
+// nested macros to make it easy to define a large amount of read-only data
+// which will require relocation.
+#define B_16 &b, &b, &b, &b, &b, &b, &b, &b, &b, &b, &b, &b, &b, &b, &b, &b,
+#define B_128 B_16 B_16 B_16 B_16 B_16 B_16 B_16 B_16
+#define B_1024 B_128 B_128 B_128 B_128 B_128 B_128 B_128 B_128
+
+extern "C" B* const lots_more_relro[] = {
+  B_1024 B_1024 B_1024 B_1024 B_1024 B_1024 B_1024 B_1024
+};
+
+extern "C" int getBiggerRandomNumber() {
+  // access the relro section (twice, in fact, once for the pointer, and once
+  // for the vtable of B) to check it's actually there.
+  return lots_more_relro[0]->getBiggerRandomNumber();
+}
diff --git a/tests/libs/segment_gap_inner.cpp b/tests/libs/segment_gap_inner.cpp
new file mode 100644
index 0000000..f23b065
--- /dev/null
+++ b/tests/libs/segment_gap_inner.cpp
@@ -0,0 +1 @@
+extern "C" void inner() {}
diff --git a/tests/libs/segment_gap_outer.cpp b/tests/libs/segment_gap_outer.cpp
new file mode 100644
index 0000000..fb448e7
--- /dev/null
+++ b/tests/libs/segment_gap_outer.cpp
@@ -0,0 +1,25 @@
+#include <android/dlext.h>
+#include <dlfcn.h>
+#include <jni.h>
+#include <stdlib.h>
+
+extern "C" void text_before_start_of_gap() {}
+char end_of_gap[0x1000];
+
+extern "C" void* get_inner() {
+  android_dlextinfo info = {};
+  info.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
+
+  char* start_of_gap =
+      reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(text_before_start_of_gap) & ~0xfffull) +
+      0x1000;
+  info.reserved_addr = start_of_gap;
+  info.reserved_size = end_of_gap - start_of_gap;
+
+  void *handle = android_dlopen_ext("libsegment_gap_inner.so", RTLD_NOW, &info);
+  if (!handle) {
+    __builtin_trap();
+  }
+
+  return dlsym(handle, "inner");
+}
diff --git a/tests/libs/segment_gap_outer.lds b/tests/libs/segment_gap_outer.lds
new file mode 100644
index 0000000..f326aab
--- /dev/null
+++ b/tests/libs/segment_gap_outer.lds
@@ -0,0 +1,27 @@
+SECTIONS {
+  # This starts off fairly normal: rodata, text, data, relro, bss with
+  # appropriate alignment between them.
+  . = SIZEOF_HEADERS;
+  .rodata : {}
+  . = ALIGN(0x1000);
+  .text : {}
+  . = ALIGN(0x1000);
+  .data : {}
+  . = ALIGN(0x1000);
+  .data.rel.ro : {}
+  . = ALIGN(0x1000);
+  .bss : {}
+
+  # Now create the gap. We need a text segment first to prevent the linker from
+  # merging .bss with .bss.end_of_gap.
+  . = ALIGN(0x1000);
+  .text.text_before_start_of_gap : {
+    *(.text.text_before_start_of_gap);
+  }
+
+  # Place end_of_gap at the end of the gap.
+  . = 0x1000000;
+  .bss.end_of_gap : {
+    *(.bss.end_of_gap);
+  }
+}
diff --git a/tests/malloc_iterate_test.cpp b/tests/malloc_iterate_test.cpp
index 5e60a6d..76583eb 100644
--- a/tests/malloc_iterate_test.cpp
+++ b/tests/malloc_iterate_test.cpp
@@ -92,14 +92,15 @@
   test_data->total_allocated_bytes = 0;
 
   // Find all of the maps that are [anon:libc_malloc].
-  ASSERT_TRUE(android::procinfo::ReadMapFile("/proc/self/maps",
-    [&](uint64_t start, uint64_t end, uint16_t, uint64_t, const char* name) {
-    if (std::string(name) == "[anon:libc_malloc]") {
-      malloc_disable();
-      malloc_iterate(start, end - start, SavePointers, test_data);
-      malloc_enable();
-    }
-  }));
+  ASSERT_TRUE(android::procinfo::ReadMapFile(
+      "/proc/self/maps",
+      [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name) {
+        if (std::string(name) == "[anon:libc_malloc]") {
+          malloc_disable();
+          malloc_iterate(start, end - start, SavePointers, test_data);
+          malloc_enable();
+        }
+      }));
 
   for (size_t i = 0; i < test_data->allocs.size(); i++) {
     EXPECT_EQ(1UL, test_data->allocs[i].count) << "Failed on size " << test_data->allocs[i].size;
@@ -180,14 +181,15 @@
   TestDataType test_data = {};
 
   // Find all of the maps that are not [anon:libc_malloc].
-  ASSERT_TRUE(android::procinfo::ReadMapFile("/proc/self/maps",
-    [&](uint64_t start, uint64_t end, uint16_t, uint64_t, const char* name) {
-    if (std::string(name) != "[anon:libc_malloc]") {
-      malloc_disable();
-      malloc_iterate(start, end - start, SavePointers, &test_data);
-      malloc_enable();
-    }
-  }));
+  ASSERT_TRUE(android::procinfo::ReadMapFile(
+      "/proc/self/maps",
+      [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name) {
+        if (std::string(name) != "[anon:libc_malloc]") {
+          malloc_disable();
+          malloc_iterate(start, end - start, SavePointers, &test_data);
+          malloc_enable();
+        }
+      }));
 
   ASSERT_EQ(0UL, test_data.total_allocated_bytes);
 #else
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 2506691..9380680 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -16,14 +16,23 @@
 
 #include <gtest/gtest.h>
 
+#include <elf.h>
 #include <limits.h>
+#include <pthread.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <malloc.h>
 #include <unistd.h>
 
+#include <atomic>
 #include <tinyxml2.h>
 
+#include <android-base/file.h>
+
 #include "private/bionic_config.h"
 #include "private/bionic_malloc.h"
 #include "utils.h"
@@ -345,35 +354,42 @@
   auto root = doc.FirstChildElement();
   ASSERT_NE(nullptr, root);
   ASSERT_STREQ("malloc", root->Name());
-  ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
+  if (std::string(root->Attribute("version")) == "jemalloc-1") {
+    // Verify jemalloc version of this data.
+    ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
 
-  auto arena = root->FirstChildElement();
-  for (; arena != nullptr; arena = arena->NextSiblingElement()) {
-    int val;
+    auto arena = root->FirstChildElement();
+    for (; arena != nullptr; arena = arena->NextSiblingElement()) {
+      int val;
 
-    ASSERT_STREQ("heap", arena->Name());
-    ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
-    ASSERT_EQ(tinyxml2::XML_SUCCESS,
-              arena->FirstChildElement("allocated-large")->QueryIntText(&val));
-    ASSERT_EQ(tinyxml2::XML_SUCCESS,
-              arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
-    ASSERT_EQ(tinyxml2::XML_SUCCESS,
-              arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
-    ASSERT_EQ(tinyxml2::XML_SUCCESS,
-              arena->FirstChildElement("bins-total")->QueryIntText(&val));
+      ASSERT_STREQ("heap", arena->Name());
+      ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
+      ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                arena->FirstChildElement("allocated-large")->QueryIntText(&val));
+      ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
+      ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
+      ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                arena->FirstChildElement("bins-total")->QueryIntText(&val));
 
-    auto bin = arena->FirstChildElement("bin");
-    for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
-      if (strcmp(bin->Name(), "bin") == 0) {
-        ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
-        ASSERT_EQ(tinyxml2::XML_SUCCESS,
-                  bin->FirstChildElement("allocated")->QueryIntText(&val));
-        ASSERT_EQ(tinyxml2::XML_SUCCESS,
-                  bin->FirstChildElement("nmalloc")->QueryIntText(&val));
-        ASSERT_EQ(tinyxml2::XML_SUCCESS,
-                  bin->FirstChildElement("ndalloc")->QueryIntText(&val));
+      auto bin = arena->FirstChildElement("bin");
+      for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
+        if (strcmp(bin->Name(), "bin") == 0) {
+          ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
+          ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                    bin->FirstChildElement("allocated")->QueryIntText(&val));
+          ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                    bin->FirstChildElement("nmalloc")->QueryIntText(&val));
+          ASSERT_EQ(tinyxml2::XML_SUCCESS,
+                    bin->FirstChildElement("ndalloc")->QueryIntText(&val));
+        }
       }
     }
+  } else {
+    // Only verify that this is debug-malloc-1, the malloc debug unit tests
+    // verify the output.
+    ASSERT_STREQ("debug-malloc-1", root->Attribute("version"));
   }
 #endif
 }
@@ -515,6 +531,7 @@
 
 TEST(malloc, mallopt_decay) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // hwasan does not implement mallopt
   errno = 0;
   ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
   ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
@@ -527,6 +544,7 @@
 
 TEST(malloc, mallopt_purge) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // hwasan does not implement mallopt
   errno = 0;
   ASSERT_EQ(1, mallopt(M_PURGE, 0));
 #else
@@ -564,6 +582,7 @@
 
 TEST(malloc, mallinfo) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // hwasan does not implement mallinfo
   static size_t sizes[] = {
     8, 32, 128, 4096, 32768, 131072, 1024000, 10240000, 20480000, 300000000
   };
@@ -585,10 +604,13 @@
       size_t new_allocated = mallinfo().uordblks;
       if (allocated != new_allocated) {
         size_t usable_size = malloc_usable_size(ptrs[i]);
-        ASSERT_GE(new_allocated, allocated + usable_size)
-            << "Failed at size " << size << " usable size " << usable_size;
-        pass = true;
-        break;
+        // Only check if the total got bigger by at least allocation size.
+        // Sometimes the mallinfo numbers can go backwards due to compaction
+        // and/or freeing of cached data.
+        if (new_allocated >= allocated + usable_size) {
+          pass = true;
+          break;
+        }
       }
     }
     for (void* ptr : ptrs) {
@@ -614,20 +636,284 @@
 #endif
 }
 
+bool IsDynamic() {
+#if defined(__LP64__)
+  Elf64_Ehdr ehdr;
+#else
+  Elf32_Ehdr ehdr;
+#endif
+  std::string path(android::base::GetExecutablePath());
+
+  int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
+  if (fd == -1) {
+    // Assume dynamic on error.
+    return true;
+  }
+  bool read_completed = android::base::ReadFully(fd, &ehdr, sizeof(ehdr));
+  close(fd);
+  // Assume dynamic in error cases.
+  return !read_completed || ehdr.e_type == ET_DYN;
+}
+
 TEST(android_mallopt, init_zygote_child_profiling) {
 #if defined(__BIONIC__)
   // Successful call.
   errno = 0;
-  EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
-  EXPECT_EQ(0, errno);
+  if (IsDynamic()) {
+    EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
+    EXPECT_EQ(0, errno);
+  } else {
+    // Not supported in static executables.
+    EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
+    EXPECT_EQ(ENOTSUP, errno);
+  }
 
   // Unexpected arguments rejected.
   errno = 0;
   char unexpected = 0;
   EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, &unexpected, 1));
-  EXPECT_EQ(EINVAL, errno);
+  if (IsDynamic()) {
+    EXPECT_EQ(EINVAL, errno);
+  } else {
+    EXPECT_EQ(ENOTSUP, errno);
+  }
 #else
   GTEST_LOG_(INFO) << "This tests a bionic implementation detail.\n";
 #endif
 }
 
+#if defined(__BIONIC__)
+template <typename FuncType>
+void CheckAllocationFunction(FuncType func) {
+  // Assumes that no more than 108MB of memory is allocated before this.
+  size_t limit = 128 * 1024 * 1024;
+  ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
+  if (!func(20 * 1024 * 1024))
+    exit(1);
+  if (func(128 * 1024 * 1024))
+    exit(1);
+  exit(0);
+}
+#endif
+
+TEST(android_mallopt, set_allocation_limit) {
+#if defined(__BIONIC__)
+  EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(bytes, 1) != nullptr; }),
+              testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(1, bytes) != nullptr; }),
+              testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return malloc(bytes) != nullptr; }),
+              testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(CheckAllocationFunction(
+                  [](size_t bytes) { return memalign(sizeof(void*), bytes) != nullptr; }),
+              testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
+                void* ptr;
+                return posix_memalign(&ptr, sizeof(void *), bytes) == 0;
+              }),
+              testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(CheckAllocationFunction(
+                  [](size_t bytes) { return aligned_alloc(sizeof(void*), bytes) != nullptr; }),
+              testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
+                void* p = malloc(1024 * 1024);
+                return realloc(p, bytes) != nullptr;
+              }),
+              testing::ExitedWithCode(0), "");
+#if !defined(__LP64__)
+  EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return pvalloc(bytes) != nullptr; }),
+              testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return valloc(bytes) != nullptr; }),
+              testing::ExitedWithCode(0), "");
+#endif
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic extension.\n";
+#endif
+}
+
+TEST(android_mallopt, set_allocation_limit_multiple) {
+#if defined(__BIONIC__)
+  // Only the first set should work.
+  size_t limit = 256 * 1024 * 1024;
+  ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
+  limit = 32 * 1024 * 1024;
+  ASSERT_FALSE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic extension.\n";
+#endif
+}
+
+#if defined(__BIONIC__)
+static constexpr size_t kAllocationSize = 8 * 1024 * 1024;
+
+static size_t GetMaxAllocations() {
+  size_t max_pointers = 0;
+  void* ptrs[20];
+  for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
+    ptrs[i] = malloc(kAllocationSize);
+    if (ptrs[i] == nullptr) {
+      max_pointers = i;
+      break;
+    }
+  }
+  for (size_t i = 0; i < max_pointers; i++) {
+    free(ptrs[i]);
+  }
+  return max_pointers;
+}
+
+static void VerifyMaxPointers(size_t max_pointers) {
+  // Now verify that we can allocate the same number as before.
+  void* ptrs[20];
+  for (size_t i = 0; i < max_pointers; i++) {
+    ptrs[i] = malloc(kAllocationSize);
+    ASSERT_TRUE(ptrs[i] != nullptr) << "Failed to allocate on iteration " << i;
+  }
+
+  // Make sure the next allocation still fails.
+  ASSERT_TRUE(malloc(kAllocationSize) == nullptr);
+  for (size_t i = 0; i < max_pointers; i++) {
+    free(ptrs[i]);
+  }
+}
+#endif
+
+TEST(android_mallopt, set_allocation_limit_realloc_increase) {
+#if defined(__BIONIC__)
+  size_t limit = 128 * 1024 * 1024;
+  ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
+
+  size_t max_pointers = GetMaxAllocations();
+  ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
+
+  void* memory = malloc(10 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+
+  // Increase size.
+  memory = realloc(memory, 20 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  memory = realloc(memory, 40 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  memory = realloc(memory, 60 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  memory = realloc(memory, 80 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  // Now push past limit.
+  memory = realloc(memory, 130 * 1024 * 1024);
+  ASSERT_TRUE(memory == nullptr);
+
+  VerifyMaxPointers(max_pointers);
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic extension.\n";
+#endif
+}
+
+TEST(android_mallopt, set_allocation_limit_realloc_decrease) {
+#if defined(__BIONIC__)
+  size_t limit = 100 * 1024 * 1024;
+  ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
+
+  size_t max_pointers = GetMaxAllocations();
+  ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
+
+  void* memory = malloc(80 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+
+  // Decrease size.
+  memory = realloc(memory, 60 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  memory = realloc(memory, 40 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  memory = realloc(memory, 20 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  memory = realloc(memory, 10 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+  free(memory);
+
+  VerifyMaxPointers(max_pointers);
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic extension.\n";
+#endif
+}
+
+TEST(android_mallopt, set_allocation_limit_realloc_free) {
+#if defined(__BIONIC__)
+  size_t limit = 100 * 1024 * 1024;
+  ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
+
+  size_t max_pointers = GetMaxAllocations();
+  ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
+
+  void* memory = malloc(60 * 1024 * 1024);
+  ASSERT_TRUE(memory != nullptr);
+
+  memory = realloc(memory, 0);
+  ASSERT_TRUE(memory == nullptr);
+
+  VerifyMaxPointers(max_pointers);
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic extension.\n";
+#endif
+}
+
+#if defined(__BIONIC__)
+static void* SetAllocationLimit(void* data) {
+  std::atomic_bool* go = reinterpret_cast<std::atomic_bool*>(data);
+  while (!go->load()) {
+  }
+  size_t limit = 500 * 1024 * 1024;
+  if (android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))) {
+    return reinterpret_cast<void*>(-1);
+  }
+  return nullptr;
+}
+
+static void SetAllocationLimitMultipleThreads() {
+  std::atomic_bool go;
+  go = false;
+
+  static constexpr size_t kNumThreads = 4;
+  pthread_t threads[kNumThreads];
+  for (size_t i = 0; i < kNumThreads; i++) {
+    ASSERT_EQ(0, pthread_create(&threads[i], nullptr, SetAllocationLimit, &go));
+  }
+
+  // Let them go all at once.
+  go = true;
+  ASSERT_EQ(0, kill(getpid(), __SIGRTMIN + 4));
+
+  size_t num_successful = 0;
+  for (size_t i = 0; i < kNumThreads; i++) {
+    void* result;
+    ASSERT_EQ(0, pthread_join(threads[i], &result));
+    if (result != nullptr) {
+      num_successful++;
+    }
+  }
+  ASSERT_EQ(1U, num_successful);
+  exit(0);
+}
+#endif
+
+TEST(android_mallopt, set_allocation_limit_multiple_threads) {
+#if defined(__BIONIC__)
+  if (IsDynamic()) {
+    ASSERT_TRUE(android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
+  }
+
+  // Run this a number of times as a stress test.
+  for (size_t i = 0; i < 100; i++) {
+    // Not using ASSERT_EXIT because errors messages are not displayed.
+    pid_t pid;
+    if ((pid = fork()) == 0) {
+      ASSERT_NO_FATAL_FAILURE(SetAllocationLimitMultipleThreads());
+    }
+    ASSERT_NE(-1, pid);
+    int status;
+    ASSERT_EQ(pid, wait(&status));
+    ASSERT_EQ(0, WEXITSTATUS(status));
+  }
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic extension.\n";
+#endif
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 9c6b975..973ca53 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -337,11 +337,14 @@
   static void* thread_fn(void* arg) {
     TestBug37410* data = reinterpret_cast<TestBug37410*>(arg);
 
+    // Unlocking data->mutex will cause the main thread to exit, invalidating *data. Save the handle.
+    pthread_t main_thread = data->main_thread;
+
     // Let the main thread know we're running.
     pthread_mutex_unlock(&data->mutex);
 
     // And wait for the main thread to exit.
-    pthread_join(data->main_thread, nullptr);
+    pthread_join(main_thread, nullptr);
 
     return nullptr;
   }
@@ -495,7 +498,8 @@
   pthread_t dead_thread;
   MakeDeadThread(dead_thread);
 
-  EXPECT_DEATH(pthread_setname_np(dead_thread, "short 3"), "invalid pthread_t");
+  EXPECT_DEATH(pthread_setname_np(dead_thread, "short 3"),
+               "invalid pthread_t (.*) passed to pthread_setname_np");
 }
 
 TEST_F(pthread_DeathTest, pthread_setname_np__null_thread) {
@@ -508,7 +512,8 @@
   MakeDeadThread(dead_thread);
 
   char name[64];
-  EXPECT_DEATH(pthread_getname_np(dead_thread, name, sizeof(name)), "invalid pthread_t");
+  EXPECT_DEATH(pthread_getname_np(dead_thread, name, sizeof(name)),
+               "invalid pthread_t (.*) passed to pthread_getname_np");
 }
 
 TEST_F(pthread_DeathTest, pthread_getname_np__null_thread) {
@@ -564,7 +569,8 @@
   pthread_t dead_thread;
   MakeDeadThread(dead_thread);
 
-  EXPECT_DEATH(pthread_detach(dead_thread), "invalid pthread_t");
+  EXPECT_DEATH(pthread_detach(dead_thread),
+               "invalid pthread_t (.*) passed to pthread_detach");
 }
 
 TEST_F(pthread_DeathTest, pthread_detach__null_thread) {
@@ -591,7 +597,8 @@
   MakeDeadThread(dead_thread);
 
   clockid_t c;
-  EXPECT_DEATH(pthread_getcpuclockid(dead_thread, &c), "invalid pthread_t");
+  EXPECT_DEATH(pthread_getcpuclockid(dead_thread, &c),
+               "invalid pthread_t (.*) passed to pthread_getcpuclockid");
 }
 
 TEST_F(pthread_DeathTest, pthread_getcpuclockid__null_thread) {
@@ -606,7 +613,8 @@
 
   int policy;
   sched_param param;
-  EXPECT_DEATH(pthread_getschedparam(dead_thread, &policy, &param), "invalid pthread_t");
+  EXPECT_DEATH(pthread_getschedparam(dead_thread, &policy, &param),
+               "invalid pthread_t (.*) passed to pthread_getschedparam");
 }
 
 TEST_F(pthread_DeathTest, pthread_getschedparam__null_thread) {
@@ -622,7 +630,8 @@
 
   int policy = 0;
   sched_param param;
-  EXPECT_DEATH(pthread_setschedparam(dead_thread, policy, &param), "invalid pthread_t");
+  EXPECT_DEATH(pthread_setschedparam(dead_thread, policy, &param),
+               "invalid pthread_t (.*) passed to pthread_setschedparam");
 }
 
 TEST_F(pthread_DeathTest, pthread_setschedparam__null_thread) {
@@ -636,7 +645,8 @@
   pthread_t dead_thread;
   MakeDeadThread(dead_thread);
 
-  EXPECT_DEATH(pthread_setschedprio(dead_thread, 123), "invalid pthread_t");
+  EXPECT_DEATH(pthread_setschedprio(dead_thread, 123),
+               "invalid pthread_t (.*) passed to pthread_setschedprio");
 }
 
 TEST_F(pthread_DeathTest, pthread_setschedprio__null_thread) {
@@ -648,7 +658,8 @@
   pthread_t dead_thread;
   MakeDeadThread(dead_thread);
 
-  EXPECT_DEATH(pthread_join(dead_thread, nullptr), "invalid pthread_t");
+  EXPECT_DEATH(pthread_join(dead_thread, nullptr),
+               "invalid pthread_t (.*) passed to pthread_join");
 }
 
 TEST_F(pthread_DeathTest, pthread_join__null_thread) {
@@ -660,7 +671,8 @@
   pthread_t dead_thread;
   MakeDeadThread(dead_thread);
 
-  EXPECT_DEATH(pthread_kill(dead_thread, 0), "invalid pthread_t");
+  EXPECT_DEATH(pthread_kill(dead_thread, 0),
+               "invalid pthread_t (.*) passed to pthread_kill");
 }
 
 TEST_F(pthread_DeathTest, pthread_kill__null_thread) {
@@ -1541,7 +1553,7 @@
   void* maps_stack_hi = nullptr;
   std::vector<map_record> maps;
   ASSERT_TRUE(Maps::parse_maps(&maps));
-  uintptr_t stack_address = reinterpret_cast<uintptr_t>(&maps_stack_hi);
+  uintptr_t stack_address = reinterpret_cast<uintptr_t>(untag_address(&maps_stack_hi));
   for (const auto& map : maps) {
     if (map.addr_start <= stack_address && map.addr_end > stack_address){
       maps_stack_hi = reinterpret_cast<void*>(map.addr_end);
@@ -1620,9 +1632,9 @@
 
   // Verify if the stack used by the signal handler is the alternate stack just registered.
   ASSERT_LE(getstack_signal_handler_arg.signal_stack_base, &attr);
-  ASSERT_LT(static_cast<void*>(&attr),
+  ASSERT_LT(static_cast<void*>(untag_address(&attr)),
             static_cast<char*>(getstack_signal_handler_arg.signal_stack_base) +
-            getstack_signal_handler_arg.signal_stack_size);
+                getstack_signal_handler_arg.signal_stack_size);
 
   // Verify if the main thread's stack got in the signal handler is correct.
   ASSERT_EQ(getstack_signal_handler_arg.main_stack_base, stack_base);
@@ -1681,7 +1693,7 @@
 
   // Test whether &local_variable is in [stack_base, stack_base + stack_size).
   ASSERT_LE(reinterpret_cast<char*>(stack_base), &local_variable);
-  ASSERT_LT(&local_variable, reinterpret_cast<char*>(stack_base) + stack_size);
+  ASSERT_LT(untag_address(&local_variable), reinterpret_cast<char*>(stack_base) + stack_size);
 }
 
 // Check whether something on stack is in the range of
diff --git a/tests/stack_protector_test.cpp b/tests/stack_protector_test.cpp
index 34e3c11..7a85cc3 100644
--- a/tests/stack_protector_test.cpp
+++ b/tests/stack_protector_test.cpp
@@ -104,6 +104,11 @@
 TEST_F(stack_protector_DeathTest, modify_stack_protector) {
   // In another file to prevent inlining, which removes stack protection.
   extern void modify_stack_protector_test();
+#if __has_feature(hwaddress_sanitizer)
+  ASSERT_EXIT(modify_stack_protector_test(),
+              testing::KilledBySignal(SIGABRT), "tag-mismatch");
+#else
   ASSERT_EXIT(modify_stack_protector_test(),
               testing::KilledBySignal(SIGABRT), "stack corruption detected");
+#endif
 }
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 479fd9d..ad6ed45 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -1820,6 +1820,14 @@
   ASSERT_EQ(0, fclose(fp));
 }
 
+TEST(STDIO_TEST, fmemopen_zero_length_buffer_overrun) {
+  char buf[2] = "x";
+  ASSERT_EQ('x', buf[0]);
+  FILE* fp = fmemopen(buf, 0, "w");
+  ASSERT_EQ('x', buf[0]);
+  ASSERT_EQ(0, fclose(fp));
+}
+
 TEST(STDIO_TEST, fmemopen_write_only_allocated) {
   // POSIX says fmemopen "may fail if the mode argument does not include a '+'".
   // BSD fails, glibc doesn't. We side with the more lenient.
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 408a9c7..ff4cb71 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -272,11 +272,11 @@
   for (size_t align = 1; align <= 2048; align <<= 1) {
     // Try all of the non power of 2 values from the last until this value.
     for (size_t fail_align = last_align + 1; fail_align < align; fail_align++) {
-      ASSERT_TRUE(aligned_alloc(fail_align, 256) == nullptr)
+      ASSERT_TRUE(aligned_alloc(fail_align, fail_align) == nullptr)
           << "Unexpected success at align " << fail_align;
       ASSERT_EQ(EINVAL, errno) << "Unexpected errno at align " << fail_align;
     }
-    void* ptr = aligned_alloc(align, 256);
+    void* ptr = aligned_alloc(align, 2 * align);
     ASSERT_TRUE(ptr != nullptr) << "Unexpected failure at align " << align;
     ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
         << "Did not return a valid aligned ptr " << ptr << " expected alignment " << align;
@@ -292,11 +292,11 @@
 
 TEST(stdlib, aligned_alloc_size_not_multiple_of_alignment) {
   SKIP_WITH_HWASAN;
-  for (size_t size = 1; size <= 2048; size++) {
-    void* ptr = aligned_alloc(2048, size);
-    ASSERT_TRUE(ptr != nullptr) << "Failed at size " << std::to_string(size);
-    free(ptr);
-  }
+
+  ASSERT_TRUE(aligned_alloc(2048, 1) == nullptr);
+  ASSERT_TRUE(aligned_alloc(4, 3) == nullptr);
+  ASSERT_TRUE(aligned_alloc(4, 7) == nullptr);
+  ASSERT_TRUE(aligned_alloc(16, 8) == nullptr);
 }
 
 TEST(stdlib, realpath__NULL_filename) {
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index fd2a787..b27ca87 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -1554,3 +1554,40 @@
   ASSERT_EQ(haystack + 1, strstr(haystack, "i"));
   ASSERT_EQ(haystack + 4, strstr(haystack, "da"));
 }
+
+TEST(STRING_TEST, strcasestr_smoke) {
+  const char* haystack = "bIg dAdDy/gIaNt hAyStAcKs";
+  ASSERT_EQ(haystack, strcasestr(haystack, ""));
+  ASSERT_EQ(haystack + 0, strcasestr(haystack, "B"));
+  ASSERT_EQ(haystack + 1, strcasestr(haystack, "i"));
+  ASSERT_EQ(haystack + 4, strcasestr(haystack, "Da"));
+}
+
+TEST(STRING_TEST, strcoll_smoke) {
+  ASSERT_TRUE(strcoll("aab", "aac") < 0);
+  ASSERT_TRUE(strcoll("aab", "aab") == 0);
+  ASSERT_TRUE(strcoll("aac", "aab") > 0);
+}
+
+TEST(STRING_TEST, strxfrm_smoke) {
+  const char* src1 = "aab";
+  char dst1[16] = {};
+  ASSERT_GT(strxfrm(dst1, src1, sizeof(dst1)), 0U);
+  const char* src2 = "aac";
+  char dst2[16] = {};
+  ASSERT_GT(strxfrm(dst2, src2, sizeof(dst2)), 0U);
+  ASSERT_TRUE(strcmp(dst1, dst2) < 0);
+}
+
+TEST(STRING_TEST, memccpy_smoke) {
+  char dst[32];
+
+  memset(dst, 0, sizeof(dst));
+  char* p = static_cast<char*>(memccpy(dst, "hello world", ' ', 32));
+  ASSERT_STREQ("hello ", dst);
+  ASSERT_EQ(ptrdiff_t(6), p - dst);
+
+  memset(dst, 0, sizeof(dst));
+  ASSERT_EQ(nullptr, memccpy(dst, "hello world", ' ', 4));
+  ASSERT_STREQ("hell", dst);
+}
diff --git a/tests/sys_ptrace_test.cpp b/tests/sys_ptrace_test.cpp
index 83fd93b..04dcd4e 100644
--- a/tests/sys_ptrace_test.cpp
+++ b/tests/sys_ptrace_test.cpp
@@ -35,6 +35,8 @@
 #include <android-base/macros.h>
 #include <android-base/unique_fd.h>
 
+#include "utils.h"
+
 using namespace std::chrono_literals;
 
 using android::base::unique_fd;
@@ -193,7 +195,7 @@
     return;
   }
 
-  set_watchpoint(child, uintptr_t(&data) + offset, size);
+  set_watchpoint(child, uintptr_t(untag_address(&data)) + offset, size);
 
   ASSERT_EQ(0, ptrace(PTRACE_CONT, child, nullptr, nullptr)) << strerror(errno);
   ASSERT_EQ(child, TEMP_FAILURE_RETRY(waitpid(child, &status, __WALL))) << strerror(errno);
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index f4a7f1f..cb94e45 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -538,7 +538,7 @@
 
 static int CloneStartRoutine(int (*start_routine)(void*)) {
   void* child_stack[1024];
-  return clone(start_routine, &child_stack[1024], SIGCHLD, nullptr);
+  return clone(start_routine, untag_address(&child_stack[1024]), SIGCHLD, nullptr);
 }
 
 static int GetPidCachingCloneStartRoutine(void*) {
diff --git a/tests/utils.h b/tests/utils.h
index 5fc1d93..cc1aa8c 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -66,6 +66,16 @@
 
 #define SKIP_WITH_HWASAN if (running_with_hwasan()) { return; }
 
+static inline void* untag_address(void* addr) {
+#if defined(__LP64__)
+  if (running_with_hwasan()) {
+    constexpr uintptr_t mask = (static_cast<uintptr_t>(1) << 56) - 1;
+    addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & mask);
+  }
+#endif
+  return addr;
+}
+
 #if defined(__linux__)
 
 #include <sys/sysmacros.h>
diff --git a/tools/Android.mk b/tools/Android.mk
deleted file mode 100644
index 4dd66fe..0000000
--- a/tools/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(call all-subdir-makefiles)
diff --git a/tools/versioner/src/Arch.h b/tools/versioner/src/Arch.h
index bac9ec4..16fa265 100644
--- a/tools/versioner/src/Arch.h
+++ b/tools/versioner/src/Arch.h
@@ -138,7 +138,7 @@
   { Arch::x86_64, "x86_64-linux-android" },
 };
 
-static const std::set<int> default_levels = { 14, 15, 16, 17, 18, 19, 21, 23, 24, 25, 26, 27, 28 };
+static const std::set<int> default_levels = { 14, 15, 16, 17, 18, 19, 21, 23, 24, 25, 26, 27, 28, 29 };
 
 static const ArchMap<int> arch_min_api = {
   { Arch::arm, 9 },
@@ -149,8 +149,6 @@
   { Arch::x86_64, 21 },
 };
 
-static constexpr int future_api = 10000;
-
 static const std::unordered_map<std::string, int> api_codename_map{
   {"G", 9},
   {"I", 14},
@@ -166,5 +164,5 @@
   {"O", 26},
   {"O-MR1", 27},
   {"P", 28},
-  {"Q", 9001},
+  {"Q", 29},
 };
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
index d9cff17..0ba51d1 100644
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ b/tools/versioner/src/DeclarationDatabase.cpp
@@ -147,9 +147,6 @@
       llvm::StringRef annotation = attr->getAnnotation();
       if (annotation == "versioner_no_guard") {
         no_guard = true;
-      } else if (annotation == "introduced_in_future") {
-        // Tag the compiled-for arch, since this can vary across archs.
-        availability.arch_availability[type.arch].future = true;
       } else {
         llvm::SmallVector<llvm::StringRef, 2> fragments;
         annotation.split(fragments, "=");
@@ -345,10 +342,6 @@
 std::string to_string(const AvailabilityValues& av) {
   std::stringstream ss;
 
-  if (av.future) {
-    ss << "future, ";
-  }
-
   if (av.introduced != 0) {
     ss << "introduced = " << av.introduced << ", ";
   }
diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h
index 0daa2cd..4496ee9 100644
--- a/tools/versioner/src/DeclarationDatabase.h
+++ b/tools/versioner/src/DeclarationDatabase.h
@@ -42,13 +42,12 @@
 };
 
 struct AvailabilityValues {
-  bool future = false;
   int introduced = 0;
   int deprecated = 0;
   int obsoleted = 0;
 
   bool empty() const {
-    return !(future || introduced || deprecated || obsoleted);
+    return !(introduced || deprecated || obsoleted);
   }
 
   bool operator==(const AvailabilityValues& rhs) const {
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
index a7f289b..9eac2ab 100644
--- a/tools/versioner/src/Preprocessor.cpp
+++ b/tools/versioner/src/Preprocessor.cpp
@@ -190,13 +190,6 @@
 
     int version = avail.arch_availability[*it.second.begin()].introduced;
 
-    // Assume that the entire declaration is declared __INTRODUCED_IN_FUTURE if one arch is.
-    bool future = avail.arch_availability[*it.second.begin()].future;
-
-    if (future) {
-      return "__ANDROID_API__ >= __ANDROID_API_FUTURE__";
-    }
-
     // The maximum min_version of the set.
     int max_min_version = 0;
     for (Arch arch : archs) {
diff --git a/tools/versioner/src/SymbolFileParser.cpp b/tools/versioner/src/SymbolFileParser.cpp
index 33308d9..c312b48 100644
--- a/tools/versioner/src/SymbolFileParser.cpp
+++ b/tools/versioner/src/SymbolFileParser.cpp
@@ -257,10 +257,6 @@
         intro_arch = true;
         continue;
       }
-
-      if (tag == "future") {
-        return compilation_type.api_level == future_api;
-      }
     }
 
     if (intro.empty() && api_level.empty()) {
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index 73eff0e..d3c2f7c 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -397,10 +397,6 @@
         should_be_available = false;
       }
 
-      if (arch_availability.future) {
-        continue;
-      }
-
       // The function declaration might be (validly) missing for the given CompilationType.
       if (!symbol_it.second.hasDeclaration(type)) {
         should_be_available = false;
diff --git a/tools/versioner/tests/future/headers/foo.h b/tools/versioner/tests/future/headers/foo.h
deleted file mode 100644
index 51a3a1c..0000000
--- a/tools/versioner/tests/future/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __INTRODUCED_IN_FUTURE;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/future/platforms/libc.map.txt b/tools/versioner/tests/future/platforms/libc.map.txt
deleted file mode 100644
index e69de29..0000000
--- a/tools/versioner/tests/future/platforms/libc.map.txt
+++ /dev/null
diff --git a/tools/versioner/tests/future/run.sh b/tools/versioner/tests/future/run.sh
deleted file mode 100644
index 041b047..0000000
--- a/tools/versioner/tests/future/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner -v headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/future_arch/headers/foo.h b/tools/versioner/tests/future_arch/headers/foo.h
deleted file mode 100644
index a3258e7..0000000
--- a/tools/versioner/tests/future_arch/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if defined(__arm__)
-int foo() __INTRODUCED_IN(9);
-#else
-int foo() __INTRODUCED_IN_FUTURE;
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/future_arch/platforms/libc.map.txt b/tools/versioner/tests/future_arch/platforms/libc.map.txt
deleted file mode 100644
index f56190e..0000000
--- a/tools/versioner/tests/future_arch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # arm
-};
diff --git a/tools/versioner/tests/future_arch/run.sh b/tools/versioner/tests/future_arch/run.sh
deleted file mode 100644
index ad8f430..0000000
--- a/tools/versioner/tests/future_arch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner -v headers -p platforms -r arm -r x86 -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/preprocessor/expected/foo.h b/tools/versioner/tests/preprocessor/expected/foo.h
index cb719f0..61e6056 100644
--- a/tools/versioner/tests/preprocessor/expected/foo.h
+++ b/tools/versioner/tests/preprocessor/expected/foo.h
@@ -74,11 +74,6 @@
 
 
 
-#if __ANDROID_API__ >= __ANDROID_API_FUTURE__
-int future() __INTRODUCED_IN_FUTURE;
-#endif /* __ANDROID_API__ >= __ANDROID_API_FUTURE__ */
-
-
 #if defined(__cplusplus)
 }
 #endif
diff --git a/tools/versioner/tests/preprocessor/headers/foo.h b/tools/versioner/tests/preprocessor/headers/foo.h
index 2429334..349e5e6 100644
--- a/tools/versioner/tests/preprocessor/headers/foo.h
+++ b/tools/versioner/tests/preprocessor/headers/foo.h
@@ -45,8 +45,6 @@
 
 int group_lp32() __INTRODUCED_IN_ARM(12) __INTRODUCED_IN_X86(12) __INTRODUCED_IN_MIPS(12);
 
-int future() __INTRODUCED_IN_FUTURE;
-
 #if defined(__cplusplus)
 }
 #endif