Merge "Remove libskia.so from the greylist"
diff --git a/libc/Android.bp b/libc/Android.bp
index 89657d7..00686ac 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -546,7 +546,6 @@
 
         // May be overriden by per-arch optimized versions
         "upstream-openbsd/lib/libc/string/memchr.c",
-        "upstream-openbsd/lib/libc/string/memmove.c",
         "upstream-openbsd/lib/libc/string/memrchr.c",
         "upstream-openbsd/lib/libc/string/stpcpy.c",
         "upstream-openbsd/lib/libc/string/stpncpy.c",
@@ -566,7 +565,6 @@
             ],
             neon: {
                 exclude_srcs: [
-                    "upstream-openbsd/lib/libc/string/memmove.c",
                     "upstream-openbsd/lib/libc/string/stpcpy.c",
                     "upstream-openbsd/lib/libc/string/strcat.c",
                 ],
@@ -575,7 +573,6 @@
         arm64: {
             exclude_srcs: [
                 "upstream-openbsd/lib/libc/string/memchr.c",
-                "upstream-openbsd/lib/libc/string/memmove.c",
                 "upstream-openbsd/lib/libc/string/stpcpy.c",
                 "upstream-openbsd/lib/libc/string/strcpy.c",
                 "upstream-openbsd/lib/libc/string/strncmp.c",
@@ -584,7 +581,6 @@
         mips: {
             exclude_srcs: [
                 "upstream-openbsd/lib/libc/string/memchr.c",
-                "upstream-openbsd/lib/libc/string/memmove.c",
                 "upstream-openbsd/lib/libc/string/strcpy.c",
                 "upstream-openbsd/lib/libc/string/strncmp.c",
             ],
@@ -592,7 +588,6 @@
         mips64: {
             exclude_srcs: [
                 "upstream-openbsd/lib/libc/string/memchr.c",
-                "upstream-openbsd/lib/libc/string/memmove.c",
                 "upstream-openbsd/lib/libc/string/strcpy.c",
                 "upstream-openbsd/lib/libc/string/strncmp.c",
             ],
@@ -600,7 +595,6 @@
         x86: {
             exclude_srcs: [
                 "upstream-openbsd/lib/libc/string/memchr.c",
-                "upstream-openbsd/lib/libc/string/memmove.c",
                 "upstream-openbsd/lib/libc/string/memrchr.c",
                 "upstream-openbsd/lib/libc/string/stpcpy.c",
                 "upstream-openbsd/lib/libc/string/stpncpy.c",
@@ -620,7 +614,6 @@
 
         x86_64: {
             exclude_srcs: [
-                "upstream-openbsd/lib/libc/string/memmove.c",
                 "upstream-openbsd/lib/libc/string/stpcpy.c",
                 "upstream-openbsd/lib/libc/string/stpncpy.c",
                 "upstream-openbsd/lib/libc/string/strcat.c",
@@ -860,6 +853,7 @@
             srcs: [
                 "arch-arm/generic/bionic/memcmp.S",
                 "arch-arm/generic/bionic/memcpy.S",
+                "arch-arm/generic/bionic/memmove.S",
                 "arch-arm/generic/bionic/memset.S",
                 "arch-arm/generic/bionic/strcmp.S",
                 "arch-arm/generic/bionic/strcpy.S",
@@ -877,8 +871,8 @@
             ],
             cortex_a7: {
                 srcs: [
-                    "arch-arm/cortex-a7/bionic/memset.S",
                     "arch-arm/cortex-a7/bionic/memcpy.S",
+                    "arch-arm/cortex-a7/bionic/memset.S",
                 ],
                 exclude_srcs: [
                     "arch-arm/cortex-a15/bionic/memcpy.S",
@@ -897,8 +891,8 @@
                     "arch-arm/cortex-a9/bionic/strlen.S",
                 ],
                 exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
                     "arch-arm/cortex-a15/bionic/memcpy.S",
+                    "arch-arm/cortex-a15/bionic/memset.S",
 
                     "arch-arm/cortex-a15/bionic/stpcpy.S",
                     "arch-arm/cortex-a15/bionic/strcat.S",
@@ -1010,6 +1004,7 @@
                 ],
                 exclude_srcs: [
                     "arch-arm/generic/bionic/memcpy.S",
+                    "arch-arm/generic/bionic/memmove.S",
                     "arch-arm/generic/bionic/memset.S",
                     "arch-arm/generic/bionic/strcmp.S",
                     "arch-arm/generic/bionic/strcpy.S",
@@ -1772,6 +1767,7 @@
     arch: {
         arm: {
             //TODO: This is to work around b/24465209. Remove after root cause is fixed
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
 
             // Don't re-export new/delete and friends, even if the compiler really wants to.
@@ -1805,6 +1801,7 @@
         },
         x86: {
             //TODO: This is to work around b/24465209. Remove after root cause is fixed
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
 
             // Don't re-export new/delete and friends, even if the compiler really wants to.
@@ -1836,6 +1833,7 @@
     //TODO (dimitry): This is to work around b/24465209. Remove after root cause is fixed
     arch: {
         arm: {
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
             version_script: "libstdc++.arm.map",
         },
@@ -1849,6 +1847,7 @@
             version_script: "libstdc++.mips64.map",
         },
         x86: {
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
             version_script: "libstdc++.x86.map",
         },
@@ -2023,7 +2022,7 @@
     defaults: ["crt_defaults"],
 }
 
-preprocessed_ndk_headers {
+versioned_ndk_headers {
     name: "common_libc",
     from: "include",
     to: "",
diff --git a/libc/NOTICE b/libc/NOTICE
index 35fc858..ae7da18 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3101,6 +3101,35 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 1997 The NetBSD Foundation, Inc.
+All rights reserved.
+
+This code is derived from software contributed to The NetBSD Foundation
+by Neil A. Carson and Mark Brinicombe
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
 Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
 
 Permission to use, copy, modify, and distribute this software for any
diff --git a/libc/arch-arm/generic/bionic/memmove.S b/libc/arch-arm/generic/bionic/memmove.S
new file mode 100644
index 0000000..d5ee99d
--- /dev/null
+++ b/libc/arch-arm/generic/bionic/memmove.S
@@ -0,0 +1,471 @@
+/*	$OpenBSD: _memcpy.S,v 1.6 2016/08/06 19:16:09 guenther Exp $	*/
+/*	$NetBSD: _memcpy.S,v 1.4 2003/04/05 23:08:52 bjh21 Exp $	*/
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <private/bionic_asm.h>
+
+  .syntax unified
+
+/*
+ * This is one fun bit of code ...
+ * Some easy listening music is suggested while trying to understand this
+ * code e.g. Iron Maiden
+ *
+ * For anyone attempting to understand it :
+ *
+ * The core code is implemented here with simple stubs for memcpy()
+ * memmove() and bcopy().
+ *
+ * All local labels are prefixed with Lmemcpy_
+ * Following the prefix a label starting f is used in the forward copy code
+ * while a label using b is used in the backwards copy code
+ * The source and destination addresses determine whether a forward or
+ * backward copy is performed.
+ * Separate bits of code are used to deal with the following situations
+ * for both the forward and backwards copy.
+ * unaligned source address
+ * unaligned destination address
+ * Separate copy routines are used to produce an optimised result for each
+ * of these cases.
+ * The copy code will use LDM/STM instructions to copy up to 32 bytes at
+ * a time where possible.
+ *
+ * Note: r12 (aka ip) can be trashed during the function along with
+ * r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
+ * Additional registers are preserved prior to use i.e. r4, r5 & lr
+ *
+ * Apologies for the state of the comments ;-)
+ */
+
+ENTRY_PRIVATE(bsd_safe_memcpy)
+	/* Determine copy direction */
+	cmp	r1, r0
+	bcc	.Lmemcpy_backwards
+
+	moveq	r0, #0			/* Quick abort for len=0 */
+	moveq	pc, lr
+
+	stmdb	sp!, {r0, lr}		/* memcpy() returns dest addr */
+	subs	r2, r2, #4
+	blt	.Lmemcpy_fl4		/* less than 4 bytes */
+	ands	r12, r0, #3
+	bne	.Lmemcpy_fdestul	/* oh unaligned destination addr */
+	ands	r12, r1, #3
+	bne	.Lmemcpy_fsrcul		/* oh unaligned source addr */
+
+.Lmemcpy_ft8:
+	/* We have aligned source and destination */
+	subs	r2, r2, #8
+	blt	.Lmemcpy_fl12		/* less than 12 bytes (4 from above) */
+	subs	r2, r2, #0x14         
+	blt	.Lmemcpy_fl32		/* less than 32 bytes (12 from above) */
+	stmdb	sp!, {r4}		/* borrow r4 */
+
+	/* blat 32 bytes at a time */
+	/* XXX for really big copies perhaps we should use more registers */
+.Lmemcpy_floop32:	
+	ldmia	r1!, {r3, r4, r12, lr}
+	stmia	r0!, {r3, r4, r12, lr}
+	ldmia	r1!, {r3, r4, r12, lr}
+	stmia	r0!, {r3, r4, r12, lr}
+	subs	r2, r2, #0x20         
+	bge	.Lmemcpy_floop32
+
+	cmn	r2, #0x10
+	ldmiage	r1!, {r3, r4, r12, lr}	/* blat a remaining 16 bytes */
+	stmiage	r0!, {r3, r4, r12, lr}
+	subge	r2, r2, #0x10         
+	ldmia	sp!, {r4}		/* return r4 */
+
+.Lmemcpy_fl32:
+	adds	r2, r2, #0x14         
+
+	/* blat 12 bytes at a time */
+.Lmemcpy_floop12:
+	ldmiage	r1!, {r3, r12, lr}
+	stmiage	r0!, {r3, r12, lr}
+	subsge	r2, r2, #0x0c         
+	bge	.Lmemcpy_floop12
+
+.Lmemcpy_fl12:
+	adds	r2, r2, #8
+	blt	.Lmemcpy_fl4
+
+	subs	r2, r2, #4
+	ldrlt	r3, [r1], #4
+	strlt	r3, [r0], #4
+	ldmiage	r1!, {r3, r12}
+	stmiage	r0!, {r3, r12}
+	subge	r2, r2, #4
+
+.Lmemcpy_fl4:
+	/* less than 4 bytes to go */
+	adds	r2, r2, #4
+	ldmiaeq	sp!, {r0, pc}		/* done */
+
+	/* copy the crud byte at a time */
+	cmp	r2, #2
+	ldrb	r3, [r1], #1
+	strb	r3, [r0], #1
+	ldrbge	r3, [r1], #1
+	strbge	r3, [r0], #1
+	ldrbgt	r3, [r1], #1
+	strbgt	r3, [r0], #1
+	ldmia	sp!, {r0, pc}
+
+	/* erg - unaligned destination */
+.Lmemcpy_fdestul:
+	rsb	r12, r12, #4
+	cmp	r12, #2
+
+	/* align destination with byte copies */
+	ldrb	r3, [r1], #1
+	strb	r3, [r0], #1
+	ldrbge	r3, [r1], #1
+	strbge	r3, [r0], #1
+	ldrbgt	r3, [r1], #1
+	strbgt	r3, [r0], #1
+	subs	r2, r2, r12
+	blt	.Lmemcpy_fl4		/* less the 4 bytes */
+
+	ands	r12, r1, #3
+	beq	.Lmemcpy_ft8		/* we have an aligned source */
+
+	/* erg - unaligned source */
+	/* This is where it gets nasty ... */
+.Lmemcpy_fsrcul:
+	bic	r1, r1, #3
+	ldr	lr, [r1], #4
+	cmp	r12, #2
+	bgt	.Lmemcpy_fsrcul3
+	beq	.Lmemcpy_fsrcul2
+	cmp	r2, #0x0c            
+	blt	.Lmemcpy_fsrcul1loop4
+	sub	r2, r2, #0x0c         
+	stmdb	sp!, {r4, r5}
+
+.Lmemcpy_fsrcul1loop16:
+	mov	r3, lr, lsr #8
+	ldmia	r1!, {r4, r5, r12, lr}
+	orr	r3, r3, r4, lsl #24
+	mov	r4, r4, lsr #8
+	orr	r4, r4, r5, lsl #24
+	mov	r5, r5, lsr #8
+	orr	r5, r5, r12, lsl #24
+	mov	r12, r12, lsr #8
+	orr	r12, r12, lr, lsl #24
+	stmia	r0!, {r3-r5, r12}
+	subs	r2, r2, #0x10         
+	bge	.Lmemcpy_fsrcul1loop16
+	ldmia	sp!, {r4, r5}
+	adds	r2, r2, #0x0c         
+	blt	.Lmemcpy_fsrcul1l4
+
+.Lmemcpy_fsrcul1loop4:
+	mov	r12, lr, lsr #8
+	ldr	lr, [r1], #4
+	orr	r12, r12, lr, lsl #24
+	str	r12, [r0], #4
+	subs	r2, r2, #4
+	bge	.Lmemcpy_fsrcul1loop4
+
+.Lmemcpy_fsrcul1l4:
+	sub	r1, r1, #3
+	b	.Lmemcpy_fl4
+
+.Lmemcpy_fsrcul2:
+	cmp	r2, #0x0c            
+	blt	.Lmemcpy_fsrcul2loop4
+	sub	r2, r2, #0x0c         
+	stmdb	sp!, {r4, r5}
+
+.Lmemcpy_fsrcul2loop16:
+	mov	r3, lr, lsr #16
+	ldmia	r1!, {r4, r5, r12, lr}
+	orr	r3, r3, r4, lsl #16
+	mov	r4, r4, lsr #16
+	orr	r4, r4, r5, lsl #16
+	mov	r5, r5, lsr #16
+	orr	r5, r5, r12, lsl #16
+	mov	r12, r12, lsr #16
+	orr	r12, r12, lr, lsl #16
+	stmia	r0!, {r3-r5, r12}
+	subs	r2, r2, #0x10         
+	bge	.Lmemcpy_fsrcul2loop16
+	ldmia	sp!, {r4, r5}
+	adds	r2, r2, #0x0c         
+	blt	.Lmemcpy_fsrcul2l4
+
+.Lmemcpy_fsrcul2loop4:
+	mov	r12, lr, lsr #16
+	ldr	lr, [r1], #4
+	orr	r12, r12, lr, lsl #16
+	str	r12, [r0], #4
+	subs	r2, r2, #4
+	bge	.Lmemcpy_fsrcul2loop4
+
+.Lmemcpy_fsrcul2l4:
+	sub	r1, r1, #2
+	b	.Lmemcpy_fl4
+
+.Lmemcpy_fsrcul3:
+	cmp	r2, #0x0c            
+	blt	.Lmemcpy_fsrcul3loop4
+	sub	r2, r2, #0x0c         
+	stmdb	sp!, {r4, r5}
+
+.Lmemcpy_fsrcul3loop16:
+	mov	r3, lr, lsr #24
+	ldmia	r1!, {r4, r5, r12, lr}
+	orr	r3, r3, r4, lsl #8
+	mov	r4, r4, lsr #24
+	orr	r4, r4, r5, lsl #8
+	mov	r5, r5, lsr #24
+	orr	r5, r5, r12, lsl #8
+	mov	r12, r12, lsr #24
+	orr	r12, r12, lr, lsl #8
+	stmia	r0!, {r3-r5, r12}
+	subs	r2, r2, #0x10         
+	bge	.Lmemcpy_fsrcul3loop16
+	ldmia	sp!, {r4, r5}
+	adds	r2, r2, #0x0c         
+	blt	.Lmemcpy_fsrcul3l4
+
+.Lmemcpy_fsrcul3loop4:
+	mov	r12, lr, lsr #24
+	ldr	lr, [r1], #4
+	orr	r12, r12, lr, lsl #8
+	str	r12, [r0], #4
+	subs	r2, r2, #4
+	bge	.Lmemcpy_fsrcul3loop4
+
+.Lmemcpy_fsrcul3l4:
+	sub	r1, r1, #1
+	b	.Lmemcpy_fl4
+
+.Lmemcpy_backwards:
+	add	r1, r1, r2
+	add	r0, r0, r2
+	subs	r2, r2, #4
+	blt	.Lmemcpy_bl4		/* less than 4 bytes */
+	ands	r12, r0, #3
+	bne	.Lmemcpy_bdestul	/* oh unaligned destination addr */
+	ands	r12, r1, #3
+	bne	.Lmemcpy_bsrcul		/* oh unaligned source addr */
+
+.Lmemcpy_bt8:
+	/* We have aligned source and destination */
+	subs	r2, r2, #8
+	blt	.Lmemcpy_bl12		/* less than 12 bytes (4 from above) */
+	stmdb	sp!, {r4, lr}
+	subs	r2, r2, #0x14		/* less than 32 bytes (12 from above) */
+	blt	.Lmemcpy_bl32
+
+	/* blat 32 bytes at a time */
+	/* XXX for really big copies perhaps we should use more registers */
+.Lmemcpy_bloop32:
+	ldmdb	r1!, {r3, r4, r12, lr}
+	stmdb	r0!, {r3, r4, r12, lr}
+	ldmdb	r1!, {r3, r4, r12, lr}
+	stmdb	r0!, {r3, r4, r12, lr}
+	subs	r2, r2, #0x20         
+	bge	.Lmemcpy_bloop32
+
+.Lmemcpy_bl32:
+	cmn	r2, #0x10            
+	ldmdbge	r1!, {r3, r4, r12, lr}	/* blat a remaining 16 bytes */
+	stmdbge	r0!, {r3, r4, r12, lr}
+	subge	r2, r2, #0x10         
+	adds	r2, r2, #0x14         
+	ldmdbge	r1!, {r3, r12, lr}	/* blat a remaining 12 bytes */
+	stmdbge	r0!, {r3, r12, lr}
+	subge	r2, r2, #0x0c         
+	ldmia	sp!, {r4, lr}
+
+.Lmemcpy_bl12:
+	adds	r2, r2, #8
+	blt	.Lmemcpy_bl4
+	subs	r2, r2, #4
+	ldrlt	r3, [r1, #-4]!
+	strlt	r3, [r0, #-4]!
+	ldmdbge	r1!, {r3, r12}
+	stmdbge	r0!, {r3, r12}
+	subge	r2, r2, #4
+
+.Lmemcpy_bl4:
+	/* less than 4 bytes to go */
+	adds	r2, r2, #4
+	moveq	pc, lr			/* done */
+
+	/* copy the crud byte at a time */
+	cmp	r2, #2
+	ldrb	r3, [r1, #-1]!
+	strb	r3, [r0, #-1]!
+	ldrbge	r3, [r1, #-1]!
+	strbge	r3, [r0, #-1]!
+	ldrbgt	r3, [r1, #-1]!
+	strbgt	r3, [r0, #-1]!
+	mov	pc, lr
+
+	/* erg - unaligned destination */
+.Lmemcpy_bdestul:
+	cmp	r12, #2
+
+	/* align destination with byte copies */
+	ldrb	r3, [r1, #-1]!
+	strb	r3, [r0, #-1]!
+	ldrbge	r3, [r1, #-1]!
+	strbge	r3, [r0, #-1]!
+	ldrbgt	r3, [r1, #-1]!
+	strbgt	r3, [r0, #-1]!
+	subs	r2, r2, r12
+	blt	.Lmemcpy_bl4		/* less than 4 bytes to go */
+	ands	r12, r1, #3
+	beq	.Lmemcpy_bt8		/* we have an aligned source */
+
+	/* erg - unaligned source */
+	/* This is where it gets nasty ... */
+.Lmemcpy_bsrcul:
+	bic	r1, r1, #3
+	ldr	r3, [r1, #0]
+	cmp	r12, #2
+	blt	.Lmemcpy_bsrcul1
+	beq	.Lmemcpy_bsrcul2
+	cmp	r2, #0x0c            
+	blt	.Lmemcpy_bsrcul3loop4
+	sub	r2, r2, #0x0c         
+	stmdb	sp!, {r4, r5, lr}
+
+.Lmemcpy_bsrcul3loop16:
+	mov	lr, r3, lsl #8
+	ldmdb	r1!, {r3-r5, r12}
+	orr	lr, lr, r12, lsr #24
+	mov	r12, r12, lsl #8
+	orr	r12, r12, r5, lsr #24
+	mov	r5, r5, lsl #8
+	orr	r5, r5, r4, lsr #24
+	mov	r4, r4, lsl #8
+	orr	r4, r4, r3, lsr #24
+	stmdb	r0!, {r4, r5, r12, lr}
+	subs	r2, r2, #0x10         
+	bge	.Lmemcpy_bsrcul3loop16
+	ldmia	sp!, {r4, r5, lr}
+	adds	r2, r2, #0x0c         
+	blt	.Lmemcpy_bsrcul3l4
+
+.Lmemcpy_bsrcul3loop4:
+	mov	r12, r3, lsl #8
+	ldr	r3, [r1, #-4]!
+	orr	r12, r12, r3, lsr #24
+	str	r12, [r0, #-4]!
+	subs	r2, r2, #4
+	bge	.Lmemcpy_bsrcul3loop4
+
+.Lmemcpy_bsrcul3l4:
+	add	r1, r1, #3
+	b	.Lmemcpy_bl4
+
+.Lmemcpy_bsrcul2:
+	cmp	r2, #0x0c            
+	blt	.Lmemcpy_bsrcul2loop4
+	sub	r2, r2, #0x0c         
+	stmdb	sp!, {r4, r5, lr}
+
+.Lmemcpy_bsrcul2loop16:
+	mov	lr, r3, lsl #16
+	ldmdb	r1!, {r3-r5, r12}
+	orr	lr, lr, r12, lsr #16
+	mov	r12, r12, lsl #16
+	orr	r12, r12, r5, lsr #16
+	mov	r5, r5, lsl #16
+	orr	r5, r5, r4, lsr #16
+	mov	r4, r4, lsl #16
+	orr	r4, r4, r3, lsr #16
+	stmdb	r0!, {r4, r5, r12, lr}
+	subs	r2, r2, #0x10         
+	bge	.Lmemcpy_bsrcul2loop16
+	ldmia	sp!, {r4, r5, lr}
+	adds	r2, r2, #0x0c         
+	blt	.Lmemcpy_bsrcul2l4
+
+.Lmemcpy_bsrcul2loop4:
+	mov	r12, r3, lsl #16
+	ldr	r3, [r1, #-4]!
+	orr	r12, r12, r3, lsr #16
+	str	r12, [r0, #-4]!
+	subs	r2, r2, #4
+	bge	.Lmemcpy_bsrcul2loop4
+
+.Lmemcpy_bsrcul2l4:
+	add	r1, r1, #2
+	b	.Lmemcpy_bl4
+
+.Lmemcpy_bsrcul1:
+	cmp	r2, #0x0c            
+	blt	.Lmemcpy_bsrcul1loop4
+	sub	r2, r2, #0x0c         
+	stmdb	sp!, {r4, r5, lr}
+
+.Lmemcpy_bsrcul1loop32:
+	mov	lr, r3, lsl #24
+	ldmdb	r1!, {r3-r5, r12}
+	orr	lr, lr, r12, lsr #8
+	mov	r12, r12, lsl #24
+	orr	r12, r12, r5, lsr #8
+	mov	r5, r5, lsl #24
+	orr	r5, r5, r4, lsr #8
+	mov	r4, r4, lsl #24
+	orr	r4, r4, r3, lsr #8
+	stmdb	r0!, {r4, r5, r12, lr}
+	subs	r2, r2, #0x10         
+	bge	.Lmemcpy_bsrcul1loop32
+	ldmia	sp!, {r4, r5, lr}
+	adds	r2, r2, #0x0c         
+	blt	.Lmemcpy_bsrcul1l4
+
+.Lmemcpy_bsrcul1loop4:
+	mov	r12, r3, lsl #24
+	ldr	r3, [r1, #-4]!
+	orr	r12, r12, r3, lsr #8
+	str	r12, [r0, #-4]!
+	subs	r2, r2, #4
+	bge	.Lmemcpy_bsrcul1loop4
+
+.Lmemcpy_bsrcul1l4:
+	add	r1, r1, #1
+	b	.Lmemcpy_bl4
+END(bsd_safe_memcpy)
+
+ENTRY(memmove)
+        stmfd   sp!, {r0, lr}
+        bl      bsd_safe_memcpy
+        ldmfd   sp!, {r0, pc}
+END(memmove)
diff --git a/libc/kernel/tools/generate_uapi_headers.sh b/libc/kernel/tools/generate_uapi_headers.sh
index 575da31..5bf1cf3 100755
--- a/libc/kernel/tools/generate_uapi_headers.sh
+++ b/libc/kernel/tools/generate_uapi_headers.sh
@@ -24,9 +24,9 @@
 ###  Options:
 ###   --skip-generation
 ###     Skip the step that generates all of the include files.
-###   --download-kernel
+###   --download-kernel <VERSION>
 ###     Automatically create a temporary git repository and check out the
-###     Android kernel source code.
+###     linux kernel source code for the given version.
 ###   --use-kernel-dir <DIR>
 ###     Do not check out the kernel source, use the kernel directory
 ###     pointed to by <DIR>.
@@ -39,7 +39,8 @@
 
 TMPDIR=""
 ANDROID_DIR=""
-KERNEL_VERSION="android-3.10"
+KERNEL_VERSION=""
+KERNEL_REPO="git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git"
 KERNEL_DIR=""
 KERNEL_DOWNLOAD=0
 ARCH_LIST=("arm" "arm64" "mips" "x86")
@@ -142,6 +143,12 @@
       SKIP_GENERATION=1
       ;;
     "--download-kernel")
+      if [[ $# -lt 2 ]]; then
+        echo "--download-kernel requires an argument."
+        exit 1
+      fi
+      shift
+      KERNEL_VERSION="$1"
       KERNEL_DOWNLOAD=1
       ;;
     "--use-kernel-dir")
@@ -191,27 +198,15 @@
   exit 1
 fi
 
-if [[ -d "${KERNEL_DIR}/linux-stable" ]]; then
-  src_dir="linux-stable"
-else
-  src_dir="common"
-fi
-
-if [[ ${VERIFY_HEADERS_ONLY} -eq 1 ]]; then
-  # Verify if modified headers have changed.
-  verify_modified_hdrs "${KERNEL_DIR}/${src_dir}/include/scsi" \
-                       "${ANDROID_KERNEL_DIR}/scsi" \
-                       "${KERNEL_DIR}/${src_dir}"
-  exit 0
-fi
+src_dir="linux-stable"
 
 if [[ ${KERNEL_DOWNLOAD} -eq 1 ]]; then
   TMPDIR=$(mktemp -d /tmp/android_kernelXXXXXXXX)
   cd "${TMPDIR}"
-  echo "Fetching android kernel source ${KERNEL_VERSION}"
-  git clone https://android.googlesource.com/kernel/common.git
-  cd "${src_dir}"
-  git checkout "${KERNEL_VERSION}"
+  echo "Fetching linux kernel source ${KERNEL_VERSION}"
+  git clone ${KERNEL_REPO}
+  cd ${src_dir}
+  git checkout tags/"${KERNEL_VERSION}"
   KERNEL_DIR="${TMPDIR}"
 elif [[ "${KERNEL_DIR}" == "" ]]; then
   echo "Must specify one of --use-kernel-dir or --download-kernel."
@@ -223,6 +218,14 @@
   cd "${KERNEL_DIR}/${src_dir}"
 fi
 
+if [[ ${VERIFY_HEADERS_ONLY} -eq 1 ]]; then
+  # Verify if modified headers have changed.
+  verify_modified_hdrs "${KERNEL_DIR}/${src_dir}/include/scsi" \
+                       "${ANDROID_KERNEL_DIR}/scsi" \
+                       "${KERNEL_DIR}/${src_dir}"
+  exit 0
+fi
+
 if [[ ${SKIP_GENERATION} -eq 0 ]]; then
   # Clean up any leftover headers.
   make distclean
@@ -249,7 +252,7 @@
           "${ANDROID_KERNEL_DIR}/uapi/linux" "no-copy-dirs"
 
 # Remove ion.h, it's not fully supported by the upstream kernel (see b/77976082).
-rm "${ANDROID_KERNEL_DIR}/uapi/linux/ion.h"
+rm -f "${ANDROID_KERNEL_DIR}/uapi/linux/ion.h"
 
 # Copy the generated headers.
 copy_hdrs "${KERNEL_DIR}/${src_dir}/include/generated/uapi" \
@@ -279,3 +282,4 @@
 verify_modified_hdrs "${KERNEL_DIR}/${src_dir}/include/scsi" \
                      "${ANDROID_KERNEL_DIR}/scsi" \
                      "${KERNEL_DIR}/${src_dir}"
+echo "Headers updated."
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index ee05b16..159d4a0 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -746,7 +746,7 @@
     pthread_cond_signal;
     pthread_cond_timedwait;
     pthread_cond_timedwait_monotonic; # arm x86 mips
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=16 introduced-x86=16 introduced-mips=16 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-mips=9 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
     pthread_cond_timedwait_relative_np; # arm x86 mips
     pthread_cond_timeout_np; # arm x86 mips
     pthread_cond_wait;
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 5e6f991..7702f9e 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -692,7 +692,7 @@
     pthread_cond_init;
     pthread_cond_signal;
     pthread_cond_timedwait;
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=16 introduced-x86=16 introduced-mips=16 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-mips=9 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
     pthread_cond_wait;
     pthread_condattr_destroy;
     pthread_condattr_getclock; # introduced=21
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 6bbffba..ebe2098 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -771,7 +771,7 @@
     pthread_cond_signal;
     pthread_cond_timedwait;
     pthread_cond_timedwait_monotonic; # arm x86 mips
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=16 introduced-x86=16 introduced-mips=16 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-mips=9 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
     pthread_cond_timedwait_relative_np; # arm x86 mips
     pthread_cond_timeout_np; # arm x86 mips
     pthread_cond_wait;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index cdba570..d04cb4f 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -744,7 +744,7 @@
     pthread_cond_signal;
     pthread_cond_timedwait;
     pthread_cond_timedwait_monotonic; # arm x86 mips
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=16 introduced-x86=16 introduced-mips=16 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-mips=9 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
     pthread_cond_timedwait_relative_np; # arm x86 mips
     pthread_cond_timeout_np; # arm x86 mips
     pthread_cond_wait;
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 5e6f991..7702f9e 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -692,7 +692,7 @@
     pthread_cond_init;
     pthread_cond_signal;
     pthread_cond_timedwait;
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=16 introduced-x86=16 introduced-mips=16 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-mips=9 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
     pthread_cond_wait;
     pthread_condattr_destroy;
     pthread_condattr_getclock; # introduced=21
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 5cb0cf4..2e10bbb 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -742,7 +742,7 @@
     pthread_cond_signal;
     pthread_cond_timedwait;
     pthread_cond_timedwait_monotonic; # arm x86 mips
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=16 introduced-x86=16 introduced-mips=16 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-mips=9 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
     pthread_cond_timedwait_relative_np; # arm x86 mips
     pthread_cond_timeout_np; # arm x86 mips
     pthread_cond_wait;
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 5e6f991..7702f9e 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -692,7 +692,7 @@
     pthread_cond_init;
     pthread_cond_signal;
     pthread_cond_timedwait;
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=16 introduced-x86=16 introduced-mips=16 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-mips=9 introduced-arm64=28 introduced-x64_64=28 introduced-mips64=28
     pthread_cond_wait;
     pthread_condattr_destroy;
     pthread_condattr_getclock; # introduced=21
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 1a79802..a4ff5d4 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -14,6 +14,7 @@
     stl: "libc++_static",
 
     whole_static_libs: [
+        "libbase",
         "libasync_safe",
         "libdemangle",
     ],
@@ -49,6 +50,7 @@
         "malloc_debug.cpp",
         "PointerData.cpp",
         "RecordData.cpp",
+        "UnwindBacktrace.cpp",
     ],
 
     stl: "libc++_static",
@@ -69,9 +71,14 @@
     static_libs: [
         "libasync_safe",
         "libbase",
+        "libdemangle",
         "libc_malloc_debug_backtrace",
     ],
 
+    shared_libs: [
+        "libunwindstack",
+    ],
+
     multilib: {
         lib32: {
             version_script: "exported32.map",
@@ -112,15 +119,21 @@
         "tests/malloc_debug_unit_tests.cpp",
     ],
 
-    whole_static_libs: ["libc_malloc_debug"],
-
     local_include_dirs: ["tests"],
     include_dirs: [
         "bionic/libc",
         "bionic/libc/async_safe/include",
     ],
 
-    shared_libs: ["libbase"],
+    static_libs: [
+        "libc_malloc_debug",
+        "libdemangle",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libunwindstack",
+    ],
 
     cflags: [
         "-Wall",
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index 2c94fe8..926b265 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -93,6 +93,9 @@
     {
         "backtrace_dump_prefix", {0, &Config::SetBacktraceDumpPrefix},
     },
+    {
+        "backtrace_full", {BACKTRACE_FULL, &Config::VerifyValueEmpty},
+    },
 
     {
         "fill", {FILL_ON_ALLOC | FILL_ON_FREE, &Config::SetFill},
@@ -316,115 +319,8 @@
 }
 
 void Config::LogUsage() const {
-  error_log("malloc debug options usage:");
-  error_log("");
-  error_log("  front_guard[=XX]");
-  error_log("    Enables a front guard on all allocations. If XX is set");
-  error_log("    it sets the number of bytes in the guard. The default is");
-  error_log("    %zu bytes, the max bytes is %zu.", DEFAULT_GUARD_BYTES, MAX_GUARD_BYTES);
-  error_log("");
-  error_log("  rear_guard[=XX]");
-  error_log("    Enables a rear guard on all allocations. If XX is set");
-  error_log("    it sets the number of bytes in the guard. The default is");
-  error_log("    %zu bytes, the max bytes is %zu.", DEFAULT_GUARD_BYTES, MAX_GUARD_BYTES);
-  error_log("");
-  error_log("  guard[=XX]");
-  error_log("    Enables both a front guard and a rear guard on all allocations.");
-  error_log("    If XX is set it sets the number of bytes in both guards.");
-  error_log("    The default is %zu bytes, the max bytes is %zu.", DEFAULT_GUARD_BYTES,
-            MAX_GUARD_BYTES);
-  error_log("");
-  error_log("  backtrace[=XX]");
-  error_log("    Enable capturing the backtrace at the point of allocation.");
-  error_log("    If XX is set it sets the number of backtrace frames.");
-  error_log("    This option also enables dumping the backtrace heap data");
-  error_log("    when a signal is received. The data is dumped to the file");
-  error_log("    backtrace_dump_prefix.<PID>.txt.");
-  error_log("    The default is %zu frames, the max number of frames is %zu.",
-            DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
-  error_log("");
-  error_log("  backtrace_enable_on_signal[=XX]");
-  error_log("    Enable capturing the backtrace at the point of allocation.");
-  error_log("    The backtrace capture is not enabled until the process");
-  error_log("    receives a signal. If XX is set it sets the number of backtrace");
-  error_log("    frames. The default is %zu frames, the max number of frames is %zu.",
-            DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
-  error_log("");
-  error_log("  backtrace_dump_prefix[=FILE]");
-  error_log("    This option only has meaning if the backtrace option has been specified.");
-  error_log("    This is the prefix of the name of the file to which backtrace heap");
-  error_log("    data will be dumped. The file will be named backtrace_dump_prefix.<PID>.txt.");
-  error_log("    The default is %s.", DEFAULT_BACKTRACE_DUMP_PREFIX);
-
-  error_log("");
-  error_log("  backtrace_dump_on_exit");
-  error_log("    This option only has meaning if the backtrace option has been specified.");
-  error_log("    This will cause all live allocations to be dumped to the file");
-  error_log("    backtrace_dump_prefix.<PID>.final.txt.");
-  error_log("    The default is false.");
-  error_log("");
-  error_log("  fill_on_alloc[=XX]");
-  error_log("    On first allocation, fill with the value 0x%02x.", DEFAULT_FILL_ALLOC_VALUE);
-  error_log("    If XX is set it will only fill up to XX bytes of the");
-  error_log("    allocation. The default is to fill the entire allocation.");
-  error_log("");
-  error_log("  fill_on_free[=XX]");
-  error_log("    On free, fill with the value 0x%02x. If XX is set it will",
-            DEFAULT_FILL_FREE_VALUE);
-  error_log("    only fill up to XX bytes of the allocation. The default is to");
-  error_log("    fill the entire allocation.");
-  error_log("");
-  error_log("  fill[=XX]");
-  error_log("    On both first allocation free, fill with the value 0x%02x on",
-            DEFAULT_FILL_ALLOC_VALUE);
-  error_log("    first allocation and the value 0x%02x. If XX is set, only fill",
-            DEFAULT_FILL_FREE_VALUE);
-  error_log("    up to XX bytes. The default is to fill the entire allocation.");
-  error_log("");
-  error_log("  expand_alloc[=XX]");
-  error_log("    Allocate an extra number of bytes for every allocation call.");
-  error_log("    If XX is set, that is the number of bytes to expand the");
-  error_log("    allocation by. The default is %zu bytes, the max bytes is %zu.",
-            DEFAULT_EXPAND_BYTES, MAX_EXPAND_BYTES);
-  error_log("");
-  error_log("  free_track[=XX]");
-  error_log("    When a pointer is freed, do not free the memory right away.");
-  error_log("    Instead, keep XX of these allocations around and then verify");
-  error_log("    that they have not been modified when the total number of freed");
-  error_log("    allocations exceeds the XX amount. When the program terminates,");
-  error_log("    the rest of these allocations are verified. When this option is");
-  error_log("    enabled, it automatically records the backtrace at the time of the free.");
-  error_log("    The default is to record %zu allocations, the max allocations",
-            DEFAULT_FREE_TRACK_ALLOCATIONS);
-  error_log("    to record is %zu.", MAX_FREE_TRACK_ALLOCATIONS);
-  error_log("");
-  error_log("  free_track_backtrace_num_frames[=XX]");
-  error_log("    This option only has meaning if free_track is set. This indicates");
-  error_log("    how many backtrace frames to capture when an allocation is freed.");
-  error_log("    If XX is set, that is the number of frames to capture. If XX");
-  error_log("    is set to zero, then no backtrace will be captured.");
-  error_log("    The default is to record %zu frames, the max number of frames is %zu.",
-            DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
-  error_log("");
-  error_log("  leak_track");
-  error_log("    Enable the leak tracking of memory allocations.");
-  error_log("");
-  error_log("  record_allocs[=XX]");
-  error_log("    Record every single allocation/free call. When a specific signal");
-  error_log("    is sent to the process, the contents of recording are written to");
-  error_log("    a file (%s) and the recording is cleared.", DEFAULT_RECORD_ALLOCS_FILE);
-  error_log("    If XX is set, that is the total number of allocations/frees that can");
-  error_log("    recorded. of frames to capture. The default value is %zu.", DEFAULT_RECORD_ALLOCS);
-  error_log("    If the allocation list fills up, all further allocations are not recorded.");
-  error_log("");
-  error_log("  record_allocs_file[=FILE]");
-  error_log("    This option only has meaning if the record_allocs options has been specified.");
-  error_log("    This is the name of the file to which recording information will be dumped.");
-  error_log("    The default is %s.", DEFAULT_RECORD_ALLOCS_FILE);
-  error_log("");
-  error_log("  verify_pointers");
-  error_log("    A lightweight way to verify that free/malloc_usable_size/realloc");
-  error_log("    are passed valid pointers.");
+  error_log("For malloc debug option descriptions go to:");
+  error_log("  https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md");
 }
 
 bool Config::GetOption(const char** options_str, std::string* option, std::string* value) {
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index 3bcef0b..86d1ee4 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -43,6 +43,7 @@
 constexpr uint64_t TRACK_ALLOCS = 0x80;
 constexpr uint64_t LEAK_TRACK = 0x100;
 constexpr uint64_t RECORD_ALLOCS = 0x200;
+constexpr uint64_t BACKTRACE_FULL = 0x400;
 
 // In order to guarantee posix compliance, set the minimum alignment
 // to 8 bytes for 32 bit systems and 16 bytes for 64 bit systems.
diff --git a/libc/malloc_debug/GuardData.cpp b/libc/malloc_debug/GuardData.cpp
index f9a2dca..debc14e 100644
--- a/libc/malloc_debug/GuardData.cpp
+++ b/libc/malloc_debug/GuardData.cpp
@@ -62,10 +62,7 @@
   }
 
   error_log("Backtrace at time of failure:");
-  std::vector<uintptr_t> frames(64);
-  size_t frame_num = backtrace_get(frames.data(), frames.size());
-  frames.resize(frame_num);
-  backtrace_log(frames.data(), frames.size());
+  BacktraceAndLog();
   error_log(LOG_DIVIDER);
 }
 
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index 85139e6..b0e2fc8 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -43,6 +43,7 @@
 
 #include <android-base/stringprintf.h>
 #include <android-base/thread_annotations.h>
+#include <demangle.h>
 #include <private/bionic_macros.h>
 
 #include "Config.h"
@@ -51,6 +52,7 @@
 #include "backtrace.h"
 #include "debug_log.h"
 #include "malloc_debug.h"
+#include "UnwindBacktrace.h"
 
 std::atomic_uint8_t PointerData::backtrace_enabled_;
 std::atomic_bool PointerData::backtrace_dump_;
@@ -63,6 +65,7 @@
 std::unordered_map<FrameKeyType, size_t> PointerData::key_to_index_ GUARDED_BY(
     PointerData::frame_mutex_);
 std::unordered_map<size_t, FrameInfoType> PointerData::frames_ GUARDED_BY(PointerData::frame_mutex_);
+std::unordered_map<size_t, std::vector<unwindstack::LocalFrameData>> PointerData::backtraces_info_ GUARDED_BY(PointerData::frame_mutex_);
 constexpr size_t kBacktraceEmptyIndex = 1;
 size_t PointerData::cur_hash_index_ GUARDED_BY(PointerData::frame_mutex_);
 
@@ -127,10 +130,18 @@
 }
 
 size_t PointerData::AddBacktrace(size_t num_frames) {
-  std::vector<uintptr_t> frames(num_frames);
-  num_frames = backtrace_get(frames.data(), frames.size());
-  if (num_frames == 0) {
-    return kBacktraceEmptyIndex;
+  std::vector<uintptr_t> frames;
+  std::vector<unwindstack::LocalFrameData> frames_info;
+  if (g_debug->config().options() & BACKTRACE_FULL) {
+    if (!Unwind(&frames, &frames_info, num_frames)) {
+      return kBacktraceEmptyIndex;
+    }
+  } else {
+    frames.resize(num_frames);
+    num_frames = backtrace_get(frames.data(), frames.size());
+    if (num_frames == 0) {
+      return kBacktraceEmptyIndex;
+    }
   }
 
   FrameKeyType key{.num_frames = num_frames, .frames = frames.data()};
@@ -144,6 +155,9 @@
     key_to_index_.emplace(key, hash_index);
 
     frames_.emplace(hash_index, FrameInfoType{.references = 1, .frames = std::move(frames)});
+    if (g_debug->config().options() & BACKTRACE_FULL) {
+      backtraces_info_.emplace(hash_index, std::move(frames_info));
+    }
   } else {
     hash_index = entry->second;
     FrameInfoType* frame_info = &frames_[hash_index];
@@ -168,6 +182,9 @@
     FrameKeyType key{.num_frames = frame_info->frames.size(), .frames = frame_info->frames.data()};
     key_to_index_.erase(key);
     frames_.erase(hash_index);
+    if (g_debug->config().options() & BACKTRACE_FULL) {
+      backtraces_info_.erase(hash_index);
+    }
   }
 }
 
@@ -230,6 +247,25 @@
   return max_frames;
 }
 
+void PointerData::LogBacktrace(size_t hash_index) {
+  std::lock_guard<std::mutex> frame_guard(frame_mutex_);
+  if (g_debug->config().options() & BACKTRACE_FULL) {
+    auto backtrace_info_entry = backtraces_info_.find(hash_index);
+    if (backtrace_info_entry != backtraces_info_.end()) {
+      UnwindLog(backtrace_info_entry->second);
+      return;
+    }
+  } else {
+    auto frame_entry = frames_.find(hash_index);
+    if (frame_entry != frames_.end()) {
+      FrameInfoType* frame_info = &frame_entry->second;
+      backtrace_log(frame_info->frames.data(), frame_info->frames.size());
+      return;
+    }
+  }
+  error_log("  hash_index %zu does not have matching frame data.", hash_index);
+}
+
 void PointerData::LogFreeError(const FreePointerInfoType& info, size_t usable_size) {
   error_log(LOG_DIVIDER);
   uint8_t* memory = reinterpret_cast<uint8_t*>(info.pointer);
@@ -242,13 +278,8 @@
   }
 
   if (info.hash_index > kBacktraceEmptyIndex) {
-    std::lock_guard<std::mutex> frame_guard(frame_mutex_);
-    auto frame_entry = frames_.find(info.hash_index);
-    if (frame_entry != frames_.end()) {
-      FrameInfoType* frame_info = &frame_entry->second;
-      error_log("Backtrace at time of free:");
-      backtrace_log(frame_info->frames.data(), frame_info->frames.size());
-    }
+    error_log("Backtrace at time of free:");
+    LogBacktrace(info.hash_index);
   }
 
   error_log(LOG_DIVIDER);
@@ -328,15 +359,8 @@
     return;
   }
 
-  std::lock_guard<std::mutex> frame_guard(frame_mutex_);
-  auto frame_entry = frames_.find(hash_index);
-  if (frame_entry == frames_.end()) {
-    error_log("Freed pointer hash_index %zu does not have matching frame data.", hash_index);
-    return;
-  }
-  FrameInfoType* frame_info = &frame_entry->second;
   error_log("Backtrace of original free:");
-  backtrace_log(frame_info->frames.data(), frame_info->frames.size());
+  LogBacktrace(hash_index);
 }
 
 void PointerData::VerifyAllFreed() {
@@ -350,18 +374,28 @@
     REQUIRES(pointer_mutex_, frame_mutex_) {
   for (const auto& entry : pointers_) {
     FrameInfoType* frame_info = nullptr;
+    std::vector<unwindstack::LocalFrameData>* backtrace_info = nullptr;
     size_t hash_index = entry.second.hash_index;
     if (hash_index > kBacktraceEmptyIndex) {
-      frame_info = &frames_[hash_index];
-      if (frame_info->references == 0) {
+      auto frame_entry = frames_.find(hash_index);
+      if (frame_entry == frames_.end()) {
         // Somehow wound up with a pointer with a valid hash_index, but
         // no frame data. This should not be possible since adding a pointer
         // occurs after the hash_index and frame data have been added.
         // When removing a pointer, the pointer is deleted before the frame
         // data.
-        frames_.erase(hash_index);
         error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
-        frame_info = nullptr;
+      } else {
+        frame_info = &frame_entry->second;
+      }
+
+      if (g_debug->config().options() & BACKTRACE_FULL) {
+        auto backtrace_entry = backtraces_info_.find(hash_index);
+        if (backtrace_entry == backtraces_info_.end()) {
+          error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+        } else {
+          backtrace_info = &backtrace_entry->second;
+        }
       }
     }
     if (hash_index == 0 && only_with_backtrace) {
@@ -369,7 +403,7 @@
     }
 
     list->emplace_back(ListInfoType{entry.first, 1, entry.second.RealSize(),
-                                    entry.second.ZygoteChildAlloc(), frame_info});
+                                    entry.second.ZygoteChildAlloc(), frame_info, backtrace_info});
   }
 
   // Sort by the size of the allocation.
@@ -440,7 +474,10 @@
   for (const auto& list_info : list) {
     error_log("+++ %s leaked block of size %zu at 0x%" PRIxPTR " (leak %zu of %zu)", getprogname(),
               list_info.size, list_info.pointer, ++track_count, list.size());
-    if (list_info.frame_info != nullptr) {
+    if (list_info.backtrace_info != nullptr) {
+      error_log("Backtrace at time of allocation:");
+      UnwindLog(*list_info.backtrace_info);
+    } else if (list_info.frame_info != nullptr) {
       error_log("Backtrace at time of allocation:");
       backtrace_log(list_info.frame_info->frames.data(), list_info.frame_info->frames.size());
     }
@@ -520,14 +557,28 @@
         if (frame_info->frames[i] == 0) {
           break;
         }
-#if defined(__LP64__)
-        fprintf(fp, " %016" PRIxPTR, frame_info->frames[i]);
-#else
-        fprintf(fp, " %08" PRIxPTR, frame_info->frames[i]);
-#endif
+        fprintf(fp, " %" PRIxPTR, frame_info->frames[i]);
       }
     }
     fprintf(fp, "\n");
+    if (info.backtrace_info != nullptr) {
+      fprintf(fp, "  bt_info");
+      for (const auto& frame : *info.backtrace_info) {
+        fprintf(fp, " {");
+        if (frame.map_info != nullptr && !frame.map_info->name.empty()) {
+          fprintf(fp, "\"%s\"", frame.map_info->name.c_str());
+        } else {
+          fprintf(fp, "\"\"");
+        }
+        fprintf(fp, " %" PRIx64, frame.rel_pc);
+        if (frame.function_name.empty()) {
+          fprintf(fp, " \"\" 0}");
+        } else {
+          fprintf(fp, " \"%s\" %" PRIx64 "}", demangle(frame.function_name.c_str()).c_str(), frame.function_offset);
+        }
+      }
+      fprintf(fp, "\n");
+    }
   }
 }
 
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 7a0b3b8..62d4186 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -39,8 +39,10 @@
 #include <vector>
 
 #include <private/bionic_macros.h>
+#include <unwindstack/LocalUnwinder.h>
 
 #include "OptionData.h"
+#include "UnwindBacktrace.h"
 
 extern int* g_malloc_zygote_child;
 
@@ -105,6 +107,7 @@
   size_t size;
   bool zygote_child_alloc;
   FrameInfoType* frame_info;
+  std::vector<unwindstack::LocalFrameData>* backtrace_info;
 };
 
 class PointerData : public OptionData {
@@ -160,6 +163,7 @@
 
  private:
   static std::string GetHashString(uintptr_t* frames, size_t num_frames);
+  static void LogBacktrace(size_t hash_index);
 
   size_t alloc_offset_ = 0;
   std::vector<uint8_t> cmp_mem_;
@@ -174,6 +178,7 @@
   static std::mutex frame_mutex_;
   static std::unordered_map<FrameKeyType, size_t> key_to_index_;
   static std::unordered_map<size_t, FrameInfoType> frames_;
+  static std::unordered_map<size_t, std::vector<unwindstack::LocalFrameData>> backtraces_info_;
   static size_t cur_hash_index_;
 
   static std::mutex free_pointer_mutex_;
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index 51540f8..18d22a4 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -150,8 +150,8 @@
 option.
 
 ### backtrace\_dump\_prefix
-As of P, when the backtrace options has been enabled, this sets the prefix
-used for dumping files when the signal SIGRTMAX - 17 is received or when
+As of P, when one of the backtrace options has been enabled, this sets the
+prefix used for dumping files when the signal SIGRTMAX - 17 is received or when
 the program exits and backtrace\_dump\_on\_exit is set.
 
 The default is /data/local/tmp/backtrace\_heap.
@@ -160,6 +160,11 @@
 on the signal will be backtrace\_dump\_prefix.**PID**.txt. The filename chosen
 when the program exits will be backtrace\_dump\_prefix.**PID**.exit.txt.
 
+### backtrace\_full
+As of P, any time that a backtrace is gathered, a different algorithm is used
+that is extra thorough and can unwind through Java frames. This will run
+slower than the normal backtracing function.
+
 ### fill\_on\_alloc[=MAX\_FILLED\_BYTES]
 Any allocation routine, other than calloc, will result in the allocation being
 filled with the value 0xeb. When doing a realloc to a larger size, the bytes
@@ -490,7 +495,47 @@
 The map data is simply the output of /proc/PID/maps. This data can be used to
 decode the frames in the backtraces.
 
-There is a tool to visualize this data, development/scripts/native\_heapdump\_viewer.py.
+As of Android P, there is a new version of this file. The new header is:
+
+    Android Native Heap Dump v1.1
+
+The new version no longer 0 pads the backtrace addresses. In v1.0:
+
+    z 0  sz      400  num    1  bt 0000a230 0000b500
+
+While v1.1:
+
+    z 0  sz      400  num    1  bt a230 b500
+
+In addition, when the new option backtrace\_full is used, another line will
+be added to every backtrace line. The line will be:
+
+      bt_info {"MAP_NAME" RELATIVE_TO_MAP_PC "FUNCTION_NAME" FUNCTION_OFFSET} ...
+
+For each backtrace pc, there will be one element in braces.
+
+MAP\_NAME is the name of the map in which the backtrace pc exists. If there is
+no valid map name, this will be empty.
+RELATIVE\_TO\_MAP\_PC is the hexadecimal value of the relative pc to the map.
+FUNCTION\_NAME the name of the function for this pc. If there is no valid
+function name, then it will be empty.
+FUNCTION\_OFFSET the hexadecimal offset from the beginning of the function. If
+the FUNCTION\_NAME is empty, then this value will always be zero.
+
+An example of this new format:
+
+    z 0  sz      400  num    1  bt a2a0 b510
+      bt_info {"/system/libc.so" 2a0 "abort" 24} {"/system/libutils.so" 510 "" 0}
+
+In this example, the first backtrace frame has a pc of 0xa2a0 and is in the
+map named /system/libc.so which starts at 0xa000. The relative pc is 0x2a0,
+and it is in the function abort + 0x24.
+The second backtrace frame has a pc of 0xb510 and is in the map named
+/system/libutils.so which starts at 0xb000. The relative pc is 0x510 and
+it is in an unknown function.
+
+There is a tool to visualize this data,
+[native\_heapdump\_viewer.py](https://android.googlesource.com/platform/development/+/master/scripts/native_heapdump_viewer.py).
 
 Examples
 ========
@@ -593,9 +638,8 @@
 
 ### Analyzing heap dumps
 
-To analyze the data produced by the dumpheap command, run this script:
-
-    development/scripts/native_heapdump_viewer.py
+To analyze the data produced by the dumpheap command, run
+[development/scripts/native\_heapdump\_viewer.py](https://android.googlesource.com/platform/development/+/master/scripts/native_heapdump_viewer.py)
 
 In order for the script to properly symbolize the stacks in the file,
 make sure the script is executed from the tree that built the image.
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
new file mode 100644
index 0000000..ddafc73
--- /dev/null
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 <inttypes.h>
+#include <pthread.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <android-base/stringprintf.h>
+#include <demangle.h>
+#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/MapInfo.h>
+
+#include "UnwindBacktrace.h"
+#include "debug_log.h"
+
+#if defined(__LP64__)
+#define PAD_PTR "016" PRIx64
+#else
+#define PAD_PTR "08" PRIx64
+#endif
+
+static pthread_once_t g_setup_once = PTHREAD_ONCE_INIT;
+
+static unwindstack::LocalUnwinder* g_unwinder;
+
+static void Setup() {
+#if defined(__LP64__)
+  std::vector<std::string> skip_libraries{"/system/lib64/libunwindstack.so", "/system/lib64/libc_malloc_debug.so"};
+#else
+  std::vector<std::string> skip_libraries{"/system/lib/libunwindstack.so", "/system/lib/libc_malloc_debug.so"};
+#endif
+
+  g_unwinder = new unwindstack::LocalUnwinder(skip_libraries);
+  g_unwinder->Init();
+}
+
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* frame_info, size_t max_frames) {
+  pthread_once(&g_setup_once, Setup);
+
+  if (g_unwinder == nullptr) {
+    return false;
+  }
+
+  if (!g_unwinder->Unwind(frame_info, max_frames)) {
+    frames->clear();
+    frame_info->clear();
+    return false;
+  }
+
+  for (const auto& frame : *frame_info) {
+    frames->push_back(frame.pc);
+  }
+  return true;
+}
+
+void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info) {
+  for (size_t i = 0; i < frame_info.size(); i++) {
+    const unwindstack::LocalFrameData* info = &frame_info[i];
+    unwindstack::MapInfo* map_info = info->map_info;
+
+    std::string line = android::base::StringPrintf("          #%0zd  pc %" PAD_PTR "  ", i, info->rel_pc);
+    if (map_info->offset != 0) {
+      line += android::base::StringPrintf("(offset 0x%" PRIx64 ") ", map_info->offset);
+    }
+
+    if (map_info->name.empty()) {
+      line += android::base::StringPrintf("<anonymous:%" PRIx64 ">", map_info->start);
+    } else {
+      line += map_info->name;
+    }
+
+    if (!info->function_name.empty()) {
+      line += " (" + demangle(info->function_name.c_str());
+      if (info->function_offset != 0) {
+        line += "+" + std::to_string(info->function_offset);
+      }
+      line += ")";
+    }
+    error_log_string(line.c_str());
+  }
+}
diff --git a/libc/malloc_debug/UnwindBacktrace.h b/libc/malloc_debug/UnwindBacktrace.h
new file mode 100644
index 0000000..4c6c8d4
--- /dev/null
+++ b/libc/malloc_debug/UnwindBacktrace.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/MapInfo.h>
+
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* info, size_t max_frames);
+
+void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info);
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 6f841ca..836c33b 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -47,6 +47,7 @@
 #include "debug_disable.h"
 #include "debug_log.h"
 #include "malloc_debug.h"
+#include "UnwindBacktrace.h"
 
 // ------------------------------------------------------------------------
 // Global Data
@@ -118,6 +119,26 @@
   });
 }
 
+void BacktraceAndLog() {
+  if (g_debug->config().options() & BACKTRACE_FULL) {
+    std::vector<uintptr_t> frames;
+    std::vector<unwindstack::LocalFrameData> frames_info;
+    if (!Unwind(&frames, &frames_info, 256)) {
+      error_log("  Backtrace failed to get any frames.");
+    } else {
+      UnwindLog(frames_info);
+    }
+  } else {
+    std::vector<uintptr_t> frames(256);
+    size_t num_frames = backtrace_get(frames.data(), frames.size());
+    if (num_frames == 0) {
+      error_log("  Backtrace failed to get any frames.");
+    } else {
+      backtrace_log(frames.data(), num_frames);
+    }
+  }
+}
+
 static void LogError(const void* pointer, const char* error_str) {
   error_log(LOG_DIVIDER);
   error_log("+++ ALLOCATION %p %s", pointer, error_str);
@@ -128,14 +149,8 @@
     PointerData::LogFreeBacktrace(pointer);
   }
 
-  std::vector<uintptr_t> frames(128);
-  size_t num_frames = backtrace_get(frames.data(), frames.size());
-  if (num_frames == 0) {
-    error_log("Backtrace failed to get any frames.");
-  } else {
-    error_log("Backtrace at time of failure:");
-    backtrace_log(frames.data(), num_frames);
-  }
+  error_log("Backtrace at time of failure:");
+  BacktraceAndLog();
   error_log(LOG_DIVIDER);
 }
 
@@ -819,7 +834,7 @@
     return false;
   }
 
-  fprintf(fp, "Android Native Heap Dump v1.0\n\n");
+  fprintf(fp, "Android Native Heap Dump v1.1\n\n");
 
   PointerData::DumpLiveToFile(fp);
 
diff --git a/libc/malloc_debug/malloc_debug.h b/libc/malloc_debug/malloc_debug.h
index ac210e2..7280ea7 100644
--- a/libc/malloc_debug/malloc_debug.h
+++ b/libc/malloc_debug/malloc_debug.h
@@ -62,3 +62,5 @@
 constexpr size_t FREE_TRACK_MEM_BUFFER_SIZE = 4096;
 
 extern const MallocDispatch* g_dispatch;
+
+void BacktraceAndLog();
diff --git a/libc/malloc_debug/tests/backtrace_fake.cpp b/libc/malloc_debug/tests/backtrace_fake.cpp
index db542e5..ad16c02 100644
--- a/libc/malloc_debug/tests/backtrace_fake.cpp
+++ b/libc/malloc_debug/tests/backtrace_fake.cpp
@@ -20,6 +20,8 @@
 #include <vector>
 #include <utility>
 
+#include <unwindstack/LocalUnwinder.h>
+
 #include "backtrace.h"
 #include "backtrace_fake.h"
 #include "debug_log.h"
@@ -57,3 +59,31 @@
     error_log("  #%02zd pc %p", i, reinterpret_cast<void*>(frames[i]));
   }
 }
+
+static std::deque<std::vector<unwindstack::LocalFrameData>> g_fake_local_frame_data;
+
+void BacktraceUnwindFakeClearAll() {
+  g_fake_local_frame_data.clear();
+}
+
+void BacktraceUnwindFake(const std::vector<unwindstack::LocalFrameData>& frames) {
+  g_fake_local_frame_data.push_back(frames);
+}
+
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* info, size_t) {
+  if (g_fake_local_frame_data.empty()) {
+    return false;
+  }
+
+  *info = g_fake_local_frame_data.front();
+  g_fake_local_frame_data.pop_front();
+  frames->clear();
+  for (const auto& frame : *info) {
+    frames->push_back(frame.pc);
+  }
+
+  return true;
+}
+
+void UnwindLog(const std::vector<unwindstack::LocalFrameData>& /*frame_info*/) {
+}
diff --git a/libc/malloc_debug/tests/backtrace_fake.h b/libc/malloc_debug/tests/backtrace_fake.h
index f2aa7a0..a9ee97d 100644
--- a/libc/malloc_debug/tests/backtrace_fake.h
+++ b/libc/malloc_debug/tests/backtrace_fake.h
@@ -21,7 +21,12 @@
 
 #include <vector>
 
+#include <unwindstack/LocalUnwinder.h>
+
 void backtrace_fake_clear_all();
 void backtrace_fake_add(const std::vector<uintptr_t>& ips);
 
+void BacktraceUnwindFakeClearAll();
+void BacktraceUnwindFake(const std::vector<unwindstack::LocalFrameData>& frames);
+
 #endif // MALLOC_DEBUG_TESTS_BACKTRACE_FAKE_H
diff --git a/libc/malloc_debug/tests/log_fake.cpp b/libc/malloc_debug/tests/log_fake.cpp
index fb64e3e..9a23ac7 100644
--- a/libc/malloc_debug/tests/log_fake.cpp
+++ b/libc/malloc_debug/tests/log_fake.cpp
@@ -45,9 +45,7 @@
 }
 
 extern "C" int async_safe_format_log(int priority, const char* tag, const char* format, ...) {
-  g_fake_log_print += std::to_string(priority) + ' ';
-  g_fake_log_print += tag;
-  g_fake_log_print += ' ';
+  g_fake_log_print += std::to_string(priority) + ' ' + tag + ' ';
 
   va_list ap;
   va_start(ap, format);
@@ -59,6 +57,12 @@
   return 0;
 }
 
+extern "C" int async_safe_write_log(int priority, const char* tag, const char* msg) {
+  g_fake_log_print += std::to_string(priority) + ' ' + tag + ' ' + msg + '\n';
+
+  return 0;
+}
+
 extern "C" int __android_log_buf_write(int bufId, int prio, const char* tag, const char* msg) {
   g_fake_log_buf += std::to_string(bufId) + ' ' + std::to_string(prio) + ' ';
   g_fake_log_buf += tag;
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index 4603535..a083b4f 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -40,106 +40,8 @@
 };
 
 std::string usage_string(
-  "6 malloc_debug malloc debug options usage:\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   front_guard[=XX]\n"
-  "6 malloc_debug     Enables a front guard on all allocations. If XX is set\n"
-  "6 malloc_debug     it sets the number of bytes in the guard. The default is\n"
-  "6 malloc_debug     32 bytes, the max bytes is 16384.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   rear_guard[=XX]\n"
-  "6 malloc_debug     Enables a rear guard on all allocations. If XX is set\n"
-  "6 malloc_debug     it sets the number of bytes in the guard. The default is\n"
-  "6 malloc_debug     32 bytes, the max bytes is 16384.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   guard[=XX]\n"
-  "6 malloc_debug     Enables both a front guard and a rear guard on all allocations.\n"
-  "6 malloc_debug     If XX is set it sets the number of bytes in both guards.\n"
-  "6 malloc_debug     The default is 32 bytes, the max bytes is 16384.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   backtrace[=XX]\n"
-  "6 malloc_debug     Enable capturing the backtrace at the point of allocation.\n"
-  "6 malloc_debug     If XX is set it sets the number of backtrace frames.\n"
-  "6 malloc_debug     This option also enables dumping the backtrace heap data\n"
-  "6 malloc_debug     when a signal is received. The data is dumped to the file\n"
-  "6 malloc_debug     backtrace_dump_prefix.<PID>.txt.\n"
-  "6 malloc_debug     The default is 16 frames, the max number of frames is 256.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   backtrace_enable_on_signal[=XX]\n"
-  "6 malloc_debug     Enable capturing the backtrace at the point of allocation.\n"
-  "6 malloc_debug     The backtrace capture is not enabled until the process\n"
-  "6 malloc_debug     receives a signal. If XX is set it sets the number of backtrace\n"
-  "6 malloc_debug     frames. The default is 16 frames, the max number of frames is 256.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   backtrace_dump_prefix[=FILE]\n"
-  "6 malloc_debug     This option only has meaning if the backtrace option has been specified.\n"
-  "6 malloc_debug     This is the prefix of the name of the file to which backtrace heap\n"
-  "6 malloc_debug     data will be dumped. The file will be named backtrace_dump_prefix.<PID>.txt.\n"
-  "6 malloc_debug     The default is /data/local/tmp/backtrace_heap.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   backtrace_dump_on_exit\n"
-  "6 malloc_debug     This option only has meaning if the backtrace option has been specified.\n"
-  "6 malloc_debug     This will cause all live allocations to be dumped to the file\n"
-  "6 malloc_debug     backtrace_dump_prefix.<PID>.final.txt.\n"
-  "6 malloc_debug     The default is false.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   fill_on_alloc[=XX]\n"
-  "6 malloc_debug     On first allocation, fill with the value 0xeb.\n"
-  "6 malloc_debug     If XX is set it will only fill up to XX bytes of the\n"
-  "6 malloc_debug     allocation. The default is to fill the entire allocation.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   fill_on_free[=XX]\n"
-  "6 malloc_debug     On free, fill with the value 0xef. If XX is set it will\n"
-  "6 malloc_debug     only fill up to XX bytes of the allocation. The default is to\n"
-  "6 malloc_debug     fill the entire allocation.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   fill[=XX]\n"
-  "6 malloc_debug     On both first allocation free, fill with the value 0xeb on\n"
-  "6 malloc_debug     first allocation and the value 0xef. If XX is set, only fill\n"
-  "6 malloc_debug     up to XX bytes. The default is to fill the entire allocation.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   expand_alloc[=XX]\n"
-  "6 malloc_debug     Allocate an extra number of bytes for every allocation call.\n"
-  "6 malloc_debug     If XX is set, that is the number of bytes to expand the\n"
-  "6 malloc_debug     allocation by. The default is 16 bytes, the max bytes is 16384.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   free_track[=XX]\n"
-  "6 malloc_debug     When a pointer is freed, do not free the memory right away.\n"
-  "6 malloc_debug     Instead, keep XX of these allocations around and then verify\n"
-  "6 malloc_debug     that they have not been modified when the total number of freed\n"
-  "6 malloc_debug     allocations exceeds the XX amount. When the program terminates,\n"
-  "6 malloc_debug     the rest of these allocations are verified. When this option is\n"
-  "6 malloc_debug     enabled, it automatically records the backtrace at the time of the free.\n"
-  "6 malloc_debug     The default is to record 100 allocations, the max allocations\n"
-  "6 malloc_debug     to record is 16384.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   free_track_backtrace_num_frames[=XX]\n"
-  "6 malloc_debug     This option only has meaning if free_track is set. This indicates\n"
-  "6 malloc_debug     how many backtrace frames to capture when an allocation is freed.\n"
-  "6 malloc_debug     If XX is set, that is the number of frames to capture. If XX\n"
-  "6 malloc_debug     is set to zero, then no backtrace will be captured.\n"
-  "6 malloc_debug     The default is to record 16 frames, the max number of frames is 256.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   leak_track\n"
-  "6 malloc_debug     Enable the leak tracking of memory allocations.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   record_allocs[=XX]\n"
-  "6 malloc_debug     Record every single allocation/free call. When a specific signal\n"
-  "6 malloc_debug     is sent to the process, the contents of recording are written to\n"
-  "6 malloc_debug     a file (/data/local/tmp/record_allocs.txt) and the recording is cleared.\n"
-  "6 malloc_debug     If XX is set, that is the total number of allocations/frees that can\n"
-  "6 malloc_debug     recorded. of frames to capture. The default value is 8000000.\n"
-  "6 malloc_debug     If the allocation list fills up, all further allocations are not recorded.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   record_allocs_file[=FILE]\n"
-  "6 malloc_debug     This option only has meaning if the record_allocs options has been specified.\n"
-  "6 malloc_debug     This is the name of the file to which recording information will be dumped.\n"
-  "6 malloc_debug     The default is /data/local/tmp/record_allocs.txt.\n"
-  "6 malloc_debug \n"
-  "6 malloc_debug   verify_pointers\n"
-  "6 malloc_debug     A lightweight way to verify that free/malloc_usable_size/realloc\n"
-  "6 malloc_debug     are passed valid pointers.\n"
-);
+  "6 malloc_debug For malloc debug option descriptions go to:\n"
+  "6 malloc_debug   https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md\n");
 
 TEST_F(MallocDebugConfigTest, unknown_option) {
 
@@ -413,6 +315,24 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugConfigTest, backtrace_full) {
+  ASSERT_TRUE(InitConfig("backtrace_full")) << getFakeLogPrint();
+  ASSERT_EQ(BACKTRACE_FULL, config->options());
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_full_fail) {
+  ASSERT_FALSE(InitConfig("backtrace_full=200")) << getFakeLogPrint();
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string log_msg(
+      "6 malloc_debug malloc_testing: value set for option 'backtrace_full' "
+      "which does not take a value\n");
+  ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
+}
+
 TEST_F(MallocDebugConfigTest, fill_on_alloc) {
   ASSERT_TRUE(InitConfig("fill_on_alloc=64")) << getFakeLogPrint();
   ASSERT_EQ(FILL_ON_ALLOC, config->options());
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 1504d06..0663f6a 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/cdefs.h>
+#include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -1311,30 +1312,23 @@
   std::string sanitized(SanitizeHeapData(actual));
 
   std::string expected =
-      "Android Native Heap Dump v1.0\n"
-      "\n"
-      "Total memory: 405\n"
-      "Allocation records: 6\n"
-      "Backtrace size: 4\n"
-      "\n"
-#if defined(__LP64__)
-      "z 0  sz       50  num    1  bt 000000000000a100 000000000000b200\n"
-      "z 0  sz       10  num    1  bt 000000000000a000 000000000000b000\n"
-      "z 0  sz        5  num    1  bt 000000000000a300 000000000000b300\n"
-      "z 1  sz      200  num    1  bt 0000000000000500 0000000000000600\n"
-      "z 1  sz      100  num    1  bt 0000000000000100 0000000000000200\n"
-      "z 1  sz       40  num    1  bt 0000000000000300 0000000000000400\n"
-#else
-      "z 0  sz       50  num    1  bt 0000a100 0000b200\n"
-      "z 0  sz       10  num    1  bt 0000a000 0000b000\n"
-      "z 0  sz        5  num    1  bt 0000a300 0000b300\n"
-      "z 1  sz      200  num    1  bt 00000500 00000600\n"
-      "z 1  sz      100  num    1  bt 00000100 00000200\n"
-      "z 1  sz       40  num    1  bt 00000300 00000400\n"
-#endif
-      "MAPS\n"
-      "MAP_DATA\n"
-      "END\n\n";
+R"(Android Native Heap Dump v1.1
+
+Total memory: 405
+Allocation records: 6
+Backtrace size: 4
+
+z 0  sz       50  num    1  bt a100 b200
+z 0  sz       10  num    1  bt a000 b000
+z 0  sz        5  num    1  bt a300 b300
+z 1  sz      200  num    1  bt 500 600
+z 1  sz      100  num    1  bt 100 200
+z 1  sz       40  num    1  bt 300 400
+MAPS
+MAP_DATA
+END
+
+)";
   ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -1383,24 +1377,20 @@
   std::string sanitized(SanitizeHeapData(actual));
 
   std::string expected =
-      "Android Native Heap Dump v1.0\n"
-      "\n"
-      "Total memory: 1200\n"
-      "Allocation records: 3\n"
-      "Backtrace size: 4\n"
-      "\n"
-#if defined(__LP64__)
-      "z 0  sz      500  num    1  bt 000000000000a000 000000000000b000 000000000000c000\n"
-      "z 0  sz      400  num    1  bt 000000000000a000 000000000000b000\n"
-      "z 0  sz      300  num    1  bt 0000000000000100 0000000000000200\n"
-#else
-      "z 0  sz      500  num    1  bt 0000a000 0000b000 0000c000\n"
-      "z 0  sz      400  num    1  bt 0000a000 0000b000\n"
-      "z 0  sz      300  num    1  bt 00000100 00000200\n"
-#endif
-      "MAPS\n"
-      "MAP_DATA\n"
-      "END\n\n";
+R"(Android Native Heap Dump v1.1
+
+Total memory: 1200
+Allocation records: 3
+Backtrace size: 4
+
+z 0  sz      500  num    1  bt a000 b000 c000
+z 0  sz      400  num    1  bt a000 b000
+z 0  sz      300  num    1  bt 100 200
+MAPS
+MAP_DATA
+END
+
+)";
   ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -1436,28 +1426,84 @@
   std::string sanitized(SanitizeHeapData(actual));
 
   std::string expected =
-      "Android Native Heap Dump v1.0\n"
-      "\n"
-      "Total memory: 1000\n"
-      "Allocation records: 2\n"
-      "Backtrace size: 4\n"
-      "\n"
-#if defined(__LP64__)
-      "z 0  sz      400  num    1  bt 000000000000a000 000000000000b000 000000000000c000\n"
-      "z 0  sz      300  num    2  bt 0000000000000100 0000000000000200\n"
-#else
-      "z 0  sz      400  num    1  bt 0000a000 0000b000 0000c000\n"
-      "z 0  sz      300  num    2  bt 00000100 00000200\n"
-#endif
-      "MAPS\n"
-      "MAP_DATA\n"
-      "END\n\n";
+R"(Android Native Heap Dump v1.1
+
+Total memory: 1000
+Allocation records: 2
+Backtrace size: 4
+
+z 0  sz      400  num    1  bt a000 b000 c000
+z 0  sz      300  num    2  bt 100 200
+MAPS
+MAP_DATA
+END
+
+)";
   ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugTest, backtrace_full_dump_on_exit) {
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    Init("backtrace=4 backtrace_full backtrace_dump_on_exit");
+    BacktraceUnwindFake(
+      std::vector<unwindstack::LocalFrameData>{{nullptr, 0x1100, 0x100, "fake1", 10},
+                                               {nullptr, 0x1200, 0x200, "fake2", 20}});
+    unwindstack::MapInfo map_info{0x10000, 0x20000, 0, PROT_READ | PROT_EXEC, "/data/fake.so"};
+    BacktraceUnwindFake(
+      std::vector<unwindstack::LocalFrameData>{{&map_info, 0x1a000, 0xa000, "level1", 0},
+                                               {&map_info, 0x1b000, 0xb000, "level2", 10}});
+    BacktraceUnwindFake(
+      std::vector<unwindstack::LocalFrameData>{{nullptr, 0x1a000, 0xa000, "func1", 0},
+                                               {nullptr, 0x1b000, 0xb000, "func2", 10},
+                                               {nullptr, 0x1c000, 0xc000, "", 30}});
+
+    std::vector<void*> pointers;
+    pointers.push_back(debug_malloc(300));
+    pointers.push_back(debug_malloc(400));
+    pointers.push_back(debug_malloc(500));
+
+    // Call the exit function manually.
+    debug_finalize();
+    exit(0);
+  }
+  ASSERT_NE(-1, pid);
+  ASSERT_EQ(pid, TEMP_FAILURE_RETRY(waitpid(pid, nullptr, 0)));
+
+  // Read all of the contents.
+  std::string actual;
+  std::string name = android::base::StringPrintf("%s.%d.exit.txt", BACKTRACE_DUMP_PREFIX, pid);
+  ASSERT_TRUE(android::base::ReadFileToString(name, &actual));
+  ASSERT_EQ(0, unlink(name.c_str()));
+
+  std::string sanitized(SanitizeHeapData(actual));
+
+  std::string expected =
+R"(Android Native Heap Dump v1.1
+
+Total memory: 1200
+Allocation records: 3
+Backtrace size: 4
+
+z 0  sz      500  num    1  bt 1a000 1b000 1c000
+  bt_info {"" a000 "func1" 0} {"" b000 "func2" a} {"" c000 "" 0}
+z 0  sz      400  num    1  bt 1a000 1b000
+  bt_info {"/data/fake.so" a000 "level1" 0} {"/data/fake.so" b000 "level2" a}
+z 0  sz      300  num    1  bt 1100 1200
+  bt_info {"" 100 "fake1" a} {"" 200 "fake2" 14}
+MAPS
+MAP_DATA
+END
+
+)";
+  ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
 
 TEST_F(MallocDebugTest, realloc_usable_size) {
   Init("front_guard");
@@ -2286,7 +2332,8 @@
   std::string realloc_pointer_str(
       android::base::StringPrintf("6 malloc_debug +++ ALLOCATION %p UNKNOWN POINTER (realloc)\n",
                                   pointer));
-  std::string backtrace_str("6 malloc_debug Backtrace failed to get any frames.\n");
+  std::string backtrace_str("6 malloc_debug Backtrace at time of failure:\n");
+  backtrace_str += "6 malloc_debug   Backtrace failed to get any frames.\n";
 
   std::string expected_log(DIVIDER + free_pointer_str + backtrace_str + DIVIDER);
   expected_log += DIVIDER + usable_pointer_str + backtrace_str + DIVIDER;
diff --git a/libc/upstream-openbsd/lib/libc/string/memmove.c b/libc/upstream-openbsd/lib/libc/string/memmove.c
deleted file mode 100644
index 2f1deb2..0000000
--- a/libc/upstream-openbsd/lib/libc/string/memmove.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*	$OpenBSD: memmove.c,v 1.2 2015/08/31 02:53:57 guenther Exp $ */
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <string.h>
-
-/*
- * sizeof(word) MUST BE A POWER OF TWO
- * SO THAT wmask BELOW IS ALL ONES
- */
-typedef	long word;		/* "word" used for optimal copy speed */
-
-#define	wsize	sizeof(word)
-#define	wmask	(wsize - 1)
-
-/*
- * Copy a block of memory, handling overlap.
- */
-void *
-memmove(void *dst0, const void *src0, size_t length)
-{
-	char *dst = dst0;
-	const char *src = src0;
-	size_t t;
-
-	if (length == 0 || dst == src)		/* nothing to do */
-		goto done;
-
-	/*
-	 * Macros: loop-t-times; and loop-t-times, t>0
-	 */
-#define	TLOOP(s) if (t) TLOOP1(s)
-#define	TLOOP1(s) do { s; } while (--t)
-
-	if ((unsigned long)dst < (unsigned long)src) {
-		/*
-		 * Copy forward.
-		 */
-		t = (long)src;	/* only need low bits */
-		if ((t | (long)dst) & wmask) {
-			/*
-			 * Try to align operands.  This cannot be done
-			 * unless the low bits match.
-			 */
-			if ((t ^ (long)dst) & wmask || length < wsize)
-				t = length;
-			else
-				t = wsize - (t & wmask);
-			length -= t;
-			TLOOP1(*dst++ = *src++);
-		}
-		/*
-		 * Copy whole words, then mop up any trailing bytes.
-		 */
-		t = length / wsize;
-		TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
-		t = length & wmask;
-		TLOOP(*dst++ = *src++);
-	} else {
-		/*
-		 * Copy backwards.  Otherwise essentially the same.
-		 * Alignment works as before, except that it takes
-		 * (t&wmask) bytes to align, not wsize-(t&wmask).
-		 */
-		src += length;
-		dst += length;
-		t = (long)src;
-		if ((t | (long)dst) & wmask) {
-			if ((t ^ (long)dst) & wmask || length <= wsize)
-				t = length;
-			else
-				t &= wmask;
-			length -= t;
-			TLOOP1(*--dst = *--src);
-		}
-		t = length / wsize;
-		TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
-		t = length & wmask;
-		TLOOP(*--dst = *--src);
-	}
-done:
-	return (dst0);
-}
-DEF_STRONG(memmove);
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 97f1038..d5f8e70 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -49,6 +49,7 @@
     arch: {
         arm: {
             version_script: "libdl.arm.map",
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
         },
         arm64: {
@@ -61,6 +62,7 @@
             version_script: "libdl.mips64.map",
         },
         x86: {
+            pack_relocations: false,
             ldflags: [
                 "-Wl,--exclude-libs=libgcc_eh.a",
                 "-Wl,--hash-style=both",
diff --git a/libm/Android.bp b/libm/Android.bp
index c67e358..9566d5f 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -293,6 +293,7 @@
                 ],
             },
             instruction_set: "arm",
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
             version_script: "libm.arm.map",
         },
@@ -420,6 +421,7 @@
                 ],
             },
             local_include_dirs: ["i387"],
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
             version_script: "libm.x86.map",
         },
diff --git a/linker/Android.bp b/linker/Android.bp
index 9e18954..78d425e 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -105,6 +105,7 @@
         },
         x86: {
             srcs: ["arch/x86/begin.S"],
+            cflags: ["-D__work_around_b_24465209__"],
             version_script: "linker.generic.map",
         },
         x86_64: {
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 7d9abf9..6d68497 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1432,10 +1432,13 @@
 }
 
 // Duplicate these definitions here because they are android specific
-// note that we cannot include <elf.h> because #defines conflict with
-// enum names provided by LLVM.
-#define DT_ANDROID_REL (llvm::ELF::DT_LOOS + 2)
-#define DT_ANDROID_RELA (llvm::ELF::DT_LOOS + 4)
+//  - note that we cannot include <elf.h> because #defines conflict with
+//    enum names provided by LLVM.
+//  - we also don't use llvm::ELF::DT_LOOS because its value is 0x60000000
+//    rather than the 0x6000000d we expect
+#define DT_LOOS 0x6000000d
+#define DT_ANDROID_REL (DT_LOOS + 2)
+#define DT_ANDROID_RELA (DT_LOOS + 4)
 
 template<typename ELFT>
 void validate_compatibility_of_native_library(const std::string& soname,
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index fa8a662..615f374 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -29,6 +29,7 @@
 #include <set>
 #include <vector>
 
+#include <android-base/file.h>
 #include <android-base/strings.h>
 #include <private/android_filesystem_config.h>
 
@@ -36,6 +37,9 @@
 #include "generated_android_ids.h"
 
 using android::base::Join;
+using android::base::ReadFileToString;
+using android::base::Split;
+using android::base::StartsWith;
 
 enum uid_type_t {
   TYPE_SYSTEM,
@@ -528,3 +532,36 @@
   print_no_getgrnam_test_info();
 #endif
 }
+
+#if defined(__BIONIC__)
+static void TestAidNamePrefix(const std::string& file_path) {
+  std::string file_contents;
+  if (!ReadFileToString(file_path, &file_contents)) {
+    // If we cannot read this file, then there are no vendor defind AID names, in which case this
+    // test passes by default.
+    return;
+  }
+  auto lines = Split(file_contents, "\n");
+  for (const auto& line : lines) {
+    if (line.empty()) continue;
+    auto name = Split(line, ":")[0];
+    EXPECT_TRUE(StartsWith(name, "vendor_"));
+  }
+}
+#endif
+
+TEST(pwd, vendor_prefix_users) {
+#if defined(__BIONIC__)
+  TestAidNamePrefix("/vendor/etc/passwd");
+#else
+  print_no_getpwnam_test_info();
+#endif
+}
+
+TEST(pwd, vendor_prefix_groups) {
+#if defined(__BIONIC__)
+  TestAidNamePrefix("/vendor/etc/group");
+#else
+  print_no_getgrnam_test_info();
+#endif
+}
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index c1f1590..c1f5f1c 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -531,6 +531,8 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["dl_df_1_global.cpp"],
     ldflags: ["-Wl,-z,global"],
+    // b/80109858, clang lld ignores -z,global
+    use_clang_lld: false,
 
     target: {
         host: {
@@ -559,6 +561,8 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["dl_df_1_global_dummy.cpp"],
     ldflags: ["-Wl,-z,global"],
+    // b/80109858, clang lld ignores -z,global
+    use_clang_lld: false,
 
     target: {
         host: {