diff options
Diffstat (limited to 'malloc')
-rw-r--r-- | malloc/Makefile | 21 | ||||
-rw-r--r-- | malloc/malloc.c | 117 | ||||
-rw-r--r-- | malloc/malloc.h | 21 | ||||
-rw-r--r-- | malloc/mcheck.c | 41 | ||||
-rw-r--r-- | malloc/mtrace.awk | 50 | ||||
-rw-r--r-- | malloc/mtrace.c | 83 | ||||
-rw-r--r-- | malloc/mtrace.pl | 192 |
7 files changed, 434 insertions, 91 deletions
diff --git a/malloc/Makefile b/malloc/Makefile index b43ce13..addabf1 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -27,7 +27,7 @@ dist-headers := malloc.h headers := $(dist-headers) obstack.h tests := mallocbug -distribute = thread-m.h mtrace.awk mcheck-init.c mcheck.h +distribute = thread-m.h mtrace.pl mcheck-init.c mcheck.h # Things which get pasted together into gmalloc.c. gmalloc-routines := malloc morecore @@ -41,6 +41,19 @@ non-lib.a := libmcheck.a # These should be removed by `make clean'. extra-objs = mcheck-init.o libmcheck.a +# The AWK script to analyze the output of the mtrace functions. +ifneq ($(PERL),no) +install-bin = mtrace + +# The Perl script will print addresses and to do this nicely we must know +# whether we are on a 32 or 64 bit machine. +ifneq ($strip($(findstring wordsize-32,$(config-sysdirs))),) +address-width=10 +else +address-width=18 +endif +endif + include ../Rules $(objpfx)libmcheck.a: $(objpfx)mcheck-init.o @@ -52,3 +65,9 @@ lib: $(objpfx)libmcheck.a # Uncomment this for test releases. For public releases it is too expensive. #CPPFLAGS-malloc.o += -DMALLOC_DEBUG + +$(objpfx)mtrace: mtrace.pl + rm -fr %@.new + sed -e 's|@PERL@|$(PERL)|' -e 's|@XXX@|$(address-width)|' \ + -e 's|@VERSION@|$(version)|' $^ > $@.new \ + && rm -fr $@ && mv $@.new $@ && chmod +x $@ diff --git a/malloc/malloc.c b/malloc/malloc.c index fb51483..17350eb 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -1178,7 +1178,19 @@ static int main_trim(size_t pad); #ifndef NO_THREADS static int heap_trim(heap_info *heap, size_t pad); #endif -#if defined(_LIBC) || defined(MALLOC_HOOKS) +#ifdef _LIBC +static Void_t* malloc_check(size_t sz, const Void_t *caller); +static void free_check(Void_t* mem, const Void_t *caller); +static Void_t* realloc_check(Void_t* oldmem, size_t bytes, + const Void_t *caller); +static Void_t* memalign_check(size_t alignment, size_t bytes, + const Void_t *caller); +static Void_t* malloc_starter(size_t sz, const Void_t *caller); +static void free_starter(Void_t* mem, const Void_t *caller); +static Void_t* malloc_atfork(size_t sz, const Void_t *caller); +static void free_atfork(Void_t* mem, const Void_t *caller); +#else +#ifdef MALLOC_HOOKS static Void_t* malloc_check(size_t sz); static void free_check(Void_t* mem); static Void_t* realloc_check(Void_t* oldmem, size_t bytes); @@ -1188,6 +1200,7 @@ static void free_starter(Void_t* mem); static Void_t* malloc_atfork(size_t sz); static void free_atfork(Void_t* mem); #endif +#endif #else @@ -1520,11 +1533,19 @@ int __malloc_initialized = 0; temporarily, because the `atfork' handler mechanism may use malloc/free internally (e.g. in LinuxThreads). */ -#if defined(_LIBC) || defined(MALLOC_HOOKS) +#ifdef _LIBC +static __malloc_ptr_t (*save_malloc_hook) __MALLOC_P ((size_t __size, + const __malloc_ptr_t)); +static void (*save_free_hook) __MALLOC_P ((__malloc_ptr_t __ptr, + const __malloc_ptr_t)); +static Void_t* save_arena; +#else +#ifdef MALLOC_HOOKS static __malloc_ptr_t (*save_malloc_hook) __MALLOC_P ((size_t __size)); static void (*save_free_hook) __MALLOC_P ((__malloc_ptr_t __ptr)); static Void_t* save_arena; #endif +#endif static void ptmalloc_lock_all __MALLOC_P((void)) @@ -1639,11 +1660,15 @@ thread_atfork_static(ptmalloc_lock_all, ptmalloc_unlock_all, \ initialization routine, then do the normal work. */ static Void_t* +#ifdef _LIBC +malloc_hook_ini(size_t sz, const __malloc_ptr_t caller) +#else #if __STD_C malloc_hook_ini(size_t sz) #else malloc_hook_ini(sz) size_t sz; #endif +#endif { __malloc_hook = NULL; __realloc_hook = NULL; @@ -1653,11 +1678,15 @@ malloc_hook_ini(sz) size_t sz; } static Void_t* +#ifdef _LIBC +realloc_hook_ini(Void_t* ptr, size_t sz, const __malloc_ptr_t caller) +#else #if __STD_C realloc_hook_ini(Void_t* ptr, size_t sz) #else realloc_hook_ini(ptr, sz) Void_t* ptr; size_t sz; #endif +#endif { __malloc_hook = NULL; __realloc_hook = NULL; @@ -1667,11 +1696,15 @@ realloc_hook_ini(ptr, sz) Void_t* ptr; size_t sz; } static Void_t* +#ifdef _LIBC +memalign_hook_ini(size_t sz, size_t alignment, const __malloc_ptr_t caller) +#else #if __STD_C memalign_hook_ini(size_t sz, size_t alignment) #else memalign_hook_ini(sz, alignment) size_t sz; size_t alignment; #endif +#endif { __malloc_hook = NULL; __realloc_hook = NULL; @@ -1681,6 +1714,18 @@ memalign_hook_ini(sz, alignment) size_t sz; size_t alignment; } void weak_variable (*__malloc_initialize_hook) __MALLOC_P ((void)) = NULL; +#ifdef _LIBC +void weak_variable (*__free_hook) __MALLOC_P ((__malloc_ptr_t __ptr, + const __malloc_ptr_t)) = NULL; +__malloc_ptr_t weak_variable (*__malloc_hook) + __MALLOC_P ((size_t __size, const __malloc_ptr_t)) = malloc_hook_ini; +__malloc_ptr_t weak_variable (*__realloc_hook) + __MALLOC_P ((__malloc_ptr_t __ptr, size_t __size, const __malloc_ptr_t)) + = realloc_hook_ini; +__malloc_ptr_t weak_variable (*__memalign_hook) + __MALLOC_P ((size_t __size, size_t __alignment, const __malloc_ptr_t)) + = memalign_hook_ini; +#else void weak_variable (*__free_hook) __MALLOC_P ((__malloc_ptr_t __ptr)) = NULL; __malloc_ptr_t weak_variable (*__malloc_hook) __MALLOC_P ((size_t __size)) = malloc_hook_ini; @@ -1688,6 +1733,7 @@ __malloc_ptr_t weak_variable (*__realloc_hook) __MALLOC_P ((__malloc_ptr_t __ptr, size_t __size)) = realloc_hook_ini; __malloc_ptr_t weak_variable (*__memalign_hook) __MALLOC_P ((size_t __size, size_t __alignment)) = memalign_hook_ini; +#endif void weak_variable (*__after_morecore_hook) __MALLOC_P ((void)) = NULL; /* Activate a standard set of debugging hooks. */ @@ -2489,7 +2535,11 @@ Void_t* mALLOc(bytes) size_t bytes; if (__malloc_hook != NULL) { Void_t* result; +#ifdef _LIBC + result = (*__malloc_hook)(bytes, __builtin_return_address (0)); +#else result = (*__malloc_hook)(bytes); +#endif return result; } #endif @@ -2780,7 +2830,11 @@ void fREe(mem) Void_t* mem; #if defined(_LIBC) || defined(MALLOC_HOOKS) if (__free_hook != NULL) { +#ifdef _LIBC + (*__free_hook)(mem, __builtin_return_address (0)); +#else (*__free_hook)(mem); +#endif return; } #endif @@ -2980,7 +3034,11 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; if (__realloc_hook != NULL) { Void_t* result; +#ifdef _LIBC + result = (*__realloc_hook)(oldmem, bytes, __builtin_return_address (0)); +#else result = (*__realloc_hook)(oldmem, bytes); +#endif return result; } #endif @@ -3242,7 +3300,12 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; if (__memalign_hook != NULL) { Void_t* result; +#ifdef _LIBC + result = (*__memalign_hook)(alignment, bytes, + __builtin_return_address (0)); +#else result = (*__memalign_hook)(alignment, bytes); +#endif return result; } #endif @@ -3413,10 +3476,14 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; #if defined(_LIBC) || defined(MALLOC_HOOKS) if (__malloc_hook != NULL) { sz = n * elem_size; +#ifdef _LIBC + mem = (*__malloc_hook)(sz, __builtin_return_address (0)); +#else mem = (*__malloc_hook)(sz); +#endif if(mem == 0) return 0; -#ifdef HAVE_MEMCPY +#ifdef HAVE_MEMSET return memset(mem, 0, sz); #else while(sz > 0) ((char*)mem)[--sz] = 0; /* rather inefficient */ @@ -4106,11 +4173,15 @@ mem2chunk_check(mem) Void_t* mem; } static Void_t* +#ifdef _LIBC +malloc_check(size_t sz, const Void_t *caller) +#else #if __STD_C malloc_check(size_t sz) #else malloc_check(sz) size_t sz; #endif +#endif { mchunkptr victim; INTERNAL_SIZE_T nb = request2size(sz + 1); @@ -4129,11 +4200,15 @@ malloc_check(sz) size_t sz; } static void +#ifdef _LIBC +free_check(Void_t* mem, const Void_t *caller) +#else #if __STD_C free_check(Void_t* mem) #else free_check(mem) Void_t* mem; #endif +#endif { mchunkptr p; @@ -4166,16 +4241,24 @@ free_check(mem) Void_t* mem; } static Void_t* +#ifdef _LIBC +realloc_check(Void_t* oldmem, size_t bytes, const Void_t *caller) +#else #if __STD_C realloc_check(Void_t* oldmem, size_t bytes) #else realloc_check(oldmem, bytes) Void_t* oldmem; size_t bytes; #endif +#endif { mchunkptr oldp, newp; INTERNAL_SIZE_T nb, oldsize; +#ifdef _LIBC + if (oldmem == 0) return malloc_check(bytes, NULL); +#else if (oldmem == 0) return malloc_check(bytes); +#endif (void)mutex_lock(&main_arena.mutex); oldp = mem2chunk_check(oldmem); if(!oldp) { @@ -4187,7 +4270,11 @@ realloc_check(oldmem, bytes) Void_t* oldmem; size_t bytes; case 2: abort(); } +#ifdef _LIBC + return malloc_check(bytes, NULL); +#else return malloc_check(bytes); +#endif } oldsize = chunksize(oldp); @@ -4240,16 +4327,24 @@ realloc_check(oldmem, bytes) Void_t* oldmem; size_t bytes; } static Void_t* +#ifdef _LIBC +memalign_check(size_t alignment, size_t bytes, const Void_t *caller) +#else #if __STD_C memalign_check(size_t alignment, size_t bytes) #else memalign_check(alignment, bytes) size_t alignment; size_t bytes; #endif +#endif { INTERNAL_SIZE_T nb; mchunkptr p; +#ifdef _LIBC + if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL); +#else if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes); +#endif if (alignment < MINSIZE) alignment = MINSIZE; nb = request2size(bytes+1); @@ -4270,11 +4365,15 @@ memalign_check(alignment, bytes) size_t alignment; size_t bytes; ptmalloc_init() hasn't completed yet. */ static Void_t* +#ifdef _LIBC +malloc_starter(size_t sz, const Void_t *caller) +#else #if __STD_C malloc_starter(size_t sz) #else malloc_starter(sz) size_t sz; #endif +#endif { mchunkptr victim = chunk_alloc(&main_arena, request2size(sz)); @@ -4282,11 +4381,15 @@ malloc_starter(sz) size_t sz; } static void +#ifdef _LIBC +free_starter(Void_t* mem, const Void_t *caller) +#else #if __STD_C free_starter(Void_t* mem) #else free_starter(mem) Void_t* mem; #endif +#endif { mchunkptr p; @@ -4305,11 +4408,15 @@ free_starter(mem) Void_t* mem; is active. */ static Void_t* +#ifdef _LIBC +malloc_atfork (size_t sz, const Void_t *caller) +#else #if __STD_C malloc_atfork(size_t sz) #else malloc_atfork(sz) size_t sz; #endif +#endif { Void_t *vptr = NULL; @@ -4328,11 +4435,15 @@ malloc_atfork(sz) size_t sz; } static void +#ifdef _LIBC +free_atfork(Void_t* mem, const Void_t *caller) +#else #if __STD_C free_atfork(Void_t* mem) #else free_atfork(mem) Void_t* mem; #endif +#endif { Void_t *vptr = NULL; arena *ar_ptr; diff --git a/malloc/malloc.h b/malloc/malloc.h index a72102e..6538170 100644 --- a/malloc/malloc.h +++ b/malloc/malloc.h @@ -178,8 +178,25 @@ extern __malloc_ptr_t malloc_get_state __MALLOC_P ((void)); malloc_get_state(). */ extern int malloc_set_state __MALLOC_P ((__malloc_ptr_t __ptr)); -#if defined(__GLIBC__) || defined(MALLOC_HOOKS) +#ifdef __GLIBC__ +/* Hooks for debugging versions. */ +extern void (*__malloc_initialize_hook) __MALLOC_P ((void)); +extern void (*__free_hook) __MALLOC_P ((__malloc_ptr_t __ptr, + __const __malloc_ptr_t)); +extern __malloc_ptr_t (*__malloc_hook) __MALLOC_P ((size_t __size, + __const __malloc_ptr_t)); +extern __malloc_ptr_t (*__realloc_hook) __MALLOC_P ((__malloc_ptr_t __ptr, + size_t __size, + __const __malloc_ptr_t)); +extern __malloc_ptr_t (*__memalign_hook) __MALLOC_P ((size_t __size, + size_t __alignment, + __const __malloc_ptr_t)); +extern void (*__after_morecore_hook) __MALLOC_P ((void)); +/* Activate a standard set of debugging hooks. */ +extern void __malloc_check_init __MALLOC_P ((void)); +#else +#ifdef MALLOC_HOOKS /* Hooks for debugging versions. */ extern void (*__malloc_initialize_hook) __MALLOC_P ((void)); extern void (*__free_hook) __MALLOC_P ((__malloc_ptr_t __ptr)); @@ -192,7 +209,7 @@ extern void (*__after_morecore_hook) __MALLOC_P ((void)); /* Activate a standard set of debugging hooks. */ extern void __malloc_check_init __MALLOC_P ((void)); - +#endif #endif #ifdef __cplusplus diff --git a/malloc/mcheck.c b/malloc/mcheck.c index 1a80a56..47d35f1 100644 --- a/malloc/mcheck.c +++ b/malloc/mcheck.c @@ -28,9 +28,10 @@ #endif /* Old hook values. */ -static void (*old_free_hook) __P ((__ptr_t ptr)); -static __ptr_t (*old_malloc_hook) __P ((__malloc_size_t size)); -static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size)); +static void (*old_free_hook) __P ((__ptr_t ptr, __const __ptr_t)); +static __ptr_t (*old_malloc_hook) __P ((__malloc_size_t size, const __ptr_t)); +static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size, + __const __ptr_t)); /* Function to call when something awful happens. */ static void (*abortfunc) __P ((enum mcheck_status)); @@ -91,10 +92,11 @@ checkhdr (hdr) return status; } -static void freehook __P ((__ptr_t)); +static void freehook __P ((__ptr_t, const __ptr_t)); static void -freehook (ptr) +freehook (ptr, caller) __ptr_t ptr; + const __ptr_t caller; { if (ptr) { @@ -105,19 +107,27 @@ freehook (ptr) ptr = (__ptr_t) hdr; } __free_hook = old_free_hook; - free (ptr); + if (old_free_hook != NULL) + (*old_free_hook) (ptr, caller); + else + free (ptr); __free_hook = freehook; } -static __ptr_t mallochook __P ((__malloc_size_t)); +static __ptr_t mallochook __P ((__malloc_size_t, const __ptr_t)); static __ptr_t -mallochook (size) +mallochook (size, caller) __malloc_size_t size; + const __ptr_t caller; { struct hdr *hdr; __malloc_hook = old_malloc_hook; - hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1); + if (old_malloc_hook != NULL) + hdr = (struct hdr *) (*old_malloc_hook) (sizeof (struct hdr) + size + 1, + caller); + else + hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1); __malloc_hook = mallochook; if (hdr == NULL) return NULL; @@ -129,11 +139,12 @@ mallochook (size) return (__ptr_t) (hdr + 1); } -static __ptr_t reallochook __P ((__ptr_t, __malloc_size_t)); +static __ptr_t reallochook __P ((__ptr_t, __malloc_size_t, const __ptr_t)); static __ptr_t -reallochook (ptr, size) +reallochook (ptr, size, caller) __ptr_t ptr; __malloc_size_t size; + const __ptr_t caller; { struct hdr *hdr; __malloc_size_t osize; @@ -155,7 +166,13 @@ reallochook (ptr, size) __free_hook = old_free_hook; __malloc_hook = old_malloc_hook; __realloc_hook = old_realloc_hook; - hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1); + if (old_realloc_hook != NULL) + hdr = (struct hdr *) (*old_realloc_hook) ((__ptr_t) hdr, + sizeof (struct hdr) + size + 1, + caller); + else + hdr = (struct hdr *) realloc ((__ptr_t) hdr, + sizeof (struct hdr) + size + 1); __free_hook = freehook; __malloc_hook = mallochook; __realloc_hook = reallochook; diff --git a/malloc/mtrace.awk b/malloc/mtrace.awk deleted file mode 100644 index 06844d1..0000000 --- a/malloc/mtrace.awk +++ /dev/null @@ -1,50 +0,0 @@ -# -# Awk program to analyze mtrace.c output. -# -{ - if ($1 == "@") { - where = " (" $2 ")" - n = 3 - } else { - where = "" - n = 1 - } - if ($n == "+") { - if (allocated[$(n+1)] != "") - print "+", $(n+1), "Alloc", NR, "duplicate:", allocated[$(n+1)], wherewas[$(n+1)], where; - else { - wherewas[$(n+1)] = where; - allocated[$(n+1)] = $(n+2); - } - } else if ($n == "-") { - if (allocated[$(n+1)] != "") { - wherewas[$(n+1)] = ""; - allocated[$(n+1)] = ""; - if (allocated[$(n+1)] != "") - print "DELETE FAILED", $(n+1), allocated[$(n+1)]; - } else - print "-", $(n+1), "Free", NR, "was never alloc'd", where; - } else if ($n == "<") { - if (allocated[$(n+1)] != "") { - wherewas[$(n+1)] = ""; - allocated[$(n+1)] = ""; - } else - print "-", $(n+1), "Realloc", NR, "was never alloc'd", where; - } else if ($n == ">") { - if (allocated[$(n+1)] != "") - print "+", $(n+1), "Realloc", NR, "duplicate:", allocated[$(n+1)], where; - else { - wherewas[$(n+1)] = $(n+2); - allocated[$(n+1)] = $(n+2); - } - } else if ($n == "=") { - # Ignore "= Start" - } else if ($n == "!") { - # Ignore failed realloc attempts for now - } -} -END { - for (x in allocated) - if (allocated[x] != "") - print "+", x, allocated[x], wherewas[x]; -} diff --git a/malloc/mtrace.c b/malloc/mtrace.c index 3f0cbb9..aeefd56 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -1,5 +1,5 @@ /* More debugging hooks for `malloc'. - Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + Copyright (C) 1991, 92, 93, 94, 96, 97 Free Software Foundation, Inc. Written April 2, 1991 by John Gilmore of Cygnus Support. Based on mcheck.c by Mike Haertel. @@ -28,6 +28,10 @@ #include <bits/libc-lock.h> #endif +#ifdef HAVE_ELF +#include <link.h> +#endif + #include <stdio.h> #ifndef __GNU_LIBRARY__ @@ -51,9 +55,12 @@ char *_mtrace_file; int _mtrace_line; /* Old hook values. */ -static void (*tr_old_free_hook) __P ((__ptr_t ptr)); -static __ptr_t (*tr_old_malloc_hook) __P ((__malloc_size_t size)); -static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size)); +static void (*tr_old_free_hook) __P ((__ptr_t ptr, const __ptr_t)); +static __ptr_t (*tr_old_malloc_hook) __P ((__malloc_size_t size, + const __ptr_t)); +static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, + __malloc_size_t size, + const __ptr_t)); /* This function is called when the block being alloc'd, realloc'd, or freed has an address matching the variable "mallwatch". In a debugger, @@ -66,51 +73,77 @@ tr_break () { } -static void tr_where __P ((void)); +static void tr_where __P ((const __ptr_t)); static void -tr_where () +tr_where (caller) + const __ptr_t caller; { if (_mtrace_file) { fprintf (mallstream, "@ %s:%d ", _mtrace_file, _mtrace_line); _mtrace_file = NULL; } + else if (caller != NULL) + { +#ifdef HAVE_ELF + Dl_info info; + if (_dl_addr (caller, &info)) + { + fprintf (mallstream, "@ %s%s%s%s%s[%p]", + info.dli_fname ?: "", info.dli_fname ? ":" : "", + info.dli_sname ? "(" : "", + info.dli_sname ?: "", info.dli_sname ? ") " : " ", + caller); + } + else +#endif + fprintf (mallstream, "@ [%p] ", caller); + } } -static void tr_freehook __P ((__ptr_t)); +static void tr_freehook __P ((__ptr_t, const __ptr_t)); static void -tr_freehook (ptr) +tr_freehook (ptr, caller) __ptr_t ptr; + const __ptr_t caller; { - tr_where (); - fprintf (mallstream, "- %p\n", ptr); /* Be sure to print it first. */ + tr_where (caller); + /* Be sure to print it first. */ + fprintf (mallstream, "- %p\n", ptr); if (ptr == mallwatch) tr_break (); __libc_lock_lock (lock); __free_hook = tr_old_free_hook; - free (ptr); + if (tr_old_free_hook != NULL) + (*tr_old_free_hook) (ptr, caller); + else + free (ptr); __free_hook = tr_freehook; __libc_lock_unlock (lock); } -static __ptr_t tr_mallochook __P ((__malloc_size_t)); +static __ptr_t tr_mallochook __P ((__malloc_size_t, const __ptr_t)); static __ptr_t -tr_mallochook (size) +tr_mallochook (size, caller) __malloc_size_t size; + const __ptr_t caller; { __ptr_t hdr; __libc_lock_lock (lock); __malloc_hook = tr_old_malloc_hook; - hdr = (__ptr_t) malloc (size); + if (tr_old_malloc_hook != NULL) + hdr = (__ptr_t) (*tr_old_malloc_hook) (size, caller); + else + hdr = (__ptr_t) malloc (size); __malloc_hook = tr_mallochook; __libc_lock_unlock (lock); - tr_where (); + tr_where (caller); /* We could be printing a NULL here; that's OK. */ - fprintf (mallstream, "+ %p %lx\n", hdr, (unsigned long)size); + fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long)size); if (hdr == mallwatch) tr_break (); @@ -118,11 +151,12 @@ tr_mallochook (size) return hdr; } -static __ptr_t tr_reallochook __P ((__ptr_t, __malloc_size_t)); +static __ptr_t tr_reallochook __P ((__ptr_t, __malloc_size_t, const __ptr_t)); static __ptr_t -tr_reallochook (ptr, size) +tr_reallochook (ptr, size, caller) __ptr_t ptr; __malloc_size_t size; + const __ptr_t caller; { __ptr_t hdr; @@ -134,21 +168,24 @@ tr_reallochook (ptr, size) __free_hook = tr_old_free_hook; __malloc_hook = tr_old_malloc_hook; __realloc_hook = tr_old_realloc_hook; - hdr = (__ptr_t) realloc (ptr, size); + if (tr_old_realloc_hook != NULL) + hdr = (__ptr_t) (*tr_old_realloc_hook) (ptr, size, caller); + else + hdr = (__ptr_t) realloc (ptr, size); __free_hook = tr_freehook; __malloc_hook = tr_mallochook; __realloc_hook = tr_reallochook; __libc_lock_unlock (lock); - tr_where (); + tr_where (caller); if (hdr == NULL) /* Failed realloc. */ - fprintf (mallstream, "! %p %lx\n", ptr, (unsigned long)size); + fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long)size); else if (ptr == NULL) - fprintf (mallstream, "+ %p %lx\n", hdr, (unsigned long)size); + fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long)size); else - fprintf (mallstream, "< %p\n> %p %lx\n", ptr, hdr, (unsigned long)size); + fprintf (mallstream, "< %p\n> %p %#lx\n", ptr, hdr, (unsigned long)size); if (hdr == mallwatch) tr_break (); diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl new file mode 100644 index 0000000..46d8425 --- /dev/null +++ b/malloc/mtrace.pl @@ -0,0 +1,192 @@ +#! @PERL@ +eval "exec @PERL@ -S $0 $*" + if 0; +# Copyright (C) 1997 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1997. +# Based on the mtrace.awk script. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public +# License along with the GNU C Library; see the file COPYING.LIB. If not, +# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +$VERSION = "@VERSION@"; +$PACKAGE = "libc"; +$progname = $0; + +sub usage { + print "Usage: mtrace [OPTION]... [Binary] MtraceData\n"; + print " --help print this help, then exit\n"; + print " --version print version number, then exit\n"; + exit 0; +} + +# We expect two arguments: +# #1: the complete path to the binary +# #2: the mtrace data filename +# The usual options are also recognized. + +arglist: while (@ARGV) { + if ($ARGV[0] eq "--v" || $ARGV[0] eq "--ve" || $ARGV[0] eq "--ver" || + $ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" || + $ARGV[0] eq "--versio" || $ARGV[0] eq "--version") { + print "mtrace (GNU $PACKAGE) $VERSION\n"; + print "Copyright (C) 1997 Free Software Foundation, Inc.\n"; + print "This is free software; see the source for copying conditions. There is NO\n"; + print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; + print "Written by Ulrich Drepper <drepper\@gnu.ai.mit.edu>\n"; + + exit 0; + } elsif ($ARGV[0] eq "--h" || $ARGV[0] eq "--he" || $ARGV[0] eq "--hel" || + $ARGV[0] eq "--help") { + &usage; + } elsif ($ARGV[0] =~ /^-/) { + print "$progname: unrecognized option `$ARGV[0]'\n"; + print "Try `$progname --help' for more information.\n"; + exit 1; + } else { + last arglist; + } +} + +if ($#ARGV == 0) { + $binary=""; + $data=$ARGV[0]; +} elsif ($#ARGV == 1) { + $binary=$ARGV[0]; + $data=$ARGV[1]; +} else { + die "Wrong number of arguments."; +} + +sub location { + my $str = pop(@_); + return $str if ($str eq ""); + if ($str =~ /[[](0x[^]]*)]:(.)*/) { + my $addr = $1; + my $fct = $2; + return $cache{$addr} if (exists $cache{$addr}); + if ($binary ne "" && open (ADDR, "addr2line -e $binary $addr|")) { + my $line = <ADDR>; + chomp $line; + close (ADDR); + if ($line ne '??:0') { + $cache{$addr} = $line; + return $cache{$addr}; + } + } + $cache{$addr} = $str = "$fct @ $addr"; + } elsif ($str =~ /^[[](0x[^]]*)]$/) { + my $addr = $1; + return $cache{$addr} if (exists $cache{$addr}); + if ($binary ne "" && open (ADDR, "addr2line -e $binary $addr|")) { + my $line = <ADDR>; + chomp $line; + close (ADDR); + if ($line ne '??:0') { + $cache{$addr} = $line; + return $cache{$addr}; + } + } + $cache{$addr} = $str = $addr; + } + return $str; +} + +$nr=0; +open(DATA, "<$data") || die "Cannot open mtrace data file"; +while (<DATA>) { + my @cols = split (' '); + my $n, $where; + if ($cols[0] eq "@") { + # We have address and/or function name. + $where=$cols[1]; + $n=2; + } else { + $where=""; + $n=0; + } + + $allocaddr=$cols[$n + 1]; + $howmuch=hex($cols[$n + 2]); + + ++$nr; + SWITCH: { + if ($cols[$n] eq "+") { + if (defined $allocated{$allocaddr}) { + printf ("+ %#010x Alloc %d duplicate: %s %s\n", + hex($allocaddr), $nr, $wherewas{$allocaddr}, $where); + } else { + $allocated{$allocaddr}=$howmuch; + $wherewas{$allocaddr}=&location($where); + } + last SWITCH; + } + if ($cols[$n] eq "-") { + if (defined $allocated{$allocaddr}) { + undef $allocated{$allocaddr}; + undef $wherewas{$allocaddr}; + } else { + printf ("- %#010x Free %d was never alloc'd %s\n", + hex($allocaddr), $nr, &location($where)); + } + last SWITCH; + } + if ($cols[$n] eq "<") { + if (defined $allocated{$allocaddr}) { + undef $allocated{$allocaddr}; + undef $wherewas{$allocaddr}; + } else { + printf ("- %#010x Realloc %d was never alloc'd %s\n", + hex($allocaddr), $nr, &location($where)); + } + last SWITCH; + } + if ($cols[$n] eq ">") { + if (defined $allocated{$allocaddr}) { + printf ("+ %#010x Realloc %d duplicate: %#010x %s %s\n", + hex($allocaddr), $nr, $allocated{$allocaddr}, + $wherewas{$allocaddr}, &location($where)); + } else { + $allocated{$allocaddr}=$howmuch; + $wherewas{$allocaddr}=&location($where); + } + last SWITCH; + } + if ($cols[$n] eq "=") { + # Ignore "= Start". + last SWITCH; + } + if ($cols[$n] eq "!") { + # Ignore failed realloc for now. + last SWITCH; + } + } +} +close (DATA); + +# Now print all remaining entries. +@addrs= keys %allocated; +if ($#addrs >= 0) { + print "\nNot freed memory:\n-----------------\n"; + print ' ' x (@XXX@ - 7), "Address Size Caller\n"; + foreach $addr (sort @addrs) { + if (defined $allocated{$addr}) { + printf ("%#0@XXX@x %#8x at %s\n", hex($addr), $allocated{$addr}, + $wherewas{$addr}); + } + } +} + +exit 0; |