aboutsummaryrefslogtreecommitdiff
path: root/malloc
diff options
context:
space:
mode:
Diffstat (limited to 'malloc')
-rw-r--r--malloc/Makefile21
-rw-r--r--malloc/malloc.c117
-rw-r--r--malloc/malloc.h21
-rw-r--r--malloc/mcheck.c41
-rw-r--r--malloc/mtrace.awk50
-rw-r--r--malloc/mtrace.c83
-rw-r--r--malloc/mtrace.pl192
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;