diff options
author | ivmai <ivmai> | 2011-05-06 04:43:49 +0000 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-26 21:06:58 +0400 |
commit | 9d99463219d3125e87c7a07cf6aba5624e16aae6 (patch) | |
tree | 5202a4816a9a04ac8fa7b8ed64dbebf238b90cfa /dbg_mlc.c | |
parent | b898fa85675826496de2c476276ff8ca4af756bf (diff) | |
download | bdwgc-9d99463219d3125e87c7a07cf6aba5624e16aae6.tar.gz |
2011-05-06 Ivan Maidanski <ivmai@mail.ru>
* dbg_mlc.c (GC_has_other_debug_info): Change return type to int;
return -1 if the object has (or had) debugging info but was
marked deallocated.
* include/private/dbg_mlc.h (GC_has_other_debug_info): Ditto.
* dbg_mlc.c (GC_has_other_debug_info): Update documentation;
remove "ohdr" local variable.
* dbg_mlc.c (GC_debug_free): Don't call GC_free if the object has
probably been deallocated.
* dbg_mlc.c (GC_debug_free): Don't actually free the object even
in the leak-finding mode if GC_findleak_delay_free.
* dbg_mlc.c (GC_print_all_smashed_proc): Print a trailing blank
line.
* dbg_mlc.c (GC_check_leaked): New function (only unless
SHORT_DBG_HDRS).
* doc/README.environment (GC_FINDLEAK_DELAY_FREE): Document.
* doc/README.macros (GC_FINDLEAK_DELAY_FREE): Ditto.
* include/private/dbg_mlc.h (START_FLAG, END_FLAG): Use GC_WORD_C
on 64-bit architectures.
* include/private/dbg_mlc.h (NOT_MARKED): Remove redundant
parentheses.
* include/private/dbg_mlc.h (GC_HAS_DEBUG_INFO): Update (due to
GC_has_other_debug_info change).
* include/private/gc_priv.h (GC_findleak_delay_free): New global
variable declaration (unless SHORT_DBG_HDRS).
* misc.c (GC_findleak_delay_free): New global variable; recognize
GC_FINDLEAK_DELAY_FREE.
* misc.c (GC_init): Recognize GC_FINDLEAK_DELAY_FREE environment
variable (unless SHORT_DBG_HDRS).
* reclaim.c (GC_check_leaked): Declare (unless SHORT_DBG_HDRS).
* reclaim.c (GC_add_leaked): Don't add the object to leaked list
if marked as deallocated.
Diffstat (limited to 'dbg_mlc.c')
-rw-r--r-- | dbg_mlc.c | 78 |
1 files changed, 57 insertions, 21 deletions
@@ -32,27 +32,27 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p); /* odd, which is added by the GC_HAS_DEBUG_INFO macro. */ /* Note that if DBG_HDRS_ALL is set, uncollectable objects */ /* on free lists may not have debug information set. Thus it's */ - /* not always safe to return TRUE, even if the client does */ - /* its part. */ - GC_INNER GC_bool GC_has_other_debug_info(ptr_t p) + /* not always safe to return TRUE (1), even if the client does */ + /* its part. Return -1 if the object with debug info has been */ + /* marked as deallocated. */ + GC_INNER int GC_has_other_debug_info(ptr_t p) { - oh * ohdr = (oh *)p; - ptr_t body = (ptr_t)(ohdr + 1); - word sz = GC_size((ptr_t) ohdr); + ptr_t body = (ptr_t)((oh *)p + 1); + word sz = GC_size(p); - if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body) + if (HBLKPTR(p) != HBLKPTR((ptr_t)body) || sz < DEBUG_BYTES + EXTRA_BYTES) { - return(FALSE); + return 0; } - if (ohdr -> oh_sz == sz) { - /* Object may have had debug info, but has been deallocated */ - return(FALSE); + if (((oh *)p) -> oh_sf != (START_FLAG ^ (word)body) + && ((word *)p)[BYTES_TO_WORDS(sz)-1] != (END_FLAG ^ (word)body)) { + return 0; } - if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE); - if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) { - return(TRUE); + if (((oh *)p)->oh_sz == sz) { + /* Object may have had debug info, but has been deallocated */ + return -1; } - return(FALSE); + return 1; } #endif /* !SHORT_DBG_HDRS */ @@ -771,17 +771,26 @@ GC_API void GC_CALL GC_debug_free(void * p) ptr_t clobbered = GC_check_annotated_obj((oh *)base); word sz = GC_size(base); if (clobbered != 0) { - GC_print_smashed_obj(((oh *)base) -> oh_sz == sz ? - "GC_debug_free: found previously deallocated (?) object at" : - "GC_debug_free: found smashed location at", - p, clobbered); GC_have_errors = TRUE; + if (((oh *)base) -> oh_sz == sz) { + GC_print_smashed_obj( + "GC_debug_free: found previously deallocated (?) object at", + p, clobbered); + return; /* ignore double free */ + } else { + GC_print_smashed_obj("GC_debug_free: found smashed location at", + p, clobbered); + } } - /* Invalidate size */ + /* Invalidate size (mark the object as deallocated) */ ((oh *)base) -> oh_sz = sz; # endif /* SHORT_DBG_HDRS */ } - if (GC_find_leak) { + if (GC_find_leak +# ifndef SHORT_DBG_HDRS + && ((ptr_t)p - (ptr_t)base != sizeof(oh) || !GC_findleak_delay_free) +# endif + ) { GC_free(base); } else { hdr * hhdr = HDR(p); @@ -914,6 +923,7 @@ STATIC void GC_print_all_smashed_proc(void) GC_smashed[i] = 0; } GC_n_smashed = 0; + GC_err_printf("\n"); } /* Check all marked objects in the given block for validity */ @@ -951,6 +961,32 @@ STATIC void GC_check_heap_proc(void) GC_apply_to_all_blocks(GC_check_heap_block, 0); } +GC_INNER GC_bool GC_check_leaked(ptr_t base) +{ + size_t i; + size_t obj_sz; + word *p; + + if ( +# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) + (*(word *)base & 1) != 0 && +# endif + GC_has_other_debug_info(base) >= 0) + return TRUE; /* object has leaked */ + + /* Validate freed object's content. */ + p = (word *)(base + sizeof(oh)); + obj_sz = BYTES_TO_WORDS(HDR(base)->hb_sz - sizeof(oh)); + for (i = 0; i < obj_sz; ++i) + if (p[i] != GC_FREED_MEM_MARKER) { + GC_set_mark_bit(base); /* do not reclaim it in this cycle */ + GC_add_smashed((ptr_t)(&p[i])); /* alter-after-free detected */ + break; /* don't report any other smashed locations in the object */ + } + + return FALSE; /* GC_debug_free() has been called */ +} + #endif /* !SHORT_DBG_HDRS */ struct closure { |