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: {