00001 # include "gc_private.h"
00002 # define START_FLAG ((word)0xfedcedcb)
00003 # define END_FLAG ((word)0xbcdecdef)
00004
00005
00006
00007
00008 typedef struct {
00009 char * oh_string;
00010 word oh_int;
00011 word oh_sz;
00012 word oh_sf;
00013 } oh;
00014
00015
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
00023
00024
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
00044
00045 ptr_t GC_store_debug_info(p, sz, string, integer)
00046 register ptr_t p;
00047 word sz;
00048 char * string;
00049 word integer;
00050 {
00051 register word * result = (word *)((oh *)p + 1);
00052 DCL_LOCK_STATE;
00053
00054
00055
00056
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
00069
00070
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
00237
00238 void GC_check_heap_block(hbp, dummy)
00239 register struct hblk *hbp;
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
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
00271
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