(linenum→info "unix/slp.c:2238")

glibc/2.7/malloc/mtrace.c

    1: /* More debugging hooks for `malloc'.
    2:    Copyright (C) 1991-1994,1996-2003, 2004 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:                  Written April 2, 1991 by John Gilmore of Cygnus Support.
    5:                  Based on mcheck.c by Mike Haertel.
    6: 
    7:    The GNU C Library is free software; you can redistribute it and/or
    8:    modify it under the terms of the GNU Lesser General Public
    9:    License as published by the Free Software Foundation; either
   10:    version 2.1 of the License, or (at your option) any later version.
   11: 
   12:    The GNU C Library is distributed in the hope that it will be useful,
   13:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15:    Lesser General Public License for more details.
   16: 
   17:    You should have received a copy of the GNU Lesser General Public
   18:    License along with the GNU C Library; if not, write to the Free
   19:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   20:    02111-1307 USA.  */
   21: 
   22: #ifndef _MALLOC_INTERNAL
   23: #define _MALLOC_INTERNAL
   24: #include <malloc.h>
   25: #include <mcheck.h>
   26: #include <bits/libc-lock.h>
   27: #endif
   28: 
   29: #include <dlfcn.h>
   30: #include <fcntl.h>
   31: #include <stdio.h>
   32: #include <string.h>
   33: #include <stdlib.h>
   34: 
   35: #include <stdio-common/_itoa.h>
   36: 
   37: #ifdef _LIBC
   38: # include <libc-internal.h>
   39: 
   40: # include <libio/iolibio.h>
   41: # define setvbuf(s, b, f, l) INTUSE(_IO_setvbuf) (s, b, f, l)
   42: # define fwrite(buf, size, count, fp) _IO_fwrite (buf, size, count, fp)
   43: #endif
   44: 
   45: #ifndef attribute_hidden
   46: # define attribute_hidden
   47: #endif
   48: 
   49: #define TRACE_BUFFER_SIZE 512
   50: 
   51: static FILE *mallstream;
   52: static const char mallenv[]= "MALLOC_TRACE";
   53: static char *malloc_trace_buffer;
   54: 
   55: __libc_lock_define_initialized (static, lock);
   56: 
   57: /* Address to breakpoint on accesses to... */
   58: __ptr_t mallwatch;
   59: 
   60: #ifdef USE_MTRACE_FILE
   61: /* File name and line number information, for callers that had
   62:    the foresight to call through a macro.  */
   63: char *_mtrace_file;
   64: int _mtrace_line;
   65: #endif
   66: 
   67: /* Old hook values.  */
   68: static void (*tr_old_free_hook) (__ptr_t ptr, const __ptr_t);
   69: static __ptr_t (*tr_old_malloc_hook) (__malloc_size_t size, const __ptr_t);
   70: static __ptr_t (*tr_old_realloc_hook) (__ptr_t ptr, __malloc_size_t size,
   71:                                        const __ptr_t);
   72: static __ptr_t (*tr_old_memalign_hook) (__malloc_size_t __alignment,
   73:                                         __malloc_size_t __size,
   74:                                         __const __ptr_t);
   75: 
   76: /* This function is called when the block being alloc'd, realloc'd, or
   77:    freed has an address matching the variable "mallwatch".  In a debugger,
   78:    set "mallwatch" to the address of interest, then put a breakpoint on
   79:    tr_break.  */
   80: 
   81: extern void tr_break (void) __THROW;
   82: libc_hidden_proto (tr_break)
   83: void
   84: tr_break ()
   85: {
   86: }
   87: libc_hidden_def (tr_break)
   88: 
   89: static void tr_where (const __ptr_t) __THROW internal_function;
   90: static void
   91: internal_function
   92: tr_where (caller)
   93:      const __ptr_t caller;
   94: {
   95: #ifdef USE_MTRACE_FILE
   96:   if (_mtrace_file)
   97:     {
   98:       fprintf (mallstream, "@ %s:%d ", _mtrace_file, _mtrace_line);
   99:       _mtrace_file = NULL;
  100:     }
  101:   else
  102: #endif
  103:     if (caller != NULL)
  104:     {
  105: #ifdef HAVE_ELF
  106:       Dl_info info;
  107:       if (_dl_addr (caller, &info, NULL, NULL))
  108:         {
  109:           char *buf = (char *) "";
  110:           if (info.dli_sname != NULL)
  111:             {
  112:               size_t len = strlen (info.dli_sname);
  113:               buf = alloca (len + 6 + 2 * sizeof (void *));
  114: 
  115:               buf[0] = '(';
  116:               __stpcpy (_fitoa (caller >= (const __ptr_t) info.dli_saddr
  117:                                 ? caller - (const __ptr_t) info.dli_saddr
  118:                                 : (const __ptr_t) info.dli_saddr - caller,
  119:                                 __stpcpy (__mempcpy (buf + 1, info.dli_sname,
  120:                                                      len),
  121:                                           caller >= (__ptr_t) info.dli_saddr
  122:                                           ? "+0x" : "-0x"),
  123:                                 16, 0),
  124:                         ")");
  125:             }
  126: 
  127:           fprintf (mallstream, "@ %s%s%s[%p] ",
  128:                    info.dli_fname ?: "", info.dli_fname ? ":" : "",
  129:                    buf, caller);
  130:         }
  131:       else
  132: #endif
  133:         fprintf (mallstream, "@ [%p] ", caller);
  134:     }
  135: }
  136: 
  137: static void tr_freehook (__ptr_t, const __ptr_t) __THROW;
  138: static void
  139: tr_freehook (ptr, caller)
  140:      __ptr_t ptr;
  141:      const __ptr_t caller;
  142: {
  143:   if (ptr == NULL)
  144:     return;
  145:   __libc_lock_lock (lock);
  146:   tr_where (caller);
  147:   /* Be sure to print it first.  */
  148:   fprintf (mallstream, "- %p\n", ptr);
  149:   __libc_lock_unlock (lock);
  150:   if (ptr == mallwatch)
  151:     tr_break ();
  152:   __libc_lock_lock (lock);
  153:   __free_hook = tr_old_free_hook;
  154:   if (tr_old_free_hook != NULL)
  155:     (*tr_old_free_hook) (ptr, caller);
  156:   else
  157:     free (ptr);
  158:   __free_hook = tr_freehook;
  159:   __libc_lock_unlock (lock);
  160: }
  161: 
  162: static __ptr_t tr_mallochook (__malloc_size_t, const __ptr_t) __THROW;
  163: static __ptr_t
  164: tr_mallochook (size, caller)
  165:      __malloc_size_t size;
  166:      const __ptr_t caller;
  167: {
  168:   __ptr_t hdr;
  169: 
  170:   __libc_lock_lock (lock);
  171: 
  172:   __malloc_hook = tr_old_malloc_hook;
  173:   if (tr_old_malloc_hook != NULL)
  174:     hdr = (__ptr_t) (*tr_old_malloc_hook) (size, caller);
  175:   else
  176:     hdr = (__ptr_t) malloc (size);
  177:   __malloc_hook = tr_mallochook;
  178: 
  179:   tr_where (caller);
  180:   /* We could be printing a NULL here; that's OK.  */
  181:   fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
  182: 
  183:   __libc_lock_unlock (lock);
  184: 
  185:   if (hdr == mallwatch)
  186:     tr_break ();
  187: 
  188:   return hdr;
  189: }
  190: 
  191: static __ptr_t tr_reallochook (__ptr_t, __malloc_size_t, const __ptr_t)
  192:      __THROW;
  193: static __ptr_t
  194: tr_reallochook (ptr, size, caller)
  195:      __ptr_t ptr;
  196:      __malloc_size_t size;
  197:      const __ptr_t caller;
  198: {
  199:   __ptr_t hdr;
  200: 
  201:   if (ptr == mallwatch)
  202:     tr_break ();
  203: 
  204:   __libc_lock_lock (lock);
  205: 
  206:   __free_hook = tr_old_free_hook;
  207:   __malloc_hook = tr_old_malloc_hook;
  208:   __realloc_hook = tr_old_realloc_hook;
  209:   if (tr_old_realloc_hook != NULL)
  210:     hdr = (__ptr_t) (*tr_old_realloc_hook) (ptr, size, caller);
  211:   else
  212:     hdr = (__ptr_t) realloc (ptr, size);
  213:   __free_hook = tr_freehook;
  214:   __malloc_hook = tr_mallochook;
  215:   __realloc_hook = tr_reallochook;
  216: 
  217:   tr_where (caller);
  218:   if (hdr == NULL)
  219:     /* Failed realloc.  */
  220:     fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
  221:   else if (ptr == NULL)
  222:     fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
  223:   else
  224:     {
  225:       fprintf (mallstream, "< %p\n", ptr);
  226:       tr_where (caller);
  227:       fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size);
  228:     }
  229: 
  230:   __libc_lock_unlock (lock);
  231: 
  232:   if (hdr == mallwatch)
  233:     tr_break ();
  234: 
  235:   return hdr;
  236: }
  237: 
  238: static __ptr_t tr_memalignhook (__malloc_size_t, __malloc_size_t,
  239:                                 const __ptr_t) __THROW;
  240: static __ptr_t
  241: tr_memalignhook (alignment, size, caller)
  242:      __malloc_size_t alignment, size;
  243:      const __ptr_t caller;
  244: {
  245:   __ptr_t hdr;
  246: 
  247:   __libc_lock_lock (lock);
  248: 
  249:   __memalign_hook = tr_old_memalign_hook;
  250:   __malloc_hook = tr_old_malloc_hook;
  251:   if (tr_old_memalign_hook != NULL)
  252:     hdr = (__ptr_t) (*tr_old_memalign_hook) (alignment, size, caller);
  253:   else
  254:     hdr = (__ptr_t) memalign (alignment, size);
  255:   __memalign_hook = tr_memalignhook;
  256:   __malloc_hook = tr_mallochook;
  257: 
  258:   tr_where (caller);
  259:   /* We could be printing a NULL here; that's OK.  */
  260:   fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
  261: 
  262:   __libc_lock_unlock (lock);
  263: 
  264:   if (hdr == mallwatch)
  265:     tr_break ();
  266: 
  267:   return hdr;
  268: }
  269: 
  270: 
  271: 
  272: #ifdef _LIBC
  273: 
  274: /* This function gets called to make sure all memory the library
  275:    allocates get freed and so does not irritate the user when studying
  276:    the mtrace output.  */
  277: static void __libc_freeres_fn_section
  278: release_libc_mem (void)
  279: {
  280:   /* Only call the free function if we still are running in mtrace mode.  */
  281:   if (mallstream != NULL)
  282:     __libc_freeres ();
  283: }
  284: #endif
  285: 
  286: 
  287: /* We enable tracing if either the environment variable MALLOC_TRACE
  288:    is set, or if the variable mallwatch has been patched to an address
  289:    that the debugging user wants us to stop on.  When patching mallwatch,
  290:    don't forget to set a breakpoint on tr_break!  */
  291: 
  292: void
  293: mtrace ()
  294: {
  295: #ifdef _LIBC
  296:   static int added_atexit_handler;
  297: #endif
  298:   char *mallfile;
  299: 
  300:   /* Don't panic if we're called more than once.  */
  301:   if (mallstream != NULL)
  302:     return;
  303: 
  304: #ifdef _LIBC
  305:   /* When compiling the GNU libc we use the secure getenv function
  306:      which prevents the misuse in case of SUID or SGID enabled
  307:      programs.  */
  308:   mallfile = __secure_getenv (mallenv);
  309: #else
  310:   mallfile = getenv (mallenv);
  311: #endif
  312:   if (mallfile != NULL || mallwatch != NULL)
  313:     {
  314:       char *mtb = malloc (TRACE_BUFFER_SIZE);
  315:       if (mtb == NULL)
  316:         return;
  317: 
  318:       mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wc");
  319:       if (mallstream != NULL)
  320:         {
  321:           /* Make sure we close the file descriptor on exec.  */
  322:           int flags = __fcntl (fileno (mallstream), F_GETFD, 0);
  323:           if (flags >= 0)
  324:             {
  325:               flags |= FD_CLOEXEC;
  326:               __fcntl (fileno (mallstream), F_SETFD, flags);
  327:             }
  328:           /* Be sure it doesn't malloc its buffer!  */
  329:           malloc_trace_buffer = mtb;
  330:           setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
  331:           fprintf (mallstream, "= Start\n");
  332:           tr_old_free_hook = __free_hook;
  333:           __free_hook = tr_freehook;
  334:           tr_old_malloc_hook = __malloc_hook;
  335:           __malloc_hook = tr_mallochook;
  336:           tr_old_realloc_hook = __realloc_hook;
  337:           __realloc_hook = tr_reallochook;
  338:           tr_old_memalign_hook = __memalign_hook;
  339:           __memalign_hook = tr_memalignhook;
  340: #ifdef _LIBC
  341:           if (!added_atexit_handler)
  342:             {
  343:               extern void *__dso_handle __attribute__ ((__weak__));
  344:               added_atexit_handler = 1;
  345:               __cxa_atexit ((void (*) (void *)) release_libc_mem, NULL,
  346:                              &__dso_handle ? __dso_handle : NULL);
  347:             }
  348: #endif
  349:         }
  350:       else
  351:         free (mtb);
  352:     }
  353: }
  354: 
  355: void
  356: muntrace ()
  357: {
  358:   if (mallstream == NULL)
  359:     return;
  360: 
  361:   fprintf (mallstream, "= End\n");
  362:   fclose (mallstream);
  363:   mallstream = NULL;
  364:   __free_hook = tr_old_free_hook;
  365:   __malloc_hook = tr_old_malloc_hook;
  366:   __realloc_hook = tr_old_realloc_hook;
  367:   __memalign_hook = tr_old_memalign_hook;
  368: }
Syntax (Markdown)