Merge "bionic: Add tests for cpu target features" into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 60a4f61..e98c2ff 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -88,6 +88,12 @@
     },
     {
       "name": "toybox-tests"
+    },
+    {
+      "name": "hwasan_test"
+    },
+    {
+      "name": "hwasan_test_static"
     }
   ],
   "kernel-presubmit": [
diff --git a/docs/clang_fortify_anatomy.md b/docs/clang_fortify_anatomy.md
index 4b95fdc..46d3a71 100644
--- a/docs/clang_fortify_anatomy.md
+++ b/docs/clang_fortify_anatomy.md
@@ -147,8 +147,7 @@
 void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
 ```
 
-Which is annotated with nothing special, except for Bionic's versioner, which
-is Android-specific (and orthogonal to FORTIFY anyway), so it will be ignored.
+Which is annotated with nothing special, so it will be ignored.
 
 The [source for `mempcpy`] in Bionic's headers for is:
 ```c
diff --git a/docs/fdtrack.md b/docs/fdtrack.md
index 07c69b3..8928a5c 100644
--- a/docs/fdtrack.md
+++ b/docs/fdtrack.md
@@ -4,9 +4,11 @@
 
 fdtrack is a file descriptor leak checker added to Android in API level 30.
 
-fdtrack consists of two parts: a set of hooks in bionic to register a callback
-that's invoked on file descriptor operations, and a library that implements a
-hook to perform and store backtraces for file descriptor creation.
+fdtrack consists of several parts: a set of hooks in bionic to register a
+callback that's invoked on file descriptor operations, a library that implements
+a hook to perform and store backtraces for file descriptor creation, and
+code in frameworks to automatically enable it (and deliberately crash a process
+that's leaking).
 
 ### bionic hooks
 bionic provides a header in the `bionic_libc_platform_headers` header_lib at <[bionic/fdtrack.h](https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/platform/bionic/fdtrack.h)>.
@@ -21,6 +23,28 @@
 [libfdtrack](https://android.googlesource.com/platform/bionic/+/refs/heads/main/libfdtrack)
 implements a library that uses libunwindstack to unwind and store fd creation backtraces.
 
+### frameworks
+As the name implies, `spawnFdLeakCheckThread` in SystemServer spawns a thread
+to monitor the number of open file descriptors every so often.
+If that passes a certain threshold, fdtrack is enabled.
+If it passes another threshold, the process is aborted.
+These thresholds are configurable via system properties:
+```
+    // Number of open file descriptors before fdtrack starts; default 1600.
+    private static final String SYSPROP_FDTRACK_ENABLE_THRESHOLD =
+            "persist.sys.debug.fdtrack_enable_threshold";
+
+    // Number of open file descriptors before aborting; default 3000.
+    private static final String SYSPROP_FDTRACK_ABORT_THRESHOLD =
+            "persist.sys.debug.fdtrack_abort_threshold";
+
+    // Number of seconds between open fd count checks; default 120s.
+    private static final String SYSPROP_FDTRACK_INTERVAL =
+            "persist.sys.debug.fdtrack_interval";
+```
+Note that it's also possible to monitor the number of open file descriptors for
+a given process from the shell. `adb shell watch ls -l /proc/<pid>/fd` will show
+them (and you can choose your own update rate as an argument to `watch`).
 
 #### Using libfdtrack
 libfdtrack registers its hook upon being loaded, so to start capturing
diff --git a/libc/Android.bp b/libc/Android.bp
index 776f101..a4f2c69 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1182,16 +1182,6 @@
                 "arch-x86/bionic/__x86.get_pc_thunk.S",
 
                 "arch-x86/generic/string/memcmp.S",
-                "arch-x86/generic/string/strcmp.S",
-                "arch-x86/generic/string/strncmp.S",
-                "arch-x86/generic/string/strcat.S",
-
-                "arch-x86/generic/string/strlcat.c",
-                "arch-x86/generic/string/strlcpy.c",
-                "arch-x86/generic/string/strncat.c",
-                "arch-x86/generic/string/wcscat.c",
-                "arch-x86/generic/string/wcscpy.c",
-                "arch-x86/generic/string/wmemcmp.c",
 
                 "arch-x86/string/sse2-memchr-atom.S",
                 "arch-x86/string/sse2-memmove-slm.S",
@@ -2978,13 +2968,6 @@
     },
 }
 
-// headers that will be placed on the include path when running versioner in bazel
-// this module should be a no-op in soong
-filegroup {
-    name: "versioner-dependencies",
-    srcs: ["versioner-dependencies/**/*"],
-}
-
 filegroup {
     name: "linux_capability_header",
     srcs: ["kernel/uapi/linux/capability.h"],
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
index 9d7a4c9..e6cc5fb 100644
--- a/libc/arch-x86/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -84,89 +84,11 @@
 }
 STRLEN_SHIM()
 
-DEFINE_IFUNC_FOR(strcmp) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strcmp_func_t, strcmp_ssse3);
-  RETURN_FUNC(strcmp_func_t, strcmp_generic);
-}
-STRCMP_SHIM()
-
-DEFINE_IFUNC_FOR(strncmp) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3"))
-    RETURN_FUNC(strncmp_func_t, strncmp_ssse3);
-  RETURN_FUNC(strncmp_func_t, strncmp_generic);
-}
-STRNCMP_SHIM()
-
-DEFINE_IFUNC_FOR(strcat) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strcat_func_t, strcat_ssse3);
-  RETURN_FUNC(strcat_func_t, strcat_generic);
-}
-STRCAT_SHIM()
-
-DEFINE_IFUNC_FOR(strncat) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strncat_func_t, strncat_ssse3);
-  RETURN_FUNC(strncat_func_t, strncat_openbsd);
-}
-STRNCAT_SHIM()
-
-typedef size_t strlcat_func_t(char*, const char*, size_t);
-DEFINE_IFUNC_FOR(strlcat) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strlcat_func_t, strlcat_ssse3);
-  RETURN_FUNC(strlcat_func_t, strlcat_openbsd);
-}
-DEFINE_STATIC_SHIM(size_t strlcat(char* dst, const char* src, size_t n) {
-  FORWARD(strlcat)(dst, src, n);
-})
-
-typedef size_t strlcpy_func_t(char*, const char*, size_t);
-DEFINE_IFUNC_FOR(strlcpy) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strlcpy_func_t, strlcpy_ssse3);
-  RETURN_FUNC(strlcpy_func_t, strlcpy_openbsd);
-}
-DEFINE_STATIC_SHIM(size_t strlcpy(char* dst, const char* src, size_t n) {
-  FORWARD(strlcpy)(dst, src, n);
-})
-
-typedef wchar_t* wcscat_func_t(wchar_t*, const wchar_t*);
-DEFINE_IFUNC_FOR(wcscat) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(wcscat_func_t, wcscat_ssse3);
-  RETURN_FUNC(wcscat_func_t, wcscat_freebsd);
-}
-DEFINE_STATIC_SHIM(wchar_t* wcscat(wchar_t* dst, const wchar_t* src) {
-  FORWARD(wcscat)(dst, src);
-})
-
-typedef wchar_t* wcscpy_func_t(wchar_t*, const wchar_t*);
-DEFINE_IFUNC_FOR(wcscpy) {
-  __builtin_cpu_init();
-  // TODO: ssse3 is required by our x86 abi!
-  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(wcscpy_func_t, wcscpy_ssse3);
-  RETURN_FUNC(wcscpy_func_t, wcscpy_freebsd);
-}
-DEFINE_STATIC_SHIM(wchar_t* wcscpy(wchar_t* dst, const wchar_t* src) {
-  FORWARD(wcscpy)(dst, src);
-})
-
 typedef int wmemcmp_func_t(const wchar_t*, const wchar_t*, size_t);
 DEFINE_IFUNC_FOR(wmemcmp) {
   __builtin_cpu_init();
   if (__builtin_cpu_supports("sse4.1")) RETURN_FUNC(wmemcmp_func_t, wmemcmp_sse4);
-  if (__builtin_cpu_is("atom")) RETURN_FUNC(wmemcmp_func_t, wmemcmp_atom);
-  RETURN_FUNC(wmemcmp_func_t, wmemcmp_freebsd);
+  RETURN_FUNC(wmemcmp_func_t, wmemcmp_atom);
 }
 DEFINE_STATIC_SHIM(int wmemcmp(const wchar_t* lhs, const wchar_t* rhs, size_t n) {
   FORWARD(wmemcmp)(lhs, rhs, n);
diff --git a/libc/arch-x86/generic/string/strcat.S b/libc/arch-x86/generic/string/strcat.S
deleted file mode 100644
index e2e9623..0000000
--- a/libc/arch-x86/generic/string/strcat.S
+++ /dev/null
@@ -1,74 +0,0 @@
-/*	$OpenBSD: strcat.S,v 1.8 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-#if defined(APIWARN)
-#APP
-	.section .gnu.warning.strcat
-	.ascii "warning: strcat() is almost always misused, please use strlcat()"
-#NO_APP
-#endif
-
-/*
- * NOTE: I've unrolled the loop eight times: large enough to make a
- * significant difference, and small enough not to totally trash the
- * cache.
- */
-
-ENTRY(strcat_generic)
-	pushl	%edi			/* save edi */
-	movl	8(%esp),%edi		/* dst address */
-	movl	12(%esp),%edx		/* src address */
-	pushl	%edi			/* push destination address */
-
-	cld				/* set search forward */
-	xorl	%eax,%eax		/* set search for null terminator */
-	movl	$-1,%ecx		/* set search for lots of characters */
-	repne				/* search! */
-	scasb
-
-	leal	-1(%edi),%ecx		/* correct dst address */
-
-	.align 2,0x90
-L1:	movb	(%edx),%al		/* unroll loop, but not too much */
-	movb	%al,(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	1(%edx),%al
-	movb	%al,1(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	2(%edx),%al
-	movb	%al,2(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	3(%edx),%al
-	movb	%al,3(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	4(%edx),%al
-	movb	%al,4(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	5(%edx),%al
-	movb	%al,5(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	6(%edx),%al
-	movb	%al,6(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	7(%edx),%al
-	movb	%al,7(%ecx)
-	addl	$8,%edx
-	addl	$8,%ecx
-	testb	%al,%al
-	jnz	L1
-L2:	popl	%eax			/* pop destination address */
-	popl	%edi			/* restore edi */
-	ret
-END(strcat_generic)
diff --git a/libc/arch-x86/generic/string/strcmp.S b/libc/arch-x86/generic/string/strcmp.S
deleted file mode 100644
index 7b003e8..0000000
--- a/libc/arch-x86/generic/string/strcmp.S
+++ /dev/null
@@ -1,82 +0,0 @@
-/*	$OpenBSD: strcmp.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-/*
- * NOTE: I've unrolled the loop eight times: large enough to make a
- * significant difference, and small enough not to totally trash the
- * cache.
- */
-
-ENTRY(strcmp_generic)
-	movl	0x04(%esp),%eax
-	movl	0x08(%esp),%edx
-	jmp	L2			/* Jump into the loop! */
-
-	.align	2,0x90
-L1:	incl	%eax
-	incl	%edx
-L2:	movb	(%eax),%cl
-	testb	%cl,%cl			/* null terminator??? */
-	jz	L3
-	cmpb	%cl,(%edx)		/* chars match??? */
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	je	L1
-	.align 2, 0x90
-L3:	movzbl	(%eax),%eax		/* unsigned comparison */
-	movzbl	(%edx),%edx
-	subl	%edx,%eax
-	ret
-END(strcmp_generic)
diff --git a/libc/arch-x86/generic/string/strlcat.c b/libc/arch-x86/generic/string/strlcat.c
deleted file mode 100644
index 95c34a3..0000000
--- a/libc/arch-x86/generic/string/strlcat.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <upstream-openbsd/android/include/openbsd-compat.h>
-
-#define strlcat strlcat_openbsd
-#include <upstream-openbsd/lib/libc/string/strlcat.c>
diff --git a/libc/arch-x86/generic/string/strlcpy.c b/libc/arch-x86/generic/string/strlcpy.c
deleted file mode 100644
index 8d4047c..0000000
--- a/libc/arch-x86/generic/string/strlcpy.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <upstream-openbsd/android/include/openbsd-compat.h>
-
-#define strlcpy strlcpy_openbsd
-#include <upstream-openbsd/lib/libc/string/strlcpy.c>
diff --git a/libc/arch-x86/generic/string/strncat.c b/libc/arch-x86/generic/string/strncat.c
deleted file mode 100644
index 687e560..0000000
--- a/libc/arch-x86/generic/string/strncat.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <upstream-openbsd/android/include/openbsd-compat.h>
-
-#define strncat strncat_openbsd
-#include <upstream-openbsd/lib/libc/string/strncat.c>
diff --git a/libc/arch-x86/generic/string/strncmp.S b/libc/arch-x86/generic/string/strncmp.S
deleted file mode 100644
index 6d9f23c..0000000
--- a/libc/arch-x86/generic/string/strncmp.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*	$OpenBSD: strncmp.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-/*
- * NOTE: I've unrolled the loop eight times: large enough to make a
- * significant difference, and small enough not to totally trash the
- * cache.
- */
-
-ENTRY(strncmp_generic)
-	pushl	%ebx
-	movl	8(%esp),%eax
-	movl	12(%esp),%ecx
-	movl	16(%esp),%edx
-	testl	%edx,%edx
-	jmp	L2			/* Jump into the loop! */
-
-	.align 2,0x90
-L1:	incl	%eax
-	incl	%ecx
-	decl	%edx
-L2:	jz	L4			/* strings are equal */
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	je	L1
-
-	.align 2,0x90
-L3:	movzbl	(%eax),%eax		/* unsigned comparision */
-	movzbl	(%ecx),%ecx
-	subl	%ecx,%eax
-	popl	%ebx
-	ret
-	.align 2,0x90
-L4:	xorl	%eax,%eax
-	popl	%ebx
-	ret
-END(strncmp_generic)
diff --git a/libc/arch-x86/generic/string/wcscat.c b/libc/arch-x86/generic/string/wcscat.c
deleted file mode 100644
index a102551..0000000
--- a/libc/arch-x86/generic/string/wcscat.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define wcscat wcscat_freebsd
-#include <upstream-freebsd/lib/libc/string/wcscat.c>
diff --git a/libc/arch-x86/generic/string/wcscpy.c b/libc/arch-x86/generic/string/wcscpy.c
deleted file mode 100644
index 10fb66d..0000000
--- a/libc/arch-x86/generic/string/wcscpy.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define wcscpy wcscpy_freebsd
-#include <upstream-freebsd/lib/libc/string/wcscpy.c>
diff --git a/libc/arch-x86/generic/string/wmemcmp.c b/libc/arch-x86/generic/string/wmemcmp.c
deleted file mode 100644
index 9d5e929..0000000
--- a/libc/arch-x86/generic/string/wmemcmp.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define wmemcmp wmemcmp_freebsd
-#include <upstream-freebsd/lib/libc/string/wmemcmp.c>
diff --git a/libc/arch-x86/string/ssse3-strcat-atom.S b/libc/arch-x86/string/ssse3-strcat-atom.S
index 8d8e89d..b851d9e 100644
--- a/libc/arch-x86/string/ssse3-strcat-atom.S
+++ b/libc/arch-x86/string/ssse3-strcat-atom.S
@@ -87,7 +87,7 @@
 #define POP(REG)	popl REG; CFI_POP (REG)
 
 #ifndef STRCAT
-# define STRCAT	strcat_ssse3
+# define STRCAT	strcat
 #endif
 
 #define PARMS	4
diff --git a/libc/arch-x86/string/ssse3-strcmp-atom.S b/libc/arch-x86/string/ssse3-strcmp-atom.S
index 08f6d4a..ee253b9 100644
--- a/libc/arch-x86/string/ssse3-strcmp-atom.S
+++ b/libc/arch-x86/string/ssse3-strcmp-atom.S
@@ -108,7 +108,7 @@
 #endif
 
 #ifndef STRCMP
-# define STRCMP strcmp_ssse3
+# define STRCMP strcmp
 #endif
 
 	.section .text.ssse3,"ax",@progbits
diff --git a/libc/arch-x86/string/ssse3-strlcat-atom.S b/libc/arch-x86/string/ssse3-strlcat-atom.S
index 055b489..daaf254 100644
--- a/libc/arch-x86/string/ssse3-strlcat-atom.S
+++ b/libc/arch-x86/string/ssse3-strlcat-atom.S
@@ -82,7 +82,7 @@
 #define LEN	SRC+4
 
 	.text
-ENTRY (strlcat_ssse3)
+ENTRY (strlcat)
 	mov	DST(%esp), %edx
 	PUSH	(%ebx)
 	mov	LEN(%esp), %ebx
diff --git a/libc/arch-x86/string/ssse3-strlcpy-atom.S b/libc/arch-x86/string/ssse3-strlcpy-atom.S
index 1671da6..cdb17cc 100644
--- a/libc/arch-x86/string/ssse3-strlcpy-atom.S
+++ b/libc/arch-x86/string/ssse3-strlcpy-atom.S
@@ -29,8 +29,8 @@
 */
 
 #define USE_AS_STRNCPY
-#define STRCPY strlcpy_ssse3
-#define STRLEN strlcpy_ssse3
+#define STRCPY strlcpy
+#define STRLEN strlcpy
 #define USE_AS_STRLCPY
 #include "ssse3-strcpy-atom.S"
 
diff --git a/libc/arch-x86/string/ssse3-strncat-atom.S b/libc/arch-x86/string/ssse3-strncat-atom.S
index ccb08a7..5618771 100644
--- a/libc/arch-x86/string/ssse3-strncat-atom.S
+++ b/libc/arch-x86/string/ssse3-strncat-atom.S
@@ -28,7 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#define STRCAT  strncat_ssse3
+#define STRCAT  strncat
 #define USE_AS_STRNCAT
 
 #include "ssse3-strcat-atom.S"
diff --git a/libc/arch-x86/string/ssse3-strncmp-atom.S b/libc/arch-x86/string/ssse3-strncmp-atom.S
index 2bf5002..234f728 100644
--- a/libc/arch-x86/string/ssse3-strncmp-atom.S
+++ b/libc/arch-x86/string/ssse3-strncmp-atom.S
@@ -30,6 +30,5 @@
 
 
 #define USE_AS_STRNCMP
-#define STRCMP  strncmp_ssse3
+#define STRCMP  strncmp
 #include "ssse3-strcmp-atom.S"
-
diff --git a/libc/arch-x86/string/ssse3-wcscat-atom.S b/libc/arch-x86/string/ssse3-wcscat-atom.S
index a307983..8a389a3 100644
--- a/libc/arch-x86/string/ssse3-wcscat-atom.S
+++ b/libc/arch-x86/string/ssse3-wcscat-atom.S
@@ -85,7 +85,7 @@
 #define USE_AS_WCSCAT
 
 .text
-ENTRY (wcscat_ssse3)
+ENTRY (wcscat)
 	PUSH    (%edi)
 	mov	STR1(%esp), %edi
 	mov	%edi, %edx
@@ -111,4 +111,4 @@
 #define RETURN  POP(%edi);	ret;	CFI_PUSH(%edi)
 #include "ssse3-wcscpy-atom.S"
 
-END (wcscat_ssse3)
+END (wcscat)
diff --git a/libc/arch-x86/string/ssse3-wcscpy-atom.S b/libc/arch-x86/string/ssse3-wcscpy-atom.S
index 80aa15f..27cb61e 100644
--- a/libc/arch-x86/string/ssse3-wcscpy-atom.S
+++ b/libc/arch-x86/string/ssse3-wcscpy-atom.S
@@ -88,7 +88,7 @@
 # define LEN	STR2+4
 
 .text
-ENTRY (wcscpy_ssse3)
+ENTRY (wcscpy)
 	mov	STR1(%esp), %edx
 	mov	STR2(%esp), %ecx
 
@@ -648,5 +648,5 @@
 	ret
 
 #ifndef USE_AS_WCSCAT
-END (wcscpy_ssse3)
+END (wcscpy)
 #endif
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 1bbdb29..63c9fab 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <errno.h>
+#include <inttypes.h>
 #include <malloc.h>
 #include <sys/param.h>
 #include <unistd.h>
@@ -30,6 +31,7 @@
 size_t je_mallinfo_nbins();
 struct mallinfo je_mallinfo_arena_info(size_t);
 struct mallinfo je_mallinfo_bin_info(size_t, size_t);
+void je_stats_arena(size_t arena_index, void (*callback)(size_t, size_t, size_t));
 
 __END_DECLS
 
@@ -136,29 +138,24 @@
     }
     return 1;
   } else if (param == M_LOG_STATS) {
+    size_t total_bytes = 0;
     for (size_t i = 0; i < je_mallinfo_narenas(); i++) {
       struct mallinfo mi = je_mallinfo_arena_info(i);
-      if (mi.hblkhd != 0) {
-        async_safe_format_log(ANDROID_LOG_INFO, "jemalloc",
-                              "Arena %zu: large bytes %zu huge bytes %zu bin bytes %zu", i,
-                              mi.ordblks, mi.uordblks, mi.fsmblks);
+      size_t arena_bytes = mi.fsmblks + mi.ordblks + mi.uordblks;
+      async_safe_format_log(ANDROID_LOG_INFO, "jemalloc",
+                            "Arena %zu: bin bytes=%zu large bytes=%zu total bytes=%zu", i,
+                            mi.fsmblks, mi.ordblks, arena_bytes);
 
-        for (size_t j = 0; j < je_mallinfo_nbins(); j++) {
-          struct mallinfo mi = je_mallinfo_bin_info(i, j);
-          if (mi.ordblks != 0) {
-            size_t total_allocs = 1;
-            if (mi.uordblks > mi.fordblks) {
-              total_allocs = mi.uordblks - mi.fordblks;
-            }
-            size_t bin_size = mi.ordblks / total_allocs;
-            async_safe_format_log(
-                ANDROID_LOG_INFO, "jemalloc",
-                "  Bin %zu (%zu bytes): allocated bytes %zu nmalloc %zu ndalloc %zu", j, bin_size,
-                mi.ordblks, mi.uordblks, mi.fordblks);
-          }
+      je_stats_arena(i, [](size_t index, size_t size, size_t allocs) {
+        if (allocs != 0) {
+          async_safe_format_log(ANDROID_LOG_INFO, "jemalloc",
+                                "  Size Class %zu(%zu bytes): allocs=%zu total bytes=%zu", index,
+                                size, allocs, allocs * size);
         }
-      }
+      });
+      total_bytes += arena_bytes;
     }
+    async_safe_format_log(ANDROID_LOG_INFO, "jemalloc", "Total Bytes=%zu", total_bytes);
     return 1;
   }
 
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index f8f7d2a..7c46113 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -421,12 +421,11 @@
 }
 
 __attribute__((no_sanitize("memtag"))) __noreturn static void __real_libc_init(
-    void* raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char**, char**),
-    structors_array_t const* const structors, bionic_tcb* temp_tcb) {
+    KernelArgumentBlock& args, void* raw_args, void (*onexit)(void) __unused,
+    int (*slingshot)(int, char**, char**), structors_array_t const* const structors,
+    bionic_tcb* temp_tcb) {
   BIONIC_STOP_UNWIND;
 
-  // Initialize TLS early so system calls and errno work.
-  KernelArgumentBlock args(raw_args);
   __libc_init_main_thread_early(args, temp_tcb);
   __libc_init_main_thread_late();
   __libc_init_globals();
@@ -473,17 +472,25 @@
 __attribute__((no_sanitize("hwaddress", "memtag"))) __noreturn void __libc_init(
     void* raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char**, char**),
     structors_array_t const* const structors) {
-  bionic_tcb temp_tcb = {};
+  // We _really_ don't want the compiler to call memset() here,
+  // but it's done so before for riscv64 (http://b/365618934),
+  // so we have to force it to behave.
+  bionic_tcb temp_tcb __attribute__((uninitialized));
+  __builtin_memset_inline(&temp_tcb, 0, sizeof(temp_tcb));
+
+  KernelArgumentBlock args(raw_args);
 #if __has_feature(hwaddress_sanitizer)
   // Install main thread TLS early. It will be initialized later in __libc_init_main_thread. For now
-  // all we need is access to TLS_SLOT_SANITIZER.
+  // all we need is access to TLS_SLOT_SANITIZER and read auxval for the page size.
   __set_tls(&temp_tcb.tls_slot(0));
+  __libc_shared_globals()->auxv = args.auxv;
   // Initialize HWASan enough to run instrumented code. This sets up TLS_SLOT_SANITIZER, among other
   // things.
   __hwasan_init_static();
   // We are ready to run HWASan-instrumented code, proceed with libc initialization...
 #endif
-  __real_libc_init(raw_args, onexit, slingshot, structors, &temp_tcb);
+
+  __real_libc_init(args, raw_args, onexit, slingshot, structors, &temp_tcb);
 }
 
 static int g_target_sdk_version{__ANDROID_API__};
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 9b37225..0a452e9 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -182,7 +182,12 @@
         return 0;
     }
     if (ret == EBUSY) {
-        ScopedTrace trace("Contending for pthread mutex");
+        char trace_msg[64];
+        const pid_t owner = atomic_load_explicit(&mutex.owner_tid, memory_order_relaxed)
+                & FUTEX_TID_MASK;
+        snprintf(trace_msg, sizeof(trace_msg),
+                 "Contending for pthread mutex owned by tid: %d", owner);
+        ScopedTrace trace(trace_msg);
         ret = -__futex_pi_lock_ex(&mutex.owner_tid, mutex.shared, use_realtime_clock, abs_timeout);
     }
     return ret;
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index ecbc33f..fe9264d 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -16,33 +16,29 @@
 
 #pragma once
 
-// The `annotate` attribute always pulls the annotated (inline) function into the object files, thus
-// we should only annotate headers when we are running versioner.
-#if defined(__BIONIC_VERSIONER)
-
-#define __INTRODUCED_IN(api_level) __attribute__((__annotate__("introduced_in=" #api_level)))
-#define __DEPRECATED_IN(api_level, msg) __attribute__((__annotate__("deprecated_in=" #api_level)))
-#define __REMOVED_IN(api_level, msg) __attribute__((__annotate__("obsoleted_in=" #api_level)))
-#define __INTRODUCED_IN_32(api_level) __attribute__((__annotate__("introduced_in_32=" #api_level)))
-#define __INTRODUCED_IN_64(api_level) __attribute__((__annotate__("introduced_in_64=" #api_level)))
-
-#define __VERSIONER_NO_GUARD __attribute__((__annotate__("versioner_no_guard")))
-#define __VERSIONER_FORTIFY_INLINE __attribute__((__annotate__("versioner_fortify_inline")))
-
-#else
-
-// When headers are not processed by the versioner (i.e. compiled into object files),
-// the availability attributed is emitted instead. The clang compiler will make the symbol weak
-// when targeting old api_level and enforce the reference to the symbol to be guarded with
-// __builtin_available(android api_level, *).
-
-// The 'strict' flag is required for NDK clients where the use of "-Wunguarded-availability" cannot
-// be enforced. In the case, the absence of 'strict' makes it possible to call an unavailable API
-// without the __builtin_available check, which will cause a link error at runtime.
-// Android platform build system defines this macro along with -Wunguarded-availability
+/**
+ * @def __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
+ *
+ * Controls whether calling APIs newer than the developer's minSdkVersion are a
+ * build error (when not defined) or allowed as a weak reference with a
+ * __builtin_available() guard (when defined).
+ *
+ * See https://developer.android.com/ndk/guides/using-newer-apis for more
+ * details.
+ */
 #if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
+// In this mode, Clang will emit weak references to the APIs if the
+// minSdkVersion is less than the __what argument. This allows the libraries to
+// load even on systems too old to contain the API, but calls must be guarded
+// with `__builtin_available(android api_level, *)` to avoid segfaults.
 #define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,__what __VA_OPT__(,) __VA_ARGS__)))
 #else
+// The 'strict' flag is required for NDK clients where the code was not written
+// to handle the case where the API was available at build-time but not at
+// run-time. Most 3p code ported to Android was not written to use
+// `__builtin_available()` for run-time availability checking, and so would not
+// compile in this mode (or worse, if the build doesn't use
+// -Werror=unguarded-availability, it would build but crash at runtime).
 #define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,strict,__what __VA_OPT__(,) __VA_ARGS__)))
 #endif
 
@@ -64,11 +60,6 @@
 #define __INTRODUCED_IN_64(api_level) __BIONIC_AVAILABILITY(introduced=api_level)
 #endif
 
-#define __VERSIONER_NO_GUARD
-#define __VERSIONER_FORTIFY_INLINE
-
-#endif  // defined(__BIONIC_VERSIONER)
-
 // Vendor modules do not follow SDK versioning. Ignore NDK guards for vendor modules.
 #if defined(__ANDROID_VENDOR__)
 #undef __BIONIC_AVAILABILITY
diff --git a/libc/include/bits/getentropy.h b/libc/include/bits/getentropy.h
index 4cd44f7..98d8879 100644
--- a/libc/include/bits/getentropy.h
+++ b/libc/include/bits/getentropy.h
@@ -48,6 +48,6 @@
  *
  * See also arc4random_buf() which is available in all API levels.
  */
-int getentropy(void* _Nonnull __buffer, size_t __buffer_size) __wur __INTRODUCED_IN(28);
+__nodiscard int getentropy(void* _Nonnull __buffer, size_t __buffer_size) __INTRODUCED_IN(28);
 
 __END_DECLS
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 5904519..2fa4b49 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -55,7 +55,7 @@
  * other processes. Obviously this is not the case for apps, which will
  * be killed in preference to killing other processes.
  */
-void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
+__nodiscard void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1);
 
 /**
  * [calloc(3)](https://man7.org/linux/man-pages/man3/calloc.3.html) allocates
@@ -64,7 +64,7 @@
  * Returns a pointer to the allocated memory on success and returns a null
  * pointer and sets `errno` on failure (but see the notes for malloc()).
  */
-void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
+__nodiscard void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2);
 
 /**
  * [realloc(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
@@ -74,11 +74,8 @@
  * memory on success and returns a null pointer and sets `errno` on failure
  * (but see the notes for malloc()).
  */
-void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
+__nodiscard void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2);
 
-// Remove the explicit guard once //external/giflib has been fixed so that it no
-// longer provides a conflicting definition: http://b/352784252
-#if __ANDROID_API__ >= 29
 /**
  * [reallocarray(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
  * allocated memory on the heap.
@@ -90,7 +87,18 @@
  * memory on success and returns a null pointer and sets `errno` on failure
  * (but see the notes for malloc()).
  */
-void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
+#if __ANDROID_API__ >= 29
+__nodiscard void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __INTRODUCED_IN(29);
+#else
+#include <errno.h>
+static __inline __nodiscard void* _Nullable reallocarray(void* _Nullable __ptr, 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 NULL;
+  }
+  return realloc(__ptr, __new_size);
+}
 #endif
 
 /**
@@ -108,13 +116,13 @@
  *
  * See also posix_memalign().
  */
-void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
+__nodiscard void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2);
 
 /**
  * [malloc_usable_size(3)](https://man7.org/linux/man-pages/man3/malloc_usable_size.3.html)
  * returns the actual size of the given heap block.
  */
-size_t malloc_usable_size(const void* _Nullable __ptr) __wur;
+__nodiscard size_t malloc_usable_size(const void* _Nullable __ptr);
 
 #define __MALLINFO_BODY \
   /** Total number of non-mmapped bytes currently allocated from OS. */ \
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 33c637f..d718b40 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -142,7 +142,7 @@
                                         const struct timespec* _Nullable __timeout) __INTRODUCED_IN_64(28);
 int pthread_cond_wait(pthread_cond_t* _Nonnull __cond, pthread_mutex_t* _Nonnull __mutex);
 
-int pthread_create(pthread_t* _Nonnull __pthread_ptr, pthread_attr_t const* _Nullable __attr, void* _Nonnull (* _Nonnull __start_routine)(void* _Nonnull), void* _Nullable);
+int pthread_create(pthread_t* _Nonnull __pthread_ptr, pthread_attr_t const* _Nullable __attr, void* _Nullable (* _Nonnull __start_routine)(void* _Nullable), void* _Nullable);
 
 int pthread_detach(pthread_t __pthread);
 void pthread_exit(void* _Nullable __return_value) __noreturn;
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index d99d032..d24f6af 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -105,10 +105,10 @@
 
 void clearerr(FILE* _Nonnull __fp);
 int fclose(FILE* _Nonnull __fp);
-__wur int feof(FILE* _Nonnull __fp);
-__wur int ferror(FILE* _Nonnull __fp);
+__nodiscard int feof(FILE* _Nonnull __fp);
+__nodiscard int ferror(FILE* _Nonnull __fp);
 int fflush(FILE* _Nullable __fp);
-__wur int fgetc(FILE* _Nonnull __fp);
+__nodiscard int fgetc(FILE* _Nonnull __fp);
 char* _Nullable fgets(char* _Nonnull __buf, int __size, FILE* _Nonnull __fp);
 int fprintf(FILE* _Nonnull __fp , const char* _Nonnull __fmt, ...) __printflike(2, 3);
 int fputc(int __ch, FILE* _Nonnull __fp);
@@ -116,8 +116,8 @@
 size_t fread(void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp);
 int fscanf(FILE* _Nonnull __fp, const char* _Nonnull __fmt, ...) __scanflike(2, 3);
 size_t fwrite(const void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp);
-__wur int getc(FILE* _Nonnull __fp);
-__wur int getchar(void);
+__nodiscard int getc(FILE* _Nonnull __fp);
+__nodiscard int getchar(void);
 ssize_t getdelim(char* _Nullable * _Nonnull __line_ptr, size_t* _Nonnull __line_length_ptr, int __delimiter, FILE* _Nonnull __fp);
 ssize_t getline(char* _Nullable * _Nonnull __line_ptr, size_t* _Nonnull __line_length_ptr, FILE* _Nonnull __fp);
 
@@ -201,17 +201,17 @@
 #endif
 
 int fseek(FILE* _Nonnull __fp, long __offset, int __whence);
-__wur long ftell(FILE* _Nonnull __fp);
+__nodiscard long ftell(FILE* _Nonnull __fp);
 
 /* See https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md */
 #if defined(__USE_FILE_OFFSET64)
 int fgetpos(FILE* _Nonnull __fp, fpos_t* _Nonnull __pos) __RENAME(fgetpos64) __INTRODUCED_IN(24);
 int fsetpos(FILE* _Nonnull __fp, const fpos_t* _Nonnull __pos) __RENAME(fsetpos64) __INTRODUCED_IN(24);
 int fseeko(FILE* _Nonnull __fp, off_t __offset, int __whence) __RENAME(fseeko64) __INTRODUCED_IN(24);
-__wur off_t ftello(FILE* _Nonnull __fp) __RENAME(ftello64) __INTRODUCED_IN(24);
+__nodiscard off_t ftello(FILE* _Nonnull __fp) __RENAME(ftello64) __INTRODUCED_IN(24);
 #  if defined(__USE_BSD)
 /* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen(const void* _Nullable __cookie,
+__nodiscard FILE* _Nullable funopen(const void* _Nullable __cookie,
               int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
               int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
               fpos_t (* _Nullable __seek_fn)(void* _Nonnull, fpos_t, int),
@@ -221,10 +221,10 @@
 int fgetpos(FILE* _Nonnull __fp, fpos_t* _Nonnull __pos);
 int fsetpos(FILE* _Nonnull __fp, const fpos_t* _Nonnull __pos);
 int fseeko(FILE* _Nonnull __fp, off_t __offset, int __whence);
-__wur off_t ftello(FILE* _Nonnull __fp);
+__nodiscard off_t ftello(FILE* _Nonnull __fp);
 #  if defined(__USE_BSD)
 /* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen(const void* _Nullable __cookie,
+__nodiscard FILE* _Nullable funopen(const void* _Nullable __cookie,
               int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
               int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
               fpos_t (* _Nullable __seek_fn)(void* _Nonnull, fpos_t, int),
@@ -234,22 +234,22 @@
 int fgetpos64(FILE* _Nonnull __fp, fpos64_t* _Nonnull __pos) __INTRODUCED_IN(24);
 int fsetpos64(FILE* _Nonnull __fp, const fpos64_t* _Nonnull __pos) __INTRODUCED_IN(24);
 int fseeko64(FILE* _Nonnull __fp, off64_t __offset, int __whence) __INTRODUCED_IN(24);
-__wur off64_t ftello64(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+__nodiscard off64_t ftello64(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
 #if defined(__USE_BSD)
 /* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen64(const void* _Nullable __cookie,
+__nodiscard FILE* _Nullable funopen64(const void* _Nullable __cookie,
                 int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
                 int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
                 fpos64_t (* _Nullable __seek_fn)(void* _Nonnull, fpos64_t, int),
                 int (* _Nullable __close_fn)(void* _Nonnull)) __INTRODUCED_IN(24);
 #endif
 
-__wur FILE* _Nullable fopen(const char* _Nonnull __path, const char* _Nonnull __mode);
-__wur FILE* _Nullable fopen64(const char* _Nonnull __path, const char* _Nonnull __mode) __INTRODUCED_IN(24);
+__nodiscard FILE* _Nullable fopen(const char* _Nonnull __path, const char* _Nonnull __mode);
+__nodiscard FILE* _Nullable fopen64(const char* _Nonnull __path, const char* _Nonnull __mode) __INTRODUCED_IN(24);
 FILE* _Nullable freopen(const char* _Nullable __path, const char* _Nonnull __mode, FILE* _Nonnull __fp);
 FILE* _Nullable freopen64(const char* _Nullable __path, const char* _Nonnull __mode, FILE* _Nonnull __fp) __INTRODUCED_IN(24);
-__wur FILE* _Nullable tmpfile(void);
-__wur FILE* _Nullable tmpfile64(void) __INTRODUCED_IN(24);
+__nodiscard FILE* _Nullable tmpfile(void);
+__nodiscard FILE* _Nullable tmpfile64(void) __INTRODUCED_IN(24);
 
 int snprintf(char* __BIONIC_COMPLICATED_NULLNESS __buf, size_t __size, const char* _Nonnull __fmt, ...) __printflike(3, 4);
 int vfscanf(FILE* _Nonnull __fp, const char* _Nonnull __fmt, va_list __args) __scanflike(2, 0);
@@ -260,20 +260,20 @@
 #define L_ctermid 1024 /* size for ctermid() */
 char* _Nonnull ctermid(char* _Nullable __buf) __INTRODUCED_IN(26);
 
-__wur FILE* _Nullable fdopen(int __fd, const char* _Nonnull __mode);
-__wur int fileno(FILE* _Nonnull __fp);
+__nodiscard FILE* _Nullable fdopen(int __fd, const char* _Nonnull __mode);
+__nodiscard int fileno(FILE* _Nonnull __fp);
 int pclose(FILE* _Nonnull __fp);
-__wur FILE* _Nullable popen(const char* _Nonnull __command, const char* _Nonnull __mode);
+__nodiscard FILE* _Nullable popen(const char* _Nonnull __command, const char* _Nonnull __mode);
 void flockfile(FILE* _Nonnull  __fp);
 int ftrylockfile(FILE* _Nonnull __fp);
 void funlockfile(FILE* _Nonnull __fp);
-__wur int getc_unlocked(FILE* _Nonnull __fp);
-__wur int getchar_unlocked(void);
+__nodiscard int getc_unlocked(FILE* _Nonnull __fp);
+__nodiscard int getchar_unlocked(void);
 int putc_unlocked(int __ch, FILE* _Nonnull __fp);
 int putchar_unlocked(int __ch);
 
-__wur FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
-__wur FILE* _Nullable open_memstream(char* _Nonnull * _Nonnull __ptr, size_t* _Nonnull __size_ptr) __INTRODUCED_IN(23);
+__nodiscard FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
+__nodiscard FILE* _Nullable open_memstream(char* _Nonnull * _Nonnull __ptr, size_t* _Nonnull __size_ptr) __INTRODUCED_IN(23);
 
 #if defined(__USE_BSD) || defined(__BIONIC__) /* Historically bionic exposed these. */
 int  asprintf(char* _Nullable * _Nonnull __s_ptr, const char* _Nonnull __fmt, ...) __printflike(2, 3);
@@ -283,16 +283,16 @@
 int setlinebuf(FILE* _Nonnull __fp);
 int vasprintf(char* _Nullable * _Nonnull __s_ptr, const char* _Nonnull __fmt, va_list __args) __printflike(2, 0);
 void clearerr_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int feof_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int ferror_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int fileno_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+__nodiscard int feof_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+__nodiscard int ferror_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+__nodiscard int fileno_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
 #define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0)
 #define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0)
 #endif
 
 #if defined(__USE_BSD)
 int fflush_unlocked(FILE* _Nullable __fp) __INTRODUCED_IN(28);
-__wur int fgetc_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+__nodiscard int fgetc_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
 int fputc_unlocked(int __ch, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
 size_t fread_unlocked(void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
 size_t fwrite_unlocked(const void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index b31b122..076a978 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -79,9 +79,9 @@
  *
  * Available since API level 28.
  */
-__wur void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
+__nodiscard void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
 
-__wur char* _Nullable realpath(const char* _Nonnull __path, char* _Nullable __resolved);
+__nodiscard char* _Nullable realpath(const char* _Nonnull __path, char* _Nullable __resolved);
 
 /**
  * [system(3)](https://man7.org/linux/man-pages/man3/system.3.html) executes
@@ -107,7 +107,7 @@
  * Returns a pointer to a matching item on success,
  * or NULL if no matching item is found.
  */
-__wur void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
+__nodiscard void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
 
 /**
  * [qsort(3)](https://man7.org/linux/man-pages/man3/qsort.3.html) sorts an array
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 5d1718e..9bd35bb 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -140,7 +140,8 @@
 #define	__predict_true(exp)	__builtin_expect((exp) != 0, 1)
 #define	__predict_false(exp)	__builtin_expect((exp) != 0, 0)
 
-#define __wur __attribute__((__warn_unused_result__))
+#define __nodiscard __attribute__((__warn_unused_result__))
+#define __wur __nodiscard
 
 #define __errorattr(msg) __attribute__((__unavailable__(msg)))
 #define __warnattr(msg) __attribute__((__deprecated__(msg)))
@@ -264,7 +265,7 @@
  * having stack protectors detracts from that (b/182948263).
  */
 #  define __BIONIC_FORTIFY_INLINE static __inline __attribute__((__no_stack_protector__)) \
-      __always_inline __VERSIONER_FORTIFY_INLINE
+      __always_inline
 /*
  * We should use __BIONIC_FORTIFY_VARIADIC instead of __BIONIC_FORTIFY_INLINE
  * for variadic functions because compilers cannot inline them.
diff --git a/libc/include/sys/random.h b/libc/include/sys/random.h
index fcea419..b4a9993 100644
--- a/libc/include/sys/random.h
+++ b/libc/include/sys/random.h
@@ -52,6 +52,6 @@
  *
  * See also arc4random_buf() which is available in all API levels.
  */
-ssize_t getrandom(void* _Nonnull __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN(28);
+__nodiscard ssize_t getrandom(void* _Nonnull __buffer, size_t __buffer_size, unsigned int __flags) __INTRODUCED_IN(28);
 
 __END_DECLS
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index bb188fe..2633b69 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -331,7 +331,7 @@
  *
  * Available since API level 30.
  */
-int statx(int __dir_fd, const char* _Nonnull __path, int __flags, unsigned __mask, struct statx* _Nonnull __buf) __INTRODUCED_IN(30);
+int statx(int __dir_fd, const char* _Nullable __path, int __flags, unsigned __mask, struct statx* _Nonnull __buf) __INTRODUCED_IN(30);
 #endif
 
 __END_DECLS
diff --git a/libc/include/threads.h b/libc/include/threads.h
index b1008de..1074fa4 100644
--- a/libc/include/threads.h
+++ b/libc/include/threads.h
@@ -72,8 +72,10 @@
   thrd_timedout = 4,
 };
 
-#if !defined(__cplusplus)
-#define thread_local _Thread_local
+/* `thread_local` is a keyword in C++11 and C23; C11 had `_Thread_local` instead. */
+#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L)
+# undef thread_local
+# define thread_local _Thread_local
 #endif
 
 __BEGIN_DECLS
diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h
index ee28d69..e1f655a 100644
--- a/libc/private/KernelArgumentBlock.h
+++ b/libc/private/KernelArgumentBlock.h
@@ -29,7 +29,7 @@
 // constituents for easy access.
 class KernelArgumentBlock {
  public:
-  explicit KernelArgumentBlock(void* raw_args) {
+  __attribute__((no_sanitize("hwaddress"))) explicit KernelArgumentBlock(void* raw_args) {
     uintptr_t* args = reinterpret_cast<uintptr_t*>(raw_args);
     argc = static_cast<int>(*args);
     argv = reinterpret_cast<char**>(args + 1);
@@ -48,7 +48,7 @@
 
   // Similar to ::getauxval but doesn't require the libc global variables to be set up,
   // so it's safe to call this really early on.
-  unsigned long getauxval(unsigned long type) {
+  __attribute__((no_sanitize("hwaddress"))) unsigned long getauxval(unsigned long type) {
     for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) {
       if (v->a_type == type) {
         return v->a_un.a_val;
diff --git a/libc/private/bionic_mbstate.h b/libc/private/bionic_mbstate.h
index 0e5f861..fb85775 100644
--- a/libc/private/bionic_mbstate.h
+++ b/libc/private/bionic_mbstate.h
@@ -38,11 +38,11 @@
   (rv == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE || \
    rv == BIONIC_MULTIBYTE_RESULT_INCOMPLETE_SEQUENCE)
 
-static inline __wur bool mbstate_is_initial(const mbstate_t* ps) {
+static inline __nodiscard bool mbstate_is_initial(const mbstate_t* ps) {
   return *(reinterpret_cast<const uint32_t*>(ps->__seq)) == 0;
 }
 
-static inline __wur size_t mbstate_bytes_so_far(const mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_bytes_so_far(const mbstate_t* ps) {
   return
       (ps->__seq[2] != 0) ? 3 :
       (ps->__seq[1] != 0) ? 2 :
@@ -53,7 +53,7 @@
   ps->__seq[i] = static_cast<uint8_t>(byte);
 }
 
-static inline __wur uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
+static inline __nodiscard uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
   return ps->__seq[n];
 }
 
@@ -61,13 +61,13 @@
   *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
 }
 
-static inline __wur size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
   errno = _errno;
   mbstate_reset(ps);
   return BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE;
 }
 
-static inline __wur size_t mbstate_reset_and_return(size_t _return, mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_reset_and_return(size_t _return, mbstate_t* ps) {
   mbstate_reset(ps);
   return _return;
 }
diff --git a/libc/versioner-dependencies/arm/kernel_uapi_asm-arm b/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
deleted file mode 120000
index 3c7584d..0000000
--- a/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-arm
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64 b/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
deleted file mode 120000
index 7ee6fd2..0000000
--- a/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-arm64
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/clang-builtins b/libc/versioner-dependencies/common/clang-builtins
deleted file mode 120000
index 148dd2b..0000000
--- a/libc/versioner-dependencies/common/clang-builtins
+++ /dev/null
@@ -1 +0,0 @@
-../../../../prebuilts/clang-tools/linux-x86/clang-headers
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_android_uapi b/libc/versioner-dependencies/common/kernel_android_uapi
deleted file mode 120000
index fd78315..0000000
--- a/libc/versioner-dependencies/common/kernel_android_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/android/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_uapi b/libc/versioner-dependencies/common/kernel_uapi
deleted file mode 120000
index d5cb8ee..0000000
--- a/libc/versioner-dependencies/common/kernel_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64 b/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64
deleted file mode 120000
index 61353cb..0000000
--- a/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-riscv/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
deleted file mode 120000
index 1b7a73d..0000000
--- a/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
deleted file mode 120000
index 1b7a73d..0000000
--- a/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 1bbd902..87db4b1 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -123,7 +123,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 }
@@ -170,7 +169,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 }
diff --git a/libm/Android.bp b/libm/Android.bp
index 9fd79f8..ee86959 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -435,7 +435,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 4365ea5..bcc2500 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -316,7 +316,7 @@
     async_safe_fatal("library name \"%s\" too long", name);
   }
 
-  TRACE("name %s: allocating soinfo for ns=%p", name, ns);
+  LD_DEBUG(any, "name %s: allocating soinfo for ns=%p", name, ns);
 
   soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(ns, name, file_stat,
                                                        file_offset, rtld_flags);
@@ -326,7 +326,7 @@
   si->generate_handle();
   ns->add_soinfo(si);
 
-  TRACE("name %s: allocated soinfo @ %p", name, si);
+  LD_DEBUG(any, "name %s: allocated soinfo @ %p", name, si);
   return si;
 }
 
@@ -349,7 +349,7 @@
     munmap(reinterpret_cast<void*>(si->get_gap_start()), si->get_gap_size());
   }
 
-  TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
+  LD_DEBUG(any, "name %s: freeing soinfo @ %p", si->get_realpath(), si);
 
   if (!solist_remove_soinfo(si)) {
     async_safe_fatal("soinfo=%p is not in soinfo_list (double unload?)", si);
@@ -387,7 +387,7 @@
   auto length = readlink(proc_self_fd, buf, sizeof(buf));
   if (length == -1) {
     if (!is_first_stage_init()) {
-      PRINT("readlink(\"%s\" [fd=%d]) failed: %m", proc_self_fd, fd);
+      DL_WARN("readlink(\"%s\" [fd=%d]) failed: %m", proc_self_fd, fd);
     }
     return false;
   }
@@ -818,8 +818,8 @@
   }
 
   if (s != nullptr) {
-    TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p",
-               name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
+    LD_DEBUG(lookup, "%s s->st_value = %p, found->base = %p",
+             name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
   }
 
   return s;
@@ -923,7 +923,7 @@
   }
 
   const char* const path = normalized_path.c_str();
-  TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+  LD_DEBUG(any, "Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
 
   // Treat an '!/' separator inside a path as the separator between the name
   // of the zip file on disk and the subdirectory to search within it.
@@ -936,7 +936,7 @@
 
   char buf[512];
   if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
-    PRINT("Warning: ignoring very long library path: %s", path);
+    DL_WARN("ignoring very long library path: %s", path);
     return -1;
   }
 
@@ -976,8 +976,8 @@
     *realpath += separator;
   } else {
     if (!is_first_stage_init()) {
-      PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
-            normalized_path.c_str());
+      DL_WARN("unable to get realpath for the library \"%s\". Will use given path.",
+              normalized_path.c_str());
     }
     *realpath = normalized_path;
   }
@@ -988,7 +988,7 @@
 static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) {
   int n = async_safe_format_buffer(buf, buf_size, "%s/%s", path, name);
   if (n < 0 || n >= static_cast<int>(buf_size)) {
-    PRINT("Warning: ignoring very long library path: %s/%s", path, name);
+    DL_WARN("ignoring very long library path: %s/%s", path, name);
     return false;
   }
 
@@ -1009,8 +1009,7 @@
       *file_offset = 0;
       if (!realpath_fd(fd, realpath)) {
         if (!is_first_stage_init()) {
-          PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
-                path);
+          DL_WARN("unable to get realpath for the library \"%s\". Will use given path.", path);
         }
         *realpath = path;
       }
@@ -1043,7 +1042,7 @@
                         ZipArchiveCache* zip_archive_cache,
                         const char* name, soinfo *needed_by,
                         off64_t* file_offset, std::string* realpath) {
-  TRACE("[ opening %s from namespace %s ]", name, ns->get_name());
+  LD_DEBUG(any, "[ 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) {
@@ -1249,15 +1248,15 @@
 
       // do not print this if a library is in the list of shared libraries for linked namespaces
       if (!maybe_accessible_via_namespace_links(ns, name)) {
-        PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
-              " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
-              " permitted_paths=\"%s\"]",
-              name, realpath.c_str(),
-              needed_or_dlopened_by,
-              ns->get_name(),
-              android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
-              android::base::Join(ns->get_default_library_paths(), ':').c_str(),
-              android::base::Join(ns->get_permitted_paths(), ':').c_str());
+        DL_WARN("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
+                " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
+                " permitted_paths=\"%s\"]",
+                name, realpath.c_str(),
+                needed_or_dlopened_by,
+                ns->get_name(),
+                android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
+                android::base::Join(ns->get_default_library_paths(), ':').c_str(),
+                android::base::Join(ns->get_permitted_paths(), ':').c_str());
       }
       return false;
     }
@@ -1330,10 +1329,9 @@
     std::string realpath;
     if (!realpath_fd(extinfo->library_fd, &realpath)) {
       if (!is_first_stage_init()) {
-        PRINT(
-            "warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
-            "Will use given name.",
-            name);
+        DL_WARN("unable to get realpath for the library \"%s\" by extinfo->library_fd. "
+                "Will use given name.",
+                name);
       }
       realpath = name;
     }
@@ -1474,8 +1472,8 @@
 
   // 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);
+  LD_DEBUG(any, "[ \"%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,
                    true /* search_linked_namespaces */)) {
@@ -1906,8 +1904,8 @@
     if (si->has_min_version(0)) {
       soinfo* child = nullptr;
       while ((child = si->get_children().pop_front()) != nullptr) {
-        TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si,
-            child->get_realpath(), child);
+        LD_DEBUG(any, "%s@%p needs to unload %s@%p", si->get_realpath(), si,
+                 child->get_realpath(), child);
 
         child->get_parents().remove(si);
 
@@ -2197,10 +2195,10 @@
       if (file_exists(translated_name_holder.c_str())) {
         soinfo* si = nullptr;
         if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
-          PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
-                translated_name_holder.c_str());
+          DL_WARN("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
+                  translated_name_holder.c_str());
         } else {
-          PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+          DL_WARN("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
           translated_name = translated_name_holder.c_str();
         }
       }
@@ -2217,10 +2215,10 @@
       if (!translated_name_holder.empty() && file_exists(translated_name_holder.c_str())) {
         soinfo* si = nullptr;
         if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
-          PRINT("linker_hwasan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
-                translated_name_holder.c_str());
+          DL_WARN("linker_hwasan dlopen NOT translating \"%s\" -> \"%s\": library already loaded",
+                  name, translated_name_holder.c_str());
         } else {
-          PRINT("linker_hwasan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+          DL_WARN("linker_hwasan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
           translated_name = translated_name_holder.c_str();
         }
       }
@@ -2589,8 +2587,8 @@
   if (g_is_ldd) return 0;
 
   ElfW(Addr) ifunc_addr = __bionic_call_ifunc_resolver(resolver_addr);
-  TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p",
-      reinterpret_cast<void *>(resolver_addr), reinterpret_cast<void*>(ifunc_addr));
+  LD_DEBUG(calls, "ifunc_resolver@%p returned %p",
+           reinterpret_cast<void *>(resolver_addr), reinterpret_cast<void*>(ifunc_addr));
 
   return ifunc_addr;
 }
@@ -2842,8 +2840,8 @@
   /* We can't log anything until the linker is relocated */
   bool relocating_linker = (flags_ & FLAG_LINKER) != 0;
   if (!relocating_linker) {
-    INFO("[ Linking \"%s\" ]", get_realpath());
-    DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
+    LD_DEBUG(any, "[ Linking \"%s\" ]", get_realpath());
+    LD_DEBUG(any, "si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
   }
 
   if (dynamic == nullptr) {
@@ -2853,7 +2851,7 @@
     return false;
   } else {
     if (!relocating_linker) {
-      DEBUG("dynamic = %p", dynamic);
+      LD_DEBUG(dynamic, "dynamic section @%p", dynamic);
     }
   }
 
@@ -2883,8 +2881,8 @@
   // source: http://www.sco.com/developers/gabi/1998-04-29/ch5.dynamic.html
   uint32_t needed_count = 0;
   for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
-    DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",
-          d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+    LD_DEBUG(dynamic, "dynamic entry @%p: d_tag=%p, d_val=%p",
+             d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
     switch (d->d_tag) {
       case DT_SONAME:
         // this is parsed after we have strtab initialized (see below).
@@ -3098,17 +3096,17 @@
 
       case DT_INIT:
         init_func_ = reinterpret_cast<linker_ctor_function_t>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
+        LD_DEBUG(dynamic, "%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
         break;
 
       case DT_FINI:
         fini_func_ = reinterpret_cast<linker_dtor_function_t>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
+        LD_DEBUG(dynamic, "%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
         break;
 
       case DT_INIT_ARRAY:
         init_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
+        LD_DEBUG(dynamic, "%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
         break;
 
       case DT_INIT_ARRAYSZ:
@@ -3117,7 +3115,7 @@
 
       case DT_FINI_ARRAY:
         fini_array_ = reinterpret_cast<linker_dtor_function_t*>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
+        LD_DEBUG(dynamic, "%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
         break;
 
       case DT_FINI_ARRAYSZ:
@@ -3126,7 +3124,7 @@
 
       case DT_PREINIT_ARRAY:
         preinit_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
+        LD_DEBUG(dynamic, "%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
         break;
 
       case DT_PREINIT_ARRAYSZ:
@@ -3266,8 +3264,8 @@
     }
   }
 
-  DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
-        reinterpret_cast<void*>(base), strtab_, symtab_);
+  LD_DEBUG(dynamic, "si->base = %p, si->strtab = %p, si->symtab = %p",
+           reinterpret_cast<void*>(base), strtab_, symtab_);
 
   // Validity checks.
   if (relocating_linker && needed_count != 0) {
@@ -3374,7 +3372,7 @@
     return false;
   }
 
-  DEBUG("[ finished linking %s ]", get_realpath());
+  LD_DEBUG(any, "[ finished linking %s ]", get_realpath());
 
 #if !defined(__LP64__)
   if (has_text_relocations) {
@@ -3556,7 +3554,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());
+    LD_DEBUG(any, "[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
     ScopedTrace trace(("linker config " + ld_config_file_path).c_str());
     std::string error_msg;
     if (!Config::read_binary_config(ld_config_file_path.c_str(), executable_path, g_is_asan, g_is_hwasan,
diff --git a/linker/linker_auxv.cpp b/linker/linker_auxv.cpp
index 95413a0..23025f7 100644
--- a/linker/linker_auxv.cpp
+++ b/linker/linker_auxv.cpp
@@ -61,10 +61,14 @@
   case AT_HWCAP2: return "AT_HWCAP2";
   case AT_RSEQ_FEATURE_SIZE: return "AT_RSEQ_FEATURE_SIZE";
   case AT_RSEQ_ALIGN: return "AT_RSEQ_ALIGN";
+  case AT_HWCAP3: return "AT_HWCAP3";
+  case AT_HWCAP4: return "AT_HWCAP4";
   case AT_EXECFN: return "AT_EXECFN";
   case AT_SYSINFO_EHDR: return "AT_SYSINFO_EHDR";
-#if defined(AT_MINSIGSTKSZ)
   case AT_MINSIGSTKSZ: return "AT_MINSIGSTKSZ";
+#if defined(AT_VECTOR_SIZE_ARCH)
+  // AT_VECTOR_SIZE_ARCH isn't a value: it's the number of architecture-specific
+  // values that exist for the current architecture, so not relevant here.
 #endif
 #if defined(AT_SYSINFO)
   case AT_SYSINFO: return "AT_SYSINFO";
@@ -114,6 +118,8 @@
     case AT_FLAGS:
     case AT_HWCAP:
     case AT_HWCAP2:
+    case AT_HWCAP3:
+    case AT_HWCAP4:
       async_safe_format_fd(STDOUT_FILENO, "%-20s %#lb\n", name, value);
       break;
     case AT_EXECFN:
diff --git a/linker/linker_cfi.cpp b/linker/linker_cfi.cpp
index 247a25d..92ec53e 100644
--- a/linker/linker_cfi.cpp
+++ b/linker/linker_cfi.cpp
@@ -166,13 +166,13 @@
   }
   uintptr_t cfi_check = soinfo_find_cfi_check(si);
   if (cfi_check == 0) {
-    INFO("[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
+    LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
          static_cast<uintptr_t>(si->size), si->get_soname());
     AddUnchecked(si->base, si->base + si->size);
     return true;
   }
 
-  INFO("[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
+  LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
        static_cast<uintptr_t>(si->size), si->get_soname(), cfi_check);
 #ifdef __arm__
   // Require Thumb encoding.
@@ -263,8 +263,8 @@
 void CFIShadowWriter::BeforeUnload(soinfo* si) {
   if (shadow_start == nullptr) return;
   if (si->base == 0 || si->size == 0) return;
-  INFO("[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
-       static_cast<uintptr_t>(si->size), si->get_soname());
+  LD_DEBUG(cfi, "[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
+           static_cast<uintptr_t>(si->size), si->get_soname());
   AddInvalid(si->base, si->base + si->size);
   FixupVmaName();
 }
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index 73ae2ef..35a93fc 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -251,10 +251,8 @@
         // the failure with INFO rather than DL_WARN. e.g. A binary in
         // /data/local/tmp may attempt to stat /postinstall. See
         // http://b/120996057.
-        INFO("%s:%zd: warning: path \"%s\" couldn't be resolved: %m",
-             ld_config_file_path,
-             cp.lineno(),
-             value.c_str());
+        LD_DEBUG(any, "%s:%zd: warning: path \"%s\" couldn't be resolved: %m",
+                 ld_config_file_path, cp.lineno(), value.c_str());
         resolved_path = value;
       }
 
@@ -265,7 +263,7 @@
     }
   }
 
-  INFO("[ Using config section \"%s\" ]", section_name.c_str());
+  LD_DEBUG(any, "[ Using config section \"%s\" ]", section_name.c_str());
 
   // skip everything until we meet a correct section
   while (true) {
diff --git a/linker/linker_debug.cpp b/linker/linker_debug.cpp
index e6211f7..430a151 100644
--- a/linker/linker_debug.cpp
+++ b/linker/linker_debug.cpp
@@ -30,19 +30,76 @@
 
 #include <unistd.h>
 
-void linker_log_va_list(int prio, const char* fmt, va_list ap) {
+#include <android-base/strings.h>
+
+LinkerDebugConfig g_linker_debug_config;
+
+void init_LD_DEBUG(const std::string& value) {
+  if (value.empty()) return;
+  std::vector<std::string> options = android::base::Split(value, ",");
+  for (const auto& o : options) {
+    if (o == "calls") g_linker_debug_config.calls = true;
+    else if (o == "cfi") g_linker_debug_config.cfi = true;
+    else if (o == "dynamic") g_linker_debug_config.dynamic = true;
+    else if (o == "lookup") g_linker_debug_config.lookup = true;
+    else if (o == "props") g_linker_debug_config.props = true;
+    else if (o == "reloc") g_linker_debug_config.reloc = true;
+    else if (o == "statistics") g_linker_debug_config.statistics = true;
+    else if (o == "timing") g_linker_debug_config.timing = true;
+    else if (o == "all") {
+      g_linker_debug_config.calls = true;
+      g_linker_debug_config.cfi = true;
+      g_linker_debug_config.dynamic = true;
+      g_linker_debug_config.lookup = true;
+      g_linker_debug_config.props = true;
+      g_linker_debug_config.reloc = true;
+      g_linker_debug_config.statistics = true;
+      g_linker_debug_config.timing = true;
+    } else {
+      __linker_error("$LD_DEBUG is a comma-separated list of:\n"
+                     "\n"
+                     "  calls       ctors/dtors/ifuncs\n"
+                     "  cfi         control flow integrity messages\n"
+                     "  dynamic     dynamic section processing\n"
+                     "  lookup      symbol lookup\n"
+                     "  props       ELF property processing\n"
+                     "  reloc       relocation resolution\n"
+                     "  statistics  relocation statistics\n"
+                     "  timing      timing information\n"
+                     "\n"
+                     "or 'all' for all of the above.\n");
+    }
+  }
+  if (g_linker_debug_config.calls || g_linker_debug_config.cfi ||
+      g_linker_debug_config.dynamic || g_linker_debug_config.lookup ||
+      g_linker_debug_config.props || g_linker_debug_config.reloc ||
+      g_linker_debug_config.statistics || g_linker_debug_config.timing) {
+    g_linker_debug_config.any = true;
+  }
+}
+
+static void linker_log_va_list(int prio, const char* fmt, va_list ap) {
   va_list ap2;
   va_copy(ap2, ap);
-  async_safe_format_log_va_list(5 - prio, "linker", fmt, ap2);
+  async_safe_format_log_va_list(prio, "linker", fmt, ap2);
   va_end(ap2);
 
   async_safe_format_fd_va_list(STDERR_FILENO, fmt, ap);
   write(STDERR_FILENO, "\n", 1);
 }
 
-void linker_log(int prio, const char* fmt, ...) {
+void __linker_log(int prio, const char* fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   linker_log_va_list(prio, fmt, ap);
   va_end(ap);
 }
+
+void __linker_error(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  linker_log_va_list(ANDROID_LOG_FATAL, fmt, ap);
+  va_end(ap);
+
+  _exit(EXIT_FAILURE);
+}
diff --git a/linker/linker_debug.h b/linker/linker_debug.h
index 3aab185..e5f17c4 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -28,54 +28,45 @@
 
 #pragma once
 
-// You can increase the verbosity of debug traces by defining the LD_DEBUG
-// environment variable to a numeric value from 0 to 2 (corresponding to
-// INFO, TRACE, and DEBUG calls in the source). This will only
-// affect new processes being launched.
-
-#define TRACE_DEBUG          1
-#define DO_TRACE_LOOKUP      1
-#define DO_TRACE_RELO        1
-#define DO_TRACE_IFUNC       1
-#define TIMING               0
-#define STATS                0
-
-/*********************************************************************
- * You shouldn't need to modify anything below unless you are adding
- * more debugging information.
- *
- * To enable/disable specific debug options, change the defines above
- *********************************************************************/
-
 #include <stdarg.h>
 #include <unistd.h>
 
+#include <string>
+
 #include <async_safe/log.h>
 #include <async_safe/CHECK.h>
 
-#define LINKER_VERBOSITY_PRINT (-1)
-#define LINKER_VERBOSITY_INFO   0
-#define LINKER_VERBOSITY_TRACE  1
-#define LINKER_VERBOSITY_DEBUG  2
+struct LinkerDebugConfig {
+  // Set automatically if any of the more specific options are set.
+  bool any;
 
-__LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
+  // Messages relating to calling ctors/dtors/ifuncs.
+  bool calls;
+  // Messages relating to CFI.
+  bool cfi;
+  // Messages relating to the dynamic section.
+  bool dynamic;
+  // Messages relating to symbol lookup.
+  bool lookup;
+  // Messages relating to relocation processing.
+  bool reloc;
+  // Messages relating to ELF properties.
+  bool props;
+  // TODO: "config" and "zip" seem likely to want to be separate?
 
-__LIBC_HIDDEN__ void linker_log_va_list(int prio, const char* fmt, va_list ap);
-__LIBC_HIDDEN__ void linker_log(int prio, const char* fmt, ...) __printflike(2, 3);
+  bool timing;
+  bool statistics;
+};
 
-#define _PRINTVF(v, x...) \
-    do { \
-      if (g_ld_debug_verbosity > (v)) linker_log((v), x); \
-    } while (0)
+extern LinkerDebugConfig g_linker_debug_config;
 
-#define PRINT(x...)          _PRINTVF(LINKER_VERBOSITY_PRINT, x)
-#define INFO(x...)           _PRINTVF(LINKER_VERBOSITY_INFO, x)
-#define TRACE(x...)          _PRINTVF(LINKER_VERBOSITY_TRACE, x)
+__LIBC_HIDDEN__ void init_LD_DEBUG(const std::string& value);
+__LIBC_HIDDEN__ void __linker_log(int prio, const char* fmt, ...) __printflike(2, 3);
+__LIBC_HIDDEN__ void __linker_error(const char* fmt, ...) __printflike(1, 2);
 
-#if TRACE_DEBUG
-#define DEBUG(x...)          _PRINTVF(LINKER_VERBOSITY_DEBUG, "DEBUG: " x)
-#else /* !TRACE_DEBUG */
-#define DEBUG(x...)          do {} while (0)
-#endif /* TRACE_DEBUG */
-
-#define TRACE_TYPE(t, x...)   do { if (DO_TRACE_##t) { TRACE(x); } } while (0)
+#define LD_DEBUG(what, x...) \
+  do { \
+    if (g_linker_debug_config.what) { \
+      __linker_log(ANDROID_LOG_INFO, x); \
+    } \
+  } while (false)
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 0cb7ca9..2bfdccd 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -54,7 +54,7 @@
 #define DL_ERR_AND_LOG(fmt, x...) \
   do { \
     DL_ERR(fmt, ##x); \
-    PRINT(fmt, ##x); \
+    __linker_log(ANDROID_LOG_ERROR, fmt, ##x); \
   } while (false)
 
 #define DL_OPEN_ERR(fmt, x...) \
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 86b6509..6ccd75b 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -73,21 +73,6 @@
 void __libc_init_mte(const memtag_dynamic_entries_t* memtag_dynamic_entries, const void* phdr_start,
                      size_t phdr_count, uintptr_t load_bias, void* stack_top);
 
-__printflike(1, 2) static void __linker_error(const char* fmt, ...) {
-  va_list ap;
-
-  va_start(ap, fmt);
-  async_safe_format_fd_va_list(STDERR_FILENO, fmt, ap);
-  write(STDERR_FILENO, "\n", 1);
-  va_end(ap);
-
-  va_start(ap, fmt);
-  async_safe_format_log_va_list(ANDROID_LOG_FATAL, "linker", fmt, ap);
-  va_end(ap);
-
-  _exit(EXIT_FAILURE);
-}
-
 static void __linker_cannot_link(const char* argv0) {
   __linker_error("CANNOT LINK EXECUTABLE \"%s\": %s", argv0, linker_get_error_buffer());
 }
@@ -119,7 +104,7 @@
 
   if (trav == nullptr) {
     // si was not in solist
-    PRINT("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
+    DL_WARN("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
     return false;
   }
 
@@ -147,7 +132,6 @@
 }
 
 bool g_is_ldd;
-int g_ld_debug_verbosity;
 
 static std::vector<std::string> g_ld_preload_names;
 
@@ -296,10 +280,8 @@
 static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load) {
   ProtectedDataGuard guard;
 
-#if TIMING
-  struct timeval t0, t1;
-  gettimeofday(&t0, 0);
-#endif
+  timeval t0, t1;
+  gettimeofday(&t0, nullptr);
 
   // Sanitize the environment.
   __libc_init_AT_SECURE(args.envp);
@@ -317,13 +299,11 @@
 
   // Enable debugging logs?
   const char* LD_DEBUG = getenv("LD_DEBUG");
-  if (LD_DEBUG != nullptr) {
-    g_ld_debug_verbosity = atoi(LD_DEBUG);
-  }
+  if (LD_DEBUG != nullptr) init_LD_DEBUG(LD_DEBUG);
 
   if (getenv("LD_SHOW_AUXV") != nullptr) ld_show_auxv(args.auxv);
 
-  INFO("[ Android dynamic linker (" ABI_STRING ") ]");
+  LD_DEBUG(any, "[ Android dynamic linker (" ABI_STRING ") ]");
 
   // These should have been sanitized by __libc_init_AT_SECURE, but the test
   // doesn't cost us anything.
@@ -332,18 +312,18 @@
   if (!getauxval(AT_SECURE)) {
     ldpath_env = getenv("LD_LIBRARY_PATH");
     if (ldpath_env != nullptr) {
-      INFO("[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
+      LD_DEBUG(any, "[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
     }
     ldpreload_env = getenv("LD_PRELOAD");
     if (ldpreload_env != nullptr) {
-      INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
+      LD_DEBUG(any, "[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
     }
   }
 
   const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) :
                                                 get_executable_info(args.argv[0]);
 
-  INFO("[ Linking executable \"%s\" ]", exe_info.path.c_str());
+  LD_DEBUG(any, "[ Linking executable \"%s\" ]", exe_info.path.c_str());
 
   // Initialize the main exe's soinfo.
   soinfo* si = soinfo_alloc(&g_default_namespace,
@@ -496,27 +476,22 @@
   si->call_pre_init_constructors();
   si->call_constructors();
 
-#if TIMING
-  gettimeofday(&t1, nullptr);
-  PRINT("LINKER TIME: %s: %d microseconds", g_argv[0],
-        static_cast<int>(((static_cast<long long>(t1.tv_sec) * 1000000LL) +
-                          static_cast<long long>(t1.tv_usec)) -
-                         ((static_cast<long long>(t0.tv_sec) * 1000000LL) +
-                          static_cast<long long>(t0.tv_usec))));
-#endif
-#if STATS
-  print_linker_stats();
-#endif
-#if TIMING || STATS
-  fflush(stdout);
-#endif
+  if (g_linker_debug_config.timing) {
+    gettimeofday(&t1, nullptr);
+    long long t0_us = (t0.tv_sec * 1000000LL) + t0.tv_usec;
+    long long t1_us = (t1.tv_sec * 1000000LL) + t1.tv_usec;
+    LD_DEBUG(timing, "LINKER TIME: %s: %lld microseconds", g_argv[0], t1_us - t0_us);
+  }
+  if (g_linker_debug_config.statistics) {
+    print_linker_stats();
+  }
 
   // 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));
+  LD_DEBUG(any, "[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry));
   return entry;
 }
 
@@ -833,7 +808,7 @@
 
   ElfW(Addr) start_address = linker_main(args, exe_to_load);
 
-  INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
+  LD_DEBUG(any, "[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
 
   // Return the address that the calling assembly stub should jump to.
   return start_address;
diff --git a/linker/linker_note_gnu_property.cpp b/linker/linker_note_gnu_property.cpp
index be1aebc..082a604 100644
--- a/linker/linker_note_gnu_property.cpp
+++ b/linker/linker_note_gnu_property.cpp
@@ -62,7 +62,7 @@
         continue;
       }
 
-      TRACE("\"%s\" PT_GNU_PROPERTY: found at segment index %zu", name, i);
+      LD_DEBUG(props, "\"%s\" PT_GNU_PROPERTY: found at segment index %zu", name, i);
 
       // Check segment size.
       if (phdr[i].p_memsz < sizeof(ElfW(NhdrGNUProperty))) {
@@ -90,7 +90,7 @@
     }
   }
 
-  TRACE("\"%s\" PT_GNU_PROPERTY: not found", name);
+  LD_DEBUG(props, "\"%s\" PT_GNU_PROPERTY: not found", name);
   return nullptr;
 }
 
@@ -122,7 +122,7 @@
   // The total length of the program property array is in _bytes_.
   ElfW(Word) offset = 0;
   while (offset < note_nhdr->nhdr.n_descsz) {
-    DEBUG("\"%s\" .note.gnu.property: processing at offset 0x%x", name, offset);
+    LD_DEBUG(props, "\"%s\" .note.gnu.property: processing at offset 0x%x", name, offset);
 
     // At least the "header" part must fit.
     // The ABI doesn't say that pr_datasz can't be 0.
@@ -161,14 +161,14 @@
         const ElfW(Word) flags = *reinterpret_cast<const ElfW(Word)*>(&property->pr_data[0]);
         properties_.bti_compatible = (flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) != 0;
         if (properties_.bti_compatible) {
-          INFO("[ BTI compatible: \"%s\" ]", name);
+          LD_DEBUG(props, "[ BTI compatible: \"%s\" ]", name);
         }
         break;
       }
 #endif
       default:
-        DEBUG("\"%s\" .note.gnu.property: found property pr_type %u pr_datasz 0x%x", name,
-              property->pr_type, property->pr_datasz);
+        LD_DEBUG(props, "\"%s\" .note.gnu.property: found property pr_type %u pr_datasz 0x%x",
+                 name, property->pr_type, property->pr_datasz);
         break;
     }
 
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index e89acb5..48206be 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -851,6 +851,106 @@
   *p_filesz += extend;
 }
 
+bool ElfReader::MapSegment(size_t seg_idx, size_t len) {
+  const ElfW(Phdr)* phdr = &phdr_table_[seg_idx];
+
+  void* start = reinterpret_cast<void*>(page_start(phdr->p_vaddr + load_bias_));
+
+  // The ELF could be being loaded directly from a zipped APK,
+  // the zip offset must be added to find the segment offset.
+  const ElfW(Addr) offset = file_offset_ + page_start(phdr->p_offset);
+
+  int prot = PFLAGS_TO_PROT(phdr->p_flags);
+
+  void* seg_addr = mmap64(start, len, prot, MAP_FIXED | MAP_PRIVATE, fd_, offset);
+
+  if (seg_addr == MAP_FAILED) {
+    DL_ERR("couldn't map \"%s\" segment %zd: %m", name_.c_str(), seg_idx);
+    return false;
+  }
+
+  // Mark segments as huge page eligible if they meet the requirements
+  if ((phdr->p_flags & PF_X) && phdr->p_align == kPmdSize &&
+      get_transparent_hugepages_supported()) {
+    madvise(seg_addr, len, MADV_HUGEPAGE);
+  }
+
+  return true;
+}
+
+void ElfReader::ZeroFillSegment(const ElfW(Phdr)* phdr) {
+  ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
+  uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz;
+
+  // If the segment is writable, and does not end on a page boundary,
+  // zero-fill it until the page limit.
+  //
+  // Do not attempt to zero the extended region past the first partial page,
+  // since doing so may:
+  //   1) Result in a SIGBUS, as the region is not backed by the underlying
+  //      file.
+  //   2) Break the COW backing, faulting in new anon pages for a region
+  //      that will not be used.
+  if ((phdr->p_flags & PF_W) != 0 && page_offset(unextended_seg_file_end) > 0) {
+    memset(reinterpret_cast<void*>(unextended_seg_file_end), 0,
+           kPageSize - page_offset(unextended_seg_file_end));
+  }
+}
+
+void ElfReader::DropPaddingPages(const ElfW(Phdr)* phdr, uint64_t seg_file_end) {
+  ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
+  uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz;
+
+  uint64_t pad_start = page_end(unextended_seg_file_end);
+  uint64_t pad_end = page_end(seg_file_end);
+  CHECK(pad_start <= pad_end);
+
+  uint64_t pad_len = pad_end - pad_start;
+  if (pad_len == 0 || !page_size_migration_supported()) {
+    return;
+  }
+
+  // Pages may be brought in due to readahead.
+  // Drop the padding (zero) pages, to avoid reclaim work later.
+  //
+  // NOTE: The madvise() here is special, as it also serves to hint to the
+  // kernel the portion of the LOAD segment that is padding.
+  //
+  // See: [1] https://android-review.googlesource.com/c/kernel/common/+/3032411
+  //      [2] https://android-review.googlesource.com/c/kernel/common/+/3048835
+  if (madvise(reinterpret_cast<void*>(pad_start), pad_len, MADV_DONTNEED)) {
+    DL_WARN("\"%s\": madvise(0x%" PRIx64 ", 0x%" PRIx64 ", MADV_DONTNEED) failed: %m",
+            name_.c_str(), pad_start, pad_len);
+  }
+}
+
+bool ElfReader::MapBssSection(const ElfW(Phdr)* phdr, ElfW(Addr) seg_page_end,
+                              ElfW(Addr) seg_file_end) {
+  // seg_file_end is now the first page address after the file content.
+  seg_file_end = page_end(seg_file_end);
+
+  if (seg_page_end <= seg_file_end) {
+    return true;
+  }
+
+  // If seg_page_end is larger than seg_file_end, we need to zero
+  // anything between them. This is done by using a private anonymous
+  // map for all extra pages
+  size_t zeromap_size = seg_page_end - seg_file_end;
+  void* zeromap =
+      mmap(reinterpret_cast<void*>(seg_file_end), zeromap_size, PFLAGS_TO_PROT(phdr->p_flags),
+           MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  if (zeromap == MAP_FAILED) {
+    DL_ERR("couldn't map .bss section for \"%s\": %m", name_.c_str());
+    return false;
+  }
+
+  // Set the VMA name using prctl
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, zeromap, zeromap_size, ".bss");
+
+  return true;
+}
+
 bool ElfReader::LoadSegments() {
   size_t min_palign = phdr_table_get_minimum_alignment(phdr_table_, phdr_num_);
   // Only enforce this on 16 KB systems. Apps may rely on undefined behavior
@@ -917,79 +1017,18 @@
         add_dlwarning(name_.c_str(), "W+E load segments");
       }
 
-      void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
-                            file_length,
-                            prot,
-                            MAP_FIXED|MAP_PRIVATE,
-                            fd_,
-                            file_offset_ + file_page_start);
-      if (seg_addr == MAP_FAILED) {
-        DL_ERR("couldn't map \"%s\" segment %zd: %m", name_.c_str(), i);
+      // Pass the file_length, since it may have been extended by _extend_load_segment_vma().
+      if (!MapSegment(i, file_length)) {
         return false;
       }
-
-      // Mark segments as huge page eligible if they meet the requirements
-      // (executable and PMD aligned).
-      if ((phdr->p_flags & PF_X) && phdr->p_align == kPmdSize &&
-          get_transparent_hugepages_supported()) {
-        madvise(seg_addr, file_length, MADV_HUGEPAGE);
-      }
     }
 
-    // if the segment is writable, and does not end on a page boundary,
-    // zero-fill it until the page limit.
-    //
-    // Do not attempt to zero the extended region past the first partial page,
-    // since doing so may:
-    //   1) Result in a SIGBUS, as the region is not backed by the underlying
-    //      file.
-    //   2) Break the COW backing, faulting in new anon pages for a region
-    //      that will not be used.
+    ZeroFillSegment(phdr);
 
-    uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz;
-    if ((phdr->p_flags & PF_W) != 0 && page_offset(unextended_seg_file_end) > 0) {
-      memset(reinterpret_cast<void*>(unextended_seg_file_end), 0,
-             kPageSize - page_offset(unextended_seg_file_end));
-    }
+    DropPaddingPages(phdr, seg_file_end);
 
-    // Pages may be brought in due to readahead.
-    // Drop the padding (zero) pages, to avoid reclaim work later.
-    //
-    // NOTE: The madvise() here is special, as it also serves to hint to the
-    // kernel the portion of the LOAD segment that is padding.
-    //
-    // See: [1] https://android-review.googlesource.com/c/kernel/common/+/3032411
-    //      [2] https://android-review.googlesource.com/c/kernel/common/+/3048835
-    uint64_t pad_start = page_end(unextended_seg_file_end);
-    uint64_t pad_end = page_end(seg_file_end);
-    CHECK(pad_start <= pad_end);
-    uint64_t pad_len = pad_end - pad_start;
-    if (page_size_migration_supported() && pad_len > 0 &&
-        madvise(reinterpret_cast<void*>(pad_start), pad_len, MADV_DONTNEED)) {
-      DL_WARN("\"%s\": madvise(0x%" PRIx64 ", 0x%" PRIx64 ", MADV_DONTNEED) failed: %m",
-              name_.c_str(), pad_start, pad_len);
-    }
-
-    seg_file_end = page_end(seg_file_end);
-
-    // seg_file_end is now the first page address after the file
-    // content. If seg_end is larger, we need to zero anything
-    // between them. This is done by using a private anonymous
-    // map for all extra pages.
-    if (seg_page_end > seg_file_end) {
-      size_t zeromap_size = seg_page_end - seg_file_end;
-      void* zeromap = mmap(reinterpret_cast<void*>(seg_file_end),
-                           zeromap_size,
-                           PFLAGS_TO_PROT(phdr->p_flags),
-                           MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
-                           -1,
-                           0);
-      if (zeromap == MAP_FAILED) {
-        DL_ERR("couldn't zero fill \"%s\" gap: %m", name_.c_str());
-        return false;
-      }
-
-      prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, zeromap, zeromap_size, ".bss");
+    if (!MapBssSection(phdr, seg_page_end, seg_file_end)) {
+      return false;
     }
   }
   return true;
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index e865a03..1d6bbe3 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -68,6 +68,11 @@
   [[nodiscard]] bool ReadDynamicSection();
   [[nodiscard]] bool ReadPadSegmentNote();
   [[nodiscard]] bool ReserveAddressSpace(address_space_params* address_space);
+  [[nodiscard]] bool MapSegment(size_t seg_idx, size_t len);
+  void ZeroFillSegment(const ElfW(Phdr)* phdr);
+  void DropPaddingPages(const ElfW(Phdr)* phdr, uint64_t seg_file_end);
+  [[nodiscard]] bool MapBssSection(const ElfW(Phdr)* phdr, ElfW(Addr) seg_page_end,
+                                   ElfW(Addr) seg_file_end);
   [[nodiscard]] bool LoadSegments();
   [[nodiscard]] bool FindPhdr();
   [[nodiscard]] bool FindGnuPropertySection();
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index 8f85871..bcb1efc 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -147,12 +147,13 @@
 }
 
 void print_linker_stats() {
-  PRINT("RELO STATS: %s: %d abs, %d rel, %d symbol (%d cached)",
-         g_argv[0],
-         linker_stats.count[kRelocAbsolute],
-         linker_stats.count[kRelocRelative],
-         linker_stats.count[kRelocSymbol],
-         linker_stats.count[kRelocSymbolCached]);
+  LD_DEBUG(statistics,
+           "RELO STATS: %s: %d abs, %d rel, %d symbol (%d cached)",
+           g_argv[0],
+           linker_stats.count[kRelocAbsolute],
+           linker_stats.count[kRelocRelative],
+           linker_stats.count[kRelocSymbol],
+           linker_stats.count[kRelocSymbolCached]);
 }
 
 static bool process_relocation_general(Relocator& relocator, const rel_t& reloc);
@@ -207,20 +208,9 @@
   };
 #endif
 
-  auto trace_reloc = [](const char* fmt, ...) __printflike(2, 3) {
-    if (IsGeneral &&
-        g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE &&
-        DO_TRACE_RELO) {
-      va_list ap;
-      va_start(ap, fmt);
-      linker_log_va_list(LINKER_VERBOSITY_TRACE, fmt, ap);
-      va_end(ap);
-    }
-  };
-
   // Skip symbol lookup for R_GENERIC_NONE relocations.
   if (__predict_false(r_type == R_GENERIC_NONE)) {
-    trace_reloc("RELO NONE");
+    LD_DEBUG(reloc && IsGeneral, "RELO NONE");
     return true;
   }
 
@@ -313,8 +303,8 @@
     if (r_type == R_GENERIC_JUMP_SLOT) {
       count_relocation_if<IsGeneral>(kRelocAbsolute);
       const ElfW(Addr) result = sym_addr + get_addend_norel();
-      trace_reloc("RELO JMP_SLOT %16p <- %16p %s",
-                  rel_target, reinterpret_cast<void*>(result), sym_name);
+      LD_DEBUG(reloc && IsGeneral, "RELO JMP_SLOT %16p <- %16p %s",
+               rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     }
@@ -327,8 +317,8 @@
     if (r_type == R_GENERIC_ABSOLUTE) {
       count_relocation_if<IsGeneral>(kRelocAbsolute);
       const ElfW(Addr) result = sym_addr + get_addend_rel();
-      trace_reloc("RELO ABSOLUTE %16p <- %16p %s",
-                  rel_target, reinterpret_cast<void*>(result), sym_name);
+      LD_DEBUG(reloc && IsGeneral, "RELO ABSOLUTE %16p <- %16p %s",
+               rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     } else if (r_type == R_GENERIC_GLOB_DAT) {
@@ -337,8 +327,8 @@
       // it.
       count_relocation_if<IsGeneral>(kRelocAbsolute);
       const ElfW(Addr) result = sym_addr + get_addend_norel();
-      trace_reloc("RELO GLOB_DAT %16p <- %16p %s",
-                  rel_target, reinterpret_cast<void*>(result), sym_name);
+      LD_DEBUG(reloc && IsGeneral, "RELO GLOB_DAT %16p <- %16p %s",
+               rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     } else if (r_type == R_GENERIC_RELATIVE) {
@@ -346,8 +336,8 @@
       // referenced symbol (and abort if the symbol isn't found), even though it isn't used.
       count_relocation_if<IsGeneral>(kRelocRelative);
       const ElfW(Addr) result = relocator.si->load_bias + get_addend_rel();
-      trace_reloc("RELO RELATIVE %16p <- %16p",
-                  rel_target, reinterpret_cast<void*>(result));
+      LD_DEBUG(reloc && IsGeneral, "RELO RELATIVE %16p <- %16p",
+               rel_target, reinterpret_cast<void*>(result));
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     }
@@ -368,8 +358,8 @@
       if (!relocator.si->is_linker()) {
         count_relocation_if<IsGeneral>(kRelocRelative);
         const ElfW(Addr) ifunc_addr = relocator.si->load_bias + get_addend_rel();
-        trace_reloc("RELO IRELATIVE %16p <- %16p",
-                    rel_target, reinterpret_cast<void*>(ifunc_addr));
+        LD_DEBUG(reloc && IsGeneral, "RELO IRELATIVE %16p <- %16p",
+                 rel_target, reinterpret_cast<void*>(ifunc_addr));
         if (handle_text_relocs && !protect_segments()) return false;
         const ElfW(Addr) result = call_ifunc_resolver(ifunc_addr);
         if (handle_text_relocs && !unprotect_segments()) return false;
@@ -406,8 +396,8 @@
           }
         }
         tpoff += sym_addr + get_addend_rel();
-        trace_reloc("RELO TLS_TPREL %16p <- %16p %s",
-                    rel_target, reinterpret_cast<void*>(tpoff), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO TLS_TPREL %16p <- %16p %s",
+                 rel_target, reinterpret_cast<void*>(tpoff), sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = tpoff;
       }
       break;
@@ -422,8 +412,8 @@
           module_id = found_in->get_tls()->module_id;
           CHECK(module_id != kTlsUninitializedModuleId);
         }
-        trace_reloc("RELO TLS_DTPMOD %16p <- %zu %s",
-                    rel_target, module_id, sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO TLS_DTPMOD %16p <- %zu %s",
+                 rel_target, module_id, sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = module_id;
       }
       break;
@@ -431,8 +421,8 @@
       count_relocation_if<IsGeneral>(kRelocRelative);
       {
         const ElfW(Addr) result = sym_addr + get_addend_rel() - TLS_DTV_OFFSET;
-        trace_reloc("RELO TLS_DTPREL %16p <- %16p %s",
-                    rel_target, reinterpret_cast<void*>(result), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO TLS_DTPREL %16p <- %16p %s",
+                 rel_target, reinterpret_cast<void*>(result), sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = result;
       }
       break;
@@ -449,8 +439,8 @@
           // Unresolved weak relocation.
           desc->func = tlsdesc_resolver_unresolved_weak;
           desc->arg = addend;
-          trace_reloc("RELO TLSDESC %16p <- unresolved weak, addend 0x%zx %s",
-                      rel_target, static_cast<size_t>(addend), sym_name);
+          LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- unresolved weak, addend 0x%zx %s",
+                   rel_target, static_cast<size_t>(addend), sym_name);
         } else {
           CHECK(found_in->get_tls() != nullptr); // We rejected a missing TLS segment above.
           size_t module_id = found_in->get_tls()->module_id;
@@ -458,10 +448,10 @@
           if (mod.static_offset != SIZE_MAX) {
             desc->func = tlsdesc_resolver_static;
             desc->arg = mod.static_offset - relocator.tls_tp_base + sym_addr + addend;
-            trace_reloc("RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s",
-                        rel_target, mod.static_offset, relocator.tls_tp_base,
-                        static_cast<size_t>(sym_addr), static_cast<size_t>(addend),
-                        sym_name);
+            LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s",
+                     rel_target, mod.static_offset, relocator.tls_tp_base,
+                     static_cast<size_t>(sym_addr), static_cast<size_t>(addend),
+                     sym_name);
           } else {
             relocator.tlsdesc_args->push_back({
               .generation = mod.first_generation,
@@ -474,9 +464,9 @@
               desc, relocator.tlsdesc_args->size() - 1
             });
             const TlsDynamicResolverArg& desc_arg = relocator.tlsdesc_args->back();
-            trace_reloc("RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
-                        rel_target, desc_arg.generation, desc_arg.index.module_id,
-                        desc_arg.index.offset, sym_name);
+            LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
+                     rel_target, desc_arg.generation, desc_arg.index.module_id,
+                     desc_arg.index.offset, sym_name);
           }
         }
       }
@@ -488,8 +478,8 @@
       count_relocation_if<IsGeneral>(kRelocAbsolute);
       {
         const Elf32_Addr result = sym_addr + reloc.r_addend;
-        trace_reloc("RELO R_X86_64_32 %16p <- 0x%08x %s",
-                    rel_target, result, sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO R_X86_64_32 %16p <- 0x%08x %s",
+                 rel_target, result, sym_name);
         *static_cast<Elf32_Addr*>(rel_target) = result;
       }
       break;
@@ -499,9 +489,9 @@
         const ElfW(Addr) target = sym_addr + reloc.r_addend;
         const ElfW(Addr) base = reinterpret_cast<ElfW(Addr)>(rel_target);
         const Elf32_Addr result = target - base;
-        trace_reloc("RELO R_X86_64_PC32 %16p <- 0x%08x (%16p - %16p) %s",
-                    rel_target, result, reinterpret_cast<void*>(target),
-                    reinterpret_cast<void*>(base), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO R_X86_64_PC32 %16p <- 0x%08x (%16p - %16p) %s",
+                 rel_target, result, reinterpret_cast<void*>(target),
+                 reinterpret_cast<void*>(base), sym_name);
         *static_cast<Elf32_Addr*>(rel_target) = result;
       }
       break;
@@ -512,9 +502,9 @@
         const ElfW(Addr) target = sym_addr + get_addend_rel();
         const ElfW(Addr) base = reinterpret_cast<ElfW(Addr)>(rel_target);
         const ElfW(Addr) result = target - base;
-        trace_reloc("RELO R_386_PC32 %16p <- 0x%08x (%16p - %16p) %s",
-                    rel_target, result, reinterpret_cast<void*>(target),
-                    reinterpret_cast<void*>(base), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO R_386_PC32 %16p <- 0x%08x (%16p - %16p) %s",
+                 rel_target, result, reinterpret_cast<void*>(target),
+                 reinterpret_cast<void*>(base), sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = result;
       }
       break;
@@ -559,15 +549,11 @@
 }
 
 static bool needs_slow_relocate_loop(const Relocator& relocator __unused) {
-#if STATS
-  // TODO: This could become a run-time flag.
-  return true;
-#endif
 #if !defined(__LP64__)
   if (relocator.si->has_text_relocations) return true;
 #endif
-  if (g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE) {
-    // If linker TRACE() is enabled, then each relocation is logged.
+  // Both LD_DEBUG relocation logging and statistics need the slow path.
+  if (g_linker_debug_config.any || g_linker_debug_config.statistics) {
     return true;
   }
   return false;
@@ -611,7 +597,7 @@
   // The linker already applied its RELR relocations in an earlier pass, so
   // skip the RELR relocations for the linker.
   if (relr_ != nullptr && !is_linker()) {
-    DEBUG("[ relocating %s relr ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s relr ]", get_realpath());
     const ElfW(Relr)* begin = relr_;
     const ElfW(Relr)* end = relr_ + relr_count_;
     if (!relocate_relr(begin, end, load_bias)) {
@@ -626,7 +612,7 @@
         android_relocs_[1] == 'P' &&
         android_relocs_[2] == 'S' &&
         android_relocs_[3] == '2') {
-      DEBUG("[ relocating %s android rel/rela ]", get_realpath());
+      LD_DEBUG(reloc, "[ relocating %s android rel/rela ]", get_realpath());
 
       const uint8_t* packed_relocs = android_relocs_ + 4;
       const size_t packed_relocs_size = android_relocs_size_ - 4;
@@ -642,27 +628,27 @@
 
 #if defined(USE_RELA)
   if (rela_ != nullptr) {
-    DEBUG("[ relocating %s rela ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s rela ]", get_realpath());
 
     if (!plain_relocate<RelocMode::Typical>(relocator, rela_, rela_count_)) {
       return false;
     }
   }
   if (plt_rela_ != nullptr) {
-    DEBUG("[ relocating %s plt rela ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s plt rela ]", get_realpath());
     if (!plain_relocate<RelocMode::JumpTable>(relocator, plt_rela_, plt_rela_count_)) {
       return false;
     }
   }
 #else
   if (rel_ != nullptr) {
-    DEBUG("[ relocating %s rel ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s rel ]", get_realpath());
     if (!plain_relocate<RelocMode::Typical>(relocator, rel_, rel_count_)) {
       return false;
     }
   }
   if (plt_rel_ != nullptr) {
-    DEBUG("[ relocating %s plt rel ]", get_realpath());
+   LD_DEBUG(reloc, "[ relocating %s plt rel ]", get_realpath());
     if (!plain_relocate<RelocMode::JumpTable>(relocator, plt_rel_, plt_rel_count_)) {
       return false;
     }
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index b2170d8..0549d36 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -45,20 +45,15 @@
 #include "linker_relocate.h"
 #include "linker_utils.h"
 
-// Enable the slow lookup path if symbol lookups should be logged.
-static bool is_lookup_tracing_enabled() {
-  return g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE && DO_TRACE_LOOKUP;
-}
-
 SymbolLookupList::SymbolLookupList(soinfo* si)
     : sole_lib_(si->get_lookup_lib()), begin_(&sole_lib_), end_(&sole_lib_ + 1) {
   CHECK(si != nullptr);
-  slow_path_count_ += is_lookup_tracing_enabled();
+  slow_path_count_ += !!g_linker_debug_config.lookup;
   slow_path_count_ += sole_lib_.needs_sysv_lookup();
 }
 
 SymbolLookupList::SymbolLookupList(const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
-  slow_path_count_ += is_lookup_tracing_enabled();
+  slow_path_count_ += !!g_linker_debug_config.lookup;
   libs_.reserve(1 + global_group.size() + local_group.size());
 
   // Reserve a space in front for DT_SYMBOLIC lookup.
@@ -144,8 +139,8 @@
       }
 
       if (IsGeneral) {
-        TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
-                   name, lib->si_->get_realpath(), reinterpret_cast<void*>(lib->si_->base));
+        LD_DEBUG(lookup, "SEARCH %s in %s@%p (gnu)",
+                 name, lib->si_->get_realpath(), reinterpret_cast<void*>(lib->si_->base));
       }
 
       const uint32_t word_num = (hash / kBloomMaskBits) & lib->gnu_maskwords_;
@@ -318,8 +313,8 @@
   const uint32_t h1 = hash % kBloomMaskBits;
   const uint32_t h2 = (hash >> gnu_shift2_) % kBloomMaskBits;
 
-  TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
-      symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
+  LD_DEBUG(lookup, "SEARCH %s in %s@%p (gnu)",
+           symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
 
   // test against bloom filter
   if ((1 & (bloom_word >> h1) & (bloom_word >> h2)) == 0) {
@@ -352,9 +347,9 @@
 const ElfW(Sym)* soinfo::elf_lookup(SymbolName& symbol_name, const version_info* vi) const {
   uint32_t hash = symbol_name.elf_hash();
 
-  TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
-             symbol_name.get_name(), get_realpath(),
-             reinterpret_cast<void*>(base), hash, hash % nbucket_);
+  LD_DEBUG(lookup, "SEARCH %s in %s@%p h=%x(elf) %zd",
+           symbol_name.get_name(), get_realpath(),
+           reinterpret_cast<void*>(base), hash, hash % nbucket_);
 
   const ElfW(Versym) verneed = find_verdef_version_index(this, vi);
   const ElfW(Versym)* versym = get_versym_table();
@@ -429,9 +424,9 @@
     return;
   }
 
-  TRACE("[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
   function(g_argc, g_argv, g_envp);
-  TRACE("[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
 }
 
 static void call_function(const char* function_name __unused,
@@ -441,9 +436,9 @@
     return;
   }
 
-  TRACE("[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
   function();
-  TRACE("[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
 }
 
 template <typename F>
@@ -453,18 +448,18 @@
     return;
   }
 
-  TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
+  LD_DEBUG(calls, "[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
 
   int begin = reverse ? (count - 1) : 0;
   int end = reverse ? -1 : count;
   int step = reverse ? -1 : 1;
 
   for (int i = begin; i != end; i += step) {
-    TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
+    LD_DEBUG(calls, "[ %s[%d] == %p ]", array_name, i, functions[i]);
     call_function("function", functions[i], realpath);
   }
 
-  TRACE("[ Done calling %s for '%s' ]", array_name, realpath);
+  LD_DEBUG(calls, "[ Done calling %s for '%s' ]", array_name, realpath);
 }
 
 void soinfo::call_pre_init_constructors() {
@@ -492,7 +487,7 @@
 
   if (!is_main_executable() && preinit_array_ != nullptr) {
     // The GNU dynamic linker silently ignores these, but we warn the developer.
-    PRINT("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
+    DL_WARN("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
   }
 
   get_children().for_each([] (soinfo* si) {
diff --git a/linker/linker_test_globals.cpp b/linker/linker_test_globals.cpp
index 4b41eed..27ec6f7 100644
--- a/linker/linker_test_globals.cpp
+++ b/linker/linker_test_globals.cpp
@@ -26,9 +26,6 @@
  * SUCH DAMAGE.
  */
 
-// To enable logging
-int g_ld_debug_verbosity = 0;
-
 // Stub some symbols to avoid linking issues
 void DL_WARN_documented_change(int api_level [[maybe_unused]],
                                const char* doc_link [[maybe_unused]],
diff --git a/linker/linker_translate_path.cpp b/linker/linker_translate_path.cpp
index 4f3fdfb..b41669e 100644
--- a/linker/linker_translate_path.cpp
+++ b/linker/linker_translate_path.cpp
@@ -42,13 +42,13 @@
 // 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.
+ * The workaround should work only when targetSdkVersion < 29.
  *
  * param out_name_to_apex pointing to /apex path
  * return true if translation is needed
  */
 bool translateSystemPathToApexPath(const char* name, std::string* out_name_to_apex) {
-  static constexpr const char* kPathTranslationQ[][2] = {
+  static constexpr const char* kPathTranslation[][2] = {
       APEX_LIB("com.android.i18n", "libicui18n.so"),
       APEX_LIB("com.android.i18n", "libicuuc.so")
   };
@@ -59,10 +59,10 @@
 
   auto comparator = [name](auto p) { return strcmp(name, p[0]) == 0; };
 
-  if (get_application_target_sdk_version() < __ANDROID_API_Q__) {
+  if (get_application_target_sdk_version() < 29) {
     if (auto it =
-            std::find_if(std::begin(kPathTranslationQ), std::end(kPathTranslationQ), comparator);
-        it != std::end(kPathTranslationQ)) {
+            std::find_if(std::begin(kPathTranslation), std::end(kPathTranslation), comparator);
+        it != std::end(kPathTranslation)) {
       *out_name_to_apex = (*it)[1];
       return true;
     }
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 9abe542..f72716e 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -75,7 +75,7 @@
 bool normalize_path(const char* path, std::string* normalized_path) {
   // Input should be an absolute path
   if (path[0] != '/') {
-    PRINT("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
+    DL_WARN("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
     return false;
   }
 
@@ -144,7 +144,7 @@
   }
 
   const char* const path = normalized_path.c_str();
-  TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+  LD_DEBUG(any, "Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
 
   // Treat an '!/' separator inside a path as the separator between the name
   // of the zip file on disk and the subdirectory to search within it.
@@ -157,7 +157,7 @@
 
   char buf[512];
   if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
-    PRINT("Warning: ignoring very long library path: %s", path);
+    DL_WARN("ignoring very long library path: %s", path);
     return false;
   }
 
diff --git a/tests/Android.bp b/tests/Android.bp
index 875efd6..6aecb40 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1084,8 +1084,8 @@
     ],
 }
 
-cc_test {
-    name: "hwasan_test",
+cc_defaults {
+    name: "hwasan_test_defaults",
     enabled: false,
     // This does not use bionic_tests_defaults because it is not supported on
     // host.
@@ -1100,9 +1100,6 @@
     srcs: [
         "hwasan_test.cpp",
     ],
-    shared_libs: [
-        "libbase",
-    ],
     data_libs: [
         "libtest_simple_hwasan",
         "libtest_simple_hwasan_nohwasan",
@@ -1112,6 +1109,24 @@
 }
 
 cc_test {
+    name: "hwasan_test",
+    defaults: ["hwasan_test_defaults"],
+    shared_libs: [
+        "libbase",
+    ],
+}
+
+cc_test {
+    name: "hwasan_test_static",
+    defaults: ["hwasan_test_defaults"],
+    static_libs: [
+        "libbase",
+    ],
+    static_executable: true,
+    cflags: ["-DHWASAN_TEST_STATIC"],
+}
+
+cc_test {
     name: "memtag_stack_dlopen_test",
     enabled: false,
     // This does not use bionic_tests_defaults because it is not supported on
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index ddc0fc1..7b7e0e5 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -444,10 +444,9 @@
     return result;
   };
 
-  // AID_UPROBESTATS (1093) was added in V, but "trunk stable" means
-  // that the 2024Q builds don't have branches like the QPR builds used
-  // to, and are tested with the _previous_ release's CTS.
-  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == __ANDROID_API_U__) {
+  // AID_UPROBESTATS (1093) was added in API level 35, but "trunk stable" means
+  // that the 2024Q* builds are tested with the _previous_ release's CTS.
+  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == 34) {
 #if !defined(AID_UPROBESTATS)
 #define AID_UPROBESTATS 1093
 #endif
@@ -457,10 +456,9 @@
       EXPECT_STREQ(getpwuid(AID_UPROBESTATS)->pw_name, "uprobestats");
     }
   }
-  // AID_VIRTUALMACHINE (3013) was added in V, but "trunk stable" means
-  // that the 2024Q builds don't have branches like the QPR builds used
-  // to, and are tested with the _previous_ release's CTS.
-  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == __ANDROID_API_U__) {
+  // AID_VIRTUALMACHINE (3013) was added in API level 35, but "trunk stable" means
+  // that the 2024Q* builds are tested with the _previous_ release's CTS.
+  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == 34) {
 #if !defined(AID_VIRTUALMACHINE)
 #define AID_VIRTUALMACHINE 3013
 #endif
@@ -470,6 +468,18 @@
       EXPECT_STREQ(getpwuid(AID_VIRTUALMACHINE)->pw_name, "virtualmachine");
     }
   }
+  // AID_CROS_EC (1094) was added in API level 36, but "trunk stable" means
+  // that the 2024Q* builds are tested with the _previous_ release's CTS.
+  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == 35) {
+#if !defined(AID_CROS_EC)
+#define AID_CROS_EC 1094
+#endif
+    ids.erase(AID_CROS_EC);
+    expected_ids.erase(AID_CROS_EC);
+    if (getpwuid(AID_CROS_EC)) {
+      EXPECT_STREQ(getpwuid(AID_CROS_EC)->pw_name, "cros_ec");
+    }
+  }
 
   EXPECT_EQ(expected_ids, ids) << return_differences();
 }
diff --git a/tests/hwasan_test.cpp b/tests/hwasan_test.cpp
index e32534e..ddf84cb 100644
--- a/tests/hwasan_test.cpp
+++ b/tests/hwasan_test.cpp
@@ -36,7 +36,18 @@
 
 using HwasanDeathTest = SilentDeathTest;
 
-TEST_F(HwasanDeathTest, UseAfterFree) {
+
+#ifdef HWASAN_TEST_STATIC
+#define MAYBE_DlopenAbsolutePath DISABLED_DlopenAbsolutePath
+// TODO(fmayer): figure out why uaf is misclassified as out of bounds for
+// static executables.
+#define MAYBE_UseAfterFree DISABLED_UseAfterFree
+#else
+#define MAYBE_DlopenAbsolutePath DlopenAbsolutePath
+#define MAYBE_UseAfterFree UseAfterFree
+#endif
+
+TEST_F(HwasanDeathTest, MAYBE_UseAfterFree) {
   EXPECT_DEATH(
       {
         void* m = malloc(1);
@@ -59,7 +70,7 @@
 }
 
 // Check whether dlopen of /foo/bar.so checks /foo/hwasan/bar.so first.
-TEST(HwasanTest, DlopenAbsolutePath) {
+TEST(HwasanTest, MAYBE_DlopenAbsolutePath) {
   std::string path = android::base::GetExecutableDirectory() + "/libtest_simple_hwasan.so";
   ASSERT_EQ(0, access(path.c_str(), F_OK));  // Verify test setup.
   std::string hwasan_path =
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index fc7fd40..35f0f0c 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -1852,7 +1852,7 @@
         " cp $(in) $(genDir)/zipdir/libdir/ &&" +
         " touch $(genDir)/zipdir/empty_file.txt &&" +
         " $(location soong_zip) -o $(out).unaligned -L 0 -C $(genDir)/zipdir -D $(genDir)/zipdir &&" +
-        " $(location bionic_tests_zipalign) 4096 $(out).unaligned $(out)",
+        " $(location bionic_tests_zipalign) 16384 $(out).unaligned $(out)",
 
 }
 
@@ -1891,5 +1891,5 @@
         " cp $(location :libtest_dt_runpath_y) $(genDir)/zipdir/libdir/dt_runpath_y/$$PRIVATE_LIB_OR_LIB64 &&" +
         " touch $(genDir)/zipdir/empty_file.txt &&" +
         " $(location soong_zip) -o $(out).unaligned -L 0 -C $(genDir)/zipdir -D $(genDir)/zipdir &&" +
-        " $(location bionic_tests_zipalign) 4096 $(out).unaligned $(out)",
+        " $(location bionic_tests_zipalign) 16384 $(out).unaligned $(out)",
 }
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
index 6463c6b..46af37f 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so
index f83bbe4..c60b0d6 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so
index fbf62c5..eb33692 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
index 4ffc7e8..c186b1d 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
index 9098310..857f702 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
index 113e455..9d2c5f1 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so
index 719fb5a..f231d11 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so
index 9d0741e..97fb5c4 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
index 78fed79..8146676 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
index 0953633..4ac70f7 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index f5c6bb1..1c51b11 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -37,7 +37,7 @@
 }
 
 TEST(stdatomic, init) {
-  atomic_int v = ATOMIC_VAR_INIT(123);
+  atomic_int v = 123;
   ASSERT_EQ(123, atomic_load(&v));
 
   atomic_init(&v, 456);
@@ -145,35 +145,35 @@
 }
 
 TEST(stdatomic, atomic_fetch_add) {
-  atomic_int i = ATOMIC_VAR_INIT(123);
+  atomic_int i = 123;
   ASSERT_EQ(123, atomic_fetch_add(&i, 1));
   ASSERT_EQ(124, atomic_fetch_add_explicit(&i, 1, memory_order_relaxed));
   ASSERT_EQ(125, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_sub) {
-  atomic_int i = ATOMIC_VAR_INIT(123);
+  atomic_int i = 123;
   ASSERT_EQ(123, atomic_fetch_sub(&i, 1));
   ASSERT_EQ(122, atomic_fetch_sub_explicit(&i, 1, memory_order_relaxed));
   ASSERT_EQ(121, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_or) {
-  atomic_int i = ATOMIC_VAR_INIT(0x100);
+  atomic_int i = 0x100;
   ASSERT_EQ(0x100, atomic_fetch_or(&i, 0x020));
   ASSERT_EQ(0x120, atomic_fetch_or_explicit(&i, 0x003, memory_order_relaxed));
   ASSERT_EQ(0x123, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_xor) {
-  atomic_int i = ATOMIC_VAR_INIT(0x100);
+  atomic_int i = 0x100;
   ASSERT_EQ(0x100, atomic_fetch_xor(&i, 0x120));
   ASSERT_EQ(0x020, atomic_fetch_xor_explicit(&i, 0x103, memory_order_relaxed));
   ASSERT_EQ(0x123, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_and) {
-  atomic_int i = ATOMIC_VAR_INIT(0x123);
+  atomic_int i = 0x123;
   ASSERT_EQ(0x123, atomic_fetch_and(&i, 0x00f));
   ASSERT_EQ(0x003, atomic_fetch_and_explicit(&i, 0x2, memory_order_relaxed));
   ASSERT_EQ(0x002, atomic_load(&i));
diff --git a/tools/NOTICE b/tools/NOTICE
index a4ec954..e69de29 100644
--- a/tools/NOTICE
+++ b/tools/NOTICE
@@ -1,32 +0,0 @@
-Copyright (C) 2016 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
--------------------------------------------------------------------
-
-Copyright (C) 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.
-
--------------------------------------------------------------------
-
diff --git a/tools/versioner/Android.bp b/tools/versioner/Android.bp
deleted file mode 100644
index cc4dbfa..0000000
--- a/tools/versioner/Android.bp
+++ /dev/null
@@ -1,7 +0,0 @@
-package {
-    default_applicable_licenses: ["bionic_tools_license"],
-}
-
-subdirs = [
-    "src",
-]
diff --git a/tools/versioner/README.md b/tools/versioner/README.md
deleted file mode 100644
index edb32be..0000000
--- a/tools/versioner/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-## versioner
-Use clang to verify the correctness of bionic's availability attributes against the NDK platform definitions.
-
-#### Build
-Build with `LLVM_BUILD_HOST_TOOLS=true mma -j48`
-
-#### Use
-`versioner -p platforms current dependencies`
diff --git a/tools/versioner/current b/tools/versioner/current
deleted file mode 120000
index 234dfe7..0000000
--- a/tools/versioner/current
+++ /dev/null
@@ -1 +0,0 @@
-../../libc/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies b/tools/versioner/dependencies
deleted file mode 120000
index 4ec3391..0000000
--- a/tools/versioner/dependencies
+++ /dev/null
@@ -1 +0,0 @@
-../../libc/versioner-dependencies
\ No newline at end of file
diff --git a/tools/versioner/platforms/crtbegin.map.txt b/tools/versioner/platforms/crtbegin.map.txt
deleted file mode 100644
index b844c1e..0000000
--- a/tools/versioner/platforms/crtbegin.map.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file lists the libc functions are included in `crtbegin.o` and not
-# exported by `libc.so`.
-
-CRTBEGIN {
-  global:
-    atexit;  # arm64 x86 x86_64
-};
diff --git a/tools/versioner/platforms/libc.map.txt b/tools/versioner/platforms/libc.map.txt
deleted file mode 120000
index 8527b2e..0000000
--- a/tools/versioner/platforms/libc.map.txt
+++ /dev/null
@@ -1 +0,0 @@
-../../../libc/libc.map.txt
\ No newline at end of file
diff --git a/tools/versioner/run_tests.py b/tools/versioner/run_tests.py
deleted file mode 100755
index 396f895..0000000
--- a/tools/versioner/run_tests.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import subprocess
-import sys
-
-red = '\033[91m'
-green = '\033[92m'
-bold = '\033[1m'
-reset = '\033[0m'
-prefix_pass = bold + "[" + green + "PASS" + reset + bold + "]" + reset
-prefix_fail = bold + "[" + red + "FAIL" + reset + bold + "]" + reset
-
-
-def indent(text, spaces=4):
-    text = text.decode("utf-8")
-    prefix = "    "
-    return "\n".join([prefix + line for line in text.split("\n")])
-
-
-def run_test(test_name, path):
-    os.chdir(path)
-    process = subprocess.Popen(
-        ["/bin/sh", "run.sh"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-    (output, _) = process.communicate()
-
-    if os.path.exists("expected_fail"):
-        with open("expected_fail", "rb") as f:
-            expected_output = f.read()
-            if process.returncode == 0:
-                print("{} {}: unexpected success:".format(prefix_fail, test_name))
-                print("")
-                print("  Expected:")
-                print(indent(expected_output))
-                print("  Actual:")
-                print(indent(output))
-                return False
-            elif not output.endswith(expected_output):
-                print("{} {}: expected output mismatch".format(
-                    prefix_fail, test_name))
-                print("")
-                print("  Expected:")
-                print(indent(expected_output))
-                print("  Actual:")
-                print(indent(output))
-                return False
-    elif process.returncode != 0:
-        print("{} {}: unexpected failure:".format(prefix_fail, test_name))
-        print("")
-        print(indent(output))
-        return False
-
-    print("{} {}".format(prefix_pass, test_name))
-    return True
-
-
-def usage():
-    print("Usage: run_tests.py [-f]")
-    print("    -f\t\tdon't run slow tests")
-    sys.exit(0)
-
-
-root_dir = os.path.dirname(os.path.realpath(__file__))
-test_dir = os.path.join(root_dir, "tests")
-tests = os.listdir(test_dir)
-run_slow = True
-
-if len(sys.argv) > 2:
-    usage()
-elif len(sys.argv) == 2:
-    if sys.argv[1] != "-f":
-        usage()
-    run_slow = False
-
-success = True
-for test in sorted(tests):
-    if test.startswith("slow") and not run_slow:
-        continue
-    path = os.path.join(test_dir, test)
-    if not os.path.isdir(path):
-        continue
-    if not run_test(test, path):
-        success = False
-
-sys.exit(0 if success else 1)
diff --git a/tools/versioner/src/Android.bp b/tools/versioner/src/Android.bp
deleted file mode 100644
index 6551e77..0000000
--- a/tools/versioner/src/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-package {
-    default_applicable_licenses: ["bionic_tools_license"],
-}
-
-cc_binary_host {
-    name: "versioner",
-
-    defaults: ["llvm-build-host-tools-defaults"],
-
-    srcs: [
-        "versioner.cpp",
-        "Arch.cpp",
-        "CompilationType.cpp",
-        "DeclarationDatabase.cpp",
-        "Driver.cpp",
-        "Preprocessor.cpp",
-        "SymbolDatabase.cpp",
-        "SymbolFileParser.cpp",
-        "Utils.cpp",
-        "VFS.cpp",
-    ],
-
-    shared_libs: [
-        "libclang-cpp_host",
-        "libbase",
-    ],
-
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-
-    target: {
-        host: {
-            cppflags: [
-                "-fno-rtti",
-            ],
-        },
-        windows: {
-            enabled: false,
-        },
-    },
-}
diff --git a/tools/versioner/src/Arch.cpp b/tools/versioner/src/Arch.cpp
deleted file mode 100644
index d4d0208..0000000
--- a/tools/versioner/src/Arch.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016 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 "Arch.h"
-
-#include <err.h>
-
-#include <string>
-
-std::string to_string(const Arch& arch) {
-  switch (arch) {
-    case Arch::arm:
-      return "arm";
-
-    case Arch::arm64:
-      return "arm64";
-
-    case Arch::riscv64:
-      return "riscv64";
-
-    case Arch::x86:
-      return "x86";
-
-    case Arch::x86_64:
-      return "x86_64";
-  }
-
-  errx(1, "unknown arch '%zu'", size_t(arch));
-}
-
-static const std::unordered_map<std::string, Arch> arch_name_map{
-  {"arm", Arch::arm},
-  {"arm64", Arch::arm64},
-  {"riscv64", Arch::riscv64},
-  {"x86", Arch::x86},
-  {"x86_64", Arch::x86_64},
-};
-
-std::optional<Arch> arch_from_string(const std::string& name) {
-  auto it = arch_name_map.find(name);
-  if (it == arch_name_map.end()) {
-    return std::nullopt;
-  }
-  return std::make_optional(it->second);
-}
diff --git a/tools/versioner/src/Arch.h b/tools/versioner/src/Arch.h
deleted file mode 100644
index fd98abc..0000000
--- a/tools/versioner/src/Arch.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdlib.h>
-
-#include <array>
-#include <initializer_list>
-#include <optional>
-#include <set>
-#include <string>
-#include <unordered_map>
-
-enum class Arch : size_t {
-  arm = 0,
-  arm64,
-  riscv64,
-  x86,
-  x86_64,
-};
-
-std::string to_string(const Arch& arch);
-std::optional<Arch> arch_from_string(const std::string& name);
-
-template <typename T>
-class ArchMapIterator;
-
-template <typename T>
-class ArchMap {
- public:
-  ArchMap() {
-  }
-
-  ArchMap(std::initializer_list<std::pair<Arch, T>> initializer) {
-    for (auto& pair : initializer) {
-      this->operator[](pair.first) = pair.second;
-    }
-  }
-
-  T& operator[](Arch arch) {
-    return data_[size_t(arch)];
-  }
-
-  const T& operator[](Arch arch) const {
-    return data_[size_t(arch)];
-  }
-
-  bool operator==(const ArchMap& other) const {
-    for (size_t i = 0; i < data_.size(); ++i) {
-      if (data_[i] != other.data_[i]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  ArchMapIterator<T> begin() const {
-    return ArchMapIterator<T>(*this, Arch::arm);
-  }
-
-  ArchMapIterator<T> end() const {
-    return ArchMapIterator<T>(*this, Arch(size_t(Arch::x86_64) + 1));
-  }
-
- private:
-  std::array<T, size_t(Arch::x86_64) + 1> data_ = {};
-};
-
-template <typename T>
-class ArchMapIterator {
-  const ArchMap<T>& map_;
-  Arch arch_ = Arch::arm;
-
- public:
-  ArchMapIterator() = delete;
-
-  ArchMapIterator(const ArchMap<T>& map, Arch arch) : map_(map), arch_(arch) {
-  }
-
-  bool operator==(const ArchMapIterator<T>& rhs) const {
-    return map_ == rhs.map_ && arch_ == rhs.arch_;
-  }
-
-  bool operator!=(const ArchMapIterator<T>& rhs) const {
-    return !(*this == rhs);
-  }
-
-  ArchMapIterator& operator++() {
-    arch_ = Arch(size_t(arch_) + 1);
-    return *this;
-  }
-
-  ArchMapIterator operator++(int) {
-    ArchMapIterator result = *this;
-    ++*this;
-    return result;
-  }
-
-  std::pair<const Arch&, const T&> operator*() const {
-    return std::tie(arch_, map_[arch_]);
-  }
-
-  std::pair<const Arch&, const T&> operator->() const {
-    return std::tie(arch_, map_[arch_]);
-  }
-};
-
-static const std::set<Arch> supported_archs = {
-  Arch::arm,
-  Arch::arm64,
-  Arch::riscv64,
-  Arch::x86,
-  Arch::x86_64,
-};
-
-static ArchMap<std::string> arch_targets = {
-  { Arch::arm, "arm-linux-androideabi" },
-  { Arch::arm64, "aarch64-linux-android" },
-  { Arch::riscv64, "riscv64-linux-android" },
-  { Arch::x86, "i686-linux-android" },
-  { 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, 29, 30, 31, 33, 34,
-};
-
-static const ArchMap<int> arch_min_api = {
-  { Arch::arm, 9 },
-  { Arch::arm64, 21 },
-  { Arch::riscv64, 10000 },
-  { Arch::x86, 9 },
-  { Arch::x86_64, 21 },
-};
-
-static const std::unordered_map<std::string, int> api_codename_map{
-  {"G", 9},
-  {"I", 14},
-  {"J", 16},
-  {"J-MR1", 17},
-  {"J-MR2", 18},
-  {"K", 19},
-  {"L", 21},
-  {"L-MR1", 22},
-  {"M", 23},
-  {"N", 24},
-  {"N-MR1", 25},
-  {"O", 26},
-  {"O-MR1", 27},
-  {"P", 28},
-  {"Q", 29},
-  {"R", 30},
-  {"S", 31},
-  {"T", 33},
-  {"U", 34},
-};
diff --git a/tools/versioner/src/CompilationType.cpp b/tools/versioner/src/CompilationType.cpp
deleted file mode 100644
index 7e7bb5d..0000000
--- a/tools/versioner/src/CompilationType.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2016 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 "CompilationType.h"
-
-#include <sstream>
-#include <string>
-
-std::string to_string(const CompilationType& type) {
-  std::stringstream ss;
-  ss << to_string(type.arch) << "-" << type.api_level << " [" << (type.cpp ? "c++" : "c")
-     << ", fob = " << type.file_offset_bits << "]";
-  return ss.str();
-}
diff --git a/tools/versioner/src/CompilationType.h b/tools/versioner/src/CompilationType.h
deleted file mode 100644
index 2f4cf5c..0000000
--- a/tools/versioner/src/CompilationType.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <functional>
-#include <utility>
-
-#include "Arch.h"
-
-struct CompilationType {
-  Arch arch;
-  bool cpp;
-  int api_level;
-  int file_offset_bits;
-
- private:
-  auto tie() const {
-    return std::tie(arch, cpp, api_level, file_offset_bits);
-  }
-
- public:
-  bool operator<(const CompilationType& other) const {
-    return tie() < other.tie();
-  }
-
-  bool operator==(const CompilationType& other) const {
-    return tie() == other.tie();
-  }
-};
-
-namespace std {
-template <>
-struct hash<CompilationType> {
-  size_t operator()(CompilationType type) const {
-    struct {
-      int32_t arch : 3;
-      int32_t cpp : 1;
-      int32_t api_level : 6;
-      int32_t file_offset_bits : 1;
-      int32_t padding : 21;
-    } packed;
-    packed.arch = static_cast<int32_t>(type.arch);
-    packed.cpp = type.cpp;
-    packed.api_level = type.api_level;
-    packed.file_offset_bits = (type.file_offset_bits == 64);
-    packed.padding = 0;
-    int32_t value;
-    memcpy(&value, &packed, sizeof(value));
-    return std::hash<int32_t>()(value);
-  }
-};
-}
-
-std::string to_string(const CompilationType& type);
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
deleted file mode 100644
index 9794286..0000000
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright (C) 2016 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 "DeclarationDatabase.h"
-
-#include <err.h>
-
-#include <iostream>
-#include <map>
-#include <mutex>
-#include <set>
-#include <sstream>
-#include <string>
-#include <utility>
-
-#include <clang/AST/AST.h>
-#include <clang/AST/Attr.h>
-#include <clang/AST/Mangle.h>
-#include <clang/AST/RecursiveASTVisitor.h>
-#include <clang/Frontend/ASTUnit.h>
-#include <llvm/Support/raw_ostream.h>
-
-using namespace clang;
-
-static bool shouldMangle(MangleContext* mangler, NamedDecl* decl) {
-  // Passing a decl with static linkage to the mangler gives incorrect results.
-  // Check some things ourselves before handing it off to the mangler.
-  if (auto FD = dyn_cast<FunctionDecl>(decl)) {
-    if (FD->isExternC()) {
-      return false;
-    }
-
-    if (FD->isInExternCContext()) {
-      return false;
-    }
-  }
-
-  return mangler->shouldMangleDeclName(decl);
-}
-
-class Visitor : public RecursiveASTVisitor<Visitor> {
-  HeaderDatabase& database;
-  CompilationType type;
-  SourceManager& src_manager;
-  std::unique_ptr<MangleContext> mangler;
-
- public:
-  Visitor(HeaderDatabase& database, CompilationType type, ASTContext& ctx)
-      : database(database), type(type), src_manager(ctx.getSourceManager()) {
-    mangler.reset(ItaniumMangleContext::create(ctx, ctx.getDiagnostics()));
-  }
-
-  std::string getDeclName(NamedDecl* decl) {
-    if (auto var_decl = dyn_cast<VarDecl>(decl)) {
-      if (!var_decl->isFileVarDecl()) {
-        return "<local var>";
-      }
-    }
-
-    // <math.h> maps fool onto foo on 32-bit, since long double is the same as double.
-    if (auto asm_attr = decl->getAttr<AsmLabelAttr>()) {
-      return asm_attr->getLabel().str();
-    }
-
-    // The decl might not have a name (e.g. bitfields).
-    if (auto identifier = decl->getIdentifier()) {
-      if (shouldMangle(mangler.get(), decl)) {
-        std::string mangled;
-        llvm::raw_string_ostream ss(mangled);
-        mangler->mangleName(decl, ss);
-        return mangled;
-      }
-
-      return identifier->getName().str();
-    }
-
-    return "<unnamed>";
-  }
-
-  bool VisitDeclaratorDecl(DeclaratorDecl* decl, SourceRange range) {
-    // Skip declarations inside of functions (function arguments, variable declarations inside of
-    // inline functions, etc).
-    if (decl->getParentFunctionOrMethod()) {
-      return true;
-    }
-
-    auto named_decl = dyn_cast<NamedDecl>(decl);
-    if (!named_decl) {
-      return true;
-    }
-
-    std::string declaration_name = getDeclName(named_decl);
-    bool is_extern = named_decl->getFormalLinkage() == Linkage::External;
-    bool is_definition = false;
-    bool no_guard = false;
-    bool fortify_inline = false;
-
-    if (auto function_decl = dyn_cast<FunctionDecl>(decl)) {
-      is_definition = function_decl->isThisDeclarationADefinition();
-    } else if (auto var_decl = dyn_cast<VarDecl>(decl)) {
-      if (!var_decl->isFileVarDecl()) {
-        return true;
-      }
-
-      switch (var_decl->isThisDeclarationADefinition()) {
-        case VarDecl::DeclarationOnly:
-          is_definition = false;
-          break;
-
-        case VarDecl::Definition:
-          is_definition = true;
-          break;
-
-        case VarDecl::TentativeDefinition:
-          // Forbid tentative definitions in headers.
-          fprintf(stderr, "ERROR: declaration '%s' is a tentative definition\n",
-                  declaration_name.c_str());
-          decl->dump();
-          abort();
-      }
-    } else {
-      // We only care about function and variable declarations.
-      return true;
-    }
-
-    if (decl->hasAttr<UnavailableAttr>()) {
-      // Skip declarations that exist only for compile-time diagnostics.
-      return true;
-    }
-
-    DeclarationAvailability availability;
-
-    // Find and parse __ANDROID_AVAILABILITY_DUMP__ annotations.
-    for (const AnnotateAttr* attr : decl->specific_attrs<AnnotateAttr>()) {
-      llvm::StringRef annotation = attr->getAnnotation();
-      if (annotation == "versioner_no_guard") {
-        no_guard = true;
-      } else if (annotation == "versioner_fortify_inline") {
-        fortify_inline = true;
-      } else {
-        llvm::SmallVector<llvm::StringRef, 2> fragments;
-        annotation.split(fragments, "=");
-        if (fragments.size() != 2) {
-          continue;
-        }
-
-        auto& global_availability = availability.global_availability;
-        auto& arch_availability = availability.arch_availability;
-        std::map<std::string, std::vector<int*>> prefix_map = {
-          { "introduced_in", { &global_availability.introduced } },
-          { "deprecated_in", { &global_availability.deprecated } },
-          { "obsoleted_in", { &global_availability.obsoleted } },
-          { "introduced_in_arm", { &arch_availability[Arch::arm].introduced } },
-          { "introduced_in_x86", { &arch_availability[Arch::x86].introduced } },
-          { "introduced_in_32",
-            { &arch_availability[Arch::arm].introduced,
-              &arch_availability[Arch::x86].introduced } },
-          { "introduced_in_64",
-            { &arch_availability[Arch::arm64].introduced,
-              &arch_availability[Arch::riscv64].introduced,
-              &arch_availability[Arch::x86_64].introduced } },
-        };
-
-        if (auto it = prefix_map.find(fragments[0].str()); it != prefix_map.end()) {
-          int value;
-          if (fragments[1].getAsInteger(10, value)) {
-            errx(1, "invalid __ANDROID_AVAILABILITY_DUMP__ annotation: '%s'",
-                 annotation.str().c_str());
-          }
-
-          for (int* ptr : it->second) {
-            *ptr = value;
-          }
-        }
-      }
-    }
-
-    auto symbol_it = database.symbols.find(declaration_name);
-    if (symbol_it == database.symbols.end()) {
-      Symbol symbol = {.name = declaration_name };
-      bool unused;
-      std::tie(symbol_it, unused) = database.symbols.insert({declaration_name, symbol});
-    }
-
-    auto expansion_range = src_manager.getExpansionRange(range);
-    auto filename = src_manager.getFilename(expansion_range.getBegin());
-    if (filename != src_manager.getFilename(expansion_range.getEnd())) {
-      errx(1, "expansion range filenames don't match");
-    }
-
-    Location location = {
-      .filename = filename.str(),
-      .start = {
-        .line = src_manager.getExpansionLineNumber(expansion_range.getBegin()),
-        .column = src_manager.getExpansionColumnNumber(expansion_range.getBegin()),
-      },
-      .end = {
-        .line = src_manager.getExpansionLineNumber(expansion_range.getEnd()),
-        .column = src_manager.getExpansionColumnNumber(expansion_range.getEnd()),
-      }
-    };
-
-    // Find or insert an entry for the declaration.
-    if (auto declaration_it = symbol_it->second.declarations.find(location);
-        declaration_it != symbol_it->second.declarations.end()) {
-      if (declaration_it->second.is_extern != is_extern ||
-          declaration_it->second.is_definition != is_definition ||
-          declaration_it->second.no_guard != no_guard ||
-          declaration_it->second.fortify_inline != fortify_inline) {
-        errx(1, "varying declaration of '%s' at %s:%u:%u", declaration_name.c_str(),
-             location.filename.c_str(), location.start.line, location.start.column);
-      }
-      declaration_it->second.availability.insert(std::make_pair(type, availability));
-    } else {
-      Declaration declaration;
-      declaration.name = declaration_name;
-      declaration.location = location;
-      declaration.is_extern = is_extern;
-      declaration.is_definition = is_definition;
-      declaration.no_guard = no_guard;
-      declaration.fortify_inline = fortify_inline;
-      declaration.availability.insert(std::make_pair(type, availability));
-      symbol_it->second.declarations.insert(std::make_pair(location, declaration));
-    }
-
-    return true;
-  }
-
-  bool VisitDeclaratorDecl(DeclaratorDecl* decl) {
-    return VisitDeclaratorDecl(decl, decl->getSourceRange());
-  }
-
-  bool TraverseLinkageSpecDecl(LinkageSpecDecl* decl) {
-    // Make sure that we correctly calculate the SourceRange of a declaration that has a non-braced
-    // extern "C"/"C++".
-    if (!decl->hasBraces()) {
-      DeclaratorDecl* child = nullptr;
-      for (auto child_decl : decl->decls()) {
-        if (child != nullptr) {
-          errx(1, "LinkageSpecDecl has multiple children");
-        }
-
-        if (DeclaratorDecl* declarator_decl = dyn_cast<DeclaratorDecl>(child_decl)) {
-          child = declarator_decl;
-        } else {
-          errx(1, "child of LinkageSpecDecl is not a DeclaratorDecl");
-        }
-      }
-
-      return VisitDeclaratorDecl(child, decl->getSourceRange());
-    }
-
-    for (auto child : decl->decls()) {
-      if (!TraverseDecl(child)) {
-        return false;
-      }
-    }
-    return true;
-  }
-};
-
-bool DeclarationAvailability::merge(const DeclarationAvailability& other) {
-#define check_avail(expr) error |= (!this->expr.empty() && this->expr != other.expr);
-  bool error = false;
-
-  if (!other.global_availability.empty()) {
-    check_avail(global_availability);
-    this->global_availability = other.global_availability;
-  }
-
-  for (Arch arch : supported_archs) {
-    if (!other.arch_availability[arch].empty()) {
-      check_avail(arch_availability[arch]);
-      this->arch_availability[arch] = other.arch_availability[arch];
-    }
-  }
-#undef check_avail
-
-  return !error;
-}
-
-bool Declaration::calculateAvailability(DeclarationAvailability* output) const {
-  DeclarationAvailability avail;
-  for (const auto& it : this->availability) {
-    if (!avail.merge(it.second)) {
-      return false;
-    }
-  }
-  *output = avail;
-  return true;
-}
-
-bool Symbol::calculateAvailability(DeclarationAvailability* output) const {
-  DeclarationAvailability avail;
-  for (const auto& it : this->declarations) {
-    // Don't merge availability for inline functions (because they shouldn't have any).
-    if (it.second.is_definition) {
-      continue;
-    }
-
-    DeclarationAvailability decl_availability;
-    if (!it.second.calculateAvailability(&decl_availability)) {
-      return false;
-      abort();
-    }
-
-    if (!avail.merge(decl_availability)) {
-      return false;
-    }
-  }
-  *output = avail;
-  return true;
-}
-
-bool Symbol::hasDeclaration(const CompilationType& type) const {
-  for (const auto& decl_it : this->declarations) {
-    for (const auto& compilation_it : decl_it.second.availability) {
-      if (compilation_it.first == type) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-void HeaderDatabase::parseAST(CompilationType type, ASTContext& ctx) {
-  std::unique_lock<std::mutex> lock(this->mutex);
-  Visitor visitor(*this, type, ctx);
-  visitor.TraverseDecl(ctx.getTranslationUnitDecl());
-}
-
-std::string to_string(const AvailabilityValues& av) {
-  std::stringstream ss;
-
-  if (av.introduced != 0) {
-    ss << "introduced = " << av.introduced << ", ";
-  }
-
-  if (av.deprecated != 0) {
-    ss << "deprecated = " << av.deprecated << ", ";
-  }
-
-  if (av.obsoleted != 0) {
-    ss << "obsoleted = " << av.obsoleted << ", ";
-  }
-
-  std::string result = ss.str();
-  if (!result.empty()) {
-    result = result.substr(0, result.length() - 2);
-  }
-  return result;
-}
-
-std::string to_string(const DeclarationType& type) {
-  switch (type) {
-    case DeclarationType::function:
-      return "function";
-    case DeclarationType::variable:
-      return "variable";
-    case DeclarationType::inconsistent:
-      return "inconsistent";
-  }
-  abort();
-}
-
-std::string to_string(const DeclarationAvailability& decl_av) {
-  std::stringstream ss;
-  if (!decl_av.global_availability.empty()) {
-    ss << to_string(decl_av.global_availability) << ", ";
-  }
-
-  for (const auto& it : decl_av.arch_availability) {
-    if (!it.second.empty()) {
-      ss << to_string(it.first) << ": " << to_string(it.second) << ", ";
-    }
-  }
-
-  std::string result = ss.str();
-  if (result.size() == 0) {
-    return "no availability";
-  }
-
-  return result.substr(0, result.length() - 2);
-}
-
-std::string to_string(const Location& loc) {
-  std::stringstream ss;
-  ss << loc.filename << ":" << loc.start.line << ":" << loc.start.column;
-  return ss.str();
-}
diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h
deleted file mode 100644
index 9a45227..0000000
--- a/tools/versioner/src/DeclarationDatabase.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdio.h>
-
-#include <map>
-#include <mutex>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <llvm/ADT/StringRef.h>
-
-#include "Arch.h"
-#include "CompilationType.h"
-#include "Utils.h"
-
-namespace clang {
-class ASTContext;
-class Decl;
-}
-
-enum class DeclarationType {
-  function,
-  variable,
-  inconsistent,
-};
-
-struct AvailabilityValues {
-  int introduced = 0;
-  int deprecated = 0;
-  int obsoleted = 0;
-
-  bool empty() const {
-    return !(introduced || deprecated || obsoleted);
-  }
-
-  bool operator==(const AvailabilityValues& rhs) const {
-    return std::tie(introduced, deprecated, obsoleted) ==
-           std::tie(rhs.introduced, rhs.deprecated, rhs.obsoleted);
-  }
-
-  bool operator!=(const AvailabilityValues& rhs) const {
-    return !(*this == rhs);
-  }
-};
-
-std::string to_string(const AvailabilityValues& av);
-
-struct DeclarationAvailability {
-  AvailabilityValues global_availability;
-  ArchMap<AvailabilityValues> arch_availability;
-
-  bool empty() const {
-    if (!global_availability.empty()) {
-      return false;
-    }
-
-    for (const auto& it : arch_availability) {
-      if (!it.second.empty()) {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  bool operator==(const DeclarationAvailability& rhs) const {
-    return std::tie(global_availability, arch_availability) ==
-           std::tie(rhs.global_availability, rhs.arch_availability);
-  }
-
-  bool operator!=(const DeclarationAvailability& rhs) const {
-    return !(*this == rhs);
-  }
-
-  // Returns false if the availability declarations conflict.
-  bool merge(const DeclarationAvailability& other);
-};
-
-std::string to_string(const DeclarationAvailability& decl_av);
-
-struct FileLocation {
-  unsigned line;
-  unsigned column;
-
-  bool operator<(const FileLocation& rhs) const {
-    return std::tie(line, column) < std::tie(rhs.line, rhs.column);
-  }
-
-  bool operator==(const FileLocation& rhs) const {
-    return std::tie(line, column) == std::tie(rhs.line, rhs.column);
-  }
-};
-
-struct Location {
-  std::string filename;
-  FileLocation start;
-  FileLocation end;
-
-  bool operator<(const Location& rhs) const {
-    return std::tie(filename, start, end) < std::tie(rhs.filename, rhs.start, rhs.end);
-  }
-};
-
-std::string to_string(const Location& loc);
-
-struct Declaration {
-  std::string name;
-  Location location;
-
-  bool is_extern;
-  bool is_definition;
-  bool no_guard;
-  bool fortify_inline;
-  std::map<CompilationType, DeclarationAvailability> availability;
-
-  bool calculateAvailability(DeclarationAvailability* output) const;
-  bool operator<(const Declaration& rhs) const {
-    return location < rhs.location;
-  }
-
-  void dump(const std::string& base_path = "", FILE* out = stdout, unsigned indent = 0) const {
-    std::string indent_str(indent, ' ');
-    fprintf(out, "%s", indent_str.c_str());
-
-    fprintf(out, "%s ", is_extern ? "extern" : "static");
-    fprintf(out, "%s ", is_definition ? "definition" : "declaration");
-    if (no_guard) {
-      fprintf(out, "no_guard ");
-    }
-    if (fortify_inline) {
-      fprintf(out, "fortify_inline ");
-    }
-    fprintf(out, "@ %s:%u:%u", StripPrefix(location.filename, base_path).str().c_str(),
-            location.start.line, location.start.column);
-
-    if (!availability.empty()) {
-      DeclarationAvailability avail;
-
-      fprintf(out, "\n%s  ", indent_str.c_str());
-      if (!calculateAvailability(&avail)) {
-        fprintf(out, "invalid availability\n");
-      } else {
-        fprintf(out, "%s\n", to_string(avail).c_str());
-      }
-    }
-  }
-};
-
-struct Symbol {
-  std::string name;
-  std::map<Location, Declaration> declarations;
-
-  bool calculateAvailability(DeclarationAvailability* output) const;
-  bool hasDeclaration(const CompilationType& type) const;
-
-  bool operator<(const Symbol& rhs) const {
-    return name < rhs.name;
-  }
-
-  bool operator==(const Symbol& rhs) const {
-    return name == rhs.name;
-  }
-
-  void dump(const std::string& base_path = "", FILE* out = stdout) const {
-    DeclarationAvailability availability;
-    bool valid_availability = calculateAvailability(&availability);
-    fprintf(out, "  %s: ", name.c_str());
-
-    if (valid_availability) {
-      fprintf(out, "%s\n", to_string(availability).c_str());
-    } else {
-      fprintf(out, "invalid\n");
-    }
-
-    for (auto& it : declarations) {
-      it.second.dump(base_path, out, 4);
-    }
-  }
-};
-
-class HeaderDatabase {
-  std::mutex mutex;
-
- public:
-  std::map<std::string, Symbol> symbols;
-
-  void parseAST(CompilationType type, clang::ASTContext& ast);
-
-  void dump(const std::string& base_path = "", FILE* out = stdout) const {
-    fprintf(out, "HeaderDatabase contains %zu symbols:\n", symbols.size());
-    for (const auto& pair : symbols) {
-      pair.second.dump(base_path, out);
-    }
-  }
-};
diff --git a/tools/versioner/src/Driver.cpp b/tools/versioner/src/Driver.cpp
deleted file mode 100644
index 79672ac..0000000
--- a/tools/versioner/src/Driver.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2016 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 "Driver.h"
-
-#include <err.h>
-#include <string.h>
-
-#include <chrono>
-#include <mutex>
-#include <string>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include <clang/AST/ASTConsumer.h>
-#include <clang/Basic/Diagnostic.h>
-#include <clang/Basic/TargetInfo.h>
-#include <clang/Driver/Compilation.h>
-#include <clang/Driver/Driver.h>
-#include <clang/Frontend/CompilerInstance.h>
-#include <clang/Frontend/CompilerInvocation.h>
-#include <clang/Frontend/FrontendAction.h>
-#include <clang/Frontend/FrontendActions.h>
-#include <clang/Frontend/TextDiagnosticPrinter.h>
-#include <clang/Frontend/Utils.h>
-#include <clang/FrontendTool/Utils.h>
-#include <llvm/ADT/IntrusiveRefCntPtr.h>
-#include <llvm/ADT/SmallVector.h>
-#include <llvm/ADT/StringRef.h>
-#include <llvm/Option/Option.h>
-#include <llvm/TargetParser/Host.h>
-#include <llvm/Support/VirtualFileSystem.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "versioner.h"
-
-using namespace std::chrono_literals;
-using namespace std::string_literals;
-
-using namespace clang;
-
-class VersionerASTConsumer : public clang::ASTConsumer {
- public:
-  HeaderDatabase* header_database;
-  CompilationType type;
-
-  VersionerASTConsumer(HeaderDatabase* header_database, CompilationType type)
-      : header_database(header_database), type(type) {
-  }
-
-  void HandleTranslationUnit(ASTContext& ctx) override {
-    header_database->parseAST(type, ctx);
-  }
-};
-
-class VersionerASTAction : public clang::ASTFrontendAction {
- public:
-  HeaderDatabase* header_database;
-  CompilationType type;
-
-  VersionerASTAction(HeaderDatabase* header_database, CompilationType type)
-      : header_database(header_database), type(type) {
-  }
-
-  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance&, llvm::StringRef) override {
-    return std::make_unique<VersionerASTConsumer>(header_database, type);
-  }
-};
-
-static IntrusiveRefCntPtr<DiagnosticsEngine> constructDiags() {
-  IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions());
-  auto diag_printer = std::make_unique<TextDiagnosticPrinter>(llvm::errs(), diag_opts.get());
-  IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs());
-  IntrusiveRefCntPtr<DiagnosticsEngine> diags(
-      new DiagnosticsEngine(diag_ids.get(), diag_opts.get(), diag_printer.release()));
-  return diags;
-}
-
-// clang's driver is slow compared to the work it performs to compile our headers.
-// Run it once to generate flags for each target, and memoize the results.
-static std::unordered_map<CompilationType, std::vector<std::string>> cc1_flags;
-static const char* filename_placeholder = "__VERSIONER_PLACEHOLDER__";
-static void generateTargetCC1Flags(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                                   CompilationType type,
-                                   const std::vector<std::string>& include_dirs) {
-  std::vector<std::string> cmd = { "versioner" };
-  if (type.cpp) {
-    cmd.push_back("-std=gnu++11");
-    cmd.push_back("-x");
-    cmd.push_back("c++");
-  } else {
-    cmd.push_back("-std=gnu11");
-    cmd.push_back("-x");
-    cmd.push_back("c");
-  }
-
-  cmd.push_back("-fsyntax-only");
-
-  cmd.push_back("-Wall");
-  cmd.push_back("-Wextra");
-  cmd.push_back("-Weverything");
-  cmd.push_back("-Werror");
-  cmd.push_back("-Wundef");
-  cmd.push_back("-Wno-unused-macros");
-  cmd.push_back("-Wno-unused-function");
-  cmd.push_back("-Wno-unused-variable");
-  cmd.push_back("-Wno-unknown-attributes");
-  cmd.push_back("-Wno-pragma-once-outside-header");
-
-  cmd.push_back("-target");
-  cmd.push_back(arch_targets[type.arch]);
-
-  cmd.push_back("-DANDROID");
-  cmd.push_back("-D__BIONIC_VERSIONER=1");
-  cmd.push_back("-D__ANDROID_API__="s + std::to_string(type.api_level));
-  cmd.push_back("-D_FORTIFY_SOURCE=2");
-  cmd.push_back("-D_GNU_SOURCE");
-  cmd.push_back("-D_FILE_OFFSET_BITS="s + std::to_string(type.file_offset_bits));
-
-  cmd.push_back("-nostdinc");
-
-  if (add_include) {
-    cmd.push_back("-include");
-    cmd.push_back("android/versioning.h");
-  }
-
-  for (const auto& dir : include_dirs) {
-    cmd.push_back("-isystem");
-    cmd.push_back(dir);
-  }
-
-  cmd.push_back("-include");
-  cmd.push_back(filename_placeholder);
-  cmd.push_back("-");
-
-  auto diags = constructDiags();
-  driver::Driver driver("versioner", llvm::sys::getDefaultTargetTriple(), *diags, "versioner", vfs);
-  driver.setCheckInputsExist(false);
-
-  llvm::SmallVector<const char*, 32> driver_args;
-  for (const std::string& str : cmd) {
-    driver_args.push_back(str.c_str());
-  }
-
-  std::unique_ptr<driver::Compilation> Compilation(driver.BuildCompilation(driver_args));
-  const driver::JobList& jobs = Compilation->getJobs();
-  if (jobs.size() != 1) {
-    errx(1, "driver returned %zu jobs for %s", jobs.size(), to_string(type).c_str());
-  }
-
-  const driver::Command& driver_cmd = llvm::cast<driver::Command>(*jobs.begin());
-  const llvm::opt::ArgStringList& cc_args = driver_cmd.getArguments();
-
-  if (cc_args.size() == 0) {
-    errx(1, "driver returned empty command for %s", to_string(type).c_str());
-  }
-
-  std::vector<std::string> result(cc_args.begin(), cc_args.end());
-
-  {
-    static std::mutex cc1_init_mutex;
-    std::unique_lock<std::mutex> lock(cc1_init_mutex);
-    if (cc1_flags.count(type) > 0) {
-      errx(1, "attemped to generate cc1 flags for existing CompilationType %s",
-           to_string(type).c_str());
-    }
-
-    cc1_flags.emplace(std::make_pair(type, std::move(result)));
-  }
-}
-
-static std::vector<const char*> getCC1Command(CompilationType type, const std::string& filename) {
-  const auto& target_flag_it = cc1_flags.find(type);
-  if (target_flag_it == cc1_flags.end()) {
-    errx(1, "failed to find target flags for CompilationType %s", to_string(type).c_str());
-  }
-
-  std::vector<const char*> result;
-  for (const std::string& flag : target_flag_it->second) {
-    if (flag == "-disable-free") {
-      continue;
-    } else if (flag == filename_placeholder) {
-      result.push_back(filename.c_str());
-    } else {
-      result.push_back(flag.c_str());
-    }
-  }
-  return result;
-}
-
-void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                                  const std::set<CompilationType>& types,
-                                  const std::unordered_map<Arch, CompilationRequirements>& reqs) {
-  if (!cc1_flags.empty()) {
-    errx(1, "reinitializing target CC1 flag cache?");
-  }
-
-  auto start = std::chrono::high_resolution_clock::now();
-  std::vector<std::thread> threads;
-  for (const CompilationType type : types) {
-    threads.emplace_back([type, &vfs, &reqs]() {
-      const auto& arch_req_it = reqs.find(type.arch);
-      if (arch_req_it == reqs.end()) {
-        errx(1, "CompilationRequirement map missing entry for CompilationType %s",
-             to_string(type).c_str());
-      }
-
-      generateTargetCC1Flags(vfs, type, arch_req_it->second.dependencies);
-    });
-  }
-  for (auto& thread : threads) {
-    thread.join();
-  }
-  auto end = std::chrono::high_resolution_clock::now();
-
-  if (verbose) {
-    auto diff = (end - start) / 1.0ms;
-    printf("Generated compiler flags for %zu targets in %0.2Lfms\n", types.size(), diff);
-  }
-
-  if (cc1_flags.empty()) {
-    errx(1, "failed to initialize target CC1 flag cache");
-  }
-}
-
-void compileHeader(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                   HeaderDatabase* header_database, CompilationType type,
-                   const std::string& filename) {
-  auto diags = constructDiags();
-  std::vector<const char*> cc1_flags = getCC1Command(type, filename);
-  auto invocation = std::make_unique<CompilerInvocation>();
-  if (!CompilerInvocation::CreateFromArgs(*invocation.get(), cc1_flags, *diags)) {
-    errx(1, "failed to create CompilerInvocation");
-  }
-
-  clang::CompilerInstance Compiler;
-
-  Compiler.setInvocation(std::move(invocation));
-  Compiler.setDiagnostics(diags.get());
-  Compiler.createFileManager(vfs);
-
-  VersionerASTAction versioner_action(header_database, type);
-  if (!Compiler.ExecuteAction(versioner_action)) {
-    errx(1, "compilation generated warnings or errors");
-  }
-
-  if (diags->getNumWarnings() || diags->hasErrorOccurred()) {
-    errx(1, "compilation generated warnings or errors");
-  }
-}
diff --git a/tools/versioner/src/Driver.h b/tools/versioner/src/Driver.h
deleted file mode 100644
index 99e57ae..0000000
--- a/tools/versioner/src/Driver.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 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 <set>
-#include <string>
-#include <unordered_map>
-
-#include <llvm/ADT/IntrusiveRefCntPtr.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "VFS.h"
-
-struct CompilationRequirements {
-  std::vector<std::string> headers;
-  std::vector<std::string> dependencies;
-};
-
-void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                                  const std::set<CompilationType>& types,
-                                  const std::unordered_map<Arch, CompilationRequirements>& reqs);
-
-void compileHeader(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                   HeaderDatabase* header_database, CompilationType type,
-                   const std::string& filename);
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
deleted file mode 100644
index 74d5ba0..0000000
--- a/tools/versioner/src/Preprocessor.cpp
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright (C) 2016 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 "Preprocessor.h"
-
-#include <err.h>
-#include <fcntl.h>
-#include <fts.h>
-#include <libgen.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <deque>
-#include <fstream>
-#include <string>
-#include <unordered_map>
-
-#include <llvm/ADT/StringRef.h>
-#include <llvm/ADT/Twine.h>
-#include <llvm/Support/FileSystem.h>
-#include <llvm/Support/Path.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "versioner.h"
-
-using namespace std::string_literals;
-
-static DeclarationAvailability calculateRequiredGuard(const Declaration& declaration) {
-  // To avoid redundant macro guards, the availability calculated by this function is the set
-  // difference of 'targets marked-available' from 'targets the declaration is visible in'.
-  // For example, a declaration that is visible always and introduced in 9 would return introduced
-  // in 9, but the same declaration, except only visible in 9+ would return an empty
-  // DeclarationAvailability.
-
-  // This currently only handles __INTRODUCED_IN.
-  // TODO: Do the same for __REMOVED_IN.
-  int global_min_api_visible = 0;
-  ArchMap<int> arch_visibility;
-
-  for (const auto& it : declaration.availability) {
-    const CompilationType& type = it.first;
-
-    if (global_min_api_visible == 0 || global_min_api_visible > type.api_level) {
-      global_min_api_visible = type.api_level;
-    }
-
-    if (arch_visibility[type.arch] == 0 || arch_visibility[type.arch] > type.api_level) {
-      arch_visibility[type.arch] = type.api_level;
-    }
-  }
-
-  DeclarationAvailability decl_av;
-  if (!declaration.calculateAvailability(&decl_av)) {
-    fprintf(stderr, "versioner: failed to calculate availability while preprocessing:\n");
-    declaration.dump("", stderr, 2);
-    exit(1);
-  }
-
-  D("Calculating required guard for %s:\n", declaration.name.c_str());
-  D("  Declaration availability: %s\n", to_string(decl_av).c_str());
-
-  if (verbose) {
-    std::string arch_visibility_str;
-    for (Arch arch : supported_archs) {
-      if (arch_visibility[arch] != 0) {
-        arch_visibility_str += to_string(arch);
-        arch_visibility_str += ": ";
-        arch_visibility_str += std::to_string(arch_visibility[arch]);
-        arch_visibility_str += ", ";
-      }
-    }
-    if (!arch_visibility_str.empty()) {
-      arch_visibility_str.resize(arch_visibility_str.size() - 2);
-    }
-    D("  Declaration visibility: global = %d, arch = %s\n", global_min_api_visible,
-      arch_visibility_str.c_str());
-  }
-
-  DeclarationAvailability result = decl_av;
-  if (result.global_availability.introduced <= global_min_api_visible) {
-    result.global_availability.introduced = 0;
-  }
-
-  for (Arch arch : supported_archs) {
-    if (result.arch_availability[arch].introduced <= arch_visibility[arch] ||
-        result.arch_availability[arch].introduced <= arch_min_api[arch]) {
-      result.arch_availability[arch].introduced = 0;
-    }
-  }
-
-  D("  Calculated result: %s\n", to_string(result).c_str());
-  D("\n");
-
-  return result;
-}
-
-static std::deque<std::string> readFileLines(const std::string& path) {
-  std::ifstream is(path.c_str());
-  std::deque<std::string> result;
-  std::string line;
-
-  while (std::getline(is, line)) {
-    result.push_back(std::move(line));
-  }
-
-  return result;
-}
-
-static void writeFileLines(const std::string& path, const std::deque<std::string>& lines) {
-  if (!mkdirs(dirname(path))) {
-    err(1, "failed to create directory '%s'", dirname(path).c_str());
-  }
-
-  std::ofstream os(path.c_str(), std::ios_base::out | std::ios_base::trunc);
-
-  for (const std::string& line : lines) {
-    os << line << "\n";
-  }
-}
-
-using GuardMap = std::map<Location, DeclarationAvailability>;
-
-static std::string generateGuardCondition(const DeclarationAvailability& avail) {
-  // Logically orred expressions that constitute the macro guard.
-  std::vector<std::string> expressions;
-  static const std::vector<std::pair<std::string, std::set<Arch>>> arch_sets = {
-      {"!defined(__LP64__)", {Arch::arm, Arch::x86}},
-      {"defined(__LP64__)", {Arch::arm64, Arch::riscv64, Arch::x86_64}},
-  };
-  std::map<Arch, std::string> individual_archs = {
-    { Arch::arm, "defined(__arm__)" },
-    { Arch::arm64, "defined(__aarch64__)" },
-    { Arch::riscv64, "defined(__riscv)" },
-    { Arch::x86, "defined(__i386__)" },
-    { Arch::x86_64, "defined(__x86_64__)" },
-  };
-
-  auto generate_guard = [](const std::string& arch_expr, int min_version) {
-    if (min_version == 0) {
-      return arch_expr;
-    }
-    return arch_expr + " && __ANDROID_API__ >= " + std::to_string(min_version);
-  };
-
-  D("Generating guard for availability: %s\n", to_string(avail).c_str());
-  if (!avail.global_availability.empty()) {
-    for (Arch arch : supported_archs) {
-      if (!avail.arch_availability[arch].empty()) {
-        errx(1, "attempted to generate guard with global and per-arch values: %s",
-             to_string(avail).c_str());
-      }
-    }
-
-    if (avail.global_availability.introduced == 0) {
-      // We currently get here for the "__sF" symbol because it's marked __REMOVED_IN(23). This
-      // symbol is the only use of __REMOVED_IN, and it's already guarded manually, so there's no
-      // need to do anything.
-      fprintf(stderr, "warning: attempted to generate guard with empty availability: %s\n",
-              to_string(avail).c_str());
-      return "";
-    }
-
-    if (avail.global_availability.introduced <= 9) {
-      return "";
-    }
-
-    return "__ANDROID_API__ >= "s + std::to_string(avail.global_availability.introduced);
-  }
-
-  for (const auto& it : arch_sets) {
-    const std::string& arch_expr = it.first;
-    const std::set<Arch>& archs = it.second;
-
-    D("  Checking arch set '%s'\n", arch_expr.c_str());
-
-    int version = 0;
-
-    // Find the architectures that need to check __ANDROID_API__ and verify that they check against
-    // the same API level.
-    for (Arch arch : archs) {
-      const int arch_version = avail.arch_availability[arch].introduced;
-      if (arch_version == 0) {
-        continue;
-      } else if (version == 0) {
-        version = arch_version;
-      } else if (version != arch_version) {
-        D("    Skipping arch set, availability for %s doesn't match %s\n",
-          to_string(*it.second.begin()).c_str(), to_string(arch).c_str());
-        goto skip;
-      }
-    }
-
-    // Verify that a non-zero version is acceptable to reuse for other archs with a higher minimum
-    // API, like riscv64. (e.g. It's OK to reuse an (__ANDROID_API__ >= 24) check if the arch's
-    // minimum API is 35.)
-    if (version != 0) {
-      for (Arch arch : archs) {
-        const int arch_version = avail.arch_availability[arch].introduced;
-        if (arch_version == 0 && version > arch_min_api[arch]) {
-          D("    Skipping arch set, availability for %s doesn't match %s\n",
-            to_string(*it.second.begin()).c_str(), to_string(arch).c_str());
-          goto skip;
-        }
-      }
-    }
-
-    expressions.emplace_back(generate_guard(arch_expr, version));
-
-    D("    Generated expression '%s'\n", expressions.rbegin()->c_str());
-
-    for (Arch arch : archs) {
-      individual_archs.erase(arch);
-    }
-
-  skip:
-    continue;
-  }
-
-  for (const auto& it : individual_archs) {
-    const std::string& arch_expr = it.second;
-    int introduced = avail.arch_availability[it.first].introduced;
-    expressions.emplace_back(generate_guard(arch_expr, introduced));
-  }
-
-  if (expressions.size() == 0) {
-    errx(1, "generated empty guard for availability %s", to_string(avail).c_str());
-  } else if (expressions.size() == 1) {
-    return expressions[0];
-  }
-
-  return "("s + Join(expressions, ") || (") + ")";
-}
-
-// Assumes that nothing weird is happening (e.g. having the semicolon be in a macro).
-static FileLocation findNextSemicolon(const std::deque<std::string>& lines, FileLocation start) {
-  unsigned current_line = start.line;
-  unsigned current_column = start.column;
-  while (current_line <= lines.size()) {
-    size_t result = lines[current_line - 1].find_first_of(';', current_column - 1);
-
-    if (result != std::string::npos) {
-      FileLocation loc = {
-        .line = current_line,
-        .column = unsigned(result) + 1,
-      };
-
-      return loc;
-    }
-
-    ++current_line;
-    current_column = 0;
-  }
-
-  errx(1, "failed to find semicolon starting from %u:%u", start.line, start.column);
-}
-
-// Merge adjacent blocks with identical guards.
-static void mergeGuards(std::deque<std::string>& file_lines, GuardMap& guard_map) {
-  if (guard_map.size() < 2) {
-    return;
-  }
-
-  auto current = guard_map.begin();
-  auto next = current;
-  ++next;
-
-  while (next != guard_map.end()) {
-    if (current->second != next->second) {
-      ++current;
-      ++next;
-      continue;
-    }
-
-    // Scan from the end of current to the beginning of next.
-    bool in_block_comment = false;
-    bool valid = true;
-
-    FileLocation current_location = current->first.end;
-    FileLocation end_location = next->first.start;
-
-    auto nextLine = [&current_location]() {
-      ++current_location.line;
-      current_location.column = 1;
-    };
-
-    auto nextCol = [&file_lines, &current_location, &nextLine]() {
-      if (current_location.column == file_lines[current_location.line - 1].length()) {
-        nextLine();
-      } else {
-        ++current_location.column;
-      }
-    };
-
-    // The end location will point to the semicolon, which we don't want to read, so skip it.
-    nextCol();
-
-    while (current_location < end_location) {
-      const std::string& line = file_lines[current_location.line - 1];
-      size_t line_index = current_location.column - 1;
-
-      if (in_block_comment) {
-        size_t pos = line.find("*/", line_index);
-        if (pos == std::string::npos) {
-          D("Didn't find block comment terminator, skipping line\n");
-          nextLine();
-          continue;
-        } else {
-          D("Found block comment terminator\n");
-          in_block_comment = false;
-          current_location.column = pos + 2;
-          nextCol();
-          continue;
-        }
-      } else {
-        size_t pos = line.find_first_not_of(" \t", line_index);
-        if (pos == std::string::npos) {
-          nextLine();
-          continue;
-        }
-
-        current_location.column = pos + 1;
-        if (line[pos] != '/') {
-          valid = false;
-          break;
-        }
-
-        nextCol();
-        if (line.length() <= pos + 1) {
-          // Trailing slash at the end of a line?
-          D("Trailing slash at end of line\n");
-          valid = false;
-          break;
-        }
-
-        if (line[pos + 1] == '/') {
-          // C++ style comment
-          nextLine();
-        } else if (line[pos + 1] == '*') {
-          // Block comment
-          nextCol();
-          in_block_comment = true;
-          D("In a block comment\n");
-        } else {
-          // Garbage?
-          D("Unexpected output after /: %s\n", line.substr(pos).c_str());
-          valid = false;
-          break;
-        }
-      }
-    }
-
-    if (!valid) {
-      D("Not merging blocks %s and %s\n", to_string(current->first).c_str(),
-        to_string(next->first).c_str());
-      ++current;
-      ++next;
-      continue;
-    }
-
-    D("Merging blocks %s and %s\n", to_string(current->first).c_str(),
-      to_string(next->first).c_str());
-
-    Location merged = current->first;
-    merged.end = next->first.end;
-
-    DeclarationAvailability avail = current->second;
-
-    guard_map.erase(current);
-    guard_map.erase(next);
-    bool unused;
-    std::tie(current, unused) = guard_map.insert(std::make_pair(merged, avail));
-    next = current;
-    ++next;
-  }
-}
-
-static void rewriteFile(const std::string& output_path, std::deque<std::string>& file_lines,
-                        const GuardMap& guard_map) {
-  for (auto it = guard_map.rbegin(); it != guard_map.rend(); ++it) {
-    const Location& loc = it->first;
-    const DeclarationAvailability& avail = it->second;
-
-    std::string condition = generateGuardCondition(avail);
-    if (condition.empty()) {
-      continue;
-    }
-
-    std::string prologue = "\n#if "s + condition + "\n";
-    std::string epilogue = "\n#endif /* " + condition + " */\n";
-
-    file_lines[loc.end.line - 1].insert(loc.end.column, epilogue);
-    file_lines[loc.start.line - 1].insert(loc.start.column - 1, prologue);
-  }
-
-  if (verbose) {
-    printf("Preprocessing %s...\n", output_path.c_str());
-  }
-  writeFileLines(output_path, file_lines);
-}
-
-bool preprocessHeaders(const std::string& dst_dir, const std::string& src_dir,
-                       HeaderDatabase* database) {
-  std::unordered_map<std::string, GuardMap> guards;
-  std::unordered_map<std::string, std::deque<std::string>> file_lines;
-
-  for (const auto& symbol_it : database->symbols) {
-    const Symbol& symbol = symbol_it.second;
-
-    for (const auto& decl_it : symbol.declarations) {
-      const Location& location = decl_it.first;
-      const Declaration& decl = decl_it.second;
-
-      if (decl.no_guard) {
-        // No guard required.
-        continue;
-      }
-
-      DeclarationAvailability macro_guard = calculateRequiredGuard(decl);
-      if (!macro_guard.empty()) {
-        guards[location.filename][location] = macro_guard;
-      }
-    }
-  }
-
-  // Copy over the original headers before preprocessing.
-  char* fts_paths[2] = { const_cast<char*>(src_dir.c_str()), nullptr };
-  std::unique_ptr<FTS, decltype(&fts_close)> fts(fts_open(fts_paths, FTS_LOGICAL, nullptr),
-                                                 fts_close);
-  if (!fts) {
-    err(1, "failed to open directory %s", src_dir.c_str());
-  }
-
-  while (FTSENT* ent = fts_read(fts.get())) {
-    llvm::StringRef path = ent->fts_path;
-    if (!path.starts_with(src_dir)) {
-      err(1, "path '%s' doesn't start with source dir '%s'", ent->fts_path, src_dir.c_str());
-    }
-
-    if (ent->fts_info != FTS_F) {
-      continue;
-    }
-
-    std::string rel_path = path.substr(src_dir.length() + 1).str();
-    std::string dst_path = dst_dir + "/" + rel_path;
-    llvm::StringRef parent_path = llvm::sys::path::parent_path(dst_path);
-    if (llvm::sys::fs::create_directories(parent_path)) {
-      errx(1, "failed to ensure existence of directory '%s'", parent_path.str().c_str());
-    }
-    if (llvm::sys::fs::copy_file(path, dst_path)) {
-      errx(1, "failed to copy '%s/%s' to '%s'", src_dir.c_str(), path.str().c_str(),
-           dst_path.c_str());
-    }
-  }
-
-  for (const auto& file_it : guards) {
-    file_lines[file_it.first] = readFileLines(file_it.first);
-  }
-
-  for (auto& file_it : guards) {
-    llvm::StringRef file_path = file_it.first;
-    GuardMap& orig_guard_map = file_it.second;
-
-    // The end positions given to us are the end of the declaration, which is some point before the
-    // semicolon. Fix up the end positions by scanning for the next semicolon.
-    GuardMap guard_map;
-    for (const auto& it : orig_guard_map) {
-      Location loc = it.first;
-      loc.end = findNextSemicolon(file_lines[file_path.str()], loc.end);
-      guard_map[loc] = it.second;
-    }
-
-    // TODO: Make sure that the Locations don't overlap.
-    // TODO: Merge adjacent non-identical guards.
-    mergeGuards(file_lines[file_path.str()], guard_map);
-
-    if (!file_path.starts_with(src_dir)) {
-      errx(1, "input file %s is not in %s\n", file_path.str().c_str(), src_dir.c_str());
-    }
-
-    // rel_path has a leading slash.
-    llvm::StringRef rel_path = file_path.substr(src_dir.size(), file_path.size() - src_dir.size());
-    std::string output_path = (llvm::Twine(dst_dir) + rel_path).str();
-
-    rewriteFile(output_path, file_lines[file_path.str()], guard_map);
-  }
-
-  return true;
-}
diff --git a/tools/versioner/src/Preprocessor.h b/tools/versioner/src/Preprocessor.h
deleted file mode 100644
index 2a17534..0000000
--- a/tools/versioner/src/Preprocessor.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2016 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 <string>
-
-class HeaderDatabase;
-
-bool preprocessHeaders(const std::string& preprocessor_output_path, const std::string& source_dir,
-                       HeaderDatabase* database);
diff --git a/tools/versioner/src/SymbolDatabase.cpp b/tools/versioner/src/SymbolDatabase.cpp
deleted file mode 100644
index c483c0f..0000000
--- a/tools/versioner/src/SymbolDatabase.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2016 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 "SymbolDatabase.h"
-
-#include "SymbolFileParser.h"
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <fstream>
-#include <streambuf>
-#include <string>
-#include <unordered_set>
-
-#include <llvm/ADT/SmallVector.h>
-#include <llvm/ADT/StringRef.h>
-#include <llvm/Object/Binary.h>
-#include <llvm/Object/ELFObjectFile.h>
-
-#include "versioner.h"
-
-using namespace llvm;
-using namespace llvm::object;
-
-std::unordered_set<std::string> getSymbols(const std::string& filename) {
-  std::unordered_set<std::string> result;
-  auto binaryOrError = createBinary(filename);
-  if (!binaryOrError) {
-    errx(1, "failed to open library at %s: %s\n", filename.c_str(),
-         llvm::toString(binaryOrError.takeError()).c_str());
-  }
-
-  ELFObjectFileBase* elf = dyn_cast_or_null<ELFObjectFileBase>(binaryOrError.get().getBinary());
-  if (!elf) {
-    errx(1, "failed to parse %s as ELF", filename.c_str());
-  }
-
-  for (const ELFSymbolRef symbol : elf->getDynamicSymbolIterators()) {
-    Expected<StringRef> symbolNameOrError = symbol.getName();
-
-    if (!symbolNameOrError) {
-      errx(1, "failed to get symbol name for symbol in %s: %s", filename.c_str(),
-           llvm::toString(symbolNameOrError.takeError()).c_str());
-    }
-
-    result.insert(symbolNameOrError.get().str());
-  }
-
-  return result;
-}
-
-static std::map<std::string, NdkSymbolType> parsePlatform(const CompilationType& type,
-                                                          const std::string& platform_dir) {
-  static const std::pair<const char*, bool> wanted_files[] = {
-    {"crtbegin.map.txt", false},
-    {"libc.map.txt", true},
-  };
-
-  std::map<std::string, NdkSymbolType> result;
-
-  for (auto&& [filename, required] : wanted_files) {
-    std::string path = platform_dir + "/" + filename;
-
-    std::optional<SymbolMap> symbols = parseSymbolFile(path, type);
-    if (!symbols) {
-      if (required) {
-        errx(1, "error: failed to load: %s", path.c_str());
-      }
-      continue;
-    }
-
-    for (auto&& [symbol_name, symbol_type] : *symbols) {
-      if (symbol_name.empty()) {
-        continue;
-      }
-
-      if (result.count(symbol_name) != 0) {
-        if (strict) {
-          printf("duplicated symbol '%s' in '%s'\n", symbol_name.c_str(), path.c_str());
-        }
-      }
-
-      result[symbol_name] = symbol_type;
-    }
-  }
-
-  return result;
-}
-
-std::optional<NdkSymbolDatabase> parsePlatforms(const std::set<CompilationType>& types,
-                                                const std::string& platform_dir) {
-  NdkSymbolDatabase result;
-  for (const CompilationType& type : types) {
-    std::map<std::string, NdkSymbolType> symbols = parsePlatform(type, platform_dir);
-    for (const auto& it : symbols) {
-      result[it.first][type] = it.second;
-    }
-  }
-  return std::make_optional(std::move(result));
-}
diff --git a/tools/versioner/src/SymbolDatabase.h b/tools/versioner/src/SymbolDatabase.h
deleted file mode 100644
index dbbba4f..0000000
--- a/tools/versioner/src/SymbolDatabase.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 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 <map>
-#include <optional>
-#include <set>
-#include <string>
-#include <unordered_set>
-
-#include "DeclarationDatabase.h"
-
-using LibrarySymbolDatabase = std::unordered_set<std::string>;
-std::unordered_set<std::string> getSymbols(const std::string& filename);
-
-enum class NdkSymbolType {
-  function,
-  variable,
-};
-
-using NdkSymbolDatabase = std::map<std::string, std::map<CompilationType, NdkSymbolType>>;
-std::optional<NdkSymbolDatabase> parsePlatforms(const std::set<CompilationType>& types,
-                                                const std::string& platform_dir);
diff --git a/tools/versioner/src/SymbolFileParser.cpp b/tools/versioner/src/SymbolFileParser.cpp
deleted file mode 100644
index 1b4adae..0000000
--- a/tools/versioner/src/SymbolFileParser.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * 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.
- */
-
-#include "SymbolFileParser.h"
-
-#include "Arch.h"
-#include "CompilationType.h"
-
-#include <android-base/strings.h>
-
-#include <fstream>
-#include <ios>
-#include <optional>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <err.h>
-
-namespace {
-
-using TagList = std::vector<std::string>;
-
-struct SymbolEnt {
-  std::string name;
-  TagList tags;
-};
-
-using SymbolList = std::vector<SymbolEnt>;
-
-struct Version {
-  std::string name;
-  std::string base;
-  SymbolList symbols;
-  TagList tags;
-};
-
-class SymbolFileParser {
- public:
-  SymbolFileParser(const std::string& path, const CompilationType& type)
-    : file_path(path),
-      compilation_type(type),
-      api_level_arch_prefix("api-level-" + to_string(type.arch) + "="),
-      intro_arch_perfix("introduced-" + to_string(type.arch) + "="),
-      file(path, std::ios_base::in),
-      curr_line_num(0) {
-  }
-
-  // Parse the version script and build a symbol map.
-  std::optional<SymbolMap> parse() {
-    if (!file) {
-      return std::nullopt;
-    }
-
-    SymbolMap symbol_map;
-    while (hasNextLine()) {
-      auto&& version = parseVersion();
-      if (!version) {
-        return std::nullopt;
-      }
-
-      if (isInArch(version->tags) && isInApi(version->tags)) {
-        for (auto&& [name, tags] : version->symbols) {
-          if (isInArch(tags) && isInApi(tags)) {
-            symbol_map[name] = getSymbolType(tags);
-          }
-        }
-      }
-    }
-    return std::make_optional(std::move(symbol_map));
-  }
-
- private:
-  // Read a non-empty line from the input and split at the first '#' character.
-  bool hasNextLine() {
-    std::string line;
-    while (std::getline(file, line)) {
-      ++curr_line_num;
-
-      size_t hash_pos = line.find('#');
-      curr_line = android::base::Trim(line.substr(0, hash_pos));
-      if (!curr_line.empty()) {
-        if (hash_pos != std::string::npos) {
-          curr_tags = parseTags(line.substr(hash_pos + 1));
-        } else {
-          curr_tags.clear();
-        }
-        return true;
-      }
-    }
-    return false;
-  }
-
-  // Tokenize the tags after the '#' character.
-  static std::vector<std::string> parseTags(const std::string& tags_line) {
-    std::vector<std::string> tags = android::base::Split(tags_line, " \t");
-    tags.erase(std::remove(tags.begin(), tags.end(), ""), tags.end());
-    return tags;
-  }
-
-  // Parse a version scope.
-  std::optional<Version> parseVersion() {
-    size_t start_line_num = curr_line_num;
-
-    std::string::size_type lparen_pos = curr_line.find('{');
-    if (lparen_pos == std::string::npos) {
-      errx(1, "%s:%zu: error: expected '{' cannot be found in this line",
-           file_path.c_str(), curr_line_num);
-    }
-
-    // Record the version name and version tags (before hasNextLine()).
-    std::string name = android::base::Trim(curr_line.substr(0, lparen_pos));
-    TagList tags = std::move(curr_tags);
-
-    // Read symbol lines.
-    SymbolList symbols;
-    bool global_scope = true;
-    bool cpp_scope = false;
-    while (hasNextLine()) {
-      size_t rparen_pos = curr_line.find('}');
-      if (rparen_pos != std::string::npos) {
-        size_t semicolon_pos = curr_line.find(';', rparen_pos + 1);
-        if (semicolon_pos == std::string::npos) {
-          errx(1, "%s:%zu: error: the line that ends a scope must end with ';'",
-               file_path.c_str(), curr_line_num);
-        }
-
-        if (cpp_scope) {
-          cpp_scope = false;
-          continue;
-        }
-
-        std::string base = android::base::Trim(
-          curr_line.substr(rparen_pos + 1, semicolon_pos - 1));
-
-        return std::make_optional(Version{std::move(name), std::move(base),
-                                          std::move(symbols), std::move(tags)});
-      }
-
-      if (android::base::StartsWith(curr_line, R"(extern "C++" {)")) {
-        cpp_scope = true;
-        continue;
-      }
-
-      if (cpp_scope) {
-        continue;
-      }
-
-      size_t colon_pos = curr_line.find(':');
-      if (colon_pos != std::string::npos) {
-        std::string visibility =
-          android::base::Trim(curr_line.substr(0, colon_pos));
-
-        if (visibility == "global") {
-          global_scope = true;
-        } else if (visibility == "local") {
-          global_scope = false;
-        } else {
-          errx(1, "%s:%zu: error: unknown version visibility: %s",
-               file_path.c_str(), curr_line_num, visibility.c_str());
-        }
-        continue;
-      }
-
-      if (global_scope) {
-        size_t semicolon_pos = curr_line.find(';');
-        if (semicolon_pos == std::string::npos) {
-          errx(1, "%s:%zu: error: symbol name line must end with ';'",
-               file_path.c_str(), curr_line_num);
-        }
-
-        std::string symbol_name =
-          android::base::Trim(curr_line.substr(0, semicolon_pos));
-
-        size_t asterisk_pos = symbol_name.find('*');
-        if (asterisk_pos != std::string::npos) {
-          errx(1, "%s:%zu: error: global symbol name must not have wildcards",
-               file_path.c_str(), curr_line_num);
-        }
-
-        symbols.push_back(SymbolEnt{std::move(symbol_name),
-                                    std::move(curr_tags)});
-      }
-    }
-
-    errx(1, "%s:%zu: error: scope started from %zu must be closed before EOF",
-         file_path.c_str(), curr_line_num, start_line_num);
-  }
-
-  static NdkSymbolType getSymbolType(const TagList& tags) {
-    for (auto&& tag : tags) {
-      if (tag == "var") {
-        return NdkSymbolType::variable;
-      }
-    }
-    return NdkSymbolType::function;
-  }
-
-  // isInArch() returns true if there is a matching arch-specific tag or there
-  // are no arch-specific tags.
-  bool isInArch(const TagList& tags) const {
-    bool has_arch_tags = false;
-    for (auto&& tag : tags) {
-      std::optional<Arch> arch = arch_from_string(tag);
-      if (!arch) {
-        continue;
-      }
-      if (*arch == compilation_type.arch) {
-        return true;
-      }
-      has_arch_tags = true;
-    }
-    return !has_arch_tags;
-  }
-
-  // isInApi() returns true if the specified API level is equal to the
-  // api-level tag, or the specified API level is greater than or equal to the
-  // introduced tag, or there are no api-level or introduced tags.
-  bool isInApi(const TagList& tags) const {
-    bool api_level_arch = false;
-    bool intro_arch = false;
-    std::string api_level;
-    std::string intro;
-
-    for (const std::string& tag : tags) {
-      // Check api-level tags.
-      if (android::base::StartsWith(tag, "api-level=") && !api_level_arch) {
-        api_level = tag;
-        continue;
-      }
-      if (android::base::StartsWith(tag, api_level_arch_prefix)) {
-        api_level = tag;
-        api_level_arch = true;
-        continue;
-      }
-
-      // Check introduced tags.
-      if (android::base::StartsWith(tag, "introduced=") && !intro_arch) {
-        intro = tag;
-        continue;
-      }
-      if (android::base::StartsWith(tag, intro_arch_perfix)) {
-        intro = tag;
-        intro_arch = true;
-        continue;
-      }
-    }
-
-    if (intro.empty() && api_level.empty()) {
-      return true;
-    }
-
-    if (!api_level.empty()) {
-      // If an api-level tag is specified, it must be an exact match (mainly
-      // for versioner unit tests).
-      return compilation_type.api_level == parseApiLevelValue(api_level);
-    }
-
-    return compilation_type.api_level >= parseApiLevelValue(intro);
-  }
-
-  // Parse the integer API level from api-level or introduced tags.
-  int parseApiLevelValue(const std::string& tag) const {
-    std::string api_level = tag.substr(tag.find('=') + 1);
-    auto it = api_codename_map.find(api_level);
-    if (it != api_codename_map.end()) {
-      return it->second;
-    }
-    if (api_level.find_first_not_of("0123456789") != std::string::npos) {
-      errx(1, "%s:%zu: error: unknown API level codename specified: \"%s\"",
-           file_path.c_str(), curr_line_num, tag.c_str());
-    }
-    return std::stoi(api_level);
-  }
-
- private:
-  const std::string& file_path;
-  const CompilationType& compilation_type;
-  const std::string api_level_arch_prefix;
-  const std::string intro_arch_perfix;
-
-  std::ifstream file;
-  std::string curr_line;
-  std::vector<std::string> curr_tags;
-  size_t curr_line_num;
-};
-
-}  // anonymous namespace
-
-
-std::optional<SymbolMap> parseSymbolFile(const std::string& file_path,
-                                         const CompilationType& type) {
-  SymbolFileParser parser(file_path, type);
-  return parser.parse();
-}
diff --git a/tools/versioner/src/SymbolFileParser.h b/tools/versioner/src/SymbolFileParser.h
deleted file mode 100644
index 5cdbf2f..0000000
--- a/tools/versioner/src/SymbolFileParser.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <map>
-#include <string>
-#include <optional>
-
-#include "DeclarationDatabase.h"
-#include "SymbolDatabase.h"
-
-using SymbolMap = std::map<std::string, NdkSymbolType>;
-
-std::optional<SymbolMap> parseSymbolFile(const std::string &file,
-                                         const CompilationType& type);
diff --git a/tools/versioner/src/Utils.cpp b/tools/versioner/src/Utils.cpp
deleted file mode 100644
index d2bb1a8..0000000
--- a/tools/versioner/src/Utils.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2016 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 "Utils.h"
-
-#include <err.h>
-#include <fts.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <android-base/strings.h>
-
-#include "DeclarationDatabase.h"
-
-std::string getWorkingDir() {
-  char buf[PATH_MAX];
-  if (!getcwd(buf, sizeof(buf))) {
-    err(1, "getcwd failed");
-  }
-  return buf;
-}
-
-std::vector<std::string> collectHeaders(const std::string& directory,
-                                        const std::unordered_set<std::string>& ignored_directories) {
-  std::vector<std::string> headers;
-
-  char* dir_argv[2] = { const_cast<char*>(directory.c_str()), nullptr };
-  std::unique_ptr<FTS, decltype(&fts_close)> fts(
-      fts_open(dir_argv, FTS_LOGICAL | FTS_NOCHDIR, nullptr), fts_close);
-
-  if (!fts) {
-    err(1, "failed to open directory '%s'", directory.c_str());
-  }
-
-  FTSENT* skipping = nullptr;
-  while (FTSENT* ent = fts_read(fts.get())) {
-    if (ent->fts_info & FTS_DP) {
-      if (ent == skipping) {
-        skipping = nullptr;
-      }
-      continue;
-    }
-
-    if (skipping != nullptr) {
-      continue;
-    }
-
-    if (ent->fts_info & FTS_D) {
-      if (ignored_directories.count(ent->fts_path) != 0) {
-        // fts_read guarantees that `ent` is valid and okay to hold on to until
-        // after it's returned with FTS_DP set.
-        skipping = ent;
-      }
-      continue;
-    }
-
-    std::string path = ent->fts_path;
-    if (!android::base::EndsWith(path, ".h")) {
-      continue;
-    }
-
-    headers.push_back(std::move(path));
-  }
-
-  return headers;
-}
-
-llvm::StringRef StripPrefix(llvm::StringRef string, llvm::StringRef prefix) {
-  if (string.starts_with(prefix)) {
-    return string.drop_front(prefix.size());
-  }
-  return string;
-}
diff --git a/tools/versioner/src/Utils.h b/tools/versioner/src/Utils.h
deleted file mode 100644
index 9b45dcd..0000000
--- a/tools/versioner/src/Utils.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <libgen.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include <llvm/ADT/StringRef.h>
-
-std::string getWorkingDir();
-std::vector<std::string> collectHeaders(const std::string& directory,
-                                        const std::unordered_set<std::string>& ignored_directories);
-
-static inline std::string dirname(const std::string& path) {
-  std::unique_ptr<char, decltype(&free)> path_copy(strdup(path.c_str()), free);
-  return dirname(path_copy.get());
-}
-
-static inline bool is_directory(const std::string& path) {
-  struct stat st;
-  if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
-    return true;
-  }
-  return false;
-}
-
-static inline bool mkdirs(const std::string& path) {
-  if (is_directory(path)) {
-    return true;
-  }
-
-  std::string parent = dirname(path);
-  if (parent == path) {
-    return false;
-  }
-
-  if (!mkdirs(parent)) {
-    return false;
-  }
-
-  if (mkdir(path.c_str(), 0700) != 0) {
-    if (errno != EEXIST) {
-      return false;
-    }
-    return is_directory(path);
-  }
-
-  return true;
-}
-
-static inline std::string to_string(const char* c) {
-  return c;
-}
-
-static inline const std::string& to_string(const std::string& str) {
-  return str;
-}
-
-template <typename Collection>
-static inline std::string Join(Collection c, const std::string& delimiter = ", ") {
-  std::string result;
-  for (const auto& item : c) {
-    using namespace std;
-    result.append(to_string(item));
-    result.append(delimiter);
-  }
-  if (!result.empty()) {
-    result.resize(result.length() - delimiter.length());
-  }
-  return result;
-}
-
-llvm::StringRef StripPrefix(llvm::StringRef string, llvm::StringRef prefix);
diff --git a/tools/versioner/src/VFS.cpp b/tools/versioner/src/VFS.cpp
deleted file mode 100644
index d797f82..0000000
--- a/tools/versioner/src/VFS.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2016 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 <err.h>
-#include <fcntl.h>
-#include <fts.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <string>
-
-#include <android-base/unique_fd.h>
-#include <llvm/ADT/IntrusiveRefCntPtr.h>
-#include <llvm/Support/MemoryBuffer.h>
-#include <llvm/Support/VirtualFileSystem.h>
-
-#include "Utils.h"
-
-using android::base::unique_fd;
-using namespace llvm::vfs;
-
-static void addDirectoryToVFS(InMemoryFileSystem* vfs, const std::string& path) {
-  char* paths[] = { const_cast<char*>(path.c_str()), nullptr };
-  std::unique_ptr<FTS, decltype(&fts_close)> fts(
-      fts_open(paths, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, nullptr), fts_close);
-
-  if (!fts) {
-    err(1, "failed to open directory %s", path.c_str());
-  }
-
-  while (FTSENT* ent = fts_read(fts.get())) {
-    if ((ent->fts_info & FTS_F) == 0) {
-      continue;
-    }
-
-    const char* file_path = ent->fts_accpath;
-    unique_fd fd(open(file_path, O_RDONLY | O_CLOEXEC));
-    if (fd == -1) {
-      err(1, "failed to open header '%s'", file_path);
-    }
-
-    auto buffer_opt = llvm::MemoryBuffer::getOpenFile(fd, file_path, -1, false, false);
-    if (!buffer_opt) {
-      errx(1, "failed to map header '%s'", file_path);
-    }
-
-    if (!vfs->addFile(file_path, ent->fts_statp->st_mtime, std::move(buffer_opt.get()))) {
-      errx(1, "failed to add file '%s'", file_path);
-    }
-  }
-}
-
-llvm::IntrusiveRefCntPtr<FileSystem> createCommonVFS(const std::string& header_dir,
-                                                     const std::string& dependency_dir,
-                                                     bool add_versioning_header) {
-  auto vfs = std::make_unique<InMemoryFileSystem>();
-  addDirectoryToVFS(vfs.get(), header_dir);
-  if (!dependency_dir.empty()) {
-    addDirectoryToVFS(vfs.get(), dependency_dir);
-  }
-
-  if (add_versioning_header) {
-    const char* top = getenv("ANDROID_BUILD_TOP");
-    if (!top) {
-      errx(1, "-i passed, but ANDROID_BUILD_TOP is unset");
-    }
-
-    std::string header_path = std::string(top) + "/bionic/libc/include/android/versioning.h";
-    auto buffer_opt = llvm::MemoryBuffer::getFile(header_path);
-    if (!buffer_opt) {
-      err(1, "failed to open %s", header_path.c_str());
-    }
-    vfs->addFile("android/versioning.h", 0, std::move(buffer_opt.get()));
-  }
-
-  return llvm::IntrusiveRefCntPtr<FileSystem>(vfs.release());
-}
diff --git a/tools/versioner/src/VFS.h b/tools/versioner/src/VFS.h
deleted file mode 100644
index e4aac75..0000000
--- a/tools/versioner/src/VFS.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2016 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 <memory>
-#include <string>
-
-#include <llvm/ADT/IntrusiveRefCntPtr.h>
-#include <llvm/Support/VirtualFileSystem.h>
-
-llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> createCommonVFS(const std::string& header_dir,
-                                                                const std::string& dependency_dir,
-                                                                bool add_versioning_header);
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
deleted file mode 100644
index 37c8bac..0000000
--- a/tools/versioner/src/versioner.cpp
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
- * Copyright (C) 2016 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 <dirent.h>
-#include <err.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#if defined(__linux__)
-#include <sched.h>
-#endif
-
-#include <atomic>
-#include <chrono>
-#include <functional>
-#include <iostream>
-#include <map>
-#include <memory>
-#include <set>
-#include <sstream>
-#include <string>
-#include <string_view>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include <llvm/ADT/StringRef.h>
-
-#include <android-base/file.h>
-#include <android-base/macros.h>
-#include <android-base/parseint.h>
-#include <android-base/strings.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "Driver.h"
-#include "Preprocessor.h"
-#include "SymbolDatabase.h"
-#include "Utils.h"
-#include "VFS.h"
-
-#include "versioner.h"
-
-using namespace std::chrono_literals;
-using namespace std::string_literals;
-
-bool strict;
-bool verbose;
-bool add_include;
-
-static int getCpuCount();
-static int max_thread_count = getCpuCount();
-
-static int getCpuCount() {
-#if defined(__linux__)
-  cpu_set_t cpu_set;
-  int rc = sched_getaffinity(getpid(), sizeof(cpu_set), &cpu_set);
-  if (rc != 0) {
-    err(1, "sched_getaffinity failed");
-  }
-  return CPU_COUNT(&cpu_set);
-#else
-  return 1;
-#endif
-}
-
-namespace {
-struct HeaderLocationInformation {
-  std::string header_path;
-  std::string dependency_dir;
-  // Absolute paths to ignore all children -- including subdirectories -- of.
-  std::unordered_set<std::string> ignored_directories;
-};
-}
-
-static bool is_dir(const std::string& path) {
-  struct stat st;
-  return stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
-}
-
-static CompilationRequirements collectRequirements(const Arch& arch,
-                                                   const HeaderLocationInformation& location) {
-  std::vector<std::string> headers =
-      collectHeaders(location.header_path, location.ignored_directories);
-  std::vector<std::string> dependencies;
-
-  if (is_dir(location.header_path)) {
-    dependencies.emplace_back(location.header_path);
-  }
-
-  if (!location.dependency_dir.empty()) {
-    auto collect_children = [&dependencies](const std::string& dir_path) {
-      DIR* dir = opendir(dir_path.c_str());
-      if (!dir) {
-        err(1, "failed to open dependency directory '%s'", dir_path.c_str());
-      }
-
-      struct dirent* dent;
-      while ((dent = readdir(dir))) {
-        if (dent->d_name[0] == '.') {
-          continue;
-        }
-
-        // TODO: Resolve symlinks.
-        std::string dependency = dir_path + "/" + dent->d_name;
-
-        struct stat st;
-        if (stat(dependency.c_str(), &st) != 0) {
-          err(1, "failed to stat dependency '%s'", dependency.c_str());
-        }
-
-        if (!S_ISDIR(st.st_mode)) {
-          errx(1, "'%s' is not a directory", dependency.c_str());
-        }
-
-        dependencies.push_back(dependency);
-      }
-
-      closedir(dir);
-    };
-
-    collect_children(location.dependency_dir + "/common");
-    collect_children(location.dependency_dir + "/" + to_string(arch));
-  }
-
-  auto new_end = std::remove_if(headers.begin(), headers.end(), [&arch](llvm::StringRef header) {
-    for (const auto& it : ignored_headers) {
-      if (!it.second.contains(arch)) {
-        continue;
-      }
-
-      if (header.ends_with("/" + it.first)) {
-        return true;
-      }
-    }
-    return false;
-  });
-
-  headers.erase(new_end, headers.end());
-
-  CompilationRequirements result = { .headers = headers, .dependencies = dependencies };
-  return result;
-}
-
-static std::set<CompilationType> generateCompilationTypes(const std::set<Arch> selected_architectures,
-                                                          const std::set<int>& selected_levels) {
-  std::set<CompilationType> result;
-  for (const auto& arch : selected_architectures) {
-    int min_api = arch_min_api[arch];
-    for (int api_level : selected_levels) {
-      if (api_level < min_api) {
-        continue;
-      }
-
-      for (int file_offset_bits : { 32, 64 }) {
-        for (bool cpp : { true, false }) {
-          CompilationType type = {
-            .arch = arch, .cpp = cpp, .api_level = api_level, .file_offset_bits = file_offset_bits
-          };
-          result.insert(type);
-        }
-      }
-    }
-  }
-  return result;
-}
-
-static std::unique_ptr<HeaderDatabase> compileHeaders(const std::set<CompilationType>& types,
-                                                      const HeaderLocationInformation& location) {
-  if (types.empty()) {
-    errx(1, "compileHeaders received no CompilationTypes");
-  }
-
-  auto vfs = createCommonVFS(location.header_path, location.dependency_dir, add_include);
-
-  size_t thread_count = max_thread_count;
-  std::vector<std::thread> threads;
-
-  std::map<CompilationType, HeaderDatabase> header_databases;
-  std::unordered_map<Arch, CompilationRequirements> requirements;
-
-  auto result = std::make_unique<HeaderDatabase>();
-  for (const auto& type : types) {
-    if (requirements.count(type.arch) == 0) {
-      requirements[type.arch] = collectRequirements(type.arch, location);
-    }
-  }
-
-  initializeTargetCC1FlagCache(vfs, types, requirements);
-
-  std::vector<std::pair<CompilationType, const std::string&>> jobs;
-  std::atomic<size_t> job_index(0);
-  for (CompilationType type : types) {
-    CompilationRequirements& req = requirements[type.arch];
-    for (const std::string& header : req.headers) {
-      jobs.emplace_back(type, header);
-    }
-  }
-
-  // Dup an empty file to stdin, so that we can use `clang -include a.h -` instead of `clang a.h`,
-  // since some warnings don't get generated in files that are compiled directly.
-  FILE* empty_file = tmpfile();
-  if (!empty_file) {
-    err(1, "failed to create temporary file");
-  }
-
-  int empty_file_fd = fileno(empty_file);
-  if (empty_file_fd == -1) {
-    errx(1, "fileno failed on tmpfile");
-  }
-
-  dup2(empty_file_fd, STDIN_FILENO);
-  fclose(empty_file);
-
-  thread_count = std::min(thread_count, jobs.size());
-
-  if (thread_count == 1) {
-    for (const auto& job : jobs) {
-      compileHeader(vfs, result.get(), job.first, job.second);
-    }
-  } else {
-    // Spawn threads.
-    for (size_t i = 0; i < thread_count; ++i) {
-      threads.emplace_back([&jobs, &job_index, &result, vfs]() {
-        while (true) {
-          size_t idx = job_index++;
-          if (idx >= jobs.size()) {
-            return;
-          }
-
-          const auto& job = jobs[idx];
-          compileHeader(vfs, result.get(), job.first, job.second);
-        }
-      });
-    }
-
-    // Reap them.
-    for (auto& thread : threads) {
-      thread.join();
-    }
-    threads.clear();
-  }
-
-  return result;
-}
-
-static std::set<CompilationType> getCompilationTypes(const Declaration* decl) {
-  std::set<CompilationType> result;
-  for (const auto& it : decl->availability) {
-    result.insert(it.first);
-  }
-  return result;
-}
-
-template<typename T>
-static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
-  std::vector<T> intersection;
-  std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(intersection));
-  return intersection;
-}
-
-// Perform a validity check on a symbol's declarations, enforcing the following invariants:
-//   1. At most one inline definition of the function exists (overloaded inline functions for
-//      _FORTIFY_SOURCE do not count because they are usually introduced to intercept the original
-//      functions or usually have enable_if attributes).
-//   2. All of the availability declarations for a symbol are compatible.
-//      If a function is declared as an inline before a certain version, the inline definition
-//      should have no version tag.
-//   3. Each availability type must only be present globally or on a per-arch basis.
-//      (e.g. __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(22) __DEPRECATED_IN(23) is fine,
-//      but not __INTRODUCED_IN(9) __INTRODUCED_IN_32(10))
-static bool checkSymbol(const Symbol& symbol) {
-  std::string cwd = getWorkingDir() + "/";
-
-  std::unordered_map<const Declaration*, std::set<CompilationType>> inline_definitions;
-  for (const auto& decl_it : symbol.declarations) {
-    const Declaration* decl = &decl_it.second;
-    if (decl->is_definition && !decl->fortify_inline) {
-      std::set<CompilationType> compilation_types = getCompilationTypes(decl);
-      for (const auto& inline_def_it : inline_definitions) {
-        auto intersection = Intersection(compilation_types, inline_def_it.second);
-        if (!intersection.empty()) {
-          fprintf(stderr, "versioner: conflicting inline definitions for symbol %s:\n",
-                  symbol.name.c_str());
-          fprintf(stderr, "  declarations visible in: %s\n", Join(intersection, ", ").c_str());
-          decl->dump(cwd, stderr, 4);
-          inline_def_it.first->dump(cwd, stderr, 4);
-          return false;
-        }
-      }
-
-      inline_definitions[decl] = std::move(compilation_types);
-    }
-
-    DeclarationAvailability availability;
-    if (!decl->calculateAvailability(&availability)) {
-      fprintf(stderr, "versioner: failed to calculate availability for declaration:\n");
-      decl->dump(cwd, stderr, 2);
-      return false;
-    }
-
-    if (decl->is_definition && !availability.empty()) {
-      fprintf(stderr, "versioner: inline definition has non-empty versioning information:\n");
-      decl->dump(cwd, stderr, 2);
-      return false;
-    }
-  }
-
-  DeclarationAvailability availability;
-  if (!symbol.calculateAvailability(&availability)) {
-    fprintf(stderr, "versioner: inconsistent availability for symbol '%s'\n", symbol.name.c_str());
-    symbol.dump(cwd);
-    return false;
-  }
-
-  // TODO: Check invariant #3.
-  return true;
-}
-
-static bool validityCheck(const HeaderDatabase* database) {
-  bool error = false;
-  std::string cwd = getWorkingDir() + "/";
-
-  for (const auto& symbol_it : database->symbols) {
-    if (!checkSymbol(symbol_it.second)) {
-      error = true;
-    }
-  }
-  return !error;
-}
-
-// Check that our symbol availability declarations match the actual NDK
-// platform symbol availability.
-static bool checkVersions(const std::set<CompilationType>& types,
-                          const HeaderDatabase* header_database,
-                          const NdkSymbolDatabase& symbol_database) {
-  std::string cwd = getWorkingDir() + "/";
-  bool failed = false;
-
-  std::map<Arch, std::set<CompilationType>> arch_types;
-  for (const CompilationType& type : types) {
-    arch_types[type.arch].insert(type);
-  }
-
-  std::set<std::string> completely_unavailable;
-  std::map<std::string, std::set<CompilationType>> missing_availability;
-  std::map<std::string, std::set<CompilationType>> extra_availability;
-
-  for (const auto& symbol_it : header_database->symbols) {
-    const auto& symbol_name = symbol_it.first;
-    DeclarationAvailability symbol_availability;
-
-    if (!symbol_it.second.calculateAvailability(&symbol_availability)) {
-      errx(1, "failed to calculate symbol availability");
-    }
-
-    const auto platform_availability_it = symbol_database.find(symbol_name);
-    if (platform_availability_it == symbol_database.end()) {
-      completely_unavailable.insert(symbol_name);
-      continue;
-    }
-
-    const auto& platform_availability = platform_availability_it->second;
-
-    for (const CompilationType& type : types) {
-      bool should_be_available = true;
-      const auto& global_availability = symbol_availability.global_availability;
-      const auto& arch_availability = symbol_availability.arch_availability[type.arch];
-      if (global_availability.introduced != 0 && global_availability.introduced > type.api_level) {
-        should_be_available = false;
-      }
-
-      if (arch_availability.introduced != 0 && arch_availability.introduced > type.api_level) {
-        should_be_available = false;
-      }
-
-      if (global_availability.obsoleted != 0 && global_availability.obsoleted <= type.api_level) {
-        should_be_available = false;
-      }
-
-      if (arch_availability.obsoleted != 0 && arch_availability.obsoleted <= type.api_level) {
-        should_be_available = false;
-      }
-
-      // The function declaration might be (validly) missing for the given CompilationType.
-      if (!symbol_it.second.hasDeclaration(type)) {
-        should_be_available = false;
-      }
-
-      bool is_available = platform_availability.count(type);
-
-      if (should_be_available != is_available) {
-        if (is_available) {
-          extra_availability[symbol_name].insert(type);
-        } else {
-          missing_availability[symbol_name].insert(type);
-        }
-      }
-    }
-  }
-
-  for (const auto& it : symbol_database) {
-    const std::string& symbol_name = it.first;
-
-    bool symbol_error = false;
-    if (auto missing_it = missing_availability.find(symbol_name);
-        missing_it != missing_availability.end()) {
-      printf("%s: declaration marked available but symbol missing in [%s]\n", symbol_name.c_str(),
-             Join(missing_it->second, ", ").c_str());
-      symbol_error = true;
-      failed = true;
-    }
-
-    if (strict) {
-      if (auto extra_it = extra_availability.find(symbol_name);
-          extra_it != extra_availability.end()) {
-        printf("%s: declaration marked unavailable but symbol available in [%s]\n",
-               symbol_name.c_str(), Join(extra_it->second, ", ").c_str());
-        symbol_error = true;
-        failed = true;
-      }
-    }
-
-    if (symbol_error) {
-      if (auto symbol_it = header_database->symbols.find(symbol_name);
-          symbol_it != header_database->symbols.end()) {
-        symbol_it->second.dump(cwd);
-      } else {
-        errx(1, "failed to find symbol in header database");
-      }
-    }
-  }
-
-  // TODO: Verify that function/variable declarations are actually function/variable symbols.
-  return !failed;
-}
-
-static void usage(bool help = false) {
-  fprintf(stderr, "Usage: versioner [OPTION]... [HEADER_PATH] [DEPS_PATH]\n");
-  if (!help) {
-    printf("Try 'versioner -h' for more information.\n");
-    exit(1);
-  } else {
-    fprintf(stderr, "Version headers at HEADER_PATH, with DEPS_PATH/ARCH/* on the include path\n");
-    fprintf(stderr, "Autodetects paths if HEADER_PATH and DEPS_PATH are not specified\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Target specification (defaults to all):\n");
-    fprintf(stderr, "  -a API_LEVEL\tbuild with specified API level (can be repeated)\n");
-    fprintf(stderr, "    \t\tdefaults to %s\n", Join(default_levels).c_str());
-    fprintf(stderr, "  -r ARCH\tbuild with specified architecture (can be repeated)\n");
-    fprintf(stderr, "    \t\tvalid architectures are %s\n", Join(supported_archs).c_str());
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Validation:\n");
-    fprintf(stderr, "  -p PATH\tcompare against NDK platform at PATH\n");
-    fprintf(stderr, "  -s\t\tenable strict warnings\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Preprocessing:\n");
-    fprintf(stderr, "  -o PATH\tpreprocess header files and emit them at PATH\n");
-    fprintf(stderr, "  -f\t\tpreprocess header files even if validation fails\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Miscellaneous:\n");
-    fprintf(stderr, "  -F\t\tdo not ignore FORTIFY headers by default\n");
-    fprintf(stderr, "  -d\t\tdump function availability\n");
-    fprintf(stderr, "  -j THREADS\tmaximum number of threads to use\n");
-    fprintf(stderr, "  -v\t\tenable verbose logging\n");
-    fprintf(stderr, "  -h\t\tdisplay this message\n");
-    exit(0);
-  }
-}
-
-// versioner uses a prebuilt version of clang, which is not up-to-date wrt/
-// container annotations. So disable container overflow checking. b/37775238
-extern "C" const char* __asan_default_options() {
-  return "detect_container_overflow=0";
-}
-
-int main(int argc, char** argv) {
-  std::string cwd = getWorkingDir() + "/";
-  std::string platform_dir;
-  std::set<Arch> selected_architectures;
-  std::set<int> selected_levels;
-  std::string preprocessor_output_path;
-  bool force = false;
-  bool dump = false;
-  bool ignore_fortify_headers = true;
-
-  int c;
-  while ((c = getopt(argc, argv, "a:r:p:so:fdj:vhFi")) != -1) {
-    switch (c) {
-      case 'a': {
-        char* end;
-        int api_level = strtol(optarg, &end, 10);
-        if (end == optarg || strlen(end) > 0) {
-          usage();
-        }
-
-        selected_levels.insert(api_level);
-        break;
-      }
-
-      case 'r': {
-        std::optional<Arch> arch = arch_from_string(optarg);
-        if (!arch) {
-          errx(1, "unknown architecture '%s'", optarg);
-        }
-        selected_architectures.insert(*arch);
-        break;
-      }
-
-      case 'p': {
-        if (!platform_dir.empty()) {
-          usage();
-        }
-
-        platform_dir = optarg;
-
-        if (platform_dir.empty()) {
-          usage();
-        }
-
-        struct stat st;
-        if (stat(platform_dir.c_str(), &st) != 0) {
-          err(1, "failed to stat platform directory '%s'", platform_dir.c_str());
-        }
-        if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) {
-          errx(1, "'%s' is not a file or directory", optarg);
-        }
-        break;
-      }
-
-      case 's':
-        strict = true;
-        break;
-
-      case 'o':
-        if (!preprocessor_output_path.empty()) {
-          usage();
-        }
-        preprocessor_output_path = optarg;
-        if (preprocessor_output_path.empty()) {
-          usage();
-        }
-        break;
-
-      case 'f':
-        force = true;
-        break;
-
-      case 'd':
-        dump = true;
-        break;
-
-      case 'j':
-        if (!android::base::ParseInt<int>(optarg, &max_thread_count, 1)) {
-          usage();
-        }
-        break;
-
-      case 'v':
-        verbose = true;
-        break;
-
-      case 'h':
-        usage(true);
-        break;
-
-      case 'i':
-        // Secret option for tests to -include <android/versioning.h>.
-        add_include = true;
-        break;
-
-      case 'F':
-        ignore_fortify_headers = false;
-        break;
-
-      default:
-        usage();
-        break;
-    }
-  }
-
-  if (argc - optind > 2 || optind > argc) {
-    usage();
-  }
-
-  HeaderLocationInformation location;
-
-  const char* top = getenv("ANDROID_BUILD_TOP");
-  if (!top && (optind == argc || add_include)) {
-    fprintf(stderr, "versioner: failed to autodetect bionic paths. Is ANDROID_BUILD_TOP set?\n");
-    usage();
-  }
-
-  if (optind == argc) {
-    // Neither HEADER_PATH nor DEPS_PATH were specified, so try to figure them out.
-    std::string versioner_dir = to_string(top) + "/bionic/tools/versioner";
-    location.header_path = versioner_dir + "/current";
-    location.dependency_dir = versioner_dir + "/dependencies";
-    if (platform_dir.empty()) {
-      platform_dir = versioner_dir + "/platforms";
-    }
-  } else {
-    if (!android::base::Realpath(argv[optind], &location.header_path)) {
-      err(1, "failed to get realpath for path '%s'", argv[optind]);
-    }
-
-    if (argc - optind == 2) {
-      location.dependency_dir = argv[optind + 1];
-    }
-  }
-
-  // Every file that lives in bits/fortify is logically a part of a header outside of bits/fortify.
-  // This makes the files there impossible to build on their own.
-  if (ignore_fortify_headers) {
-    std::string fortify_path = location.header_path;
-    if (!android::base::EndsWith(location.header_path, "/")) {
-      fortify_path += '/';
-    }
-    fortify_path += "bits/fortify";
-    location.ignored_directories.insert(std::move(fortify_path));
-  }
-
-  if (selected_levels.empty()) {
-    selected_levels = default_levels;
-  }
-
-  if (selected_architectures.empty()) {
-    selected_architectures = supported_archs;
-  }
-
-
-  struct stat st;
-  if (const char *path = location.header_path.c_str(); stat(path, &st) != 0) {
-    err(1, "failed to stat '%s'", path);
-  }
-
-  std::set<CompilationType> compilation_types;
-  std::optional<NdkSymbolDatabase> symbol_database;
-
-  compilation_types = generateCompilationTypes(selected_architectures, selected_levels);
-
-  // Do this before compiling so that we can early exit if the platforms don't match what we
-  // expect.
-  if (!platform_dir.empty()) {
-    symbol_database = parsePlatforms(compilation_types, platform_dir);
-  }
-
-  auto start = std::chrono::high_resolution_clock::now();
-  std::unique_ptr<HeaderDatabase> declaration_database =
-      compileHeaders(compilation_types, location);
-  auto end = std::chrono::high_resolution_clock::now();
-
-  if (verbose) {
-    auto diff = (end - start) / 1.0ms;
-    printf("Compiled headers for %zu targets in %0.2LFms\n", compilation_types.size(), diff);
-  }
-
-  bool failed = false;
-  if (dump) {
-    declaration_database->dump(location.header_path + "/");
-  } else {
-    if (!validityCheck(declaration_database.get())) {
-      printf("versioner: validity check failed\n");
-      failed = true;
-    }
-
-    if (symbol_database) {
-      if (!checkVersions(compilation_types, declaration_database.get(), *symbol_database)) {
-        printf("versioner: version check failed\n");
-        failed = true;
-      }
-    }
-  }
-
-  if (!preprocessor_output_path.empty() && (force || !failed)) {
-    failed = !preprocessHeaders(preprocessor_output_path, location.header_path,
-                                declaration_database.get());
-  }
-  return failed;
-}
diff --git a/tools/versioner/src/versioner.h b/tools/versioner/src/versioner.h
deleted file mode 100644
index 225e14b..0000000
--- a/tools/versioner/src/versioner.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2016 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 <map>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-extern bool strict;
-extern bool verbose;
-extern bool add_include;
-
-#define D(...)             \
-  do {                     \
-    if (verbose) {         \
-      printf(__VA_ARGS__); \
-    }                      \
-  } while (0)
-
-static const std::unordered_map<std::string, std::set<Arch>> ignored_headers = {
-  // Internal header.
-  // TODO: we should probably just admit we're never getting rid of this.
-  { "sys/_system_properties.h", supported_archs },
-
-  // time64.h #errors when included on LP64 archs.
-  { "time64.h", { Arch::arm64, Arch::riscv64, Arch::x86_64 } },
-};
diff --git a/tools/versioner/tests/.gitignore b/tools/versioner/tests/.gitignore
deleted file mode 100644
index 89f9ac0..0000000
--- a/tools/versioner/tests/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-out/
diff --git a/tools/versioner/tests/arch_specific/headers/foo.h b/tools/versioner/tests/arch_specific/headers/foo.h
deleted file mode 100644
index 4830a68..0000000
--- a/tools/versioner/tests/arch_specific/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo();
-
-#if defined(__i386__)
-int bar();
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/arch_specific/platforms/libc.map.txt b/tools/versioner/tests/arch_specific/platforms/libc.map.txt
deleted file mode 100644
index 5aa11ed..0000000
--- a/tools/versioner/tests/arch_specific/platforms/libc.map.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-LIBC {
-  global:
-    foo;  # arm x86
-    bar;  # x86
-};
diff --git a/tools/versioner/tests/arch_specific/run.sh b/tools/versioner/tests/arch_specific/run.sh
deleted file mode 100644
index f0d95ae..0000000
--- a/tools/versioner/tests/arch_specific/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -r x86 -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/compilation_error/expected_fail b/tools/versioner/tests/compilation_error/expected_fail
deleted file mode 100644
index f18b625..0000000
--- a/tools/versioner/tests/compilation_error/expected_fail
+++ /dev/null
@@ -1 +0,0 @@
-versioner: compilation generated warnings or errors
diff --git a/tools/versioner/tests/compilation_error/headers/foo.h b/tools/versioner/tests/compilation_error/headers/foo.h
deleted file mode 100644
index 51c087a..0000000
--- a/tools/versioner/tests/compilation_error/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#error foo
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/compilation_error/platforms/libc.map.txt b/tools/versioner/tests/compilation_error/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/compilation_error/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/compilation_error/run.sh b/tools/versioner/tests/compilation_error/run.sh
deleted file mode 100644
index 7e8d489..0000000
--- a/tools/versioner/tests/compilation_error/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i -j1
diff --git a/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h b/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h
deleted file mode 100644
index b2d357a..0000000
--- a/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int arm_t;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h b/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h
deleted file mode 100644
index baa5857..0000000
--- a/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int foo_t;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h b/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h
deleted file mode 100644
index b73f7cc..0000000
--- a/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int x86_t;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/headers/foo.h b/tools/versioner/tests/dependencies/headers/foo.h
deleted file mode 100644
index 875de1b..0000000
--- a/tools/versioner/tests/dependencies/headers/foo.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include <archdep.h>
-#include <foodep.h>
-
-#if defined(__i386__)
-x86_t foo(foo_t);
-#elif defined(__arm__)
-arm_t foo(foo_t);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/platforms/libc.map.txt b/tools/versioner/tests/dependencies/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/dependencies/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/dependencies/run.sh b/tools/versioner/tests/dependencies/run.sh
deleted file mode 100644
index 0c17907..0000000
--- a/tools/versioner/tests/dependencies/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers dependencies -p platforms -r arm -r x86 -a 9
\ No newline at end of file
diff --git a/tools/versioner/tests/extern_cpp/headers/string.h b/tools/versioner/tests/extern_cpp/headers/string.h
deleted file mode 100644
index 5ac43ac..0000000
--- a/tools/versioner/tests/extern_cpp/headers/string.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__cplusplus)
-extern "C++" char* basename(char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#else
-char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#endif
-
-char* foo() __INTRODUCED_IN(8);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/extern_cpp/platforms/libc.map.txt b/tools/versioner/tests/extern_cpp/platforms/libc.map.txt
deleted file mode 100644
index 297d1fb..0000000
--- a/tools/versioner/tests/extern_cpp/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    __gnu_basename;  # introduced=23
-};
diff --git a/tools/versioner/tests/extern_cpp/run.sh b/tools/versioner/tests/extern_cpp/run.sh
deleted file mode 100644
index e320c95..0000000
--- a/tools/versioner/tests/extern_cpp/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 21 -a 23 -i
diff --git a/tools/versioner/tests/extern_cpp_mismatch/headers/string.h b/tools/versioner/tests/extern_cpp_mismatch/headers/string.h
deleted file mode 100644
index 66133d8..0000000
--- a/tools/versioner/tests/extern_cpp_mismatch/headers/string.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__cplusplus)
-extern "C++" char* basename(char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#else
-char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt b/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/extern_cpp_mismatch/run.sh b/tools/versioner/tests/extern_cpp_mismatch/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/extern_cpp_mismatch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/fortify_inline/headers/fcntl.h b/tools/versioner/tests/fortify_inline/headers/fcntl.h
deleted file mode 100644
index dc81ef8..0000000
--- a/tools/versioner/tests/fortify_inline/headers/fcntl.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-extern int open_real(const char* name, int flags, ...) __asm__("open");
-
-#define O_CREAT 00000100
-
-typedef unsigned int mode_t;
-
-static inline __attribute__((always_inline))
-int open(const char* name, int flags)
-    __attribute__((annotate("versioner_fortify_inline")))
-    __attribute__((overloadable))
-    __attribute__((enable_if(!(flags & O_CREAT), ""))) {
-  return open_real(name, flags);
-}
-
-static inline __attribute__((always_inline))
-int open(const char* name, int flags, mode_t mode)
-    __attribute__((annotate("versioner_fortify_inline")))
-    __attribute__((overloadable))
-    __attribute__((enable_if(flags & O_CREAT, ""))) {
-  return open_real(name, flags, mode);
-}
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/fortify_inline/platforms/libc.map.txt b/tools/versioner/tests/fortify_inline/platforms/libc.map.txt
deleted file mode 100644
index 2f09034..0000000
--- a/tools/versioner/tests/fortify_inline/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    open;
-};
diff --git a/tools/versioner/tests/fortify_inline/run.sh b/tools/versioner/tests/fortify_inline/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/fortify_inline/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/inline/headers/foo.h b/tools/versioner/tests/inline/headers/foo.h
deleted file mode 100644
index a337f9c..0000000
--- a/tools/versioner/tests/inline/headers/foo.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ < 12
-static int foo() {
-  return 0;
-}
-#else
-int foo() __INTRODUCED_IN(12);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/inline/platforms/libc.map.txt b/tools/versioner/tests/inline/platforms/libc.map.txt
deleted file mode 100644
index 4dced92..0000000
--- a/tools/versioner/tests/inline/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # introduced=12
-};
diff --git a/tools/versioner/tests/inline/run.sh b/tools/versioner/tests/inline/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/inline/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/missing_api/expected_fail b/tools/versioner/tests/missing_api/expected_fail
deleted file mode 100644
index 9f097f7..0000000
--- a/tools/versioner/tests/missing_api/expected_fail
+++ /dev/null
@@ -1,4 +0,0 @@
-  foo: introduced = 9
-    extern declaration @ headers/foo.h:5:1
-      introduced = 9
-versioner: version check failed
diff --git a/tools/versioner/tests/missing_api/headers/foo.h b/tools/versioner/tests/missing_api/headers/foo.h
deleted file mode 100644
index c201dbb..0000000
--- a/tools/versioner/tests/missing_api/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __INTRODUCED_IN(9);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/missing_api/platforms/libc.map.txt b/tools/versioner/tests/missing_api/platforms/libc.map.txt
deleted file mode 100644
index 3701a9d..0000000
--- a/tools/versioner/tests/missing_api/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # api-level=9
-};
diff --git a/tools/versioner/tests/missing_api/run.sh b/tools/versioner/tests/missing_api/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/missing_api/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/missing_arch/expected_fail b/tools/versioner/tests/missing_arch/expected_fail
deleted file mode 100644
index 7b33e19..0000000
--- a/tools/versioner/tests/missing_arch/expected_fail
+++ /dev/null
@@ -1,4 +0,0 @@
-  foo: no availability
-    extern declaration @ headers/foo.h:5:1
-      no availability
-versioner: version check failed
diff --git a/tools/versioner/tests/missing_arch/headers/foo.h b/tools/versioner/tests/missing_arch/headers/foo.h
deleted file mode 100644
index 5ba4794..0000000
--- a/tools/versioner/tests/missing_arch/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo();
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/missing_arch/platforms/libc.map.txt b/tools/versioner/tests/missing_arch/platforms/libc.map.txt
deleted file mode 100644
index f56190e..0000000
--- a/tools/versioner/tests/missing_arch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # arm
-};
diff --git a/tools/versioner/tests/missing_arch/run.sh b/tools/versioner/tests/missing_arch/run.sh
deleted file mode 100644
index f0d95ae..0000000
--- a/tools/versioner/tests/missing_arch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -r x86 -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/multiple_decl/headers/bar.h b/tools/versioner/tests/multiple_decl/headers/bar.h
deleted file mode 100644
index b16617b..0000000
--- a/tools/versioner/tests/multiple_decl/headers/bar.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(12);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl/headers/foo.h b/tools/versioner/tests/multiple_decl/headers/foo.h
deleted file mode 100644
index b16617b..0000000
--- a/tools/versioner/tests/multiple_decl/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(12);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl/platforms/libc.map.txt b/tools/versioner/tests/multiple_decl/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_decl/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_decl/run.sh b/tools/versioner/tests/multiple_decl/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/multiple_decl/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/multiple_decl_mismatch/expected_fail b/tools/versioner/tests/multiple_decl_mismatch/expected_fail
deleted file mode 100644
index 30e7233..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/expected_fail
+++ /dev/null
@@ -1,8 +0,0 @@
-versioner: inconsistent availability for symbol 'foo'
-versioner: failed to calculate symbol availability
-  foo: invalid
-    extern declaration @ headers/bar.h:5:1
-      obsoleted = 12
-    extern declaration @ headers/foo.h:5:1
-      obsoleted = 9
-versioner: validity check failed
diff --git a/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h b/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h
deleted file mode 100644
index b16617b..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(12);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h b/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h
deleted file mode 100644
index 8e8f98c..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(9);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt b/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_decl_mismatch/run.sh b/tools/versioner/tests/multiple_decl_mismatch/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/multiple_definition/expected_fail b/tools/versioner/tests/multiple_definition/expected_fail
deleted file mode 100644
index 5abb833..0000000
--- a/tools/versioner/tests/multiple_definition/expected_fail
+++ /dev/null
@@ -1,7 +0,0 @@
-versioner: conflicting inline definitions for symbol foo:
-  declarations visible in: arm-9 [c, fob = 32], arm-9 [c, fob = 64], arm-12 [c, fob = 32], arm-12 [c, fob = 64], arm-9 [c++, fob = 32], arm-9 [c++, fob = 64], arm-12 [c++, fob = 32], arm-12 [c++, fob = 64]
-    static definition @ headers/foo.h:5:1
-      no availability
-    static definition @ headers/bar.h:5:1
-      no availability
-versioner: validity check failed
diff --git a/tools/versioner/tests/multiple_definition/headers/bar.h b/tools/versioner/tests/multiple_definition/headers/bar.h
deleted file mode 100644
index 29592c6..0000000
--- a/tools/versioner/tests/multiple_definition/headers/bar.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-static int foo() {
-  return 0;
-}
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition/headers/foo.h b/tools/versioner/tests/multiple_definition/headers/foo.h
deleted file mode 100644
index 29592c6..0000000
--- a/tools/versioner/tests/multiple_definition/headers/foo.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-static int foo() {
-  return 0;
-}
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition/platforms/libc.map.txt b/tools/versioner/tests/multiple_definition/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_definition/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_definition/run.sh b/tools/versioner/tests/multiple_definition/run.sh
deleted file mode 100644
index e4abbe7..0000000
--- a/tools/versioner/tests/multiple_definition/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/bar.h b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
deleted file mode 100644
index 6eced51..0000000
--- a/tools/versioner/tests/multiple_definition_ok/headers/bar.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ == 12
-static int foo() {
-  return 0;
-}
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/foo.h b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
deleted file mode 100644
index 773d274..0000000
--- a/tools/versioner/tests/multiple_definition_ok/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ == 9
-static int foo() {
-  return 0;
-}
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt b/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_definition_ok/run.sh b/tools/versioner/tests/multiple_definition_ok/run.sh
deleted file mode 100644
index e4abbe7..0000000
--- a/tools/versioner/tests/multiple_definition_ok/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
diff --git a/tools/versioner/tests/obsoleted/headers/foo.h b/tools/versioner/tests/obsoleted/headers/foo.h
deleted file mode 100644
index e9630e5..0000000
--- a/tools/versioner/tests/obsoleted/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __INTRODUCED_IN(9) __REMOVED_IN(11);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/obsoleted/platforms/libc.map.txt b/tools/versioner/tests/obsoleted/platforms/libc.map.txt
deleted file mode 100644
index 3701a9d..0000000
--- a/tools/versioner/tests/obsoleted/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # api-level=9
-};
diff --git a/tools/versioner/tests/obsoleted/run.sh b/tools/versioner/tests/obsoleted/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/obsoleted/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -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
deleted file mode 100644
index 4f74927..0000000
--- a/tools/versioner/tests/preprocessor/expected/foo.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int always_available();
-
-int also_always_available() __INTRODUCED_IN(9);
-
-
-#if __ANDROID_API__ >= 13
-int needs_guard() __INTRODUCED_IN(13);
-#endif /* __ANDROID_API__ >= 13 */
-
-
-#if __ANDROID_API__ >= 12
-
-#if __ANDROID_API__ >= 13
-int needs_guard_2() __INTRODUCED_IN(13);
-#endif /* __ANDROID_API__ >= 13 */
-
-#endif
-
-#if __ANDROID_API__ >= 13
-int already_guarded() __INTRODUCED_IN(13);
-#endif
-
-#if __ANDROID_API__ > 13
-int already_guarded_2() __INTRODUCED_IN(13);
-#endif
-
-#if defined(__arm__)
-
-#if __ANDROID_API__ >= 14
-int specific_arch() __INTRODUCED_IN(14);
-#endif /* __ANDROID_API__ >= 14 */
-
-
-#if __ANDROID_API__ >= 14
-int specific_arch_already_guarded() __INTRODUCED_IN(14);
-#endif
-
-#if __ANDROID_API__ > 14
-int specific_arch_already_guarded_2() __INTRODUCED_IN(14);
-#endif
-#endif
-
-#if defined(__arm__) || defined(__i386__)
-
-#if __ANDROID_API__ >= 14
-int multiple_archs() __INTRODUCED_IN(14);
-#endif /* __ANDROID_API__ >= 14 */
-
-#endif
-
-// __INTRODUCED_IN_64(21) should be ignored.
-
-#if (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__))
-int multiple_introduced_1() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(21);
-#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__)) */
-
-
-// This needs different guards for 32 vs 64.
-
-#if (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__) && __ANDROID_API__ >= 26)
-int multiple_introduced_2() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(26);
-#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__) && __ANDROID_API__ >= 26) */
-
-
-// This produces both an LP64 and a not-LP64 check, but it doesn't need to check for all 64-bit
-// targets separately.
-
-#if (!defined(__LP64__) && __ANDROID_API__ >= 23) || (defined(__LP64__) && __ANDROID_API__ >= 23)
-int multiple_introduced_3() __INTRODUCED_IN_32(23) __INTRODUCED_IN_64(23);
-#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 23) || (defined(__LP64__) && __ANDROID_API__ >= 23) */
-
-
-
-#if (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28)
-int added_to_lp64_late() __INTRODUCED_IN_64(28);
-#endif /* (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28) */
-
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor/headers/foo.h b/tools/versioner/tests/preprocessor/headers/foo.h
deleted file mode 100644
index b01d8a9..0000000
--- a/tools/versioner/tests/preprocessor/headers/foo.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int always_available();
-
-int also_always_available() __INTRODUCED_IN(9);
-
-int needs_guard() __INTRODUCED_IN(13);
-
-#if __ANDROID_API__ >= 12
-int needs_guard_2() __INTRODUCED_IN(13);
-#endif
-
-#if __ANDROID_API__ >= 13
-int already_guarded() __INTRODUCED_IN(13);
-#endif
-
-#if __ANDROID_API__ > 13
-int already_guarded_2() __INTRODUCED_IN(13);
-#endif
-
-#if defined(__arm__)
-int specific_arch() __INTRODUCED_IN(14);
-
-#if __ANDROID_API__ >= 14
-int specific_arch_already_guarded() __INTRODUCED_IN(14);
-#endif
-
-#if __ANDROID_API__ > 14
-int specific_arch_already_guarded_2() __INTRODUCED_IN(14);
-#endif
-#endif
-
-#if defined(__arm__) || defined(__i386__)
-int multiple_archs() __INTRODUCED_IN(14);
-#endif
-
-// __INTRODUCED_IN_64(21) should be ignored.
-int multiple_introduced_1() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(21);
-
-// This needs different guards for 32 vs 64.
-int multiple_introduced_2() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(26);
-
-// This produces both an LP64 and a not-LP64 check, but it doesn't need to check for all 64-bit
-// targets separately.
-int multiple_introduced_3() __INTRODUCED_IN_32(23) __INTRODUCED_IN_64(23);
-
-int added_to_lp64_late() __INTRODUCED_IN_64(28);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor/run.sh b/tools/versioner/tests/preprocessor/run.sh
deleted file mode 100644
index b039656..0000000
--- a/tools/versioner/tests/preprocessor/run.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-set -e
-
-function run_test {
-  SRC=$1
-  DST=$2
-  rm -rf $2
-  versioner -a 9 -a 12 -a 13 -a 14 -a 15 -a 21 -a 23 $1 -i -o $2
-  diff -q -w -B $2 expected
-}
-
-run_test headers out
-run_test headers/ out
-run_test headers out/
-run_test headers/ out/
-
-run_test `pwd`/headers out
-run_test `pwd`/headers/ out
-run_test `pwd`/headers out/
-run_test `pwd`/headers/ out/
-
-run_test headers `pwd`/out
-run_test headers/ `pwd`/out
-run_test headers `pwd`/out/
-run_test headers/ `pwd`/out/
-
-run_test `pwd`/headers `pwd`/out
-run_test `pwd`/headers/ `pwd`/out
-run_test `pwd`/headers `pwd`/out/
-run_test `pwd`/headers/ `pwd`/out/
diff --git a/tools/versioner/tests/preprocessor_extern_cpp/expected/foo.h b/tools/versioner/tests/preprocessor_extern_cpp/expected/foo.h
deleted file mode 100644
index 9b2d122..0000000
--- a/tools/versioner/tests/preprocessor_extern_cpp/expected/foo.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#define __RENAME(x) asm(#x)
-
-#if defined(__cplusplus)
-
-#if __ANDROID_API__ >= 24
-extern "C++" const char* strchrnul(const char*, int) __RENAME(strchrnul) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#endif
-
-#if defined(__cplusplus)
-extern "C" int foo();
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-#if __ANDROID_API__ >= 24
-char* strchrnul(char*, int) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_extern_cpp/headers/foo.h b/tools/versioner/tests/preprocessor_extern_cpp/headers/foo.h
deleted file mode 100644
index de26d21..0000000
--- a/tools/versioner/tests/preprocessor_extern_cpp/headers/foo.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#define __RENAME(x) asm(#x)
-
-#if defined(__cplusplus)
-extern "C++" const char* strchrnul(const char*, int) __RENAME(strchrnul) __INTRODUCED_IN(24);
-#endif
-
-#if defined(__cplusplus)
-extern "C" int foo();
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-char* strchrnul(char*, int) __INTRODUCED_IN(24);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_extern_cpp/run.sh b/tools/versioner/tests/preprocessor_extern_cpp/run.sh
deleted file mode 100644
index 50d9b5c..0000000
--- a/tools/versioner/tests/preprocessor_extern_cpp/run.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-set -e
-
-function run_test {
-  SRC=$1
-  DST=$2
-  rm -rf $2
-  versioner -a 9 -a 12 -a 13 -a 14 -a 15 $1 -i -o $2
-  diff -q -w -B $2 expected
-}
-
-run_test headers out
-run_test headers/ out
-run_test headers out/
-run_test headers/ out/
-
-run_test `pwd`/headers out
-run_test `pwd`/headers/ out
-run_test `pwd`/headers out/
-run_test `pwd`/headers/ out/
-
-run_test headers `pwd`/out
-run_test headers/ `pwd`/out
-run_test headers `pwd`/out/
-run_test headers/ `pwd`/out/
-
-run_test `pwd`/headers `pwd`/out
-run_test `pwd`/headers/ `pwd`/out
-run_test `pwd`/headers `pwd`/out/
-run_test `pwd`/headers/ `pwd`/out/
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
deleted file mode 100644
index dcfaaee..0000000
--- a/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int off_t;
-typedef int ssize_t;
-typedef unsigned size_t;
-
-#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
-#if _FILE_OFFSET_BITS == 64
-#define __USE_FILE_OFFSET64 1
-#endif
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= 21
-int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
-#else
-int truncate(const char* __path, off_t __length);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-
-#if __ANDROID_API__ >= 12
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset) __RENAME(pread64)
-    __INTRODUCED_IN(12);
-#endif /* __ANDROID_API__ >= 12 */
-
-#else
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
-#else
-off_t lseek(int __fd, off_t __offset, int __whence);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
deleted file mode 100644
index 5ffffa8..0000000
--- a/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int off_t;
-typedef int ssize_t;
-typedef unsigned size_t;
-
-#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
-#if _FILE_OFFSET_BITS == 64
-#define __USE_FILE_OFFSET64 1
-#endif
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= 21
-int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
-#else
-int truncate(const char* __path, off_t __length);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset) __RENAME(pread64)
-    __INTRODUCED_IN(12);
-#else
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
-#else
-off_t lseek(int __fd, off_t __offset, int __whence);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/run.sh b/tools/versioner/tests/preprocessor_file_offset_bits/run.sh
deleted file mode 100644
index d974cba..0000000
--- a/tools/versioner/tests/preprocessor_file_offset_bits/run.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-set -e
-
-rm -rf out
-versioner headers -a 9 -a 12 -a 13 -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/preprocessor_idempotence/expected/foo.h b/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
deleted file mode 100644
index bc442e5..0000000
--- a/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ >= 10
-int foo() __INTRODUCED_IN(10);
-#endif
-
-#if __ANDROID_API__ >= 21
-int bar(int) __INTRODUCED_IN(21);
-#endif
-
-#if __ANDROID_API__ >= 10
-int multiple_1() __INTRODUCED_IN(10);
-int multiple_2() __INTRODUCED_IN(10);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/headers/foo.h b/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
deleted file mode 100644
index bc442e5..0000000
--- a/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ >= 10
-int foo() __INTRODUCED_IN(10);
-#endif
-
-#if __ANDROID_API__ >= 21
-int bar(int) __INTRODUCED_IN(21);
-#endif
-
-#if __ANDROID_API__ >= 10
-int multiple_1() __INTRODUCED_IN(10);
-int multiple_2() __INTRODUCED_IN(10);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/run.sh b/tools/versioner/tests/preprocessor_idempotence/run.sh
deleted file mode 100644
index 1b0aae2..0000000
--- a/tools/versioner/tests/preprocessor_idempotence/run.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-rm -rf out
-set -e
-versioner headers -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/preprocessor_merging/expected/foo.h b/tools/versioner/tests/preprocessor_merging/expected/foo.h
deleted file mode 100644
index ecd7f71..0000000
--- a/tools/versioner/tests/preprocessor_merging/expected/foo.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-#if __ANDROID_API__ >= 10
-int block_merging_1() __INTRODUCED_IN(10); // foo
-int block_merging_2() __INTRODUCED_IN(10); /* bar */
-int block_merging_3() __INTRODUCED_IN(10); /* baz
-//*/
-int block_merging_4() __INTRODUCED_IN(10);
-#endif /* __ANDROID_API__ >= 10 */
-
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_merging/headers/foo.h b/tools/versioner/tests/preprocessor_merging/headers/foo.h
deleted file mode 100644
index 7aaa471..0000000
--- a/tools/versioner/tests/preprocessor_merging/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int block_merging_1() __INTRODUCED_IN(10); // foo
-int block_merging_2() __INTRODUCED_IN(10); /* bar */
-int block_merging_3() __INTRODUCED_IN(10); /* baz
-//*/
-int block_merging_4() __INTRODUCED_IN(10);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_merging/run.sh b/tools/versioner/tests/preprocessor_merging/run.sh
deleted file mode 100644
index 1929757..0000000
--- a/tools/versioner/tests/preprocessor_merging/run.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-rm -rf out
-set -e
-versioner headers -a 9 -a 10 -a 11 -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/preprocessor_no_guard/expected/foo.h b/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
deleted file mode 100644
index 3ef0c30..0000000
--- a/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_no_guard/headers/foo.h b/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
deleted file mode 100644
index 3ef0c30..0000000
--- a/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_no_guard/run.sh b/tools/versioner/tests/preprocessor_no_guard/run.sh
deleted file mode 100644
index 1b0aae2..0000000
--- a/tools/versioner/tests/preprocessor_no_guard/run.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-rm -rf out
-set -e
-versioner headers -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/slow_preprocessor_idempotence/run.sh b/tools/versioner/tests/slow_preprocessor_idempotence/run.sh
deleted file mode 100644
index 6426156..0000000
--- a/tools/versioner/tests/slow_preprocessor_idempotence/run.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-rm -rf out
-set -e
-mkdir out
-versioner -o out/initial
-versioner out/initial ../../dependencies -o out/second
-diff -qrwB out/initial out/second
diff --git a/tools/versioner/tests/smoke/headers/foo.h b/tools/versioner/tests/smoke/headers/foo.h
deleted file mode 100644
index c201dbb..0000000
--- a/tools/versioner/tests/smoke/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __INTRODUCED_IN(9);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/smoke/platforms/libc.map.txt b/tools/versioner/tests/smoke/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/smoke/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/smoke/run.sh b/tools/versioner/tests/smoke/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/smoke/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/unnamed_bitfield/headers/foo.h b/tools/versioner/tests/unnamed_bitfield/headers/foo.h
deleted file mode 100644
index 58686c3..0000000
--- a/tools/versioner/tests/unnamed_bitfield/headers/foo.h
+++ /dev/null
@@ -1,8 +0,0 @@
-// <sys/timex.h> was causing a segfault when compiled in C++ mode because
-// versioner was trying to mangle the name of an unnamed bitfield.
-struct foo {
-  int : 32;
-  int : 32;
-  int : 32;
-  int : 32;
-};
diff --git a/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt b/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/unnamed_bitfield/run.sh b/tools/versioner/tests/unnamed_bitfield/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/unnamed_bitfield/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/version_mismatch/expected_fail b/tools/versioner/tests/version_mismatch/expected_fail
deleted file mode 100644
index 95d284b..0000000
--- a/tools/versioner/tests/version_mismatch/expected_fail
+++ /dev/null
@@ -1,8 +0,0 @@
-versioner: inconsistent availability for symbol 'foo'
-versioner: failed to calculate symbol availability
-  foo: invalid
-    extern declaration @ headers/foo.h:6:1
-      introduced = 9
-    extern declaration @ headers/foo.h:8:1
-      introduced = 10
-versioner: validity check failed
diff --git a/tools/versioner/tests/version_mismatch/headers/foo.h b/tools/versioner/tests/version_mismatch/headers/foo.h
deleted file mode 100644
index ea35f36..0000000
--- a/tools/versioner/tests/version_mismatch/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ <= 9
-int foo() __INTRODUCED_IN(9);
-#else
-int foo() __INTRODUCED_IN(10);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/version_mismatch/platforms/libc.map.txt b/tools/versioner/tests/version_mismatch/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/version_mismatch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/version_mismatch/run.sh b/tools/versioner/tests/version_mismatch/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/version_mismatch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file