Exemple #1
0
/*ARGSUSED*/
void GC_check_heap_block(struct hblk *hbp, word dummy)
{
    struct hblkhdr * hhdr = HDR(hbp);
    size_t sz = hhdr -> hb_sz;
    size_t bit_no;
    char *p, *plim;
    
    p = hbp->hb_body;
    bit_no = 0;
    if (sz > MAXOBJBYTES) {
	plim = p;
    } else {
    	plim = hbp->hb_body + HBLKSIZE - sz;
    }
    /* go through all words in block */
	while( p <= plim ) {
	    if( mark_bit_from_hdr(hhdr, bit_no)
	        && GC_HAS_DEBUG_INFO((ptr_t)p)) {
	        ptr_t clobbered = GC_check_annotated_obj((oh *)p);
	        
	        if (clobbered != 0) GC_add_smashed(clobbered);
	    }
	    bit_no += MARK_BIT_OFFSET(sz);
	    p += sz;
	}
}
Exemple #2
0
void * GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS)
{
    void * base = GC_base(p);
    ptr_t clobbered;
    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));
    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);
        return(GC_realloc(p, lb));
    }
    hhdr = HDR(base);
    switch (hhdr -> hb_obj_kind) {
#    ifdef STUBBORN_ALLOC
      case STUBBORN:
        result = GC_debug_malloc_stubborn(lb, OPT_RA s, i);
        break;
#    endif
      case NORMAL:
        result = GC_debug_malloc(lb, OPT_RA s, i);
        break;
      case PTRFREE:
        result = GC_debug_malloc_atomic(lb, OPT_RA s, i);
        break;
      case UNCOLLECTABLE:
	result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i);
 	break;
#    ifdef ATOMIC_UNCOLLECTABLE
      case AUNCOLLECTABLE:
	result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
	break;
#    endif
      default:
        GC_err_printf("GC_debug_realloc: encountered bad kind\n");
        ABORT("bad kind");
    }
#   ifdef SHORT_DBG_HDRS
      old_sz = GC_size(base) - sizeof(oh);
#   else
      clobbered = GC_check_annotated_obj((oh *)base);
      if (clobbered != 0) {
        GC_err_printf("GC_debug_realloc: found smashed location at ");
        GC_print_smashed_obj(p, clobbered);
      }
      old_sz = ((oh *)base) -> oh_sz;
#   endif
    if (old_sz < copy_sz) copy_sz = old_sz;
    if (result == 0) return(0);
    BCOPY(p, result,  copy_sz);
    GC_debug_free(p);
    return(result);
}
Exemple #3
0
GC_API void GC_CALL GC_debug_free(void * p)
{
    ptr_t base;
    if (0 == p) return;

    base = GC_base(p);
    if (base == 0) {
      GC_err_printf("Attempt to free invalid pointer %p\n", p);
      ABORT("Invalid pointer passed to free()");
    }
    if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
      GC_err_printf(
               "GC_debug_free called on pointer %p w/o debugging info\n", p);
    } else {
#     ifndef SHORT_DBG_HDRS
        ptr_t clobbered = GC_check_annotated_obj((oh *)base);
        word sz = GC_size(base);
        if (clobbered != 0) {
          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 (mark the object as deallocated) */
        ((oh *)base) -> oh_sz = sz;
#     endif /* SHORT_DBG_HDRS */
    }
    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);
      if (hhdr -> hb_obj_kind == UNCOLLECTABLE
#         ifdef ATOMIC_UNCOLLECTABLE
            || hhdr -> hb_obj_kind == AUNCOLLECTABLE
#         endif
          ) {
        GC_free(base);
      } else {
        size_t i;
        size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - sizeof(oh));

        for (i = 0; i < obj_sz; ++i)
          ((word *)p)[i] = GC_FREED_MEM_MARKER;
        GC_ASSERT((word *)p + i == (word *)(base + hhdr -> hb_sz));
      }
    } /* !GC_find_leak */
}
Exemple #4
0
void GC_debug_free(void * p)
{
    ptr_t base;
    ptr_t clobbered;
    
    if (0 == p) return;
    base = GC_base(p);
    if (base == 0) {
        GC_err_printf("Attempt to free invalid pointer %p\n", p);
        ABORT("free(invalid pointer)");
    }
    if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
        GC_err_printf(
        	  "GC_debug_free called on pointer %p wo debugging info\n", p);
    } else {
#     ifndef SHORT_DBG_HDRS
        clobbered = GC_check_annotated_obj((oh *)base);
        if (clobbered != 0) {
          if (((oh *)base) -> oh_sz == GC_size(base)) {
            GC_err_printf(
                  "GC_debug_free: found previously deallocated (?) object at ");
          } else {
            GC_err_printf("GC_debug_free: found smashed location at ");
          }
          GC_print_smashed_obj(p, clobbered);
        }
        /* Invalidate size */
        ((oh *)base) -> oh_sz = GC_size(base);
#     endif /* SHORT_DBG_HDRS */
    }
    if (GC_find_leak) {
        GC_free(base);
    } else {
	hdr * hhdr = HDR(p);
	GC_bool uncollectable = FALSE;

        if (hhdr ->  hb_obj_kind == UNCOLLECTABLE) {
	    uncollectable = TRUE;
	}
#	ifdef ATOMIC_UNCOLLECTABLE
	    if (hhdr ->  hb_obj_kind == AUNCOLLECTABLE) {
		    uncollectable = TRUE;
	    }
#	endif
	if (uncollectable) {
	    GC_free(base);
	} else {
	    size_t i;
	    size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - 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 */
}
Exemple #5
0
/* Avoid GC_apply_to_each_object for performance reasons.       */
STATIC void GC_check_heap_block(struct hblk *hbp, word dummy GC_ATTR_UNUSED)
{
    struct hblkhdr * hhdr = HDR(hbp);
    word sz = hhdr -> hb_sz;
    word bit_no;
    char *p, *plim;

    p = hbp->hb_body;
    if (sz > MAXOBJBYTES) {
      plim = p;
    } else {
      plim = hbp->hb_body + HBLKSIZE - sz;
    }
    /* go through all words in block */
    for (bit_no = 0; (word)p <= (word)plim;
         bit_no += MARK_BIT_OFFSET(sz), p += sz) {
      if (mark_bit_from_hdr(hhdr, bit_no) && GC_HAS_DEBUG_INFO((ptr_t)p)) {
        ptr_t clobbered = GC_check_annotated_obj((oh *)p);
        if (clobbered != 0)
          GC_add_smashed(clobbered);
      }
    }
}
Exemple #6
0
#include <M2/gc-include.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <M2/config.h>
#include <stdint.h>

#include "debug.h"
#include <gmp.h>
#include <mpfr.h>
#include <string.h>

void *trapaddr = (void *)1;
int trapcount = 0;
int trapset = 0;

void trap(void) {}		/* I used to be concerned that this function would get optimized away, but it isn't static ... */

void *pointers[10];		/* during debugging we can put pointers here, visible to the garbage collector */
void trapchk(void *p) { 
     trapcount++;
     if (trapcount == trapset || p == trapaddr || p == (void *)~(intptr_t)trapaddr) trap();
}

#define STDERR 2
int badBlock() {
     char buf[120];
     sprintf(buf,"%s:%d: internal error: smashed block in memory block allocator\n",__FILE__,__LINE__);
     if (write(STDERR,buf,strlen(buf))) abort();
     abort();
}

#if GC_DEBUG
extern unsigned int GC_debug_header_size;
extern void *GC_check_annotated_obj(void *); /* returns NULL or pointer to clobbered debug header location */
void GC_check(void *p) {
  void *q = (char *)p - GC_debug_header_size;
  if (NULL != GC_check_annotated_obj(q)) trap();
}
Exemple #7
0
GC_API void GC_CALL GC_debug_free(void * p)
{
    ptr_t base;
    if (0 == p) return;

    base = (ptr_t)GC_base(p);
    if (NULL == base) {
#     if defined(REDIRECT_MALLOC) \
         && ((defined(NEED_CALLINFO) && defined(GC_HAVE_BUILTIN_BACKTRACE)) \
             || defined(GC_LINUX_THREADS) || defined(GC_SOLARIS_THREADS) \
             || defined(MSWIN32))
        /* In some cases, we should ignore objects that do not belong   */
        /* to the GC heap.  See the comment in GC_free.                 */
        if (!GC_is_heap_ptr(p)) return;
#     endif
      ABORT_ARG1("Invalid pointer passed to free()", ": %p", p);
    }
    if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
#     if defined(REDIRECT_FREE) && defined(USE_PROC_FOR_LIBRARIES)
        /* TODO: Suppress the warning if free() caller is in libpthread */
        /* or libdl.                                                    */
#     endif
      GC_err_printf(
               "GC_debug_free called on pointer %p w/o debugging info\n", p);
    } else {
#     ifndef SHORT_DBG_HDRS
        ptr_t clobbered = GC_check_annotated_obj((oh *)base);
        word sz = GC_size(base);
        if (clobbered != 0) {
          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 (mark the object as deallocated) */
        ((oh *)base) -> oh_sz = sz;
#     endif /* SHORT_DBG_HDRS */
    }
    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);
      if (hhdr -> hb_obj_kind == UNCOLLECTABLE
#         ifdef GC_ATOMIC_UNCOLLECTABLE
            || hhdr -> hb_obj_kind == AUNCOLLECTABLE
#         endif
          ) {
        GC_free(base);
      } else {
        word i;
        word sz = hhdr -> hb_sz;
        word obj_sz = BYTES_TO_WORDS(sz - sizeof(oh));

        for (i = 0; i < obj_sz; ++i)
          ((word *)p)[i] = GC_FREED_MEM_MARKER;
        GC_ASSERT((word *)p + i == (word *)(base + sz));
        /* Update the counter even though the real deallocation */
        /* is deferred.                                         */
        LOCK();
        GC_bytes_freed += sz;
        UNLOCK();
      }
    } /* !GC_find_leak */
}