C:/Users/Dennis/src/lang/russell.orig/src/gc/debug_malloc.c

Go to the documentation of this file.
00001 # include "gc_private.h"
00002 # define START_FLAG ((word)0xfedcedcb)
00003 # define END_FLAG ((word)0xbcdecdef)
00004         /* Stored both one past the end of user object, and one before  */
00005         /* the end of the object as seen by the allocator.              */
00006 
00007 /* Object header */
00008 typedef struct {
00009     char * oh_string;   /* object descriptor string     */
00010     word oh_int;                /* object descriptor integers   */
00011     word oh_sz;         /* Original malloc arg.         */
00012     word oh_sf;                 /* start flag */
00013 } oh;
00014 /* The size of the above structure is assumed not to dealign things,    */
00015 /* and to be a multiple of the word length.                             */
00016 
00017 #define DEBUG_BYTES (sizeof (oh) + sizeof (word))
00018 #define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
00019 
00020 bool GC_debugging_started = FALSE;
00021 
00022 /* Check whether object with base pointer p has debugging info  */ 
00023 /* p is assumed to point to a legitimate object in our part     */
00024 /* of the heap.                                                 */
00025 bool GC_has_debug_info(p)
00026 ptr_t p;
00027 {
00028     register oh * ohdr = (oh *)p;
00029     register ptr_t body = (ptr_t)(ohdr + 1);
00030     register word sz = GC_size((ptr_t) ohdr);
00031     
00032     if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body)
00033         || sz < sizeof (oh)) {
00034         return(FALSE);
00035     }
00036     if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE);
00037     if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) {
00038         return(TRUE);
00039     }
00040     return(FALSE);
00041 }
00042 
00043 /* Store debugging info into p.  Return displaced pointer. */
00044 /* Assumes we don't hold allocation lock.                  */
00045 ptr_t GC_store_debug_info(p, sz, string, integer)
00046 register ptr_t p;       /* base pointer */
00047 word sz;        /* bytes */
00048 char * string;
00049 word integer;
00050 {
00051     register word * result = (word *)((oh *)p + 1);
00052     DCL_LOCK_STATE;
00053     
00054     /* There is some argument that we should dissble signals here.      */
00055     /* But that's expensive.  And this way things should only appear    */
00056     /* inconsistent while we're in the handler.                         */
00057     LOCK();
00058     ((oh *)p) -> oh_string = string;
00059     ((oh *)p) -> oh_int = integer;
00060     ((oh *)p) -> oh_sz = sz;
00061     ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
00062     ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
00063          result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
00064     UNLOCK();
00065     return((ptr_t)result);
00066 }
00067 
00068 /* Check the object with debugging info at p            */
00069 /* return NIL if it's OK.  Else return clobbered        */
00070 /* address.                                             */
00071 ptr_t GC_check_annotated_obj(ohdr)
00072 register oh * ohdr;
00073 {
00074     register ptr_t body = (ptr_t)(ohdr + 1);
00075     register word gc_sz = GC_size((ptr_t)ohdr);
00076     if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
00077         return((ptr_t)(&(ohdr -> oh_sz)));
00078     }
00079     if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
00080         return((ptr_t)(&(ohdr -> oh_sf)));
00081     }
00082     if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
00083         return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
00084     }
00085     if (((word *)body)[ROUNDED_UP_WORDS(ohdr -> oh_sz)]
00086         != (END_FLAG ^ (word)body)) {
00087         return((ptr_t)((word *)body + ROUNDED_UP_WORDS(ohdr -> oh_sz)));
00088     }
00089     return(0);
00090 }
00091 
00092 void GC_print_obj(p)
00093 ptr_t p;
00094 {
00095     register oh * ohdr = (oh *)GC_base(p);
00096     
00097     GC_err_printf1("0x%lx (", (unsigned long)ohdr + sizeof(oh));
00098     GC_err_puts(ohdr -> oh_string);
00099     GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
00100                                       (unsigned long)(ohdr -> oh_sz));
00101 }
00102 void GC_print_smashed_obj(p, clobbered_addr)
00103 ptr_t p, clobbered_addr;
00104 {
00105     register oh * ohdr = (oh *)GC_base(p);
00106     
00107     GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
00108                                                 (unsigned long)p);
00109     if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))) {
00110         GC_err_printf1("<smashed>, appr. sz = %ld)\n",
00111                        BYTES_TO_WORDS(GC_size((ptr_t)ohdr)));
00112     } else {
00113         GC_err_puts(ohdr -> oh_string);
00114         GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
00115                                           (unsigned long)(ohdr -> oh_sz));
00116     }
00117 }
00118 
00119 # ifdef __STDC__
00120     extern_ptr_t GC_debug_malloc(size_t lb, char * s, int i)
00121 # else
00122     extern_ptr_t GC_debug_malloc(lb, s, i)
00123     size_t lb;
00124     char * s;
00125     int i;
00126 # endif
00127 {
00128     extern_ptr_t result = GC_malloc(lb + DEBUG_BYTES);
00129     
00130     if (result == 0) {
00131         GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
00132                        (unsigned long) lb);
00133         GC_err_puts(s);
00134         GC_err_printf1(":%ld)\n", (unsigned long)i);
00135         return(0);
00136     }
00137     if (!GC_debugging_started) {
00138         GC_debugging_started = TRUE;
00139         GC_register_displacement((word)sizeof(oh));
00140     }
00141     return (GC_store_debug_info(result, (word)lb, s, (word)i));
00142 }
00143 
00144 # ifdef __STDC__
00145     extern_ptr_t GC_debug_malloc_atomic(size_t lb, char * s, int i)
00146 # else
00147     extern_ptr_t GC_debug_malloc_atomic(lb, s, i)
00148     size_t lb;
00149     char * s;
00150     int i;
00151 # endif
00152 {
00153     extern_ptr_t result = GC_malloc_atomic(lb + DEBUG_BYTES);
00154     
00155     if (result == 0) {
00156         GC_err_printf1("GC_debug_malloc_atomic(%ld) returning NIL (",
00157                       (unsigned long) lb);
00158         GC_err_puts(s);
00159         GC_err_printf1(":%ld)\n", (unsigned long)i);
00160         return(0);
00161     }
00162     if (!GC_debugging_started) {
00163         GC_debugging_started = TRUE;
00164         GC_register_displacement((word)sizeof(oh));
00165     }
00166     return (GC_store_debug_info(result, (word)lb, s, (word)i));
00167 }
00168 # ifdef __STDC__
00169     void GC_debug_free(extern_ptr_t p)
00170 # else
00171     void GC_debug_free(p)
00172     extern_ptr_t p;
00173 # endif
00174 {
00175     register extern_ptr_t base = GC_base(p);
00176     register ptr_t clobbered;
00177     
00178     if (base == 0) {
00179         GC_err_printf1("Attempt to free invalid pointer %lx\n",
00180                        (unsigned long)p);
00181         ABORT("free(invalid pointer)");
00182     }
00183     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
00184         GC_err_printf1(
00185                   "GC_debug_free called on pointer %lx wo debugging info\n",
00186                   (unsigned long)p);
00187     } else {
00188       clobbered = GC_check_annotated_obj((oh *)base);
00189       if (clobbered != 0) {
00190         GC_err_printf0("GC_debug_free: found smashed object at ");
00191         GC_print_smashed_obj(p, clobbered);
00192       }
00193     }
00194     GC_free(GC_base(p));
00195 }
00196 
00197 # ifdef __STDC__
00198     extern_ptr_t GC_debug_realloc(extern_ptr_t p, size_t lb, char *s, int i)
00199 # else
00200     extern_ptr_t GC_debug_realloc(p, lb, s, i)
00201     extern_ptr_t p;
00202     size_t lb;
00203     char *s;
00204     int i;
00205 # endif
00206 {
00207     register extern_ptr_t base = GC_base(p);
00208     register ptr_t clobbered;
00209     register extern_ptr_t result = GC_debug_malloc(lb, s, i);
00210     register size_t copy_sz = lb;
00211     register size_t old_sz;
00212     
00213     if (base == 0) {
00214         GC_err_printf1(
00215               "Attempt to free invalid pointer %lx\n", (unsigned long)p);
00216         ABORT("realloc(invalid pointer)");
00217     }
00218     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
00219         GC_err_printf1(
00220                 "GC_debug_realloc called on pointer %lx wo debugging info\n",
00221                 (unsigned long)p);
00222         return(GC_realloc(p, lb));
00223     }
00224     clobbered = GC_check_annotated_obj((oh *)base);
00225     if (clobbered != 0) {
00226         GC_err_printf0("GC_debug_realloc: found smashed object at ");
00227         GC_print_smashed_obj(p, clobbered);
00228     }
00229     old_sz = ((oh *)base) -> oh_sz;
00230     if (old_sz < copy_sz) copy_sz = old_sz;
00231     if (result == 0) return(0);
00232     bcopy((char *)p, (char *)result, (int) copy_sz);
00233     return(result);
00234 }
00235 
00236 /* Check all marked objects in the given block for validity */
00237 /*ARGSUSED*/
00238 void GC_check_heap_block(hbp, dummy)
00239 register struct hblk *hbp;      /* ptr to current heap block            */
00240 word dummy;
00241 {
00242     register struct hblkhdr * hhdr = HDR(hbp);
00243     register word sz = hhdr -> hb_sz;
00244     register int word_no;
00245     register word *p, *plim;
00246     
00247     p = (word *)(hbp->hb_body);
00248     word_no = HDR_WORDS;
00249     plim = (word *)((((word)hbp) + HBLKSIZE)
00250                    - WORDS_TO_BYTES(sz));
00251 
00252     /* go through all words in block */
00253         do {
00254             if( mark_bit_from_hdr(hhdr, word_no)
00255                 && GC_has_debug_info((ptr_t)p)) {
00256                 ptr_t clobbered = GC_check_annotated_obj((oh *)p);
00257                 
00258                 if (clobbered != 0) {
00259                     GC_err_printf0(
00260                         "GC_check_heap_block: found smashed object at ");
00261                     GC_print_smashed_obj((ptr_t)p, clobbered);
00262                 }
00263             }
00264             word_no += sz;
00265             p += sz;
00266         } while( p <= plim );
00267 }
00268 
00269 
00270 /* This assumes that all accessible objects are marked, and that        */
00271 /* I hold the allocation lock.  Normally called by collector.           */
00272 void GC_check_heap()
00273 {
00274     GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
00275 }
00276 
00277 struct closure {
00278     GC_finalization_proc cl_fn;
00279     extern_ptr_t cl_data;
00280 };
00281 
00282 # ifdef __STDC__
00283     void * GC_make_closure(GC_finalization_proc fn, void * data)
00284 # else
00285     extern_ptr_t GC_make_closure(fn, data)
00286     GC_finalization_proc fn;
00287     extern_ptr_t data;
00288 # endif
00289 {
00290     struct closure * result =
00291                 (struct closure *) GC_malloc(sizeof (struct closure));
00292     
00293     result -> cl_fn = fn;
00294     result -> cl_data = data;
00295     return((extern_ptr_t)result);
00296 }
00297 
00298 # ifdef __STDC__
00299     void GC_debug_invoke_finalizer(void * obj, void * data)
00300 # else
00301     void GC_debug_invoke_finalizer(obj, data)
00302     char * obj;
00303     char * data;
00304 # endif
00305 {
00306     register struct closure * cl = (struct closure *) data;
00307     
00308     (*(cl -> cl_fn))((extern_ptr_t)((char *)obj + sizeof(oh)), cl -> cl_data);
00309 } 
00310 

Generated on Fri Jan 25 10:39:45 2008 for russell by  doxygen 1.5.4