mmcheck.c

Go to the documentation of this file.
00001 /* @(#)root/clib:$Id: mmcheck.c 21699 2008-01-14 16:26:38Z brun $ */
00002 /* Author: */
00003 
00004 /* Standard debugging hooks for `mmalloc'.
00005    Copyright 1990, 1991, 1992 Free Software Foundation
00006 
00007    Written May 1989 by Mike Haertel.
00008    Heavily modified Mar 1992 by Fred Fish (fnf@cygnus.com)
00009 
00010 The GNU C Library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU Library General Public License as
00012 published by the Free Software Foundation; either version 2 of the
00013 License, or (at your option) any later version.
00014 
00015 The GNU C Library is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 Library General Public License for more details.
00019 
00020 You should have received a copy of the GNU Library General Public
00021 License along with the GNU C Library; see the file COPYING.LIB.  If
00022 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023 Boston, MA 02111-1307, USA.
00024 
00025  The author may be reached (Email) at the address mike@ai.mit.edu,
00026  or (US mail) as Mike Haertel c/o Free Software Foundation. */
00027 
00028 #include "mmprivate.h"
00029 
00030 /* Default function to call when something awful happens.  The application
00031    can specify an alternate function to be called instead (and probably will
00032    want to). */
00033 
00034 extern void abort PARAMS ((void));
00035 
00036 /* Arbitrary magical numbers.  */
00037 
00038 #define MAGICWORD       (unsigned int) 0xfedabeeb       /* Active chunk */
00039 #define MAGICWORDFREE   (unsigned int) 0xdeadbeef       /* Inactive chunk */
00040 #define MAGICBYTE       ((char) 0xd7)
00041 
00042 /* Each memory allocation is bounded by a header structure and a trailer
00043    byte.  I.E.
00044 
00045         <size><magicword><user's allocation><magicbyte>
00046 
00047    The pointer returned to the user points to the first byte in the
00048    user's allocation area.  The magic word can be tested to detect
00049    buffer underruns and the magic byte can be tested to detect overruns. */
00050 
00051 struct hdr
00052   {
00053     size_t size;                /* Exact size requested by user.  */
00054     unsigned long int magic;    /* Magic number to check header integrity.  */
00055   };
00056 
00057 typedef void (*mmfree_fun_t) PARAMS ((PTR, PTR));
00058 typedef PTR (*mmalloc_fun_t) PARAMS ((PTR, size_t));
00059 typedef PTR (*mmrealloc_fun_t) PARAMS ((PTR, PTR, size_t));
00060 
00061 /* Check the magicword and magicbyte, and if either is corrupted then
00062    call the emergency abort function specified for the heap in use. */
00063 
00064 static void
00065 checkhdr (mdp, hdr)
00066   struct mdesc *mdp;
00067   const struct hdr *hdr;
00068 {
00069   if (hdr -> magic != MAGICWORD ||
00070       ((char *) &hdr[1])[hdr -> size] != MAGICBYTE)
00071     {
00072       (*mdp -> abortfunc)();
00073     }
00074 }
00075 
00076 static void
00077 mfree_check (md, ptr)
00078   PTR md;
00079   PTR ptr;
00080 {
00081   struct hdr *hdr = ((struct hdr *) ptr) - 1;
00082   struct mdesc *mdp;
00083 
00084   mdp = MD_TO_MDP (md);
00085   checkhdr (mdp, hdr);
00086   hdr -> magic = MAGICWORDFREE;
00087   mdp -> mfree_hook = NULL;
00088   mfree (md, (PTR)hdr);
00089   mdp -> mfree_hook = (mmfree_fun_t) mfree_check;
00090 }
00091 
00092 static PTR
00093 mmalloc_check (md, size)
00094   PTR md;
00095   size_t size;
00096 {
00097   struct hdr *hdr;
00098   struct mdesc *mdp;
00099   size_t nbytes;
00100 
00101   mdp = MD_TO_MDP (md);
00102   mdp -> mmalloc_hook = NULL;
00103   nbytes = sizeof (struct hdr) + size + 1;
00104   hdr = (struct hdr *) mmalloc (md, nbytes);
00105   mdp -> mmalloc_hook = (mmalloc_fun_t) mmalloc_check;
00106   if (hdr != NULL)
00107     {
00108       hdr -> size = size;
00109       hdr -> magic = MAGICWORD;
00110       hdr++;
00111       *((char *) hdr + size) = MAGICBYTE;
00112     }
00113   return ((PTR) hdr);
00114 }
00115 
00116 static PTR
00117 mrealloc_check (md, ptr, size)
00118   PTR md;
00119   PTR ptr;
00120   size_t size;
00121 {
00122   struct hdr *hdr = ((struct hdr *) ptr) - 1;
00123   struct mdesc *mdp;
00124   size_t nbytes;
00125 
00126   mdp = MD_TO_MDP (md);
00127   checkhdr (mdp, hdr);
00128   mdp -> mfree_hook = NULL;
00129   mdp -> mmalloc_hook = NULL;
00130   mdp -> mrealloc_hook = NULL;
00131   nbytes = sizeof (struct hdr) + size + 1;
00132   hdr = (struct hdr *) mrealloc (md, (PTR) hdr, nbytes);
00133   mdp -> mfree_hook = (mmfree_fun_t) mfree_check;
00134   mdp -> mmalloc_hook = (mmalloc_fun_t) mmalloc_check;
00135   mdp -> mrealloc_hook = (mmrealloc_fun_t) mrealloc_check;
00136   if (hdr != NULL)
00137     {
00138       hdr -> size = size;
00139       hdr++;
00140       *((char *) hdr + size) = MAGICBYTE;
00141     }
00142   return ((PTR) hdr);
00143 }
00144 
00145 /* Turn on default checking for mmalloc/mrealloc/mfree, for the heap specified
00146    by MD.  If FUNC is non-NULL, it is a pointer to the function to call
00147    to abort whenever memory corruption is detected.  By default, this is the
00148    standard library function abort().
00149 
00150    Note that we disallow installation of initial checking hooks if mmalloc
00151    has been called at any time for this particular heap, since if any region
00152    that is allocated prior to installation of the hooks is subsequently
00153    reallocated or freed after installation of the hooks, it is guaranteed
00154    to trigger a memory corruption error.  We do this by checking the state
00155    of the MMALLOC_INITIALIZED flag.
00156 
00157    However, we can call this function at any time after the initial call,
00158    to update the function pointers to the checking routines and to the
00159    user defined corruption handler routine, as long as these function pointers
00160    have been previously extablished by the initial call.  Note that we
00161    do this automatically when remapping an previously used heap, to ensure
00162    that the hooks get updated to the correct values, although the corruption
00163    handler pointer gets set back to the default.  The application can then
00164    call mmcheck to use a different corruption handler if desired.
00165 
00166    Returns non-zero if checking is successfully enabled, zero otherwise. */
00167 
00168 int
00169 mmcheck (md, func)
00170   PTR md;
00171   void (*func) PARAMS ((void));
00172 {
00173   struct mdesc *mdp;
00174   int rtnval;
00175 
00176   mdp = MD_TO_MDP (md);
00177 
00178   /* We can safely set or update the abort function at any time, regardless
00179      of whether or not we successfully do anything else. */
00180 
00181   mdp -> abortfunc = (func != NULL ? func : abort);
00182 
00183   /* If we haven't yet called mmalloc the first time for this heap, or if we
00184      have hooks that were previously installed, then allow the hooks to be
00185      initialized or updated. */
00186 
00187   if (1 /* FIXME: Always allow installation for now. */ ||
00188       !(mdp -> flags & MMALLOC_INITIALIZED) ||
00189       (mdp -> mfree_hook != NULL))
00190     {
00191       mdp -> mfree_hook = (mmfree_fun_t) mfree_check;
00192       mdp -> mmalloc_hook = (mmalloc_fun_t) mmalloc_check;
00193       mdp -> mrealloc_hook = (mmrealloc_fun_t) mrealloc_check;
00194       mdp -> flags |= MMALLOC_MMCHECK_USED;
00195       rtnval = 1;
00196     }
00197   else
00198     {
00199       rtnval = 0;
00200     }
00201 
00202   return (rtnval);
00203 }

Generated on Tue Jul 5 14:11:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1