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 3aadc5e80a
)
This commit is contained in:
parent
75f7b06454
commit
30659fd243
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
// =============================================================================
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
|
||||
free_malloc_leak_info(info);
|
||||
ASSERT_TRUE(android_mallopt(M_FREE_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info)));
|
||||
|
||||
malloc_enable();
|
||||
malloc_disable();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue