diff options
author | Ulrich Drepper <drepper@gmail.com> | 2011-05-16 00:58:33 -0400 |
---|---|---|
committer | Ulrich Drepper <drepper@gmail.com> | 2011-05-16 00:58:33 -0400 |
commit | 56e5eb4619a936a3b63ae71f89038d69becd2999 (patch) | |
tree | e6005c7864f9b4ecd3f3bdfcae9b5bad9c294045 /malloc/mtrace.c | |
parent | 6ce7537960cf42a0a6b0fc70957d5ce2ba9838de (diff) | |
download | glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.zip glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.tar.gz glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.tar.bz2 |
Avoid potential deadlock in mtrace
The _dl_addr function might have to call malloc which would lead
to a deadlock. Avoid by calling _dl_addr early.
Diffstat (limited to 'malloc/mtrace.c')
-rw-r--r-- | malloc/mtrace.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/malloc/mtrace.c b/malloc/mtrace.c index 51be396..b55449f 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -79,46 +79,59 @@ tr_break () } libc_hidden_def (tr_break) -static void tr_where (const __ptr_t) __THROW internal_function; +static void tr_where (const __ptr_t, Dl_info *) __THROW internal_function; static void internal_function -tr_where (caller) +tr_where (caller, info) const __ptr_t caller; + Dl_info *info; { if (caller != NULL) { -#ifdef HAVE_ELF - Dl_info info; - if (_dl_addr (caller, &info, NULL, NULL)) + if (info != NULL) { char *buf = (char *) ""; - if (info.dli_sname != NULL) + if (info->dli_sname != NULL) { - size_t len = strlen (info.dli_sname); + size_t len = strlen (info->dli_sname); buf = alloca (len + 6 + 2 * sizeof (void *)); buf[0] = '('; - __stpcpy (_fitoa (caller >= (const __ptr_t) info.dli_saddr - ? caller - (const __ptr_t) info.dli_saddr - : (const __ptr_t) info.dli_saddr - caller, - __stpcpy (__mempcpy (buf + 1, info.dli_sname, + __stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr + ? caller - (const __ptr_t) info->dli_saddr + : (const __ptr_t) info->dli_saddr - caller, + __stpcpy (__mempcpy (buf + 1, info->dli_sname, len), - caller >= (__ptr_t) info.dli_saddr + caller >= (__ptr_t) info->dli_saddr ? "+0x" : "-0x"), 16, 0), ")"); } fprintf (mallstream, "@ %s%s%s[%p] ", - info.dli_fname ?: "", info.dli_fname ? ":" : "", + info->dli_fname ?: "", info->dli_fname ? ":" : "", buf, caller); } else -#endif fprintf (mallstream, "@ [%p] ", caller); } } + +static Dl_info * +lock_and_info (const __ptr_t caller, Dl_info *mem) +{ + if (caller == NULL) + return NULL; + + Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL; + + __libc_lock_lock (lock); + + return res; +} + + static void tr_freehook (__ptr_t, const __ptr_t) __THROW; static void tr_freehook (ptr, caller) @@ -127,8 +140,10 @@ tr_freehook (ptr, caller) { if (ptr == NULL) return; - __libc_lock_lock (lock); - tr_where (caller); + + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); + tr_where (caller, info); /* Be sure to print it first. */ fprintf (mallstream, "- %p\n", ptr); __libc_lock_unlock (lock); @@ -152,7 +167,8 @@ tr_mallochook (size, caller) { __ptr_t hdr; - __libc_lock_lock (lock); + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); __malloc_hook = tr_old_malloc_hook; if (tr_old_malloc_hook != NULL) @@ -161,7 +177,7 @@ tr_mallochook (size, caller) hdr = (__ptr_t) malloc (size); __malloc_hook = tr_mallochook; - tr_where (caller); + tr_where (caller, info); /* We could be printing a NULL here; that's OK. */ fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); @@ -186,7 +202,8 @@ tr_reallochook (ptr, size, caller) if (ptr == mallwatch) tr_break (); - __libc_lock_lock (lock); + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); __free_hook = tr_old_free_hook; __malloc_hook = tr_old_malloc_hook; @@ -199,7 +216,7 @@ tr_reallochook (ptr, size, caller) __malloc_hook = tr_mallochook; __realloc_hook = tr_reallochook; - tr_where (caller); + tr_where (caller, info); if (hdr == NULL) /* Failed realloc. */ fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size); @@ -208,7 +225,7 @@ tr_reallochook (ptr, size, caller) else { fprintf (mallstream, "< %p\n", ptr); - tr_where (caller); + tr_where (caller, info); fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size); } @@ -229,7 +246,8 @@ tr_memalignhook (alignment, size, caller) { __ptr_t hdr; - __libc_lock_lock (lock); + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); __memalign_hook = tr_old_memalign_hook; __malloc_hook = tr_old_malloc_hook; @@ -240,7 +258,7 @@ tr_memalignhook (alignment, size, caller) __memalign_hook = tr_memalignhook; __malloc_hook = tr_mallochook; - tr_where (caller); + tr_where (caller, info); /* We could be printing a NULL here; that's OK. */ fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); |