dbg_mlc.h raw

   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.
   5   * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.
   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   */
  16  
  17  /*
  18   * This is mostly an internal header file.  Typical clients should
  19   * not use it.  Clients that define their own object kinds with
  20   * debugging allocators will probably want to include this, however.
  21   * No attempt is made to keep the namespace clean.  This should not be
  22   * included from header files that are frequently included by clients.
  23   */
  24  
  25  #ifndef GC_DBG_MLC_H
  26  #define GC_DBG_MLC_H
  27  
  28  #include "gc_priv.h"
  29  #ifdef KEEP_BACK_PTRS
  30  #  include "gc/gc_backptr.h"
  31  #endif
  32  
  33  EXTERN_C_BEGIN
  34  
  35  #ifndef GC_FREED_MEM_MARKER
  36  #  if CPP_WORDSZ == 32
  37  #    define GC_FREED_MEM_MARKER (GC_uintptr_t)0xdeadbeef
  38  #  else
  39  #    define GC_FREED_MEM_MARKER ((GC_uintptr_t)GC_WORD_C(0xEFBEADDEdeadbeef))
  40  #  endif
  41  #endif /* !GC_FREED_MEM_MARKER */
  42  
  43  /*
  44   * Stored both one past the end of user object, and one before the end of
  45   * the object as seen by the allocator.
  46   */
  47  #if CPP_WORDSZ == 32
  48  #  define START_FLAG (GC_uintptr_t)0xfedcedcb
  49  #  define END_FLAG (GC_uintptr_t)0xbcdecdef
  50  #else
  51  #  define START_FLAG ((GC_uintptr_t)GC_WORD_C(0xFEDCEDCBfedcedcb))
  52  #  define END_FLAG ((GC_uintptr_t)GC_WORD_C(0xBCDECDEFbcdecdef))
  53  #endif
  54  
  55  #if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST)
  56  /*
  57   * Pointer "source" variants that are not real locations.  Used in
  58   * `oh_back_ptr` fields and as `source` argument to some marking functions.
  59   */
  60  
  61  /* Object was marked because it is finalizable. */
  62  #  define MARKED_FOR_FINALIZATION ((ptr_t)NUMERIC_TO_VPTR(2))
  63  
  64  /*
  65   * Object was marked from a register.  Hence the "source" of the reference
  66   * does not have an address.
  67   */
  68  #  define MARKED_FROM_REGISTER ((ptr_t)NUMERIC_TO_VPTR(4))
  69  
  70  #  define NOT_MARKED ((ptr_t)NUMERIC_TO_VPTR(8))
  71  #endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */
  72  
  73  /*
  74   * Object debug header.  The size of the structure is assumed not to
  75   * de-align things, and to be a multiple of a double-pointer length.
  76   */
  77  typedef struct {
  78  #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
  79    /*
  80     * We potentially keep two different kinds of back pointers.
  81     * `KEEP_BACK_PTRS` stores a single back pointer in each reachable
  82     * object to allow reporting of why an object was retained.
  83     * `MAKE_BACK_GRAPH` builds a graph containing the inverse of all
  84     * "points-to" edges including those involving objects that have just
  85     * become unreachable.  This allows detection of growing chains of
  86     * unreachable objects.  It may be possible to eventually combine both,
  87     * but for now we keep them separate.  Both kinds of back pointers are
  88     * hidden using the following macros.  In both cases, the plain variant
  89     * is constrained to have the least significant bit of 1, to allow it
  90     * to be distinguished from a free-list link.  This means the plain
  91     * variant must have the least significant bit of zero.
  92     * Note that blocks dropped by black-listing will also have the least
  93     * significant bit clear once debugging has started; we are careful never
  94     * to overwrite such a value.
  95     */
  96  #  if ALIGNMENT == 1
  97    /* Fudge back pointer to be even. */
  98  #    define HIDE_BACK_PTR(p) \
  99        GC_HIDE_POINTER((ptr_t)(~(GC_uintptr_t)1 & (GC_uintptr_t)(p)))
 100  #  else
 101  #    define HIDE_BACK_PTR(p) GC_HIDE_POINTER(p)
 102  #  endif
 103    /*
 104     * Always define either none or both of the fields to ensure
 105     * double-pointer alignment.
 106     */
 107    GC_hidden_pointer oh_back_ptr;
 108    GC_hidden_pointer oh_bg_ptr;
 109  #endif
 110    const char *oh_string; /*< object descriptor string (file name) */
 111    GC_signed_word oh_int; /*< object descriptor integer (line number) */
 112  #ifdef NEED_CALLINFO
 113    struct callinfo oh_ci[NFRAMES];
 114  #endif
 115  #ifndef SHORT_DBG_HDRS
 116    GC_uintptr_t oh_sz; /*< the original `malloc` argument */
 117    GC_uintptr_t oh_sf; /*< the "start" flag (marker) */
 118  #endif
 119  } oh;
 120  
 121  #define GET_OH_LINENUM(ohdr) ((int)(ohdr)->oh_int)
 122  
 123  #ifdef SHORT_DBG_HDRS
 124  #  define DEBUG_BYTES sizeof(oh)
 125  #  define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES
 126  #else
 127  /*
 128   * Add space for `END_FLAG`, but use any extra space that was already
 129   * added to catch off-the-end pointers.  For uncollectible objects, the
 130   * extra byte is not added.
 131   */
 132  #  define UNCOLLECTABLE_DEBUG_BYTES (sizeof(oh) + sizeof(GC_uintptr_t))
 133  #  define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES)
 134  #endif
 135  
 136  /*
 137   * `ADD_CALL_CHAIN` stores a (partial) call chain into an object header;
 138   * it should be called with the allocator lock held.
 139   * `PRINT_CALL_CHAIN` prints the call chain stored in an object to `stderr`;
 140   * it requires we do not hold the allocator lock.
 141   */
 142  #if defined(SAVE_CALL_CHAIN)
 143  #  define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base))->oh_ci)
 144  #  if defined(REDIRECT_MALLOC) && defined(THREADS) && defined(DBG_HDRS_ALL) \
 145        && NARGS == 0 && NFRAMES % 2 == 0 && defined(GC_HAVE_BUILTIN_BACKTRACE)
 146  /*
 147   * A dummy variant of `GC_save_callers()` which does not call
 148   * `backtrace()`.
 149   */
 150  GC_INNER void GC_save_callers_no_unlock(struct callinfo info[NFRAMES]);
 151  
 152  #    define ADD_CALL_CHAIN_INNER(base) \
 153        GC_save_callers_no_unlock(((oh *)(base))->oh_ci)
 154  #  endif
 155  #  define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base))->oh_ci)
 156  #elif defined(GC_ADD_CALLER)
 157  #  define ADD_CALL_CHAIN(base, ra) ((oh *)(base))->oh_ci[0].ci_pc = (ra)
 158  #  define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base))->oh_ci)
 159  #else
 160  #  define ADD_CALL_CHAIN(base, ra)
 161  #  define PRINT_CALL_CHAIN(base)
 162  #endif
 163  
 164  #if !defined(ADD_CALL_CHAIN_INNER) && defined(DBG_HDRS_ALL)
 165  /* A variant of `ADD_CALL_CHAIN()` used for internal allocations. */
 166  #  define ADD_CALL_CHAIN_INNER(base) ADD_CALL_CHAIN(base, GC_RETURN_ADDR)
 167  #endif
 168  
 169  #ifdef GC_ADD_CALLER
 170  #  define OPT_RA ra,
 171  #else
 172  #  define OPT_RA
 173  #endif
 174  
 175  /*
 176   * Check whether object given by its base pointer has debugging info.
 177   * The argument (`base`) is assumed to point to a legitimate object in the
 178   * collector heap.  This excludes the check as to whether the back pointer
 179   * is odd, which is added by the `GC_HAS_DEBUG_INFO` macro.  Note that
 180   * if `DBG_HDRS_ALL` is defined, uncollectible objects on free lists
 181   * may not have debug information set.  Thus, it is not always safe to
 182   * return 1 (true), even if the client does its part.  Return -1 if the
 183   * object with debug info has been marked as deallocated.
 184   */
 185  #ifdef SHORT_DBG_HDRS
 186  #  define GC_has_other_debug_info(base) 1
 187  #else
 188  GC_INNER int GC_has_other_debug_info(ptr_t base);
 189  
 190  GC_INNER void GC_add_smashed(ptr_t smashed);
 191  
 192  /*
 193   * Use `GC_err_printf()` and friends to print a description of the object
 194   * whose client-visible address is `p`, and which was smashed at memory
 195   * location pointed by `clobbered`.
 196   */
 197  GC_INNER void GC_print_smashed_obj(const char *msg, void *p, ptr_t clobbered);
 198  
 199  /* Print all objects on the list.  Clear the list. */
 200  GC_INNER void GC_print_all_smashed_proc(void);
 201  #endif /* !SHORT_DBG_HDRS */
 202  
 203  #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
 204  #  if defined(SHORT_DBG_HDRS) && !defined(CPPCHECK)
 205  #    error Non-ptr stored in object results in GC_HAS_DEBUG_INFO malfunction
 206  /* We may mistakenly conclude that base has a debugging wrapper. */
 207  #  endif
 208  #  if defined(PARALLEL_MARK) && defined(KEEP_BACK_PTRS)
 209  /*
 210   * Note: the atomic load is used as `GC_store_back_pointer` stores
 211   * `oh_back_ptr` atomically (`base` might point to the field); this prevents
 212   * a TSan warning.
 213   */
 214  #    define GC_HAS_DEBUG_INFO(base)                                    \
 215        (((GC_uintptr_t)GC_cptr_load((volatile ptr_t *)(base)) & 1) != 0 \
 216         && GC_has_other_debug_info(base) > 0)
 217  #  else
 218  #    define GC_HAS_DEBUG_INFO(base)         \
 219        (((*(GC_uintptr_t *)(base)) & 1) != 0 \
 220         && GC_has_other_debug_info(base) > 0)
 221  #  endif
 222  #else
 223  #  define GC_HAS_DEBUG_INFO(base) (GC_has_other_debug_info(base) > 0)
 224  #endif /* !KEEP_BACK_PTRS && !MAKE_BACK_GRAPH */
 225  
 226  EXTERN_C_END
 227  
 228  #endif /* GC_DBG_MLC_H */
 229