summaryrefslogtreecommitdiff
path: root/boehm-gc/dbg_mlc.c
diff options
context:
space:
mode:
Diffstat (limited to 'boehm-gc/dbg_mlc.c')
-rw-r--r--boehm-gc/dbg_mlc.c98
1 files changed, 85 insertions, 13 deletions
diff --git a/boehm-gc/dbg_mlc.c b/boehm-gc/dbg_mlc.c
index f640930d901..aacbb7a1b63 100644
--- a/boehm-gc/dbg_mlc.c
+++ b/boehm-gc/dbg_mlc.c
@@ -2,7 +2,7 @@
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright (c) 1997 by Silicon Graphics. All rights reserved.
- * Copyright (c) 1999-2000 by Hewlett-Packard Company. All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
@@ -195,13 +195,13 @@ ptr_t p;
(unsigned long)i);
switch(source) {
case GC_REFD_FROM_ROOT:
- GC_err_printf1("root at 0x%lx\n", (unsigned long)base);
+ GC_err_printf1("root at 0x%lx\n\n", (unsigned long)base);
goto out;
case GC_REFD_FROM_REG:
- GC_err_printf0("root in register\n");
+ GC_err_printf0("root in register\n\n");
goto out;
case GC_FINALIZER_REFD:
- GC_err_printf0("list of finalizable objects\n");
+ GC_err_printf0("list of finalizable objects\n\n");
goto out;
case GC_REFD_FROM_HEAP:
GC_err_printf1("offset %ld in object:\n", (unsigned long)offset);
@@ -217,15 +217,20 @@ ptr_t p;
/* Force a garbage collection and generate a backtrace from a */
/* random heap address. */
- void GC_generate_random_backtrace(void)
+ void GC_generate_random_backtrace_no_gc(void)
{
void * current;
- GC_gcollect();
current = GC_generate_random_valid_address();
- GC_printf1("Chose address 0x%lx in object\n", (unsigned long)current);
+ GC_printf1("\n****Chose address 0x%lx in object\n", (unsigned long)current);
GC_print_backtrace(current);
}
+ void GC_generate_random_backtrace(void)
+ {
+ GC_gcollect();
+ GC_generate_random_backtrace_no_gc();
+ }
+
#endif /* KEEP_BACK_PTRS */
# define CROSSES_HBLK(p, sz) \
@@ -325,6 +330,58 @@ register oh * ohdr;
}
#endif /* !SHORT_DBG_HDRS */
+static GC_describe_type_fn GC_describe_type_fns[MAXOBJKINDS] = {0};
+
+void GC_register_describe_type_fn(kind, 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(p)
+ptr_t p;
+{
+ hdr * hhdr = GC_find_header(p);
+ char buffer[GC_TYPE_DESCR_LEN + 1];
+ int kind = hhdr -> hb_obj_kind;
+
+ if (0 != GC_describe_type_fns[kind] && GC_is_marked(GC_base(p))) {
+ /* This should preclude free list objects except with */
+ /* thread-local allocation. */
+ buffer[GC_TYPE_DESCR_LEN] = 0;
+ (GC_describe_type_fns[kind])(p, buffer);
+ GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0);
+ GC_err_puts(buffer);
+ } else {
+ switch(kind) {
+ case PTRFREE:
+ GC_err_puts("PTRFREE");
+ break;
+ case NORMAL:
+ GC_err_puts("NORMAL");
+ break;
+ case UNCOLLECTABLE:
+ GC_err_puts("UNCOLLECTABLE");
+ break;
+# ifdef ATOMIC_UNCOLLECTABLE
+ case AUNCOLLECTABLE:
+ GC_err_puts("ATOMIC UNCOLLECTABLE");
+ break;
+# endif
+ case STUBBORN:
+ GC_err_puts("STUBBORN");
+ break;
+ default:
+ GC_err_printf2("kind %ld, descr 0x%lx", kind, hhdr -> hb_descr);
+ }
+ }
+}
+
+
+
void GC_print_obj(p)
ptr_t p;
{
@@ -334,11 +391,13 @@ ptr_t p;
GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
GC_err_puts(ohdr -> oh_string);
# ifdef SHORT_DBG_HDRS
- GC_err_printf1(":%ld)\n", (unsigned long)(ohdr -> oh_int));
+ GC_err_printf1(":%ld, ", (unsigned long)(ohdr -> oh_int));
# else
- GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
+ GC_err_printf2(":%ld, sz=%ld, ", (unsigned long)(ohdr -> oh_int),
(unsigned long)(ohdr -> oh_sz));
# endif
+ GC_print_type((ptr_t)(ohdr + 1));
+ GC_err_puts(")\n");
PRINT_CALL_CHAIN(ohdr);
}
@@ -403,6 +462,8 @@ void GC_start_debugging()
GC_register_displacement((word)sizeof(oh));
}
+size_t GC_debug_header_size = sizeof(oh);
+
# if defined(__STDC__) || defined(__cplusplus)
void GC_debug_register_displacement(GC_word offset)
# else
@@ -757,7 +818,15 @@ GC_PTR p;
uncollectable = TRUE;
}
# endif
- if (uncollectable) GC_free(base);
+ if (uncollectable) {
+ GC_free(base);
+ } else {
+ size_t i;
+ size_t obj_sz = hhdr -> hb_sz - BYTES_TO_WORDS(sizeof(oh));
+
+ for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef;
+ GC_ASSERT((word *)p + i == (word *)base + hhdr -> hb_sz);
+ }
} /* !GC_find_leak */
}
@@ -1013,7 +1082,8 @@ GC_PTR *ocd;
GC_finalization_proc my_old_fn;
GC_PTR my_old_cd;
ptr_t base = GC_base(obj);
- if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
+ if (0 == base) return;
+ if ((ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1(
"GC_debug_register_finalizer called with non-base-pointer 0x%lx\n",
obj);
@@ -1045,7 +1115,8 @@ GC_PTR *ocd;
GC_finalization_proc my_old_fn;
GC_PTR my_old_cd;
ptr_t base = GC_base(obj);
- if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
+ if (0 == base) return;
+ if ((ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1(
"GC_debug_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
obj);
@@ -1078,7 +1149,8 @@ GC_PTR *ocd;
GC_finalization_proc my_old_fn;
GC_PTR my_old_cd;
ptr_t base = GC_base(obj);
- if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
+ if (0 == base) return;
+ if ((ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1(
"GC_debug_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
obj);