[BACK]Return to dbg_mlc.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Annotation of OpenXM_contrib2/asir2000/gc/dbg_mlc.c, Revision 1.6

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.
1.4       noro        5:  * Copyright (c) 1999-2000 by Hewlett-Packard Company.  All rights reserved.
1.1       noro        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:  */
1.3       noro       16:
1.4       noro       17: #include "private/dbg_mlc.h"
1.1       noro       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:
1.4       noro       25: #ifndef SHORT_DBG_HDRS
1.1       noro       26: /* Check whether object with base pointer p has debugging info */
                     27: /* p is assumed to point to a legitimate object in our part    */
                     28: /* of the heap.                                                        */
1.6     ! noro       29: /* This excludes the check as to whether the back pointer is   */
1.4       noro       30: /* odd, which is added by the GC_HAS_DEBUG_INFO macro.         */
                     31: /* Note that if DBG_HDRS_ALL is set, uncollectable objects     */
                     32: /* on free lists may not have debug information set.  Thus it's        */
                     33: /* not always safe to return TRUE, even if the client does     */
                     34: /* its part.                                                   */
                     35: GC_bool GC_has_other_debug_info(p)
1.1       noro       36: ptr_t p;
                     37: {
                     38:     register oh * ohdr = (oh *)p;
                     39:     register ptr_t body = (ptr_t)(ohdr + 1);
                     40:     register word sz = GC_size((ptr_t) ohdr);
                     41:
                     42:     if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body)
1.6     ! noro       43:         || sz < DEBUG_BYTES + EXTRA_BYTES) {
1.1       noro       44:         return(FALSE);
                     45:     }
                     46:     if (ohdr -> oh_sz == sz) {
                     47:        /* Object may have had debug info, but has been deallocated     */
                     48:        return(FALSE);
                     49:     }
                     50:     if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE);
                     51:     if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) {
                     52:         return(TRUE);
                     53:     }
                     54:     return(FALSE);
                     55: }
1.4       noro       56: #endif
1.1       noro       57:
                     58: #ifdef KEEP_BACK_PTRS
1.4       noro       59:
                     60: # include <stdlib.h>
                     61:
                     62: # if defined(LINUX) || defined(SUNOS4) || defined(SUNOS5) \
                     63:      || defined(HPUX) || defined(IRIX) || defined(OSF1)
                     64: #   define RANDOM() random()
                     65: # else
                     66: #   define RANDOM() (long)rand()
                     67: # endif
                     68:
1.1       noro       69:   /* Store back pointer to source in dest, if that appears to be possible. */
                     70:   /* This is not completely safe, since we may mistakenly conclude that           */
                     71:   /* dest has a debugging wrapper.  But the error probability is very     */
                     72:   /* small, and this shouldn't be used in production code.                */
                     73:   /* We assume that dest is the real base pointer.  Source will usually    */
                     74:   /* be a pointer to the interior of an object.                                   */
                     75:   void GC_store_back_pointer(ptr_t source, ptr_t dest)
                     76:   {
1.4       noro       77:     if (GC_HAS_DEBUG_INFO(dest)) {
                     78:       ((oh *)dest) -> oh_back_ptr = HIDE_BACK_PTR(source);
1.1       noro       79:     }
                     80:   }
                     81:
                     82:   void GC_marked_for_finalization(ptr_t dest) {
                     83:     GC_store_back_pointer(MARKED_FOR_FINALIZATION, dest);
                     84:   }
                     85:
                     86:   /* Store information about the object referencing dest in *base_p    */
                     87:   /* and *offset_p.                                                    */
1.3       noro       88:   /*   source is root ==> *base_p = address, *offset_p = 0             */
1.1       noro       89:   /*   source is heap object ==> *base_p != 0, *offset_p = offset      */
                     90:   /*   Returns 1 on success, 0 if source couldn't be determined.       */
                     91:   /* Dest can be any address within a heap object.                     */
                     92:   GC_ref_kind GC_get_back_ptr_info(void *dest, void **base_p, size_t *offset_p)
                     93:   {
                     94:     oh * hdr = (oh *)GC_base(dest);
                     95:     ptr_t bp;
                     96:     ptr_t bp_base;
1.4       noro       97:     if (!GC_HAS_DEBUG_INFO((ptr_t) hdr)) return GC_NO_SPACE;
                     98:     bp = REVEAL_POINTER(hdr -> oh_back_ptr);
1.1       noro       99:     if (MARKED_FOR_FINALIZATION == bp) return GC_FINALIZER_REFD;
1.3       noro      100:     if (MARKED_FROM_REGISTER == bp) return GC_REFD_FROM_REG;
1.4       noro      101:     if (NOT_MARKED == bp) return GC_UNREFERENCED;
                    102: #   if ALIGNMENT == 1
                    103:       /* Heuristically try to fix off by 1 errors we introduced by     */
                    104:       /* insisting on even addresses.                                  */
                    105:       {
                    106:        ptr_t alternate_ptr = bp + 1;
                    107:        ptr_t target = *(ptr_t *)bp;
                    108:        ptr_t alternate_target = *(ptr_t *)alternate_ptr;
                    109:
                    110:        if (alternate_target >= GC_least_plausible_heap_addr
                    111:            && alternate_target <= GC_greatest_plausible_heap_addr
                    112:            && (target < GC_least_plausible_heap_addr
                    113:                || target > GC_greatest_plausible_heap_addr)) {
                    114:            bp = alternate_ptr;
                    115:        }
                    116:       }
                    117: #   endif
1.1       noro      118:     bp_base = GC_base(bp);
                    119:     if (0 == bp_base) {
                    120:       *base_p = bp;
                    121:       *offset_p = 0;
                    122:       return GC_REFD_FROM_ROOT;
                    123:     } else {
1.4       noro      124:       if (GC_HAS_DEBUG_INFO(bp_base)) bp_base += sizeof(oh);
1.1       noro      125:       *base_p = bp_base;
                    126:       *offset_p = bp - bp_base;
                    127:       return GC_REFD_FROM_HEAP;
                    128:     }
                    129:   }
                    130:
                    131:   /* Generate a random heap address.           */
                    132:   /* The resulting address is in the heap, but */
                    133:   /* not necessarily inside a valid object.    */
                    134:   void *GC_generate_random_heap_address(void)
                    135:   {
                    136:     int i;
1.4       noro      137:     long heap_offset = RANDOM();
                    138:     if (GC_heapsize > RAND_MAX) {
                    139:        heap_offset *= RAND_MAX;
                    140:        heap_offset += RANDOM();
                    141:     }
                    142:     heap_offset %= GC_heapsize;
                    143:        /* This doesn't yield a uniform distribution, especially if     */
                    144:         /* e.g. RAND_MAX = 1.5* GC_heapsize.  But for typical cases,   */
                    145:         /* it's not too bad.                                           */
1.1       noro      146:     for (i = 0; i < GC_n_heap_sects; ++ i) {
                    147:        int size = GC_heap_sects[i].hs_bytes;
                    148:        if (heap_offset < size) {
                    149:            return GC_heap_sects[i].hs_start + heap_offset;
                    150:        } else {
                    151:            heap_offset -= size;
                    152:        }
                    153:     }
                    154:     ABORT("GC_generate_random_heap_address: size inconsistency");
                    155:     /*NOTREACHED*/
                    156:     return 0;
                    157:   }
                    158:
                    159:   /* Generate a random address inside a valid marked heap object. */
                    160:   void *GC_generate_random_valid_address(void)
                    161:   {
                    162:     ptr_t result;
                    163:     ptr_t base;
                    164:     for (;;) {
                    165:        result = GC_generate_random_heap_address();
                    166:        base = GC_base(result);
                    167:        if (0 == base) continue;
                    168:        if (!GC_is_marked(base)) continue;
                    169:        return result;
                    170:     }
                    171:   }
                    172:
1.3       noro      173:   /* Print back trace for p */
                    174:   void GC_print_backtrace(void *p)
1.1       noro      175:   {
1.3       noro      176:     void *current = p;
1.1       noro      177:     int i;
1.3       noro      178:     GC_ref_kind source;
1.1       noro      179:     size_t offset;
1.3       noro      180:     void *base;
                    181:
1.1       noro      182:     GC_print_heap_obj(GC_base(current));
                    183:     GC_err_printf0("\n");
                    184:     for (i = 0; ; ++i) {
                    185:       source = GC_get_back_ptr_info(current, &base, &offset);
                    186:       if (GC_UNREFERENCED == source) {
                    187:        GC_err_printf0("Reference could not be found\n");
                    188:        goto out;
                    189:       }
                    190:       if (GC_NO_SPACE == source) {
                    191:        GC_err_printf0("No debug info in object: Can't find reference\n");
                    192:        goto out;
                    193:       }
                    194:       GC_err_printf1("Reachable via %d levels of pointers from ",
                    195:                 (unsigned long)i);
                    196:       switch(source) {
                    197:        case GC_REFD_FROM_ROOT:
                    198:          GC_err_printf1("root at 0x%lx\n", (unsigned long)base);
                    199:          goto out;
1.3       noro      200:        case GC_REFD_FROM_REG:
                    201:          GC_err_printf0("root in register\n");
                    202:          goto out;
1.1       noro      203:        case GC_FINALIZER_REFD:
                    204:          GC_err_printf0("list of finalizable objects\n");
                    205:          goto out;
                    206:        case GC_REFD_FROM_HEAP:
                    207:          GC_err_printf1("offset %ld in object:\n", (unsigned long)offset);
                    208:          /* Take GC_base(base) to get real base, i.e. header. */
                    209:          GC_print_heap_obj(GC_base(base));
                    210:          GC_err_printf0("\n");
                    211:          break;
                    212:       }
                    213:       current = base;
                    214:     }
                    215:     out:;
                    216:   }
1.3       noro      217:
                    218:   /* Force a garbage collection and generate a backtrace from a        */
                    219:   /* random heap address.                                      */
                    220:   void GC_generate_random_backtrace(void)
                    221:   {
                    222:     void * current;
                    223:     GC_gcollect();
                    224:     current = GC_generate_random_valid_address();
                    225:     GC_printf1("Chose address 0x%lx in object\n", (unsigned long)current);
                    226:     GC_print_backtrace(current);
                    227:   }
1.1       noro      228:
                    229: #endif /* KEEP_BACK_PTRS */
                    230:
                    231: /* Store debugging info into p.  Return displaced pointer. */
                    232: /* Assumes we don't hold allocation lock.                 */
                    233: ptr_t GC_store_debug_info(p, sz, string, integer)
                    234: register ptr_t p;      /* base pointer */
                    235: word sz;       /* bytes */
1.6     ! noro      236: GC_CONST char * string;
1.1       noro      237: word integer;
                    238: {
                    239:     register word * result = (word *)((oh *)p + 1);
                    240:     DCL_LOCK_STATE;
                    241:
                    242:     /* There is some argument that we should dissble signals here.     */
                    243:     /* But that's expensive.  And this way things should only appear   */
                    244:     /* inconsistent while we're in the handler.                                */
                    245:     LOCK();
                    246: #   ifdef KEEP_BACK_PTRS
1.4       noro      247:       ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
                    248: #   endif
1.6     ! noro      249: #   ifdef MAKE_BACK_GRAPH
        !           250:       ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0);
        !           251: #   endif
1.4       noro      252:     ((oh *)p) -> oh_string = string;
                    253:     ((oh *)p) -> oh_int = integer;
                    254: #   ifndef SHORT_DBG_HDRS
                    255:       ((oh *)p) -> oh_sz = sz;
                    256:       ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
                    257:       ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
1.6     ! noro      258:          result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
1.4       noro      259: #   endif
                    260:     UNLOCK();
                    261:     return((ptr_t)result);
                    262: }
                    263:
                    264: #ifdef DBG_HDRS_ALL
                    265: /* Store debugging info into p.  Return displaced pointer.        */
                    266: /* This version assumes we do hold the allocation lock.                   */
                    267: ptr_t GC_store_debug_info_inner(p, sz, string, integer)
                    268: register ptr_t p;      /* base pointer */
                    269: word sz;       /* bytes */
                    270: char * string;
                    271: word integer;
                    272: {
                    273:     register word * result = (word *)((oh *)p + 1);
                    274:
                    275:     /* There is some argument that we should disable signals here.     */
                    276:     /* But that's expensive.  And this way things should only appear   */
                    277:     /* inconsistent while we're in the handler.                                */
                    278: #   ifdef KEEP_BACK_PTRS
1.6     ! noro      279:       ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
        !           280: #   endif
        !           281: #   ifdef MAKE_BACK_GRAPH
        !           282:       ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0);
1.1       noro      283: #   endif
                    284:     ((oh *)p) -> oh_string = string;
                    285:     ((oh *)p) -> oh_int = integer;
1.4       noro      286: #   ifndef SHORT_DBG_HDRS
                    287:       ((oh *)p) -> oh_sz = sz;
                    288:       ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
                    289:       ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
1.6     ! noro      290:          result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
1.4       noro      291: #   endif
1.1       noro      292:     return((ptr_t)result);
                    293: }
1.4       noro      294: #endif
1.1       noro      295:
1.4       noro      296: #ifndef SHORT_DBG_HDRS
1.1       noro      297: /* Check the object with debugging info at ohdr                */
                    298: /* return NIL if it's OK.  Else return clobbered       */
                    299: /* address.                                            */
                    300: ptr_t GC_check_annotated_obj(ohdr)
                    301: register oh * ohdr;
                    302: {
                    303:     register ptr_t body = (ptr_t)(ohdr + 1);
                    304:     register word gc_sz = GC_size((ptr_t)ohdr);
                    305:     if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
                    306:         return((ptr_t)(&(ohdr -> oh_sz)));
                    307:     }
                    308:     if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
                    309:         return((ptr_t)(&(ohdr -> oh_sf)));
                    310:     }
                    311:     if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
                    312:         return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
                    313:     }
1.6     ! noro      314:     if (((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)]
1.1       noro      315:         != (END_FLAG ^ (word)body)) {
1.6     ! noro      316:         return((ptr_t)((word *)body + SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)));
1.1       noro      317:     }
                    318:     return(0);
                    319: }
1.4       noro      320: #endif /* !SHORT_DBG_HDRS */
1.1       noro      321:
                    322: void GC_print_obj(p)
                    323: ptr_t p;
                    324: {
                    325:     register oh * ohdr = (oh *)GC_base(p);
                    326:
1.6     ! noro      327:     GC_ASSERT(!I_HOLD_LOCK());
1.1       noro      328:     GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
                    329:     GC_err_puts(ohdr -> oh_string);
1.4       noro      330: #   ifdef SHORT_DBG_HDRS
1.6     ! noro      331:       GC_err_printf1(":%ld)\n", (unsigned long)(ohdr -> oh_int));
1.4       noro      332: #   else
                    333:       GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
                    334:                                        (unsigned long)(ohdr -> oh_sz));
                    335: #   endif
1.1       noro      336:     PRINT_CALL_CHAIN(ohdr);
                    337: }
                    338:
1.4       noro      339: # if defined(__STDC__) || defined(__cplusplus)
                    340:     void GC_debug_print_heap_obj_proc(ptr_t p)
                    341: # else
                    342:     void GC_debug_print_heap_obj_proc(p)
                    343:     ptr_t p;
                    344: # endif
1.1       noro      345: {
1.6     ! noro      346:     GC_ASSERT(!I_HOLD_LOCK());
1.4       noro      347:     if (GC_HAS_DEBUG_INFO(p)) {
1.1       noro      348:        GC_print_obj(p);
                    349:     } else {
                    350:        GC_default_print_heap_obj_proc(p);
                    351:     }
                    352: }
                    353:
1.4       noro      354: #ifndef SHORT_DBG_HDRS
1.1       noro      355: void GC_print_smashed_obj(p, clobbered_addr)
                    356: ptr_t p, clobbered_addr;
                    357: {
                    358:     register oh * ohdr = (oh *)GC_base(p);
                    359:
1.6     ! noro      360:     GC_ASSERT(!I_HOLD_LOCK());
1.1       noro      361:     GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
                    362:                                                (unsigned long)p);
                    363:     if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
                    364:         || ohdr -> oh_string == 0) {
                    365:         GC_err_printf1("<smashed>, appr. sz = %ld)\n",
                    366:                       (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
                    367:     } else {
                    368:         if (ohdr -> oh_string[0] == '\0') {
                    369:             GC_err_puts("EMPTY(smashed?)");
                    370:         } else {
                    371:             GC_err_puts(ohdr -> oh_string);
                    372:         }
                    373:         GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
                    374:                                          (unsigned long)(ohdr -> oh_sz));
                    375:         PRINT_CALL_CHAIN(ohdr);
                    376:     }
                    377: }
1.4       noro      378: #endif
1.1       noro      379:
1.4       noro      380: void GC_check_heap_proc GC_PROTO((void));
                    381:
1.6     ! noro      382: void GC_print_all_smashed_proc GC_PROTO((void));
        !           383:
1.4       noro      384: void GC_do_nothing() {}
1.1       noro      385:
                    386: void GC_start_debugging()
                    387: {
1.4       noro      388: #   ifndef SHORT_DBG_HDRS
                    389:       GC_check_heap = GC_check_heap_proc;
1.6     ! noro      390:       GC_print_all_smashed = GC_print_all_smashed_proc;
1.4       noro      391: #   else
                    392:       GC_check_heap = GC_do_nothing;
1.6     ! noro      393:       GC_print_all_smashed = GC_do_nothing;
1.4       noro      394: #   endif
1.1       noro      395:     GC_print_heap_obj = GC_debug_print_heap_obj_proc;
                    396:     GC_debugging_started = TRUE;
                    397:     GC_register_displacement((word)sizeof(oh));
                    398: }
                    399:
                    400: # if defined(__STDC__) || defined(__cplusplus)
                    401:     void GC_debug_register_displacement(GC_word offset)
                    402: # else
                    403:     void GC_debug_register_displacement(offset)
                    404:     GC_word offset;
                    405: # endif
                    406: {
                    407:     GC_register_displacement(offset);
                    408:     GC_register_displacement((word)sizeof(oh) + offset);
                    409: }
                    410:
                    411: # ifdef __STDC__
1.3       noro      412:     GC_PTR GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      413: # else
                    414:     GC_PTR GC_debug_malloc(lb, s, i)
                    415:     size_t lb;
                    416:     char * s;
                    417:     int i;
                    418: #   ifdef GC_ADD_CALLER
                    419:        --> GC_ADD_CALLER not implemented for K&R C
                    420: #   endif
                    421: # endif
                    422: {
                    423:     GC_PTR result = GC_malloc(lb + DEBUG_BYTES);
                    424:
                    425:     if (result == 0) {
                    426:         GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
                    427:                       (unsigned long) lb);
                    428:         GC_err_puts(s);
                    429:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    430:         return(0);
                    431:     }
                    432:     if (!GC_debugging_started) {
                    433:        GC_start_debugging();
                    434:     }
                    435:     ADD_CALL_CHAIN(result, ra);
                    436:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    437: }
                    438:
1.4       noro      439: # ifdef DBG_HDRS_ALL
                    440: /*
                    441:  * An allocation function for internal use.
                    442:  * Normally internally allocated objects do not have debug information.
                    443:  * But in this case, we need to make sure that all objects have debug
                    444:  * headers.
                    445:  * We assume debugging was started in collector initialization,
                    446:  * and we already hold the GC lock.
                    447:  */
                    448:   GC_PTR GC_debug_generic_malloc_inner(size_t lb, int k)
                    449:   {
                    450:     GC_PTR result = GC_generic_malloc_inner(lb + DEBUG_BYTES, k);
                    451:
                    452:     if (result == 0) {
                    453:         GC_err_printf1("GC internal allocation (%ld bytes) returning NIL\n",
                    454:                       (unsigned long) lb);
                    455:         return(0);
                    456:     }
                    457:     ADD_CALL_CHAIN(result, ra);
                    458:     return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0));
                    459:   }
                    460:
                    461:   GC_PTR GC_debug_generic_malloc_inner_ignore_off_page(size_t lb, int k)
                    462:   {
                    463:     GC_PTR result = GC_generic_malloc_inner_ignore_off_page(
                    464:                                                lb + DEBUG_BYTES, k);
                    465:
                    466:     if (result == 0) {
                    467:         GC_err_printf1("GC internal allocation (%ld bytes) returning NIL\n",
                    468:                       (unsigned long) lb);
                    469:         return(0);
                    470:     }
                    471:     ADD_CALL_CHAIN(result, ra);
                    472:     return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0));
                    473:   }
                    474: # endif
                    475:
1.1       noro      476: #ifdef STUBBORN_ALLOC
                    477: # ifdef __STDC__
1.3       noro      478:     GC_PTR GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      479: # else
                    480:     GC_PTR GC_debug_malloc_stubborn(lb, s, i)
                    481:     size_t lb;
                    482:     char * s;
                    483:     int i;
                    484: # endif
                    485: {
                    486:     GC_PTR result = GC_malloc_stubborn(lb + DEBUG_BYTES);
                    487:
                    488:     if (result == 0) {
                    489:         GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
                    490:                       (unsigned long) lb);
                    491:         GC_err_puts(s);
                    492:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    493:         return(0);
                    494:     }
                    495:     if (!GC_debugging_started) {
                    496:        GC_start_debugging();
                    497:     }
                    498:     ADD_CALL_CHAIN(result, ra);
                    499:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    500: }
                    501:
                    502: void GC_debug_change_stubborn(p)
                    503: GC_PTR p;
                    504: {
                    505:     register GC_PTR q = GC_base(p);
                    506:     register hdr * hhdr;
                    507:
                    508:     if (q == 0) {
                    509:         GC_err_printf1("Bad argument: 0x%lx to GC_debug_change_stubborn\n",
                    510:                       (unsigned long) p);
                    511:         ABORT("GC_debug_change_stubborn: bad arg");
                    512:     }
                    513:     hhdr = HDR(q);
                    514:     if (hhdr -> hb_obj_kind != STUBBORN) {
                    515:         GC_err_printf1("GC_debug_change_stubborn arg not stubborn: 0x%lx\n",
                    516:                       (unsigned long) p);
                    517:         ABORT("GC_debug_change_stubborn: arg not stubborn");
                    518:     }
                    519:     GC_change_stubborn(q);
                    520: }
                    521:
                    522: void GC_debug_end_stubborn_change(p)
                    523: GC_PTR p;
                    524: {
                    525:     register GC_PTR q = GC_base(p);
                    526:     register hdr * hhdr;
                    527:
                    528:     if (q == 0) {
                    529:         GC_err_printf1("Bad argument: 0x%lx to GC_debug_end_stubborn_change\n",
                    530:                       (unsigned long) p);
                    531:         ABORT("GC_debug_end_stubborn_change: bad arg");
                    532:     }
                    533:     hhdr = HDR(q);
                    534:     if (hhdr -> hb_obj_kind != STUBBORN) {
                    535:         GC_err_printf1("debug_end_stubborn_change arg not stubborn: 0x%lx\n",
                    536:                       (unsigned long) p);
                    537:         ABORT("GC_debug_end_stubborn_change: arg not stubborn");
                    538:     }
                    539:     GC_end_stubborn_change(q);
                    540: }
                    541:
1.3       noro      542: #else /* !STUBBORN_ALLOC */
                    543:
                    544: # ifdef __STDC__
                    545:     GC_PTR GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
                    546: # else
                    547:     GC_PTR GC_debug_malloc_stubborn(lb, s, i)
                    548:     size_t lb;
                    549:     char * s;
                    550:     int i;
                    551: # endif
                    552: {
                    553:     return GC_debug_malloc(lb, OPT_RA s, i);
                    554: }
                    555:
                    556: void GC_debug_change_stubborn(p)
                    557: GC_PTR p;
                    558: {
                    559: }
                    560:
                    561: void GC_debug_end_stubborn_change(p)
                    562: GC_PTR p;
                    563: {
                    564: }
                    565:
                    566: #endif /* !STUBBORN_ALLOC */
1.1       noro      567:
                    568: # ifdef __STDC__
1.3       noro      569:     GC_PTR GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      570: # else
                    571:     GC_PTR GC_debug_malloc_atomic(lb, s, i)
                    572:     size_t lb;
                    573:     char * s;
                    574:     int i;
                    575: # endif
                    576: {
                    577:     GC_PTR result = GC_malloc_atomic(lb + DEBUG_BYTES);
                    578:
                    579:     if (result == 0) {
                    580:         GC_err_printf1("GC_debug_malloc_atomic(%ld) returning NIL (",
                    581:                      (unsigned long) lb);
                    582:         GC_err_puts(s);
                    583:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    584:         return(0);
                    585:     }
                    586:     if (!GC_debugging_started) {
                    587:         GC_start_debugging();
                    588:     }
                    589:     ADD_CALL_CHAIN(result, ra);
                    590:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    591: }
                    592:
                    593: # ifdef __STDC__
1.3       noro      594:     GC_PTR GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      595: # else
                    596:     GC_PTR GC_debug_malloc_uncollectable(lb, s, i)
                    597:     size_t lb;
                    598:     char * s;
                    599:     int i;
                    600: # endif
                    601: {
1.6     ! noro      602:     GC_PTR result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
1.1       noro      603:
                    604:     if (result == 0) {
                    605:         GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (",
                    606:                      (unsigned long) lb);
                    607:         GC_err_puts(s);
                    608:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    609:         return(0);
                    610:     }
                    611:     if (!GC_debugging_started) {
                    612:         GC_start_debugging();
                    613:     }
                    614:     ADD_CALL_CHAIN(result, ra);
                    615:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    616: }
                    617:
                    618: #ifdef ATOMIC_UNCOLLECTABLE
                    619: # ifdef __STDC__
1.3       noro      620:     GC_PTR GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      621: # else
                    622:     GC_PTR GC_debug_malloc_atomic_uncollectable(lb, s, i)
                    623:     size_t lb;
                    624:     char * s;
                    625:     int i;
                    626: # endif
                    627: {
1.6     ! noro      628:     GC_PTR result =
        !           629:        GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
1.1       noro      630:
                    631:     if (result == 0) {
                    632:         GC_err_printf1(
                    633:                "GC_debug_malloc_atomic_uncollectable(%ld) returning NIL (",
                    634:                 (unsigned long) lb);
                    635:         GC_err_puts(s);
                    636:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    637:         return(0);
                    638:     }
                    639:     if (!GC_debugging_started) {
                    640:         GC_start_debugging();
                    641:     }
                    642:     ADD_CALL_CHAIN(result, ra);
                    643:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    644: }
                    645: #endif /* ATOMIC_UNCOLLECTABLE */
                    646:
                    647: # ifdef __STDC__
                    648:     void GC_debug_free(GC_PTR p)
                    649: # else
                    650:     void GC_debug_free(p)
                    651:     GC_PTR p;
                    652: # endif
                    653: {
1.2       noro      654:     register GC_PTR base;
1.1       noro      655:     register ptr_t clobbered;
                    656:
1.2       noro      657:     if (0 == p) return;
                    658:     base = GC_base(p);
1.1       noro      659:     if (base == 0) {
                    660:         GC_err_printf1("Attempt to free invalid pointer %lx\n",
                    661:                       (unsigned long)p);
1.2       noro      662:         ABORT("free(invalid pointer)");
1.1       noro      663:     }
                    664:     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
                    665:         GC_err_printf1(
                    666:                  "GC_debug_free called on pointer %lx wo debugging info\n",
                    667:                  (unsigned long)p);
                    668:     } else {
1.4       noro      669: #     ifndef SHORT_DBG_HDRS
                    670:         clobbered = GC_check_annotated_obj((oh *)base);
                    671:         if (clobbered != 0) {
                    672:           if (((oh *)base) -> oh_sz == GC_size(base)) {
1.1       noro      673:             GC_err_printf0(
                    674:                   "GC_debug_free: found previously deallocated (?) object at ");
1.4       noro      675:           } else {
1.1       noro      676:             GC_err_printf0("GC_debug_free: found smashed location at ");
1.4       noro      677:           }
                    678:           GC_print_smashed_obj(p, clobbered);
1.1       noro      679:         }
1.4       noro      680:         /* Invalidate size */
                    681:         ((oh *)base) -> oh_sz = GC_size(base);
                    682: #     endif /* SHORT_DBG_HDRS */
1.1       noro      683:     }
1.2       noro      684:     if (GC_find_leak) {
1.1       noro      685:         GC_free(base);
1.2       noro      686:     } else {
                    687:        register hdr * hhdr = HDR(p);
                    688:        GC_bool uncollectable = FALSE;
1.1       noro      689:
1.2       noro      690:         if (hhdr ->  hb_obj_kind == UNCOLLECTABLE) {
                    691:            uncollectable = TRUE;
                    692:        }
                    693: #      ifdef ATOMIC_UNCOLLECTABLE
                    694:            if (hhdr ->  hb_obj_kind == AUNCOLLECTABLE) {
                    695:                    uncollectable = TRUE;
1.1       noro      696:            }
1.2       noro      697: #      endif
                    698:        if (uncollectable) GC_free(base);
                    699:     } /* !GC_find_leak */
1.1       noro      700: }
                    701:
1.4       noro      702: #ifdef THREADS
                    703:
                    704: extern void GC_free_inner(GC_PTR p);
                    705:
                    706: /* Used internally; we assume it's called correctly.   */
                    707: void GC_debug_free_inner(GC_PTR p)
                    708: {
                    709:     GC_free_inner(GC_base(p));
                    710: }
                    711: #endif
                    712:
1.1       noro      713: # ifdef __STDC__
1.3       noro      714:     GC_PTR GC_debug_realloc(GC_PTR p, size_t lb, GC_EXTRA_PARAMS)
1.1       noro      715: # else
                    716:     GC_PTR GC_debug_realloc(p, lb, s, i)
                    717:     GC_PTR p;
                    718:     size_t lb;
                    719:     char *s;
                    720:     int i;
                    721: # endif
                    722: {
                    723:     register GC_PTR base = GC_base(p);
                    724:     register ptr_t clobbered;
                    725:     register GC_PTR result;
                    726:     register size_t copy_sz = lb;
                    727:     register size_t old_sz;
                    728:     register hdr * hhdr;
                    729:
                    730:     if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i));
                    731:     if (base == 0) {
                    732:         GC_err_printf1(
                    733:               "Attempt to reallocate invalid pointer %lx\n", (unsigned long)p);
                    734:         ABORT("realloc(invalid pointer)");
                    735:     }
                    736:     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
                    737:         GC_err_printf1(
                    738:                "GC_debug_realloc called on pointer %lx wo debugging info\n",
                    739:                (unsigned long)p);
                    740:         return(GC_realloc(p, lb));
                    741:     }
                    742:     hhdr = HDR(base);
                    743:     switch (hhdr -> hb_obj_kind) {
                    744: #    ifdef STUBBORN_ALLOC
                    745:       case STUBBORN:
                    746:         result = GC_debug_malloc_stubborn(lb, OPT_RA s, i);
                    747:         break;
                    748: #    endif
                    749:       case NORMAL:
                    750:         result = GC_debug_malloc(lb, OPT_RA s, i);
                    751:         break;
                    752:       case PTRFREE:
                    753:         result = GC_debug_malloc_atomic(lb, OPT_RA s, i);
                    754:         break;
                    755:       case UNCOLLECTABLE:
                    756:        result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i);
                    757:        break;
                    758: #    ifdef ATOMIC_UNCOLLECTABLE
                    759:       case AUNCOLLECTABLE:
                    760:        result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
                    761:        break;
                    762: #    endif
                    763:       default:
                    764:         GC_err_printf0("GC_debug_realloc: encountered bad kind\n");
                    765:         ABORT("bad kind");
                    766:     }
1.4       noro      767: #   ifdef SHORT_DBG_HDRS
                    768:       old_sz = GC_size(base) - sizeof(oh);
                    769: #   else
                    770:       clobbered = GC_check_annotated_obj((oh *)base);
                    771:       if (clobbered != 0) {
1.1       noro      772:         GC_err_printf0("GC_debug_realloc: found smashed location at ");
                    773:         GC_print_smashed_obj(p, clobbered);
1.4       noro      774:       }
                    775:       old_sz = ((oh *)base) -> oh_sz;
                    776: #   endif
1.1       noro      777:     if (old_sz < copy_sz) copy_sz = old_sz;
                    778:     if (result == 0) return(0);
                    779:     BCOPY(p, result,  copy_sz);
                    780:     GC_debug_free(p);
                    781:     return(result);
                    782: }
                    783:
1.4       noro      784: #ifndef SHORT_DBG_HDRS
1.6     ! noro      785:
        !           786: /* List of smashed objects.  We defer printing these, since we can't   */
        !           787: /* always print them nicely with the allocation lock held.             */
        !           788: /* We put them here instead of in GC_arrays, since it may be useful to */
        !           789: /* be able to look at them with the debugger.                          */
        !           790: #define MAX_SMASHED 20
        !           791: ptr_t GC_smashed[MAX_SMASHED];
        !           792: unsigned GC_n_smashed = 0;
        !           793:
        !           794: # if defined(__STDC__) || defined(__cplusplus)
        !           795:     void GC_add_smashed(ptr_t smashed)
        !           796: # else
        !           797:     void GC_add_smashed(smashed)
        !           798:     ptr_t smashed;
        !           799: #endif
        !           800: {
        !           801:     GC_smashed[GC_n_smashed] = smashed;
        !           802:     if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed;
        !           803: }
        !           804:
        !           805: /* Print all objects on the list.  Clear the list.     */
        !           806: void GC_print_all_smashed_proc ()
        !           807: {
        !           808:     int i;
        !           809:
        !           810:     GC_ASSERT(!I_HOLD_LOCK());
        !           811:     if (GC_n_smashed == 0) return;
        !           812:     GC_err_printf0("GC_check_heap_block: found smashed heap objects:\n");
        !           813:     for (i = 0; i < GC_n_smashed; ++i) {
        !           814:         GC_print_smashed_obj(GC_base(GC_smashed[i]), GC_smashed[i]);
        !           815:        GC_smashed[i] = 0;
        !           816:     }
        !           817:     GC_n_smashed = 0;
        !           818: }
        !           819:
1.1       noro      820: /* Check all marked objects in the given block for validity */
                    821: /*ARGSUSED*/
1.4       noro      822: # if defined(__STDC__) || defined(__cplusplus)
                    823:     void GC_check_heap_block(register struct hblk *hbp, word dummy)
                    824: # else
                    825:     void GC_check_heap_block(hbp, dummy)
                    826:     register struct hblk *hbp; /* ptr to current heap block            */
                    827:     word dummy;
                    828: # endif
1.1       noro      829: {
                    830:     register struct hblkhdr * hhdr = HDR(hbp);
                    831:     register word sz = hhdr -> hb_sz;
                    832:     register int word_no;
                    833:     register word *p, *plim;
                    834:
                    835:     p = (word *)(hbp->hb_body);
1.4       noro      836:     word_no = 0;
1.1       noro      837:     if (sz > MAXOBJSZ) {
                    838:        plim = p;
                    839:     } else {
                    840:        plim = (word *)((((word)hbp) + HBLKSIZE) - WORDS_TO_BYTES(sz));
                    841:     }
                    842:     /* go through all words in block */
                    843:        while( p <= plim ) {
                    844:            if( mark_bit_from_hdr(hhdr, word_no)
1.4       noro      845:                && GC_HAS_DEBUG_INFO((ptr_t)p)) {
1.1       noro      846:                ptr_t clobbered = GC_check_annotated_obj((oh *)p);
                    847:
1.6     ! noro      848:                if (clobbered != 0) GC_add_smashed(clobbered);
1.1       noro      849:            }
                    850:            word_no += sz;
                    851:            p += sz;
                    852:        }
                    853: }
                    854:
                    855:
                    856: /* This assumes that all accessible objects are marked, and that       */
                    857: /* I hold the allocation lock. Normally called by collector.           */
                    858: void GC_check_heap_proc()
                    859: {
                    860: #   ifndef SMALL_CONFIG
                    861:        if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) {
                    862:            ABORT("Alignment problem: object header has inappropriate size\n");
                    863:        }
                    864: #   endif
                    865:     GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
                    866: }
                    867:
1.4       noro      868: #endif /* !SHORT_DBG_HDRS */
                    869:
1.1       noro      870: struct closure {
                    871:     GC_finalization_proc cl_fn;
                    872:     GC_PTR cl_data;
                    873: };
                    874:
                    875: # ifdef __STDC__
                    876:     void * GC_make_closure(GC_finalization_proc fn, void * data)
                    877: # else
                    878:     GC_PTR GC_make_closure(fn, data)
                    879:     GC_finalization_proc fn;
                    880:     GC_PTR data;
                    881: # endif
                    882: {
                    883:     struct closure * result =
1.4       noro      884: #              ifdef DBG_HDRS_ALL
                    885:                  (struct closure *) GC_debug_malloc(sizeof (struct closure),
                    886:                                                     GC_EXTRAS);
                    887: #              else
                    888:                  (struct closure *) GC_malloc(sizeof (struct closure));
                    889: #              endif
1.1       noro      890:
                    891:     result -> cl_fn = fn;
                    892:     result -> cl_data = data;
                    893:     return((GC_PTR)result);
                    894: }
                    895:
                    896: # ifdef __STDC__
                    897:     void GC_debug_invoke_finalizer(void * obj, void * data)
                    898: # else
                    899:     void GC_debug_invoke_finalizer(obj, data)
                    900:     char * obj;
                    901:     char * data;
                    902: # endif
                    903: {
                    904:     register struct closure * cl = (struct closure *) data;
                    905:
                    906:     (*(cl -> cl_fn))((GC_PTR)((char *)obj + sizeof(oh)), cl -> cl_data);
                    907: }
                    908:
1.6     ! noro      909: /* Set ofn and ocd to reflect the values we got back.  */
        !           910: static void store_old (obj, my_old_fn, my_old_cd, ofn, ocd)
        !           911: GC_PTR obj;
        !           912: GC_finalization_proc my_old_fn;
        !           913: struct closure * my_old_cd;
        !           914: GC_finalization_proc *ofn;
        !           915: GC_PTR *ocd;
        !           916: {
        !           917:     if (0 != my_old_fn) {
        !           918:       if (my_old_fn != GC_debug_invoke_finalizer) {
        !           919:         GC_err_printf1("Debuggable object at 0x%lx had non-debug finalizer.\n",
        !           920:                       obj);
        !           921:         /* This should probably be fatal. */
        !           922:       } else {
        !           923:         if (ofn) *ofn = my_old_cd -> cl_fn;
        !           924:         if (ocd) *ocd = my_old_cd -> cl_data;
        !           925:       }
        !           926:     } else {
        !           927:       if (ofn) *ofn = 0;
        !           928:       if (ocd) *ocd = 0;
        !           929:     }
        !           930: }
1.1       noro      931:
                    932: # ifdef __STDC__
                    933:     void GC_debug_register_finalizer(GC_PTR obj, GC_finalization_proc fn,
                    934:                                     GC_PTR cd, GC_finalization_proc *ofn,
                    935:                                     GC_PTR *ocd)
                    936: # else
                    937:     void GC_debug_register_finalizer(obj, fn, cd, ofn, ocd)
                    938:     GC_PTR obj;
                    939:     GC_finalization_proc fn;
                    940:     GC_PTR cd;
                    941:     GC_finalization_proc *ofn;
                    942:     GC_PTR *ocd;
                    943: # endif
                    944: {
1.6     ! noro      945:     GC_finalization_proc my_old_fn;
        !           946:     GC_PTR my_old_cd;
1.1       noro      947:     ptr_t base = GC_base(obj);
                    948:     if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
                    949:         GC_err_printf1(
                    950:            "GC_register_finalizer called with non-base-pointer 0x%lx\n",
                    951:            obj);
                    952:     }
1.6     ! noro      953:     if (0 == fn) {
        !           954:       GC_register_finalizer(base, 0, 0, &my_old_fn, &my_old_cd);
        !           955:     } else {
        !           956:       GC_register_finalizer(base, GC_debug_invoke_finalizer,
        !           957:                            GC_make_closure(fn,cd), &my_old_fn, &my_old_cd);
        !           958:     }
        !           959:     store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
1.1       noro      960: }
                    961:
                    962: # ifdef __STDC__
                    963:     void GC_debug_register_finalizer_no_order
                    964:                                    (GC_PTR obj, GC_finalization_proc fn,
                    965:                                     GC_PTR cd, GC_finalization_proc *ofn,
                    966:                                     GC_PTR *ocd)
                    967: # else
                    968:     void GC_debug_register_finalizer_no_order
                    969:                                    (obj, fn, cd, ofn, ocd)
                    970:     GC_PTR obj;
                    971:     GC_finalization_proc fn;
                    972:     GC_PTR cd;
                    973:     GC_finalization_proc *ofn;
                    974:     GC_PTR *ocd;
                    975: # endif
                    976: {
1.6     ! noro      977:     GC_finalization_proc my_old_fn;
        !           978:     GC_PTR my_old_cd;
1.1       noro      979:     ptr_t base = GC_base(obj);
                    980:     if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
                    981:         GC_err_printf1(
                    982:          "GC_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
                    983:          obj);
                    984:     }
1.6     ! noro      985:     if (0 == fn) {
        !           986:       GC_register_finalizer_no_order(base, 0, 0, &my_old_fn, &my_old_cd);
        !           987:     } else {
        !           988:       GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer,
        !           989:                                     GC_make_closure(fn,cd), &my_old_fn,
        !           990:                                     &my_old_cd);
        !           991:     }
        !           992:     store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
1.1       noro      993:  }
                    994:
                    995: # ifdef __STDC__
                    996:     void GC_debug_register_finalizer_ignore_self
                    997:                                    (GC_PTR obj, GC_finalization_proc fn,
                    998:                                     GC_PTR cd, GC_finalization_proc *ofn,
                    999:                                     GC_PTR *ocd)
                   1000: # else
                   1001:     void GC_debug_register_finalizer_ignore_self
                   1002:                                    (obj, fn, cd, ofn, ocd)
                   1003:     GC_PTR obj;
                   1004:     GC_finalization_proc fn;
                   1005:     GC_PTR cd;
                   1006:     GC_finalization_proc *ofn;
                   1007:     GC_PTR *ocd;
                   1008: # endif
                   1009: {
1.6     ! noro     1010:     GC_finalization_proc my_old_fn;
        !          1011:     GC_PTR my_old_cd;
1.1       noro     1012:     ptr_t base = GC_base(obj);
                   1013:     if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
                   1014:         GC_err_printf1(
                   1015:            "GC_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
                   1016:            obj);
                   1017:     }
1.6     ! noro     1018:     if (0 == fn) {
        !          1019:       GC_register_finalizer_ignore_self(base, 0, 0, &my_old_fn, &my_old_cd);
        !          1020:     } else {
        !          1021:       GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer,
        !          1022:                                     GC_make_closure(fn,cd), &my_old_fn,
        !          1023:                                     &my_old_cd);
        !          1024:     }
        !          1025:     store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
1.4       noro     1026: }
                   1027:
1.6     ! noro     1028: #ifdef GC_ADD_CALLER
        !          1029: # define RA GC_RETURN_ADDR,
        !          1030: #else
        !          1031: # define RA
        !          1032: #endif
        !          1033:
1.4       noro     1034: GC_PTR GC_debug_malloc_replacement(lb)
                   1035: size_t lb;
                   1036: {
1.6     ! noro     1037:     return GC_debug_malloc(lb, RA "unknown", 0);
1.4       noro     1038: }
                   1039:
                   1040: GC_PTR GC_debug_realloc_replacement(p, lb)
                   1041: GC_PTR p;
                   1042: size_t lb;
                   1043: {
1.6     ! noro     1044:     return GC_debug_realloc(p, lb, RA "unknown", 0);
1.1       noro     1045: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>