Merge "Change heap dump format slightly."
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 1ea4ac1..40a0023 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -39,6 +39,7 @@
// allocations that are currently in use.
// free_malloc_leak_info: Frees the data allocated by the call to
// get_malloc_leak_info.
+// write_malloc_leak_info: Writes the leak info data to a file.
#include <pthread.h>
@@ -211,6 +212,7 @@
FUNC_GET_MALLOC_LEAK_INFO,
FUNC_FREE_MALLOC_LEAK_INFO,
FUNC_MALLOC_BACKTRACE,
+ FUNC_WRITE_LEAK_INFO,
FUNC_LAST,
};
static void* g_functions[FUNC_LAST];
@@ -219,6 +221,7 @@
typedef bool (*init_func_t)(const MallocDispatch*, int*, const char*);
typedef void (*get_malloc_leak_info_func_t)(uint8_t**, size_t*, size_t*, size_t*, size_t*);
typedef void (*free_malloc_leak_info_func_t)(uint8_t*);
+typedef bool (*write_malloc_leak_info_func_t)(FILE*);
typedef ssize_t (*malloc_backtrace_func_t)(void*, uintptr_t*, size_t);
// =============================================================================
@@ -260,6 +263,26 @@
reinterpret_cast<free_malloc_leak_info_func_t>(func)(info);
}
+extern "C" void write_malloc_leak_info(FILE* fp) {
+ if (fp == nullptr) {
+ error_log("write_malloc_leak_info called with a nullptr");
+ return;
+ }
+
+ void* func = g_functions[FUNC_WRITE_LEAK_INFO];
+ bool written = false;
+ if (func != nullptr) {
+ written = reinterpret_cast<write_malloc_leak_info_func_t>(func)(fp);
+ }
+
+ if (!written) {
+ fprintf(fp, "Native heap dump not available. To enable, run these commands (requires root):\n");
+ fprintf(fp, "# adb shell stop\n");
+ fprintf(fp, "# adb shell setprop libc.debug.malloc.options backtrace\n");
+ fprintf(fp, "# adb shell start\n");
+ }
+}
+
// =============================================================================
template<typename FunctionType>
@@ -392,6 +415,7 @@
"get_malloc_leak_info",
"free_malloc_leak_info",
"malloc_backtrace",
+ "write_malloc_leak_info",
};
for (size_t i = 0; i < FUNC_LAST; i++) {
char symbol[128];
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 159d4a0..18099dd 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1634,6 +1634,7 @@
tkill; # arm x86 mips
wait3; # arm x86 mips
wcswcs; # arm x86 mips
+ write_malloc_leak_info;
} LIBC_P;
LIBC_DEPRECATED {
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 7702f9e..f37641e 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1352,6 +1352,7 @@
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild;
+ write_malloc_leak_info;
} LIBC_P;
LIBC_DEPRECATED {
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index ebe2098..21966b3 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1660,6 +1660,7 @@
tkill; # arm x86 mips
wait3; # arm x86 mips
wcswcs; # arm x86 mips
+ write_malloc_leak_info;
} LIBC_P;
LIBC_DEPRECATED {
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index d04cb4f..0bc6fce 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1475,6 +1475,7 @@
tkill; # arm x86 mips
wait3; # arm x86 mips
wcswcs; # arm x86 mips
+ write_malloc_leak_info;
} LIBC_P;
LIBC_DEPRECATED {
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 7702f9e..f37641e 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1352,6 +1352,7 @@
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild;
+ write_malloc_leak_info;
} LIBC_P;
LIBC_DEPRECATED {
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 2e10bbb..14ee151 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1474,6 +1474,7 @@
tkill; # arm x86 mips
wait3; # arm x86 mips
wcswcs; # arm x86 mips
+ write_malloc_leak_info;
} LIBC_P;
LIBC_DEPRECATED {
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 7702f9e..f37641e 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1352,6 +1352,7 @@
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild;
+ write_malloc_leak_info;
} LIBC_P;
LIBC_DEPRECATED {
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index a4ff5d4..0cb4cca 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -139,5 +139,6 @@
"-Wall",
"-Werror",
"-Wno-error=format-zero-length",
+ "-O0",
],
}
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index c427d5f..c4ee722 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -161,7 +161,7 @@
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
+As of Q, 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.
@@ -495,15 +495,32 @@
The map data is simply the output of /proc/PID/maps. This data can be used to
decode the frames in the backtraces.
-As of Android P, there is a new version of this file. The new header is:
+There are now multiple versions of the file:
+
+Android P produces version v1.1 of the heap dump.
Android Native Heap Dump v1.1
-The new version no longer 0 pads the backtrace addresses. In v1.0:
+The only difference between v1.0 and v1.1 is that the NUM\_ALLOCATIONS
+value is always accurate in v1.1. A previous version of malloc debug set
+NUM\_ALLOCATIONS to an incorrect value. For heap dump v1.0, the
+NUM\_ALLOCATIONS value should be treated as always 1 no matter what is
+actually present.
+
+Android Q introduces v1.2 of the heap dump. The new header looks like this:
+
+ Android Native Heap Dump v1.2
+
+ Build fingerprint: 'google/taimen/taimen:8.1.0/OPM2.171026.006.C1/4769658:user/release-keys'
+
+The new line fingerprint line is the contents of the ro.build.fingerprint
+property.
+
+The new version no longer 0 pads the backtrace addresses. In v1.0/v1.1:
z 0 sz 400 num 1 bt 0000a230 0000b500
-While v1.1:
+While v1.2:
z 0 sz 400 num 1 bt a230 b500
diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map
index 78a6990..2f590d0 100644
--- a/libc/malloc_debug/exported32.map
+++ b/libc/malloc_debug/exported32.map
@@ -21,6 +21,7 @@
debug_pvalloc;
debug_realloc;
debug_valloc;
+ debug_write_malloc_leak_info;
local:
*;
diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map
index 2bfc38b..08d36a5 100644
--- a/libc/malloc_debug/exported64.map
+++ b/libc/malloc_debug/exported64.map
@@ -19,6 +19,7 @@
debug_memalign;
debug_posix_memalign;
debug_realloc;
+ debug_write_malloc_leak_info;
local:
*;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 836c33b..1e7086c 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -38,6 +38,7 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <private/bionic_malloc_dispatch.h>
@@ -69,9 +70,10 @@
bool debug_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_child,
const char* options);
void debug_finalize();
-bool debug_dump_heap(const char* file_name);
+void debug_dump_heap(const char* file_name);
void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
size_t* total_memory, size_t* backtrace_size);
+bool debug_write_malloc_leak_info(FILE* fp);
ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
void debug_free_malloc_leak_info(uint8_t* info);
size_t debug_malloc_usable_size(void* pointer);
@@ -813,28 +815,11 @@
static std::mutex g_dump_lock;
-bool debug_dump_heap(const char* file_name) {
- ScopedDisableDebugCalls disable;
+static void write_dump(FILE* fp) {
+ fprintf(fp, "Android Native Heap Dump v1.2\n\n");
- std::lock_guard<std::mutex> guard(g_dump_lock);
-
- FILE* fp = fopen(file_name, "w+e");
- if (fp == nullptr) {
- error_log("Unable to create file: %s", file_name);
- return false;
- }
- error_log("Dumping to file: %s\n", file_name);
-
- if (!(g_debug->config().options() & BACKTRACE)) {
- fprintf(fp, "Native heap dump not available. To enable, run these commands (requires root):\n");
- fprintf(fp, "# adb shell stop\n");
- fprintf(fp, "# adb shell setprop libc.debug.malloc.options backtrace\n");
- fprintf(fp, "# adb shell start\n");
- fclose(fp);
- return false;
- }
-
- fprintf(fp, "Android Native Heap Dump v1.1\n\n");
+ std::string fingerprint = android::base::GetProperty("ro.build.fingerprint", "unknown");
+ fprintf(fp, "Build fingerprint: '%s'\n\n", fingerprint.c_str());
PointerData::DumpLiveToFile(fp);
@@ -846,6 +831,33 @@
fprintf(fp, "%s", content.c_str());
}
fprintf(fp, "END\n");
- fclose(fp);
+}
+
+bool debug_write_malloc_leak_info(FILE* fp) {
+ ScopedDisableDebugCalls disable;
+
+ std::lock_guard<std::mutex> guard(g_dump_lock);
+
+ if (!(g_debug->config().options() & BACKTRACE)) {
+ return false;
+ }
+
+ write_dump(fp);
return true;
}
+
+void debug_dump_heap(const char* file_name) {
+ ScopedDisableDebugCalls disable;
+
+ std::lock_guard<std::mutex> guard(g_dump_lock);
+
+ FILE* fp = fopen(file_name, "w+e");
+ if (fp == nullptr) {
+ error_log("Unable to create file: %s", file_name);
+ return;
+ }
+
+ error_log("Dumping to file: %s\n", file_name);
+ write_dump(fp);
+ fclose(fp);
+}
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 0663f6a..cd6d2c2 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -1250,10 +1250,15 @@
continue;
}
}
- if (line == "MAPS") {
- skip_map_data = true;
+
+ if (android::base::StartsWith(line, "Build fingerprint:")) {
+ sanitized += "Build fingerprint: ''\n";
+ } else {
+ if (line == "MAPS") {
+ skip_map_data = true;
+ }
+ sanitized += line + '\n';
}
- sanitized += line + '\n';
}
return sanitized;
}
@@ -1312,7 +1317,9 @@
std::string sanitized(SanitizeHeapData(actual));
std::string expected =
-R"(Android Native Heap Dump v1.1
+R"(Android Native Heap Dump v1.2
+
+Build fingerprint: ''
Total memory: 405
Allocation records: 6
@@ -1377,7 +1384,9 @@
std::string sanitized(SanitizeHeapData(actual));
std::string expected =
-R"(Android Native Heap Dump v1.1
+R"(Android Native Heap Dump v1.2
+
+Build fingerprint: ''
Total memory: 1200
Allocation records: 3
@@ -1426,7 +1435,9 @@
std::string sanitized(SanitizeHeapData(actual));
std::string expected =
-R"(Android Native Heap Dump v1.1
+R"(Android Native Heap Dump v1.2
+
+Build fingerprint: ''
Total memory: 1000
Allocation records: 2
@@ -1482,7 +1493,9 @@
std::string sanitized(SanitizeHeapData(actual));
std::string expected =
-R"(Android Native Heap Dump v1.1
+R"(Android Native Heap Dump v1.2
+
+Build fingerprint: ''
Total memory: 1200
Allocation records: 3