More debug malloc fixes.
Include the leaky executable's name in the log output. Fix the "sh" test.
Use uintptr_t instead of intptr_t.
Also fix debug formatting of NULL with %s.
Bug: 7291287
Change-Id: I015bf341cd48d43a247173612e6ccb1bf1243d53
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index 7b6a536..d366b56 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -78,9 +78,9 @@
uint32_t tag;
hdr_t* prev;
hdr_t* next;
- intptr_t bt[MAX_BACKTRACE_DEPTH];
+ uintptr_t bt[MAX_BACKTRACE_DEPTH];
int bt_depth;
- intptr_t freed_bt[MAX_BACKTRACE_DEPTH];
+ uintptr_t freed_bt[MAX_BACKTRACE_DEPTH];
int freed_bt_depth;
size_t size;
char front_guard[FRONT_GUARD_LEN];
@@ -102,7 +102,7 @@
return reinterpret_cast<hdr_t*>(user) - 1;
}
-static unsigned num;
+static unsigned gAllocatedBlockCount;
static hdr_t *tail;
static hdr_t *head;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
@@ -181,7 +181,7 @@
hdr->size = size;
init_front_guard(hdr);
init_rear_guard(hdr);
- num++;
+ ++gAllocatedBlockCount;
add_locked(hdr, &tail, &head);
}
@@ -192,7 +192,7 @@
ScopedPthreadMutexLocker locker(&lock);
del_locked(hdr, &tail, &head);
- num--;
+ --gAllocatedBlockCount;
return 0;
}
@@ -298,7 +298,7 @@
static inline int del_leak(hdr_t *hdr, int *safe) {
ScopedPthreadMutexLocker locker(&lock);
- return del_and_check_locked(hdr, &tail, &head, &num, safe);
+ return del_and_check_locked(hdr, &tail, &head, &gAllocatedBlockCount, safe);
}
static inline void add_to_backlog(hdr_t *hdr) {
@@ -342,7 +342,7 @@
hdr_t* hdr = meta(ptr);
if (del(hdr) < 0) {
- intptr_t bt[MAX_BACKTRACE_DEPTH];
+ uintptr_t bt[MAX_BACKTRACE_DEPTH];
int depth;
depth = get_backtrace(bt, MAX_BACKTRACE_DEPTH);
if (hdr->tag == BACKLOG_TAG) {
@@ -387,7 +387,7 @@
hdr_t* hdr = meta(ptr);
if (del(hdr) < 0) {
- intptr_t bt[MAX_BACKTRACE_DEPTH];
+ uintptr_t bt[MAX_BACKTRACE_DEPTH];
int depth;
depth = get_backtrace(bt, MAX_BACKTRACE_DEPTH);
if (hdr->tag == BACKLOG_TAG) {
@@ -442,28 +442,36 @@
}
static void heaptracker_free_leaked_memory() {
- size_t total = num;
- if (num) {
- log_message("+++ Leaked allocations: %d\n", num);
- }
+ if (gAllocatedBlockCount == 0) {
+ return;
+ }
- hdr_t *del = NULL;
- while (head) {
- int safe;
- del = head;
- log_message("+++ Leaked block of size %d at %p (leak %d of %d)\n",
- del->size, user(del), 1 + total - num, total);
- if (del_leak(del, &safe)) {
- /* safe == 1, because the allocation is valid */
- log_backtrace(gMapInfo, del->bt, del->bt_depth);
- }
- }
+ // Use /proc/self/exe link to obtain the program name for logging
+ // purposes. If it's not available, we set it to "<unknown>".
+ char exe[PATH_MAX];
+ int count;
+ if ((count = readlink("/proc/self/exe", exe, sizeof(exe) - 1)) == -1) {
+ strlcpy(exe, "<unknown>", sizeof(exe));
+ } else {
+ exe[count] = '\0';
+ }
-// log_message("+++ DELETING %d BACKLOGGED ALLOCATIONS\n", backlog_num);
- while (backlog_head) {
- del = backlog_tail;
- del_from_backlog(del);
+ size_t index = 1;
+ const size_t total = gAllocatedBlockCount;
+ while (head != NULL) {
+ int safe;
+ hdr_t* block = head;
+ log_message("+++ %s leaked block of size %d at %p (leak %d of %d)",
+ exe, block->size, user(block), index++, total);
+ if (del_leak(block, &safe)) {
+ /* safe == 1, because the allocation is valid */
+ log_backtrace(gMapInfo, block->bt, block->bt_depth);
}
+ }
+
+ while (backlog_head != NULL) {
+ del_from_backlog(backlog_tail);
+ }
}
/* Initializes malloc debugging framework.