Annotation of OpenXM_contrib2/asir2000/gc5.3/dbg_mlc.c, Revision 1.1
1.1 ! noro 1: /*
! 2: * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
! 3: * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
! 4: * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
! 5: * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
! 6: *
! 7: * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
! 8: * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
! 9: *
! 10: * Permission is hereby granted to use or copy this program
! 11: * for any purpose, provided the above notices are retained on all copies.
! 12: * Permission to modify the code and to distribute modified code is granted,
! 13: * provided the above notices are retained, and a notice that the code was
! 14: * modified is included with the above copyright notice.
! 15: */
! 16:
! 17: #include "dbg_mlc.h"
! 18:
! 19: void GC_default_print_heap_obj_proc();
! 20: GC_API void GC_register_finalizer_no_order
! 21: GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
! 22: GC_finalization_proc *ofn, GC_PTR *ocd));
! 23:
! 24:
! 25: /* Check whether object with base pointer p has debugging info */
! 26: /* p is assumed to point to a legitimate object in our part */
! 27: /* of the heap. */
! 28: GC_bool GC_has_debug_info(p)
! 29: ptr_t p;
! 30: {
! 31: register oh * ohdr = (oh *)p;
! 32: register ptr_t body = (ptr_t)(ohdr + 1);
! 33: register word sz = GC_size((ptr_t) ohdr);
! 34:
! 35: if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body)
! 36: || sz < sizeof (oh)) {
! 37: return(FALSE);
! 38: }
! 39: if (ohdr -> oh_sz == sz) {
! 40: /* Object may have had debug info, but has been deallocated */
! 41: return(FALSE);
! 42: }
! 43: if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE);
! 44: if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) {
! 45: return(TRUE);
! 46: }
! 47: return(FALSE);
! 48: }
! 49:
! 50: #ifdef KEEP_BACK_PTRS
! 51: /* Store back pointer to source in dest, if that appears to be possible. */
! 52: /* This is not completely safe, since we may mistakenly conclude that */
! 53: /* dest has a debugging wrapper. But the error probability is very */
! 54: /* small, and this shouldn't be used in production code. */
! 55: /* We assume that dest is the real base pointer. Source will usually */
! 56: /* be a pointer to the interior of an object. */
! 57: void GC_store_back_pointer(ptr_t source, ptr_t dest)
! 58: {
! 59: if (GC_has_debug_info(dest)) {
! 60: ((oh *)dest) -> oh_back_ptr = (ptr_t)HIDE_POINTER(source);
! 61: }
! 62: }
! 63:
! 64: void GC_marked_for_finalization(ptr_t dest) {
! 65: GC_store_back_pointer(MARKED_FOR_FINALIZATION, dest);
! 66: }
! 67:
! 68: /* Store information about the object referencing dest in *base_p */
! 69: /* and *offset_p. */
! 70: /* source is root ==> *base_p = address, *offset_p = 0 */
! 71: /* source is heap object ==> *base_p != 0, *offset_p = offset */
! 72: /* Returns 1 on success, 0 if source couldn't be determined. */
! 73: /* Dest can be any address within a heap object. */
! 74: GC_ref_kind GC_get_back_ptr_info(void *dest, void **base_p, size_t *offset_p)
! 75: {
! 76: oh * hdr = (oh *)GC_base(dest);
! 77: ptr_t bp;
! 78: ptr_t bp_base;
! 79: if (!GC_has_debug_info((ptr_t) hdr)) return GC_NO_SPACE;
! 80: bp = hdr -> oh_back_ptr;
! 81: if (MARKED_FOR_FINALIZATION == bp) return GC_FINALIZER_REFD;
! 82: if (MARKED_FROM_REGISTER == bp) return GC_REFD_FROM_REG;
! 83: if (0 == bp) return GC_UNREFERENCED;
! 84: bp = REVEAL_POINTER(bp);
! 85: bp_base = GC_base(bp);
! 86: if (0 == bp_base) {
! 87: *base_p = bp;
! 88: *offset_p = 0;
! 89: return GC_REFD_FROM_ROOT;
! 90: } else {
! 91: if (GC_has_debug_info(bp_base)) bp_base += sizeof(oh);
! 92: *base_p = bp_base;
! 93: *offset_p = bp - bp_base;
! 94: return GC_REFD_FROM_HEAP;
! 95: }
! 96: }
! 97:
! 98: /* Generate a random heap address. */
! 99: /* The resulting address is in the heap, but */
! 100: /* not necessarily inside a valid object. */
! 101: void *GC_generate_random_heap_address(void)
! 102: {
! 103: int i;
! 104: int heap_offset = random() % GC_heapsize;
! 105: for (i = 0; i < GC_n_heap_sects; ++ i) {
! 106: int size = GC_heap_sects[i].hs_bytes;
! 107: if (heap_offset < size) {
! 108: return GC_heap_sects[i].hs_start + heap_offset;
! 109: } else {
! 110: heap_offset -= size;
! 111: }
! 112: }
! 113: ABORT("GC_generate_random_heap_address: size inconsistency");
! 114: /*NOTREACHED*/
! 115: return 0;
! 116: }
! 117:
! 118: /* Generate a random address inside a valid marked heap object. */
! 119: void *GC_generate_random_valid_address(void)
! 120: {
! 121: ptr_t result;
! 122: ptr_t base;
! 123: for (;;) {
! 124: result = GC_generate_random_heap_address();
! 125: base = GC_base(result);
! 126: if (0 == base) continue;
! 127: if (!GC_is_marked(base)) continue;
! 128: return result;
! 129: }
! 130: }
! 131:
! 132: /* Print back trace for p */
! 133: void GC_print_backtrace(void *p)
! 134: {
! 135: void *current = p;
! 136: int i;
! 137: GC_ref_kind source;
! 138: size_t offset;
! 139: void *base;
! 140:
! 141: GC_print_heap_obj(GC_base(current));
! 142: GC_err_printf0("\n");
! 143: for (i = 0; ; ++i) {
! 144: source = GC_get_back_ptr_info(current, &base, &offset);
! 145: if (GC_UNREFERENCED == source) {
! 146: GC_err_printf0("Reference could not be found\n");
! 147: goto out;
! 148: }
! 149: if (GC_NO_SPACE == source) {
! 150: GC_err_printf0("No debug info in object: Can't find reference\n");
! 151: goto out;
! 152: }
! 153: GC_err_printf1("Reachable via %d levels of pointers from ",
! 154: (unsigned long)i);
! 155: switch(source) {
! 156: case GC_REFD_FROM_ROOT:
! 157: GC_err_printf1("root at 0x%lx\n", (unsigned long)base);
! 158: goto out;
! 159: case GC_REFD_FROM_REG:
! 160: GC_err_printf0("root in register\n");
! 161: goto out;
! 162: case GC_FINALIZER_REFD:
! 163: GC_err_printf0("list of finalizable objects\n");
! 164: goto out;
! 165: case GC_REFD_FROM_HEAP:
! 166: GC_err_printf1("offset %ld in object:\n", (unsigned long)offset);
! 167: /* Take GC_base(base) to get real base, i.e. header. */
! 168: GC_print_heap_obj(GC_base(base));
! 169: GC_err_printf0("\n");
! 170: break;
! 171: }
! 172: current = base;
! 173: }
! 174: out:;
! 175: }
! 176:
! 177: /* Force a garbage collection and generate a backtrace from a */
! 178: /* random heap address. */
! 179: void GC_generate_random_backtrace(void)
! 180: {
! 181: void * current;
! 182: GC_gcollect();
! 183: current = GC_generate_random_valid_address();
! 184: GC_printf1("Chose address 0x%lx in object\n", (unsigned long)current);
! 185: GC_print_backtrace(current);
! 186: }
! 187:
! 188: #endif /* KEEP_BACK_PTRS */
! 189:
! 190: /* Store debugging info into p. Return displaced pointer. */
! 191: /* Assumes we don't hold allocation lock. */
! 192: ptr_t GC_store_debug_info(p, sz, string, integer)
! 193: register ptr_t p; /* base pointer */
! 194: word sz; /* bytes */
! 195: char * string;
! 196: word integer;
! 197: {
! 198: register word * result = (word *)((oh *)p + 1);
! 199: DCL_LOCK_STATE;
! 200:
! 201: /* There is some argument that we should dissble signals here. */
! 202: /* But that's expensive. And this way things should only appear */
! 203: /* inconsistent while we're in the handler. */
! 204: LOCK();
! 205: # ifdef KEEP_BACK_PTRS
! 206: ((oh *)p) -> oh_back_ptr = 0;
! 207: # endif
! 208: ((oh *)p) -> oh_string = string;
! 209: ((oh *)p) -> oh_int = integer;
! 210: ((oh *)p) -> oh_sz = sz;
! 211: ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
! 212: ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
! 213: result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
! 214: UNLOCK();
! 215: return((ptr_t)result);
! 216: }
! 217:
! 218: /* Check the object with debugging info at ohdr */
! 219: /* return NIL if it's OK. Else return clobbered */
! 220: /* address. */
! 221: ptr_t GC_check_annotated_obj(ohdr)
! 222: register oh * ohdr;
! 223: {
! 224: register ptr_t body = (ptr_t)(ohdr + 1);
! 225: register word gc_sz = GC_size((ptr_t)ohdr);
! 226: if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
! 227: return((ptr_t)(&(ohdr -> oh_sz)));
! 228: }
! 229: if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
! 230: return((ptr_t)(&(ohdr -> oh_sf)));
! 231: }
! 232: if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
! 233: return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
! 234: }
! 235: if (((word *)body)[ROUNDED_UP_WORDS(ohdr -> oh_sz)]
! 236: != (END_FLAG ^ (word)body)) {
! 237: return((ptr_t)((word *)body + ROUNDED_UP_WORDS(ohdr -> oh_sz)));
! 238: }
! 239: return(0);
! 240: }
! 241:
! 242: void GC_print_obj(p)
! 243: ptr_t p;
! 244: {
! 245: register oh * ohdr = (oh *)GC_base(p);
! 246:
! 247: GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
! 248: GC_err_puts(ohdr -> oh_string);
! 249: GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
! 250: (unsigned long)(ohdr -> oh_sz));
! 251: PRINT_CALL_CHAIN(ohdr);
! 252: }
! 253:
! 254: void GC_debug_print_heap_obj_proc(p)
! 255: ptr_t p;
! 256: {
! 257: if (GC_has_debug_info(p)) {
! 258: GC_print_obj(p);
! 259: } else {
! 260: GC_default_print_heap_obj_proc(p);
! 261: }
! 262: }
! 263:
! 264: void GC_print_smashed_obj(p, clobbered_addr)
! 265: ptr_t p, clobbered_addr;
! 266: {
! 267: register oh * ohdr = (oh *)GC_base(p);
! 268:
! 269: GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
! 270: (unsigned long)p);
! 271: if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
! 272: || ohdr -> oh_string == 0) {
! 273: GC_err_printf1("<smashed>, appr. sz = %ld)\n",
! 274: (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
! 275: } else {
! 276: if (ohdr -> oh_string[0] == '\0') {
! 277: GC_err_puts("EMPTY(smashed?)");
! 278: } else {
! 279: GC_err_puts(ohdr -> oh_string);
! 280: }
! 281: GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
! 282: (unsigned long)(ohdr -> oh_sz));
! 283: PRINT_CALL_CHAIN(ohdr);
! 284: }
! 285: }
! 286:
! 287: void GC_check_heap_proc();
! 288:
! 289: void GC_start_debugging()
! 290: {
! 291: GC_check_heap = GC_check_heap_proc;
! 292: GC_print_heap_obj = GC_debug_print_heap_obj_proc;
! 293: GC_debugging_started = TRUE;
! 294: GC_register_displacement((word)sizeof(oh));
! 295: }
! 296:
! 297: # if defined(__STDC__) || defined(__cplusplus)
! 298: void GC_debug_register_displacement(GC_word offset)
! 299: # else
! 300: void GC_debug_register_displacement(offset)
! 301: GC_word offset;
! 302: # endif
! 303: {
! 304: GC_register_displacement(offset);
! 305: GC_register_displacement((word)sizeof(oh) + offset);
! 306: }
! 307:
! 308: # ifdef __STDC__
! 309: GC_PTR GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)
! 310: # else
! 311: GC_PTR GC_debug_malloc(lb, s, i)
! 312: size_t lb;
! 313: char * s;
! 314: int i;
! 315: # ifdef GC_ADD_CALLER
! 316: --> GC_ADD_CALLER not implemented for K&R C
! 317: # endif
! 318: # endif
! 319: {
! 320: GC_PTR result = GC_malloc(lb + DEBUG_BYTES);
! 321:
! 322: if (result == 0) {
! 323: GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
! 324: (unsigned long) lb);
! 325: GC_err_puts(s);
! 326: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 327: return(0);
! 328: }
! 329: if (!GC_debugging_started) {
! 330: GC_start_debugging();
! 331: }
! 332: ADD_CALL_CHAIN(result, ra);
! 333: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 334: }
! 335:
! 336: #ifdef STUBBORN_ALLOC
! 337: # ifdef __STDC__
! 338: GC_PTR GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
! 339: # else
! 340: GC_PTR GC_debug_malloc_stubborn(lb, s, i)
! 341: size_t lb;
! 342: char * s;
! 343: int i;
! 344: # endif
! 345: {
! 346: GC_PTR result = GC_malloc_stubborn(lb + DEBUG_BYTES);
! 347:
! 348: if (result == 0) {
! 349: GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
! 350: (unsigned long) lb);
! 351: GC_err_puts(s);
! 352: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 353: return(0);
! 354: }
! 355: if (!GC_debugging_started) {
! 356: GC_start_debugging();
! 357: }
! 358: ADD_CALL_CHAIN(result, ra);
! 359: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 360: }
! 361:
! 362: void GC_debug_change_stubborn(p)
! 363: GC_PTR p;
! 364: {
! 365: register GC_PTR q = GC_base(p);
! 366: register hdr * hhdr;
! 367:
! 368: if (q == 0) {
! 369: GC_err_printf1("Bad argument: 0x%lx to GC_debug_change_stubborn\n",
! 370: (unsigned long) p);
! 371: ABORT("GC_debug_change_stubborn: bad arg");
! 372: }
! 373: hhdr = HDR(q);
! 374: if (hhdr -> hb_obj_kind != STUBBORN) {
! 375: GC_err_printf1("GC_debug_change_stubborn arg not stubborn: 0x%lx\n",
! 376: (unsigned long) p);
! 377: ABORT("GC_debug_change_stubborn: arg not stubborn");
! 378: }
! 379: GC_change_stubborn(q);
! 380: }
! 381:
! 382: void GC_debug_end_stubborn_change(p)
! 383: GC_PTR p;
! 384: {
! 385: register GC_PTR q = GC_base(p);
! 386: register hdr * hhdr;
! 387:
! 388: if (q == 0) {
! 389: GC_err_printf1("Bad argument: 0x%lx to GC_debug_end_stubborn_change\n",
! 390: (unsigned long) p);
! 391: ABORT("GC_debug_end_stubborn_change: bad arg");
! 392: }
! 393: hhdr = HDR(q);
! 394: if (hhdr -> hb_obj_kind != STUBBORN) {
! 395: GC_err_printf1("debug_end_stubborn_change arg not stubborn: 0x%lx\n",
! 396: (unsigned long) p);
! 397: ABORT("GC_debug_end_stubborn_change: arg not stubborn");
! 398: }
! 399: GC_end_stubborn_change(q);
! 400: }
! 401:
! 402: #else /* !STUBBORN_ALLOC */
! 403:
! 404: # ifdef __STDC__
! 405: GC_PTR GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
! 406: # else
! 407: GC_PTR GC_debug_malloc_stubborn(lb, s, i)
! 408: size_t lb;
! 409: char * s;
! 410: int i;
! 411: # endif
! 412: {
! 413: return GC_debug_malloc(lb, OPT_RA s, i);
! 414: }
! 415:
! 416: void GC_debug_change_stubborn(p)
! 417: GC_PTR p;
! 418: {
! 419: }
! 420:
! 421: void GC_debug_end_stubborn_change(p)
! 422: GC_PTR p;
! 423: {
! 424: }
! 425:
! 426: #endif /* !STUBBORN_ALLOC */
! 427:
! 428: # ifdef __STDC__
! 429: GC_PTR GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
! 430: # else
! 431: GC_PTR GC_debug_malloc_atomic(lb, s, i)
! 432: size_t lb;
! 433: char * s;
! 434: int i;
! 435: # endif
! 436: {
! 437: GC_PTR result = GC_malloc_atomic(lb + DEBUG_BYTES);
! 438:
! 439: if (result == 0) {
! 440: GC_err_printf1("GC_debug_malloc_atomic(%ld) returning NIL (",
! 441: (unsigned long) lb);
! 442: GC_err_puts(s);
! 443: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 444: return(0);
! 445: }
! 446: if (!GC_debugging_started) {
! 447: GC_start_debugging();
! 448: }
! 449: ADD_CALL_CHAIN(result, ra);
! 450: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 451: }
! 452:
! 453: # ifdef __STDC__
! 454: GC_PTR GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
! 455: # else
! 456: GC_PTR GC_debug_malloc_uncollectable(lb, s, i)
! 457: size_t lb;
! 458: char * s;
! 459: int i;
! 460: # endif
! 461: {
! 462: GC_PTR result = GC_malloc_uncollectable(lb + DEBUG_BYTES);
! 463:
! 464: if (result == 0) {
! 465: GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (",
! 466: (unsigned long) lb);
! 467: GC_err_puts(s);
! 468: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 469: return(0);
! 470: }
! 471: if (!GC_debugging_started) {
! 472: GC_start_debugging();
! 473: }
! 474: ADD_CALL_CHAIN(result, ra);
! 475: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 476: }
! 477:
! 478: #ifdef ATOMIC_UNCOLLECTABLE
! 479: # ifdef __STDC__
! 480: GC_PTR GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS)
! 481: # else
! 482: GC_PTR GC_debug_malloc_atomic_uncollectable(lb, s, i)
! 483: size_t lb;
! 484: char * s;
! 485: int i;
! 486: # endif
! 487: {
! 488: GC_PTR result = GC_malloc_atomic_uncollectable(lb + DEBUG_BYTES);
! 489:
! 490: if (result == 0) {
! 491: GC_err_printf1(
! 492: "GC_debug_malloc_atomic_uncollectable(%ld) returning NIL (",
! 493: (unsigned long) lb);
! 494: GC_err_puts(s);
! 495: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 496: return(0);
! 497: }
! 498: if (!GC_debugging_started) {
! 499: GC_start_debugging();
! 500: }
! 501: ADD_CALL_CHAIN(result, ra);
! 502: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 503: }
! 504: #endif /* ATOMIC_UNCOLLECTABLE */
! 505:
! 506: # ifdef __STDC__
! 507: void GC_debug_free(GC_PTR p)
! 508: # else
! 509: void GC_debug_free(p)
! 510: GC_PTR p;
! 511: # endif
! 512: {
! 513: register GC_PTR base;
! 514: register ptr_t clobbered;
! 515:
! 516: if (0 == p) return;
! 517: base = GC_base(p);
! 518: if (base == 0) {
! 519: GC_err_printf1("Attempt to free invalid pointer %lx\n",
! 520: (unsigned long)p);
! 521: ABORT("free(invalid pointer)");
! 522: }
! 523: if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
! 524: GC_err_printf1(
! 525: "GC_debug_free called on pointer %lx wo debugging info\n",
! 526: (unsigned long)p);
! 527: } else {
! 528: clobbered = GC_check_annotated_obj((oh *)base);
! 529: if (clobbered != 0) {
! 530: if (((oh *)base) -> oh_sz == GC_size(base)) {
! 531: GC_err_printf0(
! 532: "GC_debug_free: found previously deallocated (?) object at ");
! 533: } else {
! 534: GC_err_printf0("GC_debug_free: found smashed location at ");
! 535: }
! 536: GC_print_smashed_obj(p, clobbered);
! 537: }
! 538: /* Invalidate size */
! 539: ((oh *)base) -> oh_sz = GC_size(base);
! 540: }
! 541: if (GC_find_leak) {
! 542: GC_free(base);
! 543: } else {
! 544: register hdr * hhdr = HDR(p);
! 545: GC_bool uncollectable = FALSE;
! 546:
! 547: if (hhdr -> hb_obj_kind == UNCOLLECTABLE) {
! 548: uncollectable = TRUE;
! 549: }
! 550: # ifdef ATOMIC_UNCOLLECTABLE
! 551: if (hhdr -> hb_obj_kind == AUNCOLLECTABLE) {
! 552: uncollectable = TRUE;
! 553: }
! 554: # endif
! 555: if (uncollectable) GC_free(base);
! 556: } /* !GC_find_leak */
! 557: }
! 558:
! 559: # ifdef __STDC__
! 560: GC_PTR GC_debug_realloc(GC_PTR p, size_t lb, GC_EXTRA_PARAMS)
! 561: # else
! 562: GC_PTR GC_debug_realloc(p, lb, s, i)
! 563: GC_PTR p;
! 564: size_t lb;
! 565: char *s;
! 566: int i;
! 567: # endif
! 568: {
! 569: register GC_PTR base = GC_base(p);
! 570: register ptr_t clobbered;
! 571: register GC_PTR result;
! 572: register size_t copy_sz = lb;
! 573: register size_t old_sz;
! 574: register hdr * hhdr;
! 575:
! 576: if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i));
! 577: if (base == 0) {
! 578: GC_err_printf1(
! 579: "Attempt to reallocate invalid pointer %lx\n", (unsigned long)p);
! 580: ABORT("realloc(invalid pointer)");
! 581: }
! 582: if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
! 583: GC_err_printf1(
! 584: "GC_debug_realloc called on pointer %lx wo debugging info\n",
! 585: (unsigned long)p);
! 586: return(GC_realloc(p, lb));
! 587: }
! 588: hhdr = HDR(base);
! 589: switch (hhdr -> hb_obj_kind) {
! 590: # ifdef STUBBORN_ALLOC
! 591: case STUBBORN:
! 592: result = GC_debug_malloc_stubborn(lb, OPT_RA s, i);
! 593: break;
! 594: # endif
! 595: case NORMAL:
! 596: result = GC_debug_malloc(lb, OPT_RA s, i);
! 597: break;
! 598: case PTRFREE:
! 599: result = GC_debug_malloc_atomic(lb, OPT_RA s, i);
! 600: break;
! 601: case UNCOLLECTABLE:
! 602: result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i);
! 603: break;
! 604: # ifdef ATOMIC_UNCOLLECTABLE
! 605: case AUNCOLLECTABLE:
! 606: result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
! 607: break;
! 608: # endif
! 609: default:
! 610: GC_err_printf0("GC_debug_realloc: encountered bad kind\n");
! 611: ABORT("bad kind");
! 612: }
! 613: clobbered = GC_check_annotated_obj((oh *)base);
! 614: if (clobbered != 0) {
! 615: GC_err_printf0("GC_debug_realloc: found smashed location at ");
! 616: GC_print_smashed_obj(p, clobbered);
! 617: }
! 618: old_sz = ((oh *)base) -> oh_sz;
! 619: if (old_sz < copy_sz) copy_sz = old_sz;
! 620: if (result == 0) return(0);
! 621: BCOPY(p, result, copy_sz);
! 622: GC_debug_free(p);
! 623: return(result);
! 624: }
! 625:
! 626: /* Check all marked objects in the given block for validity */
! 627: /*ARGSUSED*/
! 628: void GC_check_heap_block(hbp, dummy)
! 629: register struct hblk *hbp; /* ptr to current heap block */
! 630: word dummy;
! 631: {
! 632: register struct hblkhdr * hhdr = HDR(hbp);
! 633: register word sz = hhdr -> hb_sz;
! 634: register int word_no;
! 635: register word *p, *plim;
! 636:
! 637: p = (word *)(hbp->hb_body);
! 638: word_no = HDR_WORDS;
! 639: if (sz > MAXOBJSZ) {
! 640: plim = p;
! 641: } else {
! 642: plim = (word *)((((word)hbp) + HBLKSIZE) - WORDS_TO_BYTES(sz));
! 643: }
! 644: /* go through all words in block */
! 645: while( p <= plim ) {
! 646: if( mark_bit_from_hdr(hhdr, word_no)
! 647: && GC_has_debug_info((ptr_t)p)) {
! 648: ptr_t clobbered = GC_check_annotated_obj((oh *)p);
! 649:
! 650: if (clobbered != 0) {
! 651: GC_err_printf0(
! 652: "GC_check_heap_block: found smashed location at ");
! 653: GC_print_smashed_obj((ptr_t)p, clobbered);
! 654: }
! 655: }
! 656: word_no += sz;
! 657: p += sz;
! 658: }
! 659: }
! 660:
! 661:
! 662: /* This assumes that all accessible objects are marked, and that */
! 663: /* I hold the allocation lock. Normally called by collector. */
! 664: void GC_check_heap_proc()
! 665: {
! 666: # ifndef SMALL_CONFIG
! 667: if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) {
! 668: ABORT("Alignment problem: object header has inappropriate size\n");
! 669: }
! 670: # endif
! 671: GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
! 672: }
! 673:
! 674: struct closure {
! 675: GC_finalization_proc cl_fn;
! 676: GC_PTR cl_data;
! 677: };
! 678:
! 679: # ifdef __STDC__
! 680: void * GC_make_closure(GC_finalization_proc fn, void * data)
! 681: # else
! 682: GC_PTR GC_make_closure(fn, data)
! 683: GC_finalization_proc fn;
! 684: GC_PTR data;
! 685: # endif
! 686: {
! 687: struct closure * result =
! 688: (struct closure *) GC_malloc(sizeof (struct closure));
! 689:
! 690: result -> cl_fn = fn;
! 691: result -> cl_data = data;
! 692: return((GC_PTR)result);
! 693: }
! 694:
! 695: # ifdef __STDC__
! 696: void GC_debug_invoke_finalizer(void * obj, void * data)
! 697: # else
! 698: void GC_debug_invoke_finalizer(obj, data)
! 699: char * obj;
! 700: char * data;
! 701: # endif
! 702: {
! 703: register struct closure * cl = (struct closure *) data;
! 704:
! 705: (*(cl -> cl_fn))((GC_PTR)((char *)obj + sizeof(oh)), cl -> cl_data);
! 706: }
! 707:
! 708:
! 709: # ifdef __STDC__
! 710: void GC_debug_register_finalizer(GC_PTR obj, GC_finalization_proc fn,
! 711: GC_PTR cd, GC_finalization_proc *ofn,
! 712: GC_PTR *ocd)
! 713: # else
! 714: void GC_debug_register_finalizer(obj, fn, cd, ofn, ocd)
! 715: GC_PTR obj;
! 716: GC_finalization_proc fn;
! 717: GC_PTR cd;
! 718: GC_finalization_proc *ofn;
! 719: GC_PTR *ocd;
! 720: # endif
! 721: {
! 722: ptr_t base = GC_base(obj);
! 723: if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
! 724: GC_err_printf1(
! 725: "GC_register_finalizer called with non-base-pointer 0x%lx\n",
! 726: obj);
! 727: }
! 728: GC_register_finalizer(base, GC_debug_invoke_finalizer,
! 729: GC_make_closure(fn,cd), ofn, ocd);
! 730: }
! 731:
! 732: # ifdef __STDC__
! 733: void GC_debug_register_finalizer_no_order
! 734: (GC_PTR obj, GC_finalization_proc fn,
! 735: GC_PTR cd, GC_finalization_proc *ofn,
! 736: GC_PTR *ocd)
! 737: # else
! 738: void GC_debug_register_finalizer_no_order
! 739: (obj, fn, cd, ofn, ocd)
! 740: GC_PTR obj;
! 741: GC_finalization_proc fn;
! 742: GC_PTR cd;
! 743: GC_finalization_proc *ofn;
! 744: GC_PTR *ocd;
! 745: # endif
! 746: {
! 747: ptr_t base = GC_base(obj);
! 748: if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
! 749: GC_err_printf1(
! 750: "GC_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
! 751: obj);
! 752: }
! 753: GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer,
! 754: GC_make_closure(fn,cd), ofn, ocd);
! 755: }
! 756:
! 757: # ifdef __STDC__
! 758: void GC_debug_register_finalizer_ignore_self
! 759: (GC_PTR obj, GC_finalization_proc fn,
! 760: GC_PTR cd, GC_finalization_proc *ofn,
! 761: GC_PTR *ocd)
! 762: # else
! 763: void GC_debug_register_finalizer_ignore_self
! 764: (obj, fn, cd, ofn, ocd)
! 765: GC_PTR obj;
! 766: GC_finalization_proc fn;
! 767: GC_PTR cd;
! 768: GC_finalization_proc *ofn;
! 769: GC_PTR *ocd;
! 770: # endif
! 771: {
! 772: ptr_t base = GC_base(obj);
! 773: if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
! 774: GC_err_printf1(
! 775: "GC_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
! 776: obj);
! 777: }
! 778: GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer,
! 779: GC_make_closure(fn,cd), ofn, ocd);
! 780: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>