aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2019-04-15 19:01:08 -0700
committerChristopher Ferris <cferris@google.com>2019-04-19 11:16:17 -0700
commit2601d434599fc830d7a8d1965fd8e27519e520fb (patch)
tree667778a661c50ced98862e2d023cf2809fbb04a0
parent21f5850627bb9d5485073e6c07ba7b05067f7b16 (diff)
downloadandroid_bionic-2601d434599fc830d7a8d1965fd8e27519e520fb.tar.gz
android_bionic-2601d434599fc830d7a8d1965fd8e27519e520fb.tar.bz2
android_bionic-2601d434599fc830d7a8d1965fd8e27519e520fb.zip
Move all leak info functions to android_mallopt.
Bug: 130028357 Test: malloc_hooks unit tests. Test: Enable backtrace for mediaserver, run dumpsys media.player -m Test: Enable backtrace for calendar, run am dumpheap -n <PID> <FILE> Change-Id: I6774e28ccd9b3f2310127a5b39ccd15fe696a787 Merged-In: I6774e28ccd9b3f2310127a5b39ccd15fe696a787 (cherry picked from commit 3aadc5e80a5e2cf6b6760ed90d528709223bb449)
-rw-r--r--libc/bionic/malloc_common.cpp9
-rw-r--r--libc/bionic/malloc_common_dynamic.cpp59
-rw-r--r--libc/libc.map.txt7
-rw-r--r--libc/malloc_hooks/tests/malloc_hooks_tests.cpp23
-rw-r--r--libc/private/bionic_malloc.h36
5 files changed, 84 insertions, 50 deletions
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 3f1bcc36d..60ee138c7 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -32,14 +32,7 @@
// calls and add special debugging code to attempt to catch allocation
// errors. All of the debugging code is implemented in a separate shared
// library that is only loaded when the property "libc.debug.malloc.options"
-// is set to a non-zero value. There are two functions exported to
-// allow ddms, or other external users to get information from the debug
-// allocation.
-// get_malloc_leak_info: Returns information about all of the known native
-// allocations that are currently in use.
-// free_malloc_leak_info: Frees the data allocated by the call to
-// get_malloc_leak_info.
-// write_malloc_leak_info: Writes the leak info data to a file.
+// is set to a non-zero value.
#include <errno.h>
#include <stdint.h>
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 64f9f6f7b..599ac6a58 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -409,39 +409,29 @@ __LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
// =============================================================================
// Functions to support dumping of native heap allocations using malloc debug.
// =============================================================================
-
-// Retrieve native heap information.
-//
-// "*info" is set to a buffer we allocate
-// "*overall_size" is set to the size of the "info" buffer
-// "*info_size" is set to the size of a single entry
-// "*total_memory" is set to the sum of all allocations we're tracking; does
-// not include heap overhead
-// "*backtrace_size" is set to the maximum number of entries in the back trace
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size,
- size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
+bool GetMallocLeakInfo(android_mallopt_leak_info_t* leak_info) {
void* func = gFunctions[FUNC_GET_MALLOC_LEAK_INFO];
if (func == nullptr) {
- return;
+ errno = ENOTSUP;
+ return false;
}
- reinterpret_cast<get_malloc_leak_info_func_t>(func)(info, overall_size, info_size, total_memory,
- backtrace_size);
+ reinterpret_cast<get_malloc_leak_info_func_t>(func)(
+ &leak_info->buffer, &leak_info->overall_size, &leak_info->info_size,
+ &leak_info->total_memory, &leak_info->backtrace_size);
+ return true;
}
-extern "C" void free_malloc_leak_info(uint8_t* info) {
+bool FreeMallocLeakInfo(android_mallopt_leak_info_t* leak_info) {
void* func = gFunctions[FUNC_FREE_MALLOC_LEAK_INFO];
if (func == nullptr) {
- return;
+ errno = ENOTSUP;
+ return false;
}
- reinterpret_cast<free_malloc_leak_info_func_t>(func)(info);
+ reinterpret_cast<free_malloc_leak_info_func_t>(func)(leak_info->buffer);
+ return true;
}
-extern "C" void write_malloc_leak_info(FILE* fp) {
- if (fp == nullptr) {
- error_log("write_malloc_leak_info called with a nullptr");
- return;
- }
-
+bool WriteMallocLeakInfo(FILE* fp) {
void* func = gFunctions[FUNC_WRITE_LEAK_INFO];
bool written = false;
if (func != nullptr) {
@@ -453,7 +443,9 @@ extern "C" void write_malloc_leak_info(FILE* fp) {
fprintf(fp, "# adb shell stop\n");
fprintf(fp, "# adb shell setprop libc.debug.malloc.options backtrace\n");
fprintf(fp, "# adb shell start\n");
+ errno = ENOTSUP;
}
+ return written;
}
// =============================================================================
@@ -484,6 +476,27 @@ extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
return LimitEnable(arg, arg_size);
}
+ if (opcode == M_WRITE_MALLOC_LEAK_INFO_TO_FILE) {
+ if (arg == nullptr || arg_size != sizeof(FILE*)) {
+ errno = EINVAL;
+ return false;
+ }
+ return WriteMallocLeakInfo(reinterpret_cast<FILE*>(arg));
+ }
+ if (opcode == M_GET_MALLOC_LEAK_INFO) {
+ if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
+ errno = EINVAL;
+ return false;
+ }
+ return GetMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
+ }
+ if (opcode == M_FREE_MALLOC_LEAK_INFO) {
+ if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
+ errno = EINVAL;
+ return false;
+ }
+ return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
+ }
return HeapprofdMallopt(opcode, arg, arg_size);
}
// =============================================================================
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 55ca9dcfb..f0fccf553 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1473,15 +1473,10 @@ LIBC_Q { # introduced=Q
malloc_enable; # apex
malloc_iterate; # apex
- # Used by libmediautils
- write_malloc_leak_info; # apex
- free_malloc_leak_info; # apex
- get_malloc_leak_info; # apex
-
# Used by libandroid_net
android_getaddrinfofornet; # apex
- # Used by libandroid_runtime and libmedia
+ # Used by libandroid_runtime, libmedia and libmediautils
android_mallopt; # apex
} LIBC_P;
diff --git a/libc/malloc_hooks/tests/malloc_hooks_tests.cpp b/libc/malloc_hooks/tests/malloc_hooks_tests.cpp
index 0d23a6a8f..86e20ea90 100644
--- a/libc/malloc_hooks/tests/malloc_hooks_tests.cpp
+++ b/libc/malloc_hooks/tests/malloc_hooks_tests.cpp
@@ -38,6 +38,7 @@
#include <gtest/gtest.h>
+#include <private/bionic_malloc.h>
#include <private/bionic_malloc_dispatch.h>
#include <tests/utils.h>
@@ -197,19 +198,15 @@ TEST_F(MallocHooksTest, extended_functions) {
}
TEST_F(MallocHooksTest, DISABLED_extended_functions) {
- uint8_t* info = nullptr;
- size_t overall_size = 100;
- size_t info_size = 200;
- size_t total_memory = 300;
- size_t backtrace_size = 400;
- get_malloc_leak_info(&info, &overall_size, &info_size, &total_memory, &backtrace_size);
- EXPECT_EQ(nullptr, info);
- EXPECT_EQ(0U, overall_size);
- EXPECT_EQ(0U, info_size);
- EXPECT_EQ(0U, total_memory);
- EXPECT_EQ(0U, backtrace_size);
-
- free_malloc_leak_info(info);
+ android_mallopt_leak_info_t leak_info;
+ ASSERT_TRUE(android_mallopt(M_GET_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info)));
+ EXPECT_EQ(nullptr, leak_info.buffer);
+ EXPECT_EQ(0U, leak_info.overall_size);
+ EXPECT_EQ(0U, leak_info.info_size);
+ EXPECT_EQ(0U, leak_info.total_memory);
+ EXPECT_EQ(0U, leak_info.backtrace_size);
+
+ ASSERT_TRUE(android_mallopt(M_FREE_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info)));
malloc_enable();
malloc_disable();
diff --git a/libc/private/bionic_malloc.h b/libc/private/bionic_malloc.h
index e8a6f6ef5..9c602eadf 100644
--- a/libc/private/bionic_malloc.h
+++ b/libc/private/bionic_malloc.h
@@ -30,6 +30,22 @@
#include <stdbool.h>
+// Structures for android_mallopt.
+
+typedef struct {
+ // Pointer to the buffer allocated by a call to M_GET_MALLOC_LEAK_INFO.
+ uint8_t* buffer;
+ // The size of the "info" buffer.
+ size_t overall_size;
+ // The size of a single entry.
+ size_t info_size;
+ // The sum of all allocations that have been tracked. Does not include
+ // any heap overhead.
+ size_t total_memory;
+ // The maximum number of backtrace entries.
+ size_t backtrace_size;
+} android_mallopt_leak_info_t;
+
// Opcodes for android_mallopt.
enum {
@@ -48,6 +64,26 @@ enum {
// Called after the zygote forks to indicate this is a child.
M_SET_ZYGOTE_CHILD = 4,
#define M_SET_ZYGOTE_CHILD M_SET_ZYGOTE_CHILD
+
+ // Options to dump backtraces of allocations. These options only
+ // work when malloc debug has been enabled.
+
+ // Writes the backtrace information of all current allocations to a file.
+ // NOTE: arg_size has to be sizeof(FILE*) because FILE is an opaque type.
+ // arg = FILE*
+ // arg_size = sizeof(FILE*)
+ M_WRITE_MALLOC_LEAK_INFO_TO_FILE = 5,
+#define M_WRITE_MALLOC_LEAK_INFO_TO_FILE M_WRITE_MALLOC_LEAK_INFO_TO_FILE
+ // Get information about the backtraces of all
+ // arg = android_mallopt_leak_info_t*
+ // arg_size = sizeof(android_mallopt_leak_info_t)
+ M_GET_MALLOC_LEAK_INFO = 6,
+#define M_GET_MALLOC_LEAK_INFO M_GET_MALLOC_LEAK_INFO
+ // Free the memory allocated and returned by M_GET_MALLOC_LEAK_INFO.
+ // arg = android_mallopt_leak_info_t*
+ // arg_size = sizeof(android_mallopt_leak_info_t)
+ M_FREE_MALLOC_LEAK_INFO = 7,
+#define M_FREE_MALLOC_LEAK_INFO M_FREE_MALLOC_LEAK_INFO
};
// Manipulates bionic-specific handling of memory allocation APIs such as