root/gc/ptr_chck.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GC_default_same_obj_print_proc
  2. GC_same_obj
  3. GC_default_is_valid_displacement_print_proc
  4. GC_is_valid_displacement
  5. GC_default_is_visible_print_proc
  6. GC_on_stack
  7. GC_is_visible
  8. GC_pre_incr
  9. GC_post_incr

   1 /* 
   2  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
   3  *
   4  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   5  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
   6  *
   7  * Permission is hereby granted to use or copy this program
   8  * for any purpose,  provided the above notices are retained on all copies.
   9  * Permission to modify the code and to distribute modified code is granted,
  10  * provided the above notices are retained, and a notice that the code was
  11  * modified is included with the above copyright notice.
  12  */
  13 
  14 /*
  15  * These are checking routines calls to which could be inserted by a
  16  * preprocessor to validate C pointer arithmetic.
  17  */
  18 
  19 #include "private/gc_pmark.h"
  20 
  21 #ifdef __STDC__
  22 void GC_default_same_obj_print_proc(GC_PTR p, GC_PTR q)
  23 #else
  24 void GC_default_same_obj_print_proc (p, q)
  25 GC_PTR p, q;
  26 #endif
  27 {
  28     GC_err_printf2("0x%lx and 0x%lx are not in the same object\n",
  29                    (unsigned long)p, (unsigned long)q);
  30     ABORT("GC_same_obj test failed");
  31 }
  32 
  33 void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR, GC_PTR))
  34                 = GC_default_same_obj_print_proc;
  35 
  36 /* Check that p and q point to the same object.  Call           */
  37 /* *GC_same_obj_print_proc if they don't.                       */
  38 /* Returns the first argument.  (Return value may be hard       */
  39 /* to use,due to typing issues.  But if we had a suitable       */
  40 /* preprocessor ...)                                            */
  41 /* Succeeds if neither p nor q points to the heap.              */
  42 /* We assume this is performance critical.  (It shouldn't       */
  43 /* be called by production code, but this can easily make       */
  44 /* debugging intolerably slow.)                                 */
  45 #ifdef __STDC__
  46   GC_PTR GC_same_obj(register void *p, register void *q)
  47 #else
  48   GC_PTR GC_same_obj(p, q)
  49   register char *p, *q;
  50 #endif
  51 {
  52     register struct hblk *h;
  53     register hdr *hhdr;
  54     register ptr_t base, limit;
  55     register word sz;
  56     
  57     if (!GC_is_initialized) GC_init();
  58     hhdr = HDR((word)p);
  59     if (hhdr == 0) {
  60         if (divHBLKSZ((word)p) != divHBLKSZ((word)q)
  61             && HDR((word)q) != 0) {
  62             goto fail;
  63         }
  64         return(p);
  65     }
  66     /* If it's a pointer to the middle of a large object, move it       */
  67     /* to the beginning.                                                */
  68     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
  69         h = HBLKPTR(p) - (word)hhdr;
  70         hhdr = HDR(h);
  71         while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
  72            h = FORWARDED_ADDR(h, hhdr);
  73            hhdr = HDR(h);
  74         }
  75         limit = (ptr_t)((word *)h + hhdr -> hb_sz);
  76         if ((ptr_t)p >= limit || (ptr_t)q >= limit || (ptr_t)q < (ptr_t)h ) {
  77             goto fail;
  78         }
  79         return(p);
  80     }
  81     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
  82     if (sz > MAXOBJBYTES) {
  83       base = (ptr_t)HBLKPTR(p);
  84       limit = base + sz;
  85       if ((ptr_t)p >= limit) {
  86         goto fail;
  87       }
  88     } else {
  89       register int map_entry;
  90       register int pdispl = HBLKDISPL(p);
  91       
  92       map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
  93       if (map_entry > CPP_MAX_OFFSET) {
  94          map_entry = BYTES_TO_WORDS(pdispl) % BYTES_TO_WORDS(sz);
  95          if (HBLKPTR(p) != HBLKPTR(q)) goto fail;
  96                 /* W/o this check, we might miss an error if    */
  97                 /* q points to the first object on a page, and  */
  98                 /* points just before the page.                 */
  99       }
 100       base = (char *)((word)p & ~(WORDS_TO_BYTES(1) - 1));
 101       base -= WORDS_TO_BYTES(map_entry);
 102       limit = base + sz;
 103     }
 104     /* [base, limit) delimits the object containing p, if any.  */
 105     /* If p is not inside a valid object, then either q is      */
 106     /* also outside any valid object, or it is outside          */
 107     /* [base, limit).                                           */
 108     if ((ptr_t)q >= limit || (ptr_t)q < base) {
 109         goto fail;
 110     }
 111     return(p);
 112 fail:
 113     (*GC_same_obj_print_proc)((ptr_t)p, (ptr_t)q);
 114     return(p);
 115 }
 116 
 117 #ifdef __STDC__
 118 void GC_default_is_valid_displacement_print_proc (GC_PTR p)
 119 #else
 120 void GC_default_is_valid_displacement_print_proc (p)
 121 GC_PTR p;
 122 #endif
 123 {
 124     GC_err_printf1("0x%lx does not point to valid object displacement\n",
 125                    (unsigned long)p);
 126     ABORT("GC_is_valid_displacement test failed");
 127 }
 128 
 129 void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) = 
 130         GC_default_is_valid_displacement_print_proc;
 131 
 132 /* Check that if p is a pointer to a heap page, then it points to       */
 133 /* a valid displacement within a heap object.                           */
 134 /* Uninteresting with GC_all_interior_pointers.                         */
 135 /* Always returns its argument.                                         */
 136 /* Note that we don't lock, since nothing relevant about the header     */
 137 /* should change while we have a valid object pointer to the block.     */
 138 #ifdef __STDC__
 139   void * GC_is_valid_displacement(void *p)
 140 #else
 141   char *GC_is_valid_displacement(p)
 142   char *p;
 143 #endif
 144 {
 145     register hdr *hhdr;
 146     register word pdispl;
 147     register struct hblk *h;
 148     register map_entry_type map_entry;
 149     register word sz;
 150     
 151     if (!GC_is_initialized) GC_init();
 152     hhdr = HDR((word)p);
 153     if (hhdr == 0) return(p);
 154     h = HBLKPTR(p);
 155     if (GC_all_interior_pointers) {
 156         while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
 157            h = FORWARDED_ADDR(h, hhdr);
 158            hhdr = HDR(h);
 159         }
 160     }
 161     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
 162         goto fail;
 163     }
 164     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
 165     pdispl = HBLKDISPL(p);
 166     map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
 167     if (map_entry == OBJ_INVALID
 168         || sz > MAXOBJBYTES && (ptr_t)p >= (ptr_t)h + sz) {
 169         goto fail;
 170     }
 171     return(p);
 172 fail:
 173     (*GC_is_valid_displacement_print_proc)((ptr_t)p);
 174     return(p);
 175 }
 176 
 177 #ifdef __STDC__
 178 void GC_default_is_visible_print_proc(GC_PTR p)
 179 #else
 180 void GC_default_is_visible_print_proc(p)
 181 GC_PTR p;
 182 #endif
 183 {
 184     GC_err_printf1("0x%lx is not a GC visible pointer location\n",
 185                    (unsigned long)p);
 186     ABORT("GC_is_visible test failed");
 187 }
 188 
 189 void (*GC_is_visible_print_proc) GC_PROTO((GC_PTR p)) = 
 190         GC_default_is_visible_print_proc;
 191 
 192 /* Could p be a stack address? */
 193 GC_bool GC_on_stack(p)
 194 ptr_t p;
 195 {
 196 #   ifdef THREADS
 197         return(TRUE);
 198 #   else
 199         int dummy;
 200 #       ifdef STACK_GROWS_DOWN
 201             if ((ptr_t)p >= (ptr_t)(&dummy) && (ptr_t)p < GC_stackbottom ) {
 202                 return(TRUE);
 203             }
 204 #       else
 205             if ((ptr_t)p <= (ptr_t)(&dummy) && (ptr_t)p > GC_stackbottom ) {
 206                 return(TRUE);
 207             }
 208 #       endif
 209         return(FALSE);
 210 #   endif
 211 }
 212 
 213 /* Check that p is visible                                              */
 214 /* to the collector as a possibly pointer containing location.          */
 215 /* If it isn't invoke *GC_is_visible_print_proc.                        */
 216 /* Returns the argument in all cases.  May erroneously succeed          */
 217 /* in hard cases.  (This is intended for debugging use with             */
 218 /* untyped allocations.  The idea is that it should be possible, though */
 219 /* slow, to add such a call to all indirect pointer stores.)            */
 220 /* Currently useless for multithreaded worlds.                          */
 221 #ifdef __STDC__
 222   void * GC_is_visible(void *p)
 223 #else
 224   char *GC_is_visible(p)
 225   char *p;
 226 #endif
 227 {
 228     register hdr *hhdr;
 229     
 230     if ((word)p & (ALIGNMENT - 1)) goto fail;
 231     if (!GC_is_initialized) GC_init();
 232 #   ifdef THREADS
 233         hhdr = HDR((word)p);
 234         if (hhdr != 0 && GC_base(p) == 0) {
 235             goto fail;
 236         } else {
 237             /* May be inside thread stack.  We can't do much. */
 238             return(p);
 239         }
 240 #   else
 241         /* Check stack first: */
 242           if (GC_on_stack(p)) return(p);
 243         hhdr = HDR((word)p);
 244         if (hhdr == 0) {
 245             GC_bool result;
 246             
 247             if (GC_is_static_root(p)) return(p);
 248             /* Else do it again correctly:      */
 249 #           if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || \
 250                 defined(MSWINCE) || defined(PCR)) \
 251                 && !defined(SRC_M3)
 252                 DISABLE_SIGNALS();
 253                 GC_register_dynamic_libraries();
 254                 result = GC_is_static_root(p);
 255                 ENABLE_SIGNALS();
 256                 if (result) return(p);
 257 #           endif
 258             goto fail;
 259         } else {
 260             /* p points to the heap. */
 261             word descr;
 262             ptr_t base = GC_base(p);    /* Should be manually inlined? */
 263             
 264             if (base == 0) goto fail;
 265             if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
 266             descr = hhdr -> hb_descr;
 267     retry:
 268             switch(descr & GC_DS_TAGS) {
 269                 case GC_DS_LENGTH:
 270                     if ((word)((ptr_t)p - (ptr_t)base) > (word)descr) goto fail;
 271                     break;
 272                 case GC_DS_BITMAP:
 273                     if ((ptr_t)p - (ptr_t)base
 274                          >= WORDS_TO_BYTES(BITMAP_BITS)
 275                          || ((word)p & (sizeof(word) - 1))) goto fail;
 276                     if (!((1 << (WORDSZ - ((ptr_t)p - (ptr_t)base) - 1))
 277                           & descr)) goto fail;
 278                     break;
 279                 case GC_DS_PROC:
 280                     /* We could try to decipher this partially.         */
 281                     /* For now we just punt.                            */
 282                     break;
 283                 case GC_DS_PER_OBJECT:
 284                     if ((signed_word)descr >= 0) {
 285                       descr = *(word *)((ptr_t)base + (descr & ~GC_DS_TAGS));
 286                     } else {
 287                       ptr_t type_descr = *(ptr_t *)base;
 288                       descr = *(word *)(type_descr
 289                               - (descr - (GC_DS_PER_OBJECT
 290                                           - GC_INDIR_PER_OBJ_BIAS)));
 291                     }
 292                     goto retry;
 293             }
 294             return(p);
 295         }
 296 #   endif
 297 fail:
 298     (*GC_is_visible_print_proc)((ptr_t)p);
 299     return(p);
 300 }
 301 
 302 
 303 GC_PTR GC_pre_incr (p, how_much)
 304 GC_PTR *p;
 305 size_t how_much;
 306 {
 307     GC_PTR initial = *p;
 308     GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
 309     
 310     if (!GC_all_interior_pointers) {
 311         (void) GC_is_valid_displacement(result);
 312     }
 313     return (*p = result);
 314 }
 315 
 316 GC_PTR GC_post_incr (p, how_much)
 317 GC_PTR *p;
 318 size_t how_much;
 319 {
 320     GC_PTR initial = *p;
 321     GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
 322  
 323     if (!GC_all_interior_pointers) {
 324         (void) GC_is_valid_displacement(result);
 325     }
 326     *p = result;
 327     return(initial);
 328 }

/* [<][>][^][v][top][bottom][index][help] */