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

glibc/2.7/malloc/mcheck.c

    1: /* Standard debugging hooks for `malloc'.
    2:    Copyright (C) 1990-1997,1999,2000-2002,2007 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:    Written May 1989 by Mike Haertel.
    5: 
    6:    The GNU C Library is free software; you can redistribute it and/or
    7:    modify it under the terms of the GNU Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the License, or (at your option) any later version.
   10: 
   11:    The GNU C Library is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.  */
   20: 
   21: #ifndef _MALLOC_INTERNAL
   22: # define _MALLOC_INTERNAL
   23: # include <malloc.h>
   24: # include <mcheck.h>
   25: # include <stdint.h>
   26: # include <stdio.h>
   27: # include <libintl.h>
   28: #endif
   29: 
   30: /* Old hook values.  */
   31: static void (*old_free_hook) (__ptr_t ptr, __const __ptr_t);
   32: static __ptr_t (*old_malloc_hook) (__malloc_size_t size, const __ptr_t);
   33: static __ptr_t (*old_memalign_hook) (__malloc_size_t alignment,
   34:                                      __malloc_size_t size,
   35:                                      const __ptr_t);
   36: static __ptr_t (*old_realloc_hook) (__ptr_t ptr, __malloc_size_t size,
   37:                                     __const __ptr_t);
   38: 
   39: /* Function to call when something awful happens.  */
   40: static void (*abortfunc) (enum mcheck_status);
   41: 
   42: /* Arbitrary magical numbers.  */
   43: #define MAGICWORD       0xfedabeeb
   44: #define MAGICFREE       0xd8675309
   45: #define MAGICBYTE       ((char) 0xd7)
   46: #define MALLOCFLOOD     ((char) 0x93)
   47: #define FREEFLOOD       ((char) 0x95)
   48: 
   49: struct hdr
   50:   {
   51:     __malloc_size_t size;       /* Exact size requested by user.  */
   52:     unsigned long int magic;    /* Magic number to check header integrity.  */
   53:     struct hdr *prev;
   54:     struct hdr *next;
   55:     __ptr_t block;              /* Real block allocated, for memalign.  */
   56:     unsigned long int magic2;   /* Extra, keeps us doubleword aligned.  */
   57:   };
   58: 
   59: /* This is the beginning of the list of all memory blocks allocated.
   60:    It is only constructed if the pedantic testing is requested.  */
   61: static struct hdr *root;
   62: 
   63: static int mcheck_used;
   64: 
   65: /* Nonzero if pedentic checking of all blocks is requested.  */
   66: static int pedantic;
   67: 
   68: #if defined _LIBC || defined STDC_HEADERS || defined USG
   69: # include <string.h>
   70: # define flood memset
   71: #else
   72: static void flood (__ptr_t, int, __malloc_size_t);
   73: static void
   74: flood (ptr, val, size)
   75:      __ptr_t ptr;
   76:      int val;
   77:      __malloc_size_t size;
   78: {
   79:   char *cp = ptr;
   80:   while (size--)
   81:     *cp++ = val;
   82: }
   83: #endif
   84: 
   85: static enum mcheck_status
   86: checkhdr (const struct hdr *hdr)
   87: {
   88:   enum mcheck_status status;
   89: 
   90:   if (!mcheck_used)
   91:     /* Maybe the mcheck used is disabled?  This happens when we find
   92:        an error and report it.  */
   93:     return MCHECK_OK;
   94: 
   95:   switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
   96:     {
   97:     default:
   98:       status = MCHECK_HEAD;
   99:       break;
  100:     case MAGICFREE:
  101:       status = MCHECK_FREE;
  102:       break;
  103:     case MAGICWORD:
  104:       if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
  105:         status = MCHECK_TAIL;
  106:       else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
  107:         status = MCHECK_HEAD;
  108:       else
  109:         status = MCHECK_OK;
  110:       break;
  111:     }
  112:   if (status != MCHECK_OK)
  113:     {
  114:       mcheck_used = 0;
  115:       (*abortfunc) (status);
  116:       mcheck_used = 1;
  117:     }
  118:   return status;
  119: }
  120: 
  121: void
  122: mcheck_check_all (void)
  123: {
  124:   /* Walk through all the active blocks and test whether they were tempered
  125:      with.  */
  126:   struct hdr *runp = root;
  127: 
  128:   /* Temporarily turn off the checks.  */
  129:   pedantic = 0;
  130: 
  131:   while (runp != NULL)
  132:     {
  133:       (void) checkhdr (runp);
  134: 
  135:       runp = runp->next;
  136:     }
  137: 
  138:   /* Turn checks on again.  */
  139:   pedantic = 1;
  140: }
  141: #ifdef _LIBC
  142: libc_hidden_def (mcheck_check_all)
  143: #endif
  144: 
  145: static void
  146: unlink_blk (struct hdr *ptr)
  147: {
  148:   if (ptr->next != NULL)
  149:     {
  150:       ptr->next->prev = ptr->prev;
  151:       ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
  152:                                       + (uintptr_t) ptr->next->next);
  153:     }
  154:   if (ptr->prev != NULL)
  155:     {
  156:       ptr->prev->next = ptr->next;
  157:       ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
  158:                                       + (uintptr_t) ptr->prev->next);
  159:     }
  160:   else
  161:     root = ptr->next;
  162: }
  163: 
  164: static void
  165: link_blk (struct hdr *hdr)
  166: {
  167:   hdr->prev = NULL;
  168:   hdr->next = root;
  169:   root = hdr;
  170:   hdr->magic = MAGICWORD ^ (uintptr_t) hdr->next;
  171: 
  172:   /* And the next block.  */
  173:   if (hdr->next != NULL)
  174:     {
  175:       hdr->next->prev = hdr;
  176:       hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
  177:                                       + (uintptr_t) hdr->next->next);
  178:     }
  179: }
  180: static void
  181: freehook (__ptr_t ptr, const __ptr_t caller)
  182: {
  183:   if (pedantic)
  184:     mcheck_check_all ();
  185:   if (ptr)
  186:     {
  187:       struct hdr *hdr = ((struct hdr *) ptr) - 1;
  188:       checkhdr (hdr);
  189:       hdr->magic = MAGICFREE;
  190:       hdr->magic2 = MAGICFREE;
  191:       unlink_blk (hdr);
  192:       hdr->prev = hdr->next = NULL;
  193:       flood (ptr, FREEFLOOD, hdr->size);
  194:       ptr = hdr->block;
  195:     }
  196:   __free_hook = old_free_hook;
  197:   if (old_free_hook != NULL)
  198:     (*old_free_hook) (ptr, caller);
  199:   else
  200:     free (ptr);
  201:   __free_hook = freehook;
  202: }
  203: 
  204: static __ptr_t
  205: mallochook (__malloc_size_t size, const __ptr_t caller)
  206: {
  207:   struct hdr *hdr;
  208: 
  209:   if (pedantic)
  210:     mcheck_check_all ();
  211: 
  212:   __malloc_hook = old_malloc_hook;
  213:   if (old_malloc_hook != NULL)
  214:     hdr = (struct hdr *) (*old_malloc_hook) (sizeof (struct hdr) + size + 1,
  215:                                              caller);
  216:   else
  217:     hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
  218:   __malloc_hook = mallochook;
  219:   if (hdr == NULL)
  220:     return NULL;
  221: 
  222:   hdr->size = size;
  223:   link_blk (hdr);
  224:   hdr->block = hdr;
  225:   hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
  226:   ((char *) &hdr[1])[size] = MAGICBYTE;
  227:   flood ((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
  228:   return (__ptr_t) (hdr + 1);
  229: }
  230: 
  231: static __ptr_t
  232: memalignhook (__malloc_size_t alignment, __malloc_size_t size,
  233:               const __ptr_t caller)
  234: {
  235:   struct hdr *hdr;
  236:   __malloc_size_t slop;
  237:   char *block;
  238: 
  239:   if (pedantic)
  240:     mcheck_check_all ();
  241: 
  242:   slop = (sizeof *hdr + alignment - 1) & -alignment;
  243: 
  244:   __memalign_hook = old_memalign_hook;
  245:   if (old_memalign_hook != NULL)
  246:     block = (*old_memalign_hook) (alignment, slop + size + 1, caller);
  247:   else
  248:     block = memalign (alignment, slop + size + 1);
  249:   __memalign_hook = memalignhook;
  250:   if (block == NULL)
  251:     return NULL;
  252: 
  253:   hdr = ((struct hdr *) (block + slop)) - 1;
  254: 
  255:   hdr->size = size;
  256:   link_blk (hdr);
  257:   hdr->block = (__ptr_t) block;
  258:   hdr->magic2 = (uintptr_t) block ^ MAGICWORD;
  259:   ((char *) &hdr[1])[size] = MAGICBYTE;
  260:   flood ((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
  261:   return (__ptr_t) (hdr + 1);
  262: }
  263: 
  264: static __ptr_t
  265: reallochook (__ptr_t ptr, __malloc_size_t size, const __ptr_t caller)
  266: {
  267:   if (size == 0)
  268:     {
  269:       freehook (ptr, caller);
  270:       return NULL;
  271:     }
  272: 
  273:   struct hdr *hdr;
  274:   __malloc_size_t osize;
  275: 
  276:   if (pedantic)
  277:     mcheck_check_all ();
  278: 
  279:   if (ptr)
  280:     {
  281:       hdr = ((struct hdr *) ptr) - 1;
  282:       osize = hdr->size;
  283: 
  284:       checkhdr (hdr);
  285:       unlink_blk (hdr);
  286:       if (size < osize)
  287:         flood ((char *) ptr + size, FREEFLOOD, osize - size);
  288:     }
  289:   else
  290:     {
  291:       osize = 0;
  292:       hdr = NULL;
  293:     }
  294:   __free_hook = old_free_hook;
  295:   __malloc_hook = old_malloc_hook;
  296:   __memalign_hook = old_memalign_hook;
  297:   __realloc_hook = old_realloc_hook;
  298:   if (old_realloc_hook != NULL)
  299:     hdr = (struct hdr *) (*old_realloc_hook) ((__ptr_t) hdr,
  300:                                               sizeof (struct hdr) + size + 1,
  301:                                               caller);
  302:   else
  303:     hdr = (struct hdr *) realloc ((__ptr_t) hdr,
  304:                                   sizeof (struct hdr) + size + 1);
  305:   __free_hook = freehook;
  306:   __malloc_hook = mallochook;
  307:   __memalign_hook = memalignhook;
  308:   __realloc_hook = reallochook;
  309:   if (hdr == NULL)
  310:     return NULL;
  311: 
  312:   hdr->size = size;
  313:   link_blk (hdr);
  314:   hdr->block = hdr;
  315:   hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
  316:   ((char *) &hdr[1])[size] = MAGICBYTE;
  317:   if (size > osize)
  318:     flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
  319:   return (__ptr_t) (hdr + 1);
  320: }
  321: 
  322: __attribute__ ((noreturn))
  323: static void
  324: mabort (enum mcheck_status status)
  325: {
  326:   const char *msg;
  327:   switch (status)
  328:     {
  329:     case MCHECK_OK:
  330:       msg = _("memory is consistent, library is buggy\n");
  331:       break;
  332:     case MCHECK_HEAD:
  333:       msg = _("memory clobbered before allocated block\n");
  334:       break;
  335:     case MCHECK_TAIL:
  336:       msg = _("memory clobbered past end of allocated block\n");
  337:       break;
  338:     case MCHECK_FREE:
  339:       msg = _("block freed twice\n");
  340:       break;
  341:     default:
  342:       msg = _("bogus mcheck_status, library is buggy\n");
  343:       break;
  344:     }
  345: #ifdef _LIBC
  346:   __libc_fatal (msg);
  347: #else
  348:   fprintf (stderr, "mcheck: %s", msg);
  349:   fflush (stderr);
  350:   abort ();
  351: #endif
  352: }
  353: 
  354: int
  355: mcheck (func)
  356:      void (*func) (enum mcheck_status);
  357: {
  358:   abortfunc = (func != NULL) ? func : &mabort;
  359: 
  360:   /* These hooks may not be safely inserted if malloc is already in use.  */
  361:   if (__malloc_initialized <= 0 && !mcheck_used)
  362:     {
  363:       /* We call malloc() once here to ensure it is initialized.  */
  364:       void *p = malloc (0);
  365:       free (p);
  366: 
  367:       old_free_hook = __free_hook;
  368:       __free_hook = freehook;
  369:       old_malloc_hook = __malloc_hook;
  370:       __malloc_hook = mallochook;
  371:       old_memalign_hook = __memalign_hook;
  372:       __memalign_hook = memalignhook;
  373:       old_realloc_hook = __realloc_hook;
  374:       __realloc_hook = reallochook;
  375:       mcheck_used = 1;
  376:     }
  377: 
  378:   return mcheck_used ? 0 : -1;
  379: }
  380: #ifdef _LIBC
  381: libc_hidden_def (mcheck)
  382: #endif
  383: 
  384: int
  385: mcheck_pedantic (func)
  386:       void (*func) (enum mcheck_status);
  387: {
  388:   int res = mcheck (func);
  389:   if (res == 0)
  390:     pedantic = 1;
  391:   return res;
  392: }
  393: 
  394: enum mcheck_status
  395: mprobe (__ptr_t ptr)
  396: {
  397:   return mcheck_used ? checkhdr (((struct hdr *) ptr) - 1) : MCHECK_DISABLED;
  398: }
Syntax (Markdown)