Merge "Don't claim there were no leaks if we weren't even checking."
This commit is contained in:
commit
3dc6b57cf5
@ -53,13 +53,13 @@
|
|||||||
#include "ScopedPthreadMutexLocker.h"
|
#include "ScopedPthreadMutexLocker.h"
|
||||||
|
|
||||||
/* libc.debug.malloc.backlog */
|
/* libc.debug.malloc.backlog */
|
||||||
extern unsigned int malloc_double_free_backlog;
|
extern unsigned int gMallocDebugBacklog;
|
||||||
|
extern int gMallocDebugLevel;
|
||||||
|
|
||||||
#define MAX_BACKTRACE_DEPTH 16
|
#define MAX_BACKTRACE_DEPTH 16
|
||||||
#define ALLOCATION_TAG 0x1ee7d00d
|
#define ALLOCATION_TAG 0x1ee7d00d
|
||||||
#define BACKLOG_TAG 0xbabecafe
|
#define BACKLOG_TAG 0xbabecafe
|
||||||
#define FREE_POISON 0xa5
|
#define FREE_POISON 0xa5
|
||||||
#define BACKLOG_DEFAULT_LEN 100
|
|
||||||
#define FRONT_GUARD 0xaa
|
#define FRONT_GUARD 0xaa
|
||||||
#define FRONT_GUARD_LEN (1<<5)
|
#define FRONT_GUARD_LEN (1<<5)
|
||||||
#define REAR_GUARD 0xbb
|
#define REAR_GUARD 0xbb
|
||||||
@ -306,7 +306,7 @@ static inline void add_to_backlog(hdr_t *hdr) {
|
|||||||
add_locked(hdr, &backlog_tail, &backlog_head);
|
add_locked(hdr, &backlog_tail, &backlog_head);
|
||||||
poison(hdr);
|
poison(hdr);
|
||||||
/* If we've exceeded the maximum backlog, clear it up */
|
/* If we've exceeded the maximum backlog, clear it up */
|
||||||
while (backlog_num > malloc_double_free_backlog) {
|
while (backlog_num > gMallocDebugBacklog) {
|
||||||
hdr_t *gone = backlog_tail;
|
hdr_t *gone = backlog_tail;
|
||||||
del_from_backlog_locked(gone);
|
del_from_backlog_locked(gone);
|
||||||
dlfree(gone);
|
dlfree(gone);
|
||||||
@ -436,7 +436,12 @@ extern "C" void *chk_calloc(int nmemb, size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void heaptracker_free_leaked_memory() {
|
static void ReportMemoryLeaks() {
|
||||||
|
// We only track leaks at level 10.
|
||||||
|
if (gMallocDebugLevel != 10) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Use /proc/self/exe link to obtain the program name for logging
|
// Use /proc/self/exe link to obtain the program name for logging
|
||||||
// purposes. If it's not available, we set it to "<unknown>".
|
// purposes. If it's not available, we set it to "<unknown>".
|
||||||
char exe[PATH_MAX];
|
char exe[PATH_MAX];
|
||||||
@ -471,14 +476,11 @@ static void heaptracker_free_leaked_memory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int malloc_debug_initialize() {
|
extern "C" int malloc_debug_initialize() {
|
||||||
if (!malloc_double_free_backlog) {
|
|
||||||
malloc_double_free_backlog = BACKLOG_DEFAULT_LEN;
|
|
||||||
}
|
|
||||||
backtrace_startup();
|
backtrace_startup();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void malloc_debug_finalize() {
|
extern "C" void malloc_debug_finalize() {
|
||||||
heaptracker_free_leaked_memory();
|
ReportMemoryLeaks();
|
||||||
backtrace_shutdown();
|
backtrace_shutdown();
|
||||||
}
|
}
|
||||||
|
@ -288,14 +288,17 @@ static void* libc_malloc_impl_handle = NULL;
|
|||||||
/* This variable is set to the value of property libc.debug.malloc.backlog,
|
/* This variable is set to the value of property libc.debug.malloc.backlog,
|
||||||
* when the value of libc.debug.malloc = 10. It determines the size of the
|
* when the value of libc.debug.malloc = 10. It determines the size of the
|
||||||
* backlog we use to detect multiple frees. If the property is not set, the
|
* backlog we use to detect multiple frees. If the property is not set, the
|
||||||
* backlog length defaults to an internal constant defined in
|
* backlog length defaults to BACKLOG_DEFAULT_LEN.
|
||||||
* malloc_debug_check.cpp.
|
|
||||||
*/
|
*/
|
||||||
unsigned int malloc_double_free_backlog;
|
unsigned int gMallocDebugBacklog;
|
||||||
|
#define BACKLOG_DEFAULT_LEN 100
|
||||||
|
|
||||||
static void InitMalloc(MallocDebug* table, int debug_level, const char* prefix) {
|
/* The value of libc.debug.malloc. */
|
||||||
|
int gMallocDebugLevel;
|
||||||
|
|
||||||
|
static void InitMalloc(MallocDebug* table, const char* prefix) {
|
||||||
__libc_format_log(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n",
|
__libc_format_log(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n",
|
||||||
__progname, debug_level, prefix);
|
__progname, gMallocDebugLevel, prefix);
|
||||||
|
|
||||||
char symbol[128];
|
char symbol[128];
|
||||||
|
|
||||||
@ -335,7 +338,6 @@ static void malloc_init_impl() {
|
|||||||
const char* so_name = NULL;
|
const char* so_name = NULL;
|
||||||
MallocDebugInit malloc_debug_initialize = NULL;
|
MallocDebugInit malloc_debug_initialize = NULL;
|
||||||
unsigned int qemu_running = 0;
|
unsigned int qemu_running = 0;
|
||||||
unsigned int debug_level = 0;
|
|
||||||
unsigned int memcheck_enabled = 0;
|
unsigned int memcheck_enabled = 0;
|
||||||
char env[PROP_VALUE_MAX];
|
char env[PROP_VALUE_MAX];
|
||||||
char memcheck_tracing[PROP_VALUE_MAX];
|
char memcheck_tracing[PROP_VALUE_MAX];
|
||||||
@ -349,7 +351,7 @@ static void malloc_init_impl() {
|
|||||||
if (__system_property_get("ro.kernel.memcheck", memcheck_tracing)) {
|
if (__system_property_get("ro.kernel.memcheck", memcheck_tracing)) {
|
||||||
if (memcheck_tracing[0] != '0') {
|
if (memcheck_tracing[0] != '0') {
|
||||||
// Emulator has started with memory tracing enabled. Enforce it.
|
// Emulator has started with memory tracing enabled. Enforce it.
|
||||||
debug_level = 20;
|
gMallocDebugLevel = 20;
|
||||||
memcheck_enabled = 1;
|
memcheck_enabled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,13 +359,13 @@ static void malloc_init_impl() {
|
|||||||
|
|
||||||
/* If debug level has not been set by memcheck option in the emulator,
|
/* If debug level has not been set by memcheck option in the emulator,
|
||||||
* lets grab it from libc.debug.malloc system property. */
|
* lets grab it from libc.debug.malloc system property. */
|
||||||
if (debug_level == 0 && __system_property_get("libc.debug.malloc", env)) {
|
if (gMallocDebugLevel == 0 && __system_property_get("libc.debug.malloc", env)) {
|
||||||
debug_level = atoi(env);
|
gMallocDebugLevel = atoi(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Debug level 0 means that we should use dlxxx allocation
|
/* Debug level 0 means that we should use dlxxx allocation
|
||||||
* routines (default). */
|
* routines (default). */
|
||||||
if (debug_level == 0) {
|
if (gMallocDebugLevel == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,24 +379,25 @@ static void malloc_init_impl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// mksh is way too leaky. http://b/7291287.
|
// mksh is way too leaky. http://b/7291287.
|
||||||
if (debug_level >= 10) {
|
if (gMallocDebugLevel >= 10) {
|
||||||
if (strcmp(__progname, "sh") == 0 || strcmp(__progname, "/system/bin/sh") == 0) {
|
if (strcmp(__progname, "sh") == 0 || strcmp(__progname, "/system/bin/sh") == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose the appropriate .so for the requested debug level.
|
// Choose the appropriate .so for the requested debug level.
|
||||||
switch (debug_level) {
|
switch (gMallocDebugLevel) {
|
||||||
case 1:
|
case 1:
|
||||||
case 5:
|
case 5:
|
||||||
case 10: {
|
case 10: {
|
||||||
char debug_backlog[PROP_VALUE_MAX];
|
char debug_backlog[PROP_VALUE_MAX];
|
||||||
if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
|
if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
|
||||||
malloc_double_free_backlog = atoi(debug_backlog);
|
gMallocDebugBacklog = atoi(debug_backlog);
|
||||||
info_log("%s: setting backlog length to %d\n",
|
info_log("%s: setting backlog length to %d\n", __progname, gMallocDebugBacklog);
|
||||||
__progname, malloc_double_free_backlog);
|
}
|
||||||
|
if (gMallocDebugBacklog == 0) {
|
||||||
|
gMallocDebugBacklog = BACKLOG_DEFAULT_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
so_name = "/system/lib/libc_malloc_debug_leak.so";
|
so_name = "/system/lib/libc_malloc_debug_leak.so";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -402,7 +405,7 @@ static void malloc_init_impl() {
|
|||||||
// Quick check: debug level 20 can only be handled in emulator.
|
// Quick check: debug level 20 can only be handled in emulator.
|
||||||
if (!qemu_running) {
|
if (!qemu_running) {
|
||||||
error_log("%s: Debug level %d can only be set in emulator\n",
|
error_log("%s: Debug level %d can only be set in emulator\n",
|
||||||
__progname, debug_level);
|
__progname, gMallocDebugLevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Make sure that memory checking has been enabled in emulator.
|
// Make sure that memory checking has been enabled in emulator.
|
||||||
@ -414,8 +417,7 @@ static void malloc_init_impl() {
|
|||||||
so_name = "/system/lib/libc_malloc_debug_qemu.so";
|
so_name = "/system/lib/libc_malloc_debug_qemu.so";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_log("%s: Debug level %d is unknown\n",
|
error_log("%s: Debug level %d is unknown\n", __progname, gMallocDebugLevel);
|
||||||
__progname, debug_level);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +425,7 @@ static void malloc_init_impl() {
|
|||||||
libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
|
libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
|
||||||
if (libc_malloc_impl_handle == NULL) {
|
if (libc_malloc_impl_handle == NULL) {
|
||||||
error_log("%s: Missing module %s required for malloc debug level %d: %s",
|
error_log("%s: Missing module %s required for malloc debug level %d: %s",
|
||||||
__progname, so_name, debug_level, dlerror());
|
__progname, so_name, gMallocDebugLevel, dlerror());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,7 +443,7 @@ static void malloc_init_impl() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_level == 20) {
|
if (gMallocDebugLevel == 20) {
|
||||||
// For memory checker we need to do extra initialization.
|
// For memory checker we need to do extra initialization.
|
||||||
typedef int (*MemCheckInit)(int, const char*);
|
typedef int (*MemCheckInit)(int, const char*);
|
||||||
MemCheckInit memcheck_initialize =
|
MemCheckInit memcheck_initialize =
|
||||||
@ -461,18 +463,18 @@ static void malloc_init_impl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize malloc dispatch table with appropriate routines.
|
// Initialize malloc dispatch table with appropriate routines.
|
||||||
switch (debug_level) {
|
switch (gMallocDebugLevel) {
|
||||||
case 1:
|
case 1:
|
||||||
InitMalloc(&gMallocUse, debug_level, "leak");
|
InitMalloc(&gMallocUse, "leak");
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
InitMalloc(&gMallocUse, debug_level, "fill");
|
InitMalloc(&gMallocUse, "fill");
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
InitMalloc(&gMallocUse, debug_level, "chk");
|
InitMalloc(&gMallocUse, "chk");
|
||||||
break;
|
break;
|
||||||
case 20:
|
case 20:
|
||||||
InitMalloc(&gMallocUse, debug_level, "qemu_instrumented");
|
InitMalloc(&gMallocUse, "qemu_instrumented");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -485,7 +487,7 @@ static void malloc_init_impl() {
|
|||||||
(gMallocUse.realloc == NULL) ||
|
(gMallocUse.realloc == NULL) ||
|
||||||
(gMallocUse.memalign == NULL)) {
|
(gMallocUse.memalign == NULL)) {
|
||||||
error_log("%s: some symbols for libc.debug.malloc level %d were not found (see above)",
|
error_log("%s: some symbols for libc.debug.malloc level %d were not found (see above)",
|
||||||
__progname, debug_level);
|
__progname, gMallocDebugLevel);
|
||||||
dlclose(libc_malloc_impl_handle);
|
dlclose(libc_malloc_impl_handle);
|
||||||
libc_malloc_impl_handle = NULL;
|
libc_malloc_impl_handle = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user