* modified is included with the above copyright notice.
*/
-#include "config.h"
-
#include <errno.h>
#include <string.h>
#include "private/dbg_mlc.h"
-void GC_default_print_heap_obj_proc();
-GC_API void GC_register_finalizer_no_order
+void GC_default_print_heap_obj_proc(ptr_t p);
+GC_API void GC_CALL GC_register_finalizer_no_order
(void * obj, GC_finalization_proc fn, void * cd,
GC_finalization_proc *ofn, void * *ocd);
/* not necessarily inside a valid object. */
void *GC_generate_random_heap_address(void)
{
- int i;
- long heap_offset = RANDOM();
+ size_t i;
+ word heap_offset = RANDOM();
if (GC_heapsize > RAND_MAX) {
heap_offset *= RAND_MAX;
heap_offset += RANDOM();
GC_err_printf("No debug info in object: Can't find reference\n");
goto out;
}
- GC_err_printf("Reachable via %d levels of pointers from ",
- (unsigned long)i);
+ GC_err_printf("Reachable via %d levels of pointers from ", i);
switch(source) {
case GC_REFD_FROM_ROOT:
GC_err_printf("root at %p\n\n", base);
GC_print_heap_obj(GC_base(base));
GC_err_printf("\n");
break;
+ default:
+ GC_err_printf("INTERNAL ERROR: UNEXPECTED SOURCE!!!!\n");
+ goto out;
}
current = base;
}
register word * result = (word *)((oh *)p + 1);
DCL_LOCK_STATE;
- /* There is some argument that we should dissble signals here. */
- /* But that's expensive. And this way things should only appear */
- /* inconsistent while we're in the handler. */
LOCK();
GC_ASSERT(GC_size(p) >= sizeof(oh) + sz);
GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz)));
#ifdef DBG_HDRS_ALL
/* Store debugging info into p. Return displaced pointer. */
/* This version assumes we do hold the allocation lock. */
-ptr_t GC_store_debug_info_inner(ptr_t p, word sz, char *string, word integer)
+STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz, char *string,
+ word integer)
{
register word * result = (word *)((oh *)p + 1);
- /* There is some argument that we should disable signals here. */
- /* But that's expensive. And this way things should only appear */
- /* inconsistent while we're in the handler. */
GC_ASSERT(GC_size(p) >= sizeof(oh) + sz);
GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz)));
# ifdef KEEP_BACK_PTRS
/* Check the object with debugging info at ohdr */
/* return NIL if it's OK. Else return clobbered */
/* address. */
-ptr_t GC_check_annotated_obj(oh *ohdr)
+STATIC ptr_t GC_check_annotated_obj(oh *ohdr)
{
register ptr_t body = (ptr_t)(ohdr + 1);
register word gc_sz = GC_size((ptr_t)ohdr);
static GC_describe_type_fn GC_describe_type_fns[MAXOBJKINDS] = {0};
-void GC_register_describe_type_fn(int kind, GC_describe_type_fn fn)
+void GC_CALL GC_register_describe_type_fn(int kind, GC_describe_type_fn fn)
{
GC_describe_type_fns[kind] = fn;
}
/* Print a type description for the object whose client-visible address */
/* is p. */
-void GC_print_type(ptr_t p)
+STATIC void GC_print_type(ptr_t p)
{
hdr * hhdr = GC_find_header(p);
char buffer[GC_TYPE_DESCR_LEN + 1];
PRINT_CALL_CHAIN(ohdr);
}
-void GC_debug_print_heap_obj_proc(ptr_t p)
+STATIC void GC_debug_print_heap_obj_proc(ptr_t p)
{
GC_ASSERT(I_DONT_HOLD_LOCK());
if (GC_HAS_DEBUG_INFO(p)) {
/* Use GC_err_printf and friends to print a description of the object */
/* whose client-visible address is p, and which was smashed at */
/* clobbered_addr. */
-void GC_print_smashed_obj(ptr_t p, ptr_t clobbered_addr)
+STATIC void GC_print_smashed_obj(ptr_t p, ptr_t clobbered_addr)
{
register oh * ohdr = (oh *)GC_base(p);
GC_ASSERT(I_DONT_HOLD_LOCK());
- GC_err_printf("%p in or near object at %p(", clobbered_addr, p);
if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
|| ohdr -> oh_string == 0) {
- GC_err_printf("<smashed>, appr. sz = %ld)\n",
- (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
+ GC_err_printf(
+ "%p in or near object at %p(<smashed>, appr. sz = %lu)\n",
+ clobbered_addr, p,
+ (unsigned long)(GC_size((ptr_t)ohdr) - DEBUG_BYTES));
} else {
- if (ohdr -> oh_string[0] == '\0') {
- GC_err_puts("EMPTY(smashed?)");
- } else {
- GC_err_puts(ohdr -> oh_string);
- }
- GC_err_printf(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
- (unsigned long)(ohdr -> oh_sz));
+ GC_err_printf("%p in or near object at %p(%s:%lu, sz=%lu)\n",
+ clobbered_addr, p,
+ (word)(ohdr -> oh_string) < HBLKSIZE ? "(smashed string)" :
+ ohdr -> oh_string[0] == '\0' ? "EMPTY(smashed?)" :
+ ohdr -> oh_string,
+ (unsigned long)(ohdr -> oh_int),
+ (unsigned long)(ohdr -> oh_sz));
PRINT_CALL_CHAIN(ohdr);
}
}
#endif
-void GC_check_heap_proc (void);
-
-void GC_print_all_smashed_proc (void);
-
-void GC_do_nothing(void) {}
+#ifndef SHORT_DBG_HDRS
+ STATIC void GC_check_heap_proc (void);
+ STATIC void GC_print_all_smashed_proc (void);
+#else
+ STATIC void GC_do_nothing(void) {}
+#endif
void GC_start_debugging(void)
{
size_t GC_debug_header_size = sizeof(oh);
-void GC_debug_register_displacement(size_t offset)
+GC_API void GC_CALL GC_debug_register_displacement(size_t offset)
{
GC_register_displacement(offset);
GC_register_displacement((word)sizeof(oh) + offset);
}
-void * GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)
{
void * result = GC_malloc(lb + DEBUG_BYTES);
return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
-void * GC_debug_malloc_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_malloc_ignore_off_page(size_t lb,
+ GC_EXTRA_PARAMS)
{
void * result = GC_malloc_ignore_off_page(lb + DEBUG_BYTES);
return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
-void * GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb,
+ GC_EXTRA_PARAMS)
{
void * result = GC_malloc_atomic_ignore_off_page(lb + DEBUG_BYTES);
# endif
#ifdef STUBBORN_ALLOC
-void * GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
{
void * result = GC_malloc_stubborn(lb + DEBUG_BYTES);
return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
-void GC_debug_change_stubborn(void *p)
+GC_API void GC_CALL GC_debug_change_stubborn(void *p)
{
void * q = GC_base(p);
hdr * hhdr;
GC_change_stubborn(q);
}
-void GC_debug_end_stubborn_change(void *p)
+GC_API void GC_CALL GC_debug_end_stubborn_change(void *p)
{
register void * q = GC_base(p);
register hdr * hhdr;
#else /* !STUBBORN_ALLOC */
-void * GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
{
return GC_debug_malloc(lb, OPT_RA s, i);
}
-void GC_debug_change_stubborn(void *p)
+/*ARGSUSED*/
+GC_API void GC_CALL GC_debug_change_stubborn(void *p)
{
}
-void GC_debug_end_stubborn_change(void *p)
+/*ARGSUSED*/
+GC_API void GC_CALL GC_debug_end_stubborn_change(void *p)
{
}
#endif /* !STUBBORN_ALLOC */
-void * GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
{
void * result = GC_malloc_atomic(lb + DEBUG_BYTES);
return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
-char *GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
+GC_API char * GC_CALL GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
{
char *copy;
if (str == NULL) return NULL;
return copy;
}
-void * GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
{
void * result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
}
#endif /* ATOMIC_UNCOLLECTABLE */
-void GC_debug_free(void * p)
+GC_API void GC_CALL GC_debug_free(void * p)
{
ptr_t base;
- ptr_t clobbered;
+# ifndef SHORT_DBG_HDRS
+ ptr_t clobbered;
+# endif
if (0 == p) return;
base = GC_base(p);
}
if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
GC_err_printf(
- "GC_debug_free called on pointer %p wo debugging info\n", p);
+ "GC_debug_free called on pointer %p w/o debugging info\n", p);
} else {
# ifndef SHORT_DBG_HDRS
clobbered = GC_check_annotated_obj((oh *)base);
/* Used internally; we assume it's called correctly. */
void GC_debug_free_inner(void * p)
{
- GC_free_inner(GC_base(p));
+ ptr_t base = GC_base(p);
+ GC_ASSERT((ptr_t)p - (ptr_t)base == sizeof(oh));
+# ifndef SHORT_DBG_HDRS
+ /* Invalidate size */
+ ((oh *)base) -> oh_sz = GC_size(base);
+# endif
+ GC_free_inner(base);
}
#endif
-void * GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS)
+GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS)
{
- void * base = GC_base(p);
- ptr_t clobbered;
+ void * base;
+# ifndef SHORT_DBG_HDRS
+ ptr_t clobbered;
+# endif
void * result;
size_t copy_sz = lb;
size_t old_sz;
hdr * hhdr;
if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i));
+ base = GC_base(p);
if (base == 0) {
GC_err_printf("Attempt to reallocate invalid pointer %p\n", p);
ABORT("realloc(invalid pointer)");
}
if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
GC_err_printf(
- "GC_debug_realloc called on pointer %p wo debugging info\n", p);
+ "GC_debug_realloc called on pointer %p w/o debugging info\n", p);
return(GC_realloc(p, lb));
}
hhdr = HDR(base);
break;
# endif
default:
+ result = NULL; /* initialized to prevent warning. */
GC_err_printf("GC_debug_realloc: encountered bad kind\n");
ABORT("bad kind");
}
ptr_t GC_smashed[MAX_SMASHED];
unsigned GC_n_smashed = 0;
-void GC_add_smashed(ptr_t smashed)
+STATIC void GC_add_smashed(ptr_t smashed)
{
GC_ASSERT(GC_is_marked(GC_base(smashed)));
GC_smashed[GC_n_smashed] = smashed;
}
/* Print all objects on the list. Clear the list. */
-void GC_print_all_smashed_proc(void)
+STATIC void GC_print_all_smashed_proc(void)
{
unsigned i;
/* Check all marked objects in the given block for validity */
/* Avoid GC_apply_to_each_object for performance reasons. */
/*ARGSUSED*/
-void GC_check_heap_block(struct hblk *hbp, word dummy)
+STATIC void GC_check_heap_block(struct hblk *hbp, word dummy)
{
struct hblkhdr * hhdr = HDR(hbp);
size_t sz = hhdr -> hb_sz;
/* This assumes that all accessible objects are marked, and that */
/* I hold the allocation lock. Normally called by collector. */
-void GC_check_heap_proc(void)
+STATIC void GC_check_heap_proc(void)
{
# ifndef SMALL_CONFIG
- /* Ignore gcc no effect warning on the following. */
GC_STATIC_ASSERT((sizeof(oh) & (GRANULE_BYTES - 1)) == 0);
/* FIXME: Should we check for twice that alignment? */
# endif
return((void *)result);
}
-void GC_debug_invoke_finalizer(void * obj, void * data)
+void GC_CALLBACK GC_debug_invoke_finalizer(void * obj, void * data)
{
register struct closure * cl = (struct closure *) data;
}
}
-void GC_debug_register_finalizer(void * obj, GC_finalization_proc fn,
- void * cd, GC_finalization_proc *ofn,
- void * *ocd)
+GC_API void GC_CALL GC_debug_register_finalizer(void * obj,
+ GC_finalization_proc fn,
+ void * cd, GC_finalization_proc *ofn,
+ void * *ocd)
{
GC_finalization_proc my_old_fn;
void * my_old_cd;
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
-void GC_debug_register_finalizer_no_order
+GC_API void GC_CALL GC_debug_register_finalizer_no_order
(void * obj, GC_finalization_proc fn,
void * cd, GC_finalization_proc *ofn,
void * *ocd)
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
-void GC_debug_register_finalizer_unreachable
+GC_API void GC_CALL GC_debug_register_finalizer_unreachable
(void * obj, GC_finalization_proc fn,
void * cd, GC_finalization_proc *ofn,
void * *ocd)
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
-void GC_debug_register_finalizer_ignore_self
+GC_API void GC_CALL GC_debug_register_finalizer_ignore_self
(void * obj, GC_finalization_proc fn,
void * cd, GC_finalization_proc *ofn,
void * *ocd)
# define RA
#endif
-void * GC_debug_malloc_replacement(size_t lb)
+GC_API void * GC_CALL GC_debug_malloc_replacement(size_t lb)
{
return GC_debug_malloc(lb, RA "unknown", 0);
}
-void * GC_debug_realloc_replacement(void *p, size_t lb)
+GC_API void * GC_CALL GC_debug_realloc_replacement(void *p, size_t lb)
{
return GC_debug_realloc(p, lb, RA "unknown", 0);
}