Last active
September 5, 2015 04:50
-
-
Save swarren/ae40611b9c5493470a01 to your computer and use it in GitHub Desktop.
Malloc leak tracing hacks for U-Boot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
See other files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 3cb19cec2bbe7d5f4dc05eec393ccf48189a3d9a Mon Sep 17 00:00:00 2001 | |
From: Stephen Warren <swarren@nvidia.com> | |
Date: Fri, 4 Sep 2015 11:29:23 -0600 | |
Subject: [PATCH 1/2] dump malloc_stats() | |
X-NVConfidentiality: public | |
Signed-off-by: Stephen Warren <swarren@nvidia.com> | |
--- | |
common/cmd_dfu.c | 2 ++ | |
common/cmd_fs.c | 5 ++++- | |
common/dlmalloc.c | 2 +- | |
3 files changed, 7 insertions(+), 2 deletions(-) | |
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c | |
index 857148f8afef..82b70be71632 100644 | |
--- a/common/cmd_dfu.c | |
+++ b/common/cmd_dfu.c | |
@@ -9,6 +9,7 @@ | |
*/ | |
#include <common.h> | |
+#include <malloc.h> | |
#include <watchdog.h> | |
#include <dfu.h> | |
#include <g_dnl.h> | |
@@ -78,6 +79,7 @@ done: | |
run_command("reset", 0); | |
g_dnl_clear_detach(); | |
+malloc_stats(); | |
return ret; | |
} | |
diff --git a/common/cmd_fs.c b/common/cmd_fs.c | |
index e146254f6d68..1ed0312ca04a 100644 | |
--- a/common/cmd_fs.c | |
+++ b/common/cmd_fs.c | |
@@ -19,6 +19,7 @@ | |
#include <common.h> | |
#include <command.h> | |
#include <fs.h> | |
+#include <malloc.h> | |
static int do_size_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
{ | |
@@ -54,7 +55,9 @@ U_BOOT_CMD( | |
static int do_save_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, | |
char * const argv[]) | |
{ | |
- return do_save(cmdtp, flag, argc, argv, FS_TYPE_ANY); | |
+ int ret = do_save(cmdtp, flag, argc, argv, FS_TYPE_ANY); | |
+malloc_stats(); | |
+return ret; | |
} | |
U_BOOT_CMD( | |
diff --git a/common/dlmalloc.c b/common/dlmalloc.c | |
index b5bb05191c24..845c0b4ce24b 100644 | |
--- a/common/dlmalloc.c | |
+++ b/common/dlmalloc.c | |
@@ -1,6 +1,6 @@ | |
#include <common.h> | |
-#ifdef CONFIG_SANDBOX | |
+#if 1//def CONFIG_SANDBOX | |
#define DEBUG | |
#endif | |
-- | |
1.9.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 23a5881984e5f52cf475998219e6e05b33b121f5 Mon Sep 17 00:00:00 2001 | |
From: Stephen Warren <swarren@nvidia.com> | |
Date: Thu, 3 Sep 2015 22:11:16 -0600 | |
Subject: [PATCH 2/2] malloc debug | |
X-NVConfidentiality: public | |
Signed-off-by: Stephen Warren <swarren@nvidia.com> | |
--- | |
common/cli_hush.c | 26 ++++++++++++++++ | |
common/dlmalloc.c | 89 ++++++++++++++++++++++++++++++++++++++++++------------- | |
2 files changed, 94 insertions(+), 21 deletions(-) | |
diff --git a/common/cli_hush.c b/common/cli_hush.c | |
index 296542f4c2d6..a333dcb42862 100644 | |
--- a/common/cli_hush.c | |
+++ b/common/cli_hush.c | |
@@ -386,9 +386,33 @@ static void __syntax(char *file, int line) { | |
#endif | |
#ifdef __U_BOOT__ | |
+#if 0 | |
static void *xmalloc(size_t size); | |
static void *xrealloc(void *ptr, size_t size); | |
#else | |
+static inline void *xmalloc(size_t size) | |
+{ | |
+ void *p = NULL; | |
+ | |
+ if (!(p = malloc(size))) { | |
+ printf("ERROR : memory not allocated\n"); | |
+ for(;;); | |
+ } | |
+ return p; | |
+} | |
+ | |
+static inline void *xrealloc(void *ptr, size_t size) | |
+{ | |
+ void *p = NULL; | |
+ | |
+ if (!(p = realloc(ptr, size))) { | |
+ printf("ERROR : memory not allocated\n"); | |
+ for(;;); | |
+ } | |
+ return p; | |
+} | |
+#endif | |
+#else | |
/* Index of subroutines: */ | |
/* function prototypes for builtins */ | |
static int builtin_cd(struct child_prog *child); | |
@@ -3304,6 +3328,7 @@ int u_boot_hush_start(void) | |
return 0; | |
} | |
+#if 0 | |
static void *xmalloc(size_t size) | |
{ | |
void *p = NULL; | |
@@ -3325,6 +3350,7 @@ static void *xrealloc(void *ptr, size_t size) | |
} | |
return p; | |
} | |
+#endif | |
#endif /* __U_BOOT__ */ | |
#ifndef __U_BOOT__ | |
diff --git a/common/dlmalloc.c b/common/dlmalloc.c | |
index 845c0b4ce24b..5ae2a5900e01 100644 | |
--- a/common/dlmalloc.c | |
+++ b/common/dlmalloc.c | |
@@ -948,6 +948,12 @@ void malloc_stats(); | |
DECLARE_GLOBAL_DATA_PTR; | |
+#if __STD_C | |
+void free_imp(Void_t* mem); | |
+#else | |
+void free_imp(mem) Void_t* mem; | |
+#endif | |
+ | |
/* | |
Emulation of sbrk for WIN32 | |
All code within the ifdef WIN32 is untested by me. | |
@@ -2084,7 +2090,7 @@ static void malloc_extend_top(nb) INTERNAL_SIZE_T nb; | |
SIZE_SZ|PREV_INUSE; | |
/* If possible, release the rest. */ | |
if (old_top_size >= MINSIZE) | |
- fREe(chunk2mem(old_top)); | |
+ free_imp(chunk2mem(old_top)); | |
} | |
} | |
@@ -2163,9 +2169,9 @@ static void malloc_extend_top(nb) INTERNAL_SIZE_T nb; | |
*/ | |
#if __STD_C | |
-Void_t* mALLOc(size_t bytes) | |
+Void_t* malloc_imp(size_t bytes) | |
#else | |
-Void_t* mALLOc(bytes) size_t bytes; | |
+Void_t* malloc_imp(bytes) size_t bytes; | |
#endif | |
{ | |
mchunkptr victim; /* inspected/selected chunk */ | |
@@ -2409,6 +2415,17 @@ Void_t* mALLOc(bytes) size_t bytes; | |
} | |
+#if __STD_C | |
+Void_t* mALLOc(size_t bytes) | |
+#else | |
+Void_t* mALLOc(bytes) size_t bytes; | |
+#endif | |
+{ | |
+ Void_t *p = malloc_imp(bytes); | |
+printf("malloc(%ld) -> %p @%p\n", bytes, p, __builtin_return_address(0)); | |
+ return p; | |
+} | |
+ | |
@@ -2435,9 +2452,9 @@ Void_t* mALLOc(bytes) size_t bytes; | |
#if __STD_C | |
-void fREe(Void_t* mem) | |
+void free_imp(Void_t* mem) | |
#else | |
-void fREe(mem) Void_t* mem; | |
+void free_imp(mem) Void_t* mem; | |
#endif | |
{ | |
mchunkptr p; /* chunk corresponding to mem */ | |
@@ -2532,7 +2549,15 @@ void fREe(mem) Void_t* mem; | |
frontlink(p, sz, idx, bck, fwd); | |
} | |
- | |
+#if __STD_C | |
+void fREe(Void_t* mem) | |
+#else | |
+void fREe(mem) Void_t* mem; | |
+#endif | |
+{ | |
+printf("free(%p) @%p\n", mem, __builtin_return_address(0)); | |
+ free_imp(mem); | |
+} | |
@@ -2573,9 +2598,9 @@ void fREe(mem) Void_t* mem; | |
#if __STD_C | |
-Void_t* rEALLOc(Void_t* oldmem, size_t bytes) | |
+Void_t* realloc_imp(Void_t* oldmem, size_t bytes) | |
#else | |
-Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
+Void_t* realloc_imp(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
#endif | |
{ | |
INTERNAL_SIZE_T nb; /* padded request size */ | |
@@ -2600,13 +2625,13 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
mchunkptr fwd; /* misc temp for linking */ | |
#ifdef REALLOC_ZERO_BYTES_FREES | |
- if (bytes == 0) { fREe(oldmem); return 0; } | |
+ if (bytes == 0) { free_imp(oldmem); return 0; } | |
#endif | |
if ((long)bytes < 0) return NULL; | |
/* realloc of null is supposed to be same as malloc */ | |
- if (oldmem == NULL) return mALLOc(bytes); | |
+ if (oldmem == NULL) return malloc_imp(bytes); | |
#ifdef CONFIG_SYS_MALLOC_F_LEN | |
if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) { | |
@@ -2631,7 +2656,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
/* Note the extra SIZE_SZ overhead. */ | |
if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */ | |
/* Must alloc, copy, free. */ | |
- newmem = mALLOc(bytes); | |
+ newmem = malloc_imp(bytes); | |
if (newmem == 0) return 0; /* propagate failure */ | |
MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ); | |
munmap_chunk(oldp); | |
@@ -2733,7 +2758,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
/* Must allocate */ | |
- newmem = mALLOc (bytes); | |
+ newmem = malloc_imp(bytes); | |
if (newmem == NULL) /* propagate failure */ | |
return NULL; | |
@@ -2750,7 +2775,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
/* Otherwise copy, free, and exit */ | |
MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); | |
- fREe(oldmem); | |
+ free_imp(oldmem); | |
return newmem; | |
} | |
@@ -2764,7 +2789,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
set_head_size(newp, nb); | |
set_head(remainder, remainder_size | PREV_INUSE); | |
set_inuse_bit_at_offset(remainder, remainder_size); | |
- fREe(chunk2mem(remainder)); /* let free() deal with it */ | |
+ free_imp(chunk2mem(remainder)); /* let free() deal with it */ | |
} | |
else | |
{ | |
@@ -2776,6 +2801,17 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
return chunk2mem(newp); | |
} | |
+#if __STD_C | |
+Void_t* rEALLOc(Void_t* oldmem, size_t bytes) | |
+#else | |
+Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
+#endif | |
+{ | |
+ Void_t *p = realloc_imp(oldmem, bytes); | |
+printf("realloc(%p, %ld) -> %p @%p\n", oldmem, bytes, p, __builtin_return_address(0)); | |
+ return p; | |
+} | |
+ | |
@@ -2799,9 +2835,9 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; | |
#if __STD_C | |
-Void_t* mEMALIGn(size_t alignment, size_t bytes) | |
+Void_t* memalign_imp(size_t alignment, size_t bytes) | |
#else | |
-Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; | |
+Void_t* memalign_imp(alignment, bytes) size_t alignment; size_t bytes; | |
#endif | |
{ | |
INTERNAL_SIZE_T nb; /* padded request size */ | |
@@ -2818,7 +2854,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; | |
/* If need less alignment than we give anyway, just relay to malloc */ | |
- if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes); | |
+ if (alignment <= MALLOC_ALIGNMENT) return malloc_imp(bytes); | |
/* Otherwise, ensure that it is at least a minimum chunk size */ | |
@@ -2827,7 +2863,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; | |
/* Call malloc with worst case padding to hit alignment. */ | |
nb = request2size(bytes); | |
- m = (char*)(mALLOc(nb + alignment + MINSIZE)); | |
+ m = (char*)(malloc_imp(nb + alignment + MINSIZE)); | |
if (m == NULL) return NULL; /* propagate failure */ | |
@@ -2872,7 +2908,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; | |
set_head(newp, newsize | PREV_INUSE); | |
set_inuse_bit_at_offset(newp, newsize); | |
set_head_size(p, leadsize); | |
- fREe(chunk2mem(p)); | |
+ free_imp(chunk2mem(p)); | |
p = newp; | |
assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0); | |
@@ -2887,7 +2923,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; | |
remainder = chunk_at_offset(p, nb); | |
set_head(remainder, remainder_size | PREV_INUSE); | |
set_head_size(p, nb); | |
- fREe(chunk2mem(remainder)); | |
+ free_imp(chunk2mem(remainder)); | |
} | |
check_inuse_chunk(p); | |
@@ -2895,6 +2931,16 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; | |
} | |
+#if __STD_C | |
+Void_t* mEMALIGn(size_t alignment, size_t bytes) | |
+#else | |
+Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; | |
+#endif | |
+{ | |
+ Void_t *p = memalign_imp(alignment, bytes); | |
+printf("memalign(%ld, %ld) -> %p @%p\n", alignment, bytes, p, __builtin_return_address(0)); | |
+ return p; | |
+} | |
@@ -2954,7 +3000,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; | |
INTERNAL_SIZE_T oldtopsize = chunksize(top); | |
#endif | |
#endif | |
- Void_t* mem = mALLOc (sz); | |
+ Void_t* mem = malloc_imp (sz); | |
if ((long)n < 0) return NULL; | |
@@ -2990,6 +3036,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; | |
#endif | |
MALLOC_ZERO(mem, csz - SIZE_SZ); | |
+printf("calloc(%ld, %ld) -> %p @%p\n", n, elem_size, mem, __builtin_return_address(0)); | |
return mem; | |
} | |
} | |
-- | |
1.9.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import re | |
import sys | |
re_alloc = re.compile('[mc]alloc\(([\d, ]+)\) -> ([A-Za-z0-9]+) @([A-Za-z0-9]+)') | |
re_memalign = re.compile('memalign\(\d+, (\d+)\) -> ([A-Za-z0-9]+) @([A-Za-z0-9]+)') | |
re_realloc = re.compile('realloc\(([A-Za-z0-9]+), ([\d, ]+)\) -> ([A-Za-z0-9]+) @([A-Za-z0-9]+)') | |
re_free = re.compile('free\(([A-Za-z0-9]+)\) @([A-Za-z0-9]+)') | |
re_relocoff = re.compile('reloc off = (0x[A-Za-z0-9]+)') | |
MALLOC = 0 | |
REALLOC = 1 | |
FREE = 2 | |
entries = [] | |
relocoff = 0 | |
lnum = 0 | |
for l in sys.stdin.readlines(): | |
lnum += 1 | |
m = re_alloc.match(l) | |
if m: | |
entries.append({ | |
'lnum': lnum, | |
'type': MALLOC, | |
'size': m.group(1), | |
'ptr': m.group(2), | |
'caller': m.group(3) | |
}) | |
continue | |
m = re_memalign.match(l) | |
if m: | |
entries.append({ | |
'lnum': lnum, | |
'type': MALLOC, | |
'size': m.group(1), | |
'ptr': m.group(2), | |
'caller': m.group(3) | |
}) | |
continue | |
m = re_realloc.match(l) | |
if m: | |
entries.append({ | |
'lnum': lnum, | |
'type': REALLOC, | |
'oldptr': m.group(1), | |
'size': m.group(2), | |
'ptr': m.group(3), | |
'caller': m.group(4), | |
}) | |
continue | |
m = re_free.match(l) | |
if m: | |
entries.append({ | |
'lnum': lnum, | |
'type': FREE, | |
'oldptr': m.group(1), | |
'caller': m.group(2) | |
}) | |
continue | |
m = re_relocoff.match(l) | |
if m: | |
relocoff = int(m.group(1), 16) | |
continue | |
print("No format match: " + l.strip()) | |
num_entries = len(entries) | |
for i in range(num_entries): | |
if entries[i]['type'] == FREE: | |
continue | |
ptr = entries[i]['ptr'] | |
found = False | |
for j in range(i + 1, num_entries): | |
if entries[j]['type'] == MALLOC: | |
continue | |
if entries[j]['oldptr'] == ptr: | |
found = True | |
break | |
if not found: | |
caller = int(entries[i]['caller'], 16) - relocoff | |
print('No match: line', str(entries[i]['lnum']), 'caller %x' % caller, 'size', entries[i]['size']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment