LCOV - code coverage report
Current view: top level - mm/boehm-gc - ptr_chck.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 80 0.0 %
Date: 2017-07-14 10:03:36 Functions: 0 8 0.0 %

          Line data    Source code
       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             : #include "private/gc_pmark.h"
      15             : 
      16             : /*
      17             :  * These are checking routines calls to which could be inserted by a
      18             :  * preprocessor to validate C pointer arithmetic.
      19             :  */
      20             : 
      21           0 : STATIC void GC_CALLBACK GC_default_same_obj_print_proc(void * p, void * q)
      22             : {
      23           0 :     ABORT_ARG2("GC_same_obj test failed",
      24             :                ": %p and %p are not in the same object", p, q);
      25             : }
      26             : 
      27             : void (GC_CALLBACK *GC_same_obj_print_proc) (void *, void *)
      28             :                 = GC_default_same_obj_print_proc;
      29             : 
      30             : /* Check that p and q point to the same object.  Call           */
      31             : /* *GC_same_obj_print_proc if they don't.                       */
      32             : /* Returns the first argument.  (Return value may be hard       */
      33             : /* to use due to typing issues.  But if we had a suitable       */
      34             : /* preprocessor...)                                             */
      35             : /* Succeeds if neither p nor q points to the heap.              */
      36             : /* We assume this is performance critical.  (It shouldn't       */
      37             : /* be called by production code, but this can easily make       */
      38             : /* debugging intolerably slow.)                                 */
      39           0 : GC_API void * GC_CALL GC_same_obj(void *p, void *q)
      40             : {
      41             :     struct hblk *h;
      42             :     hdr *hhdr;
      43             :     ptr_t base, limit;
      44             :     word sz;
      45             : 
      46           0 :     if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
      47           0 :     hhdr = HDR((word)p);
      48           0 :     if (hhdr == 0) {
      49           0 :         if (divHBLKSZ((word)p) != divHBLKSZ((word)q)
      50           0 :             && HDR((word)q) != 0) {
      51           0 :             goto fail;
      52             :         }
      53           0 :         return(p);
      54             :     }
      55             :     /* If it's a pointer to the middle of a large object, move it       */
      56             :     /* to the beginning.                                                */
      57           0 :     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
      58           0 :         h = HBLKPTR(p) - (word)hhdr;
      59           0 :         hhdr = HDR(h);
      60           0 :         while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
      61           0 :            h = FORWARDED_ADDR(h, hhdr);
      62           0 :            hhdr = HDR(h);
      63             :         }
      64           0 :         limit = (ptr_t)h + hhdr -> hb_sz;
      65           0 :         if ((word)p >= (word)limit || (word)q >= (word)limit
      66           0 :             || (word)q < (word)h) {
      67             :             goto fail;
      68             :         }
      69           0 :         return(p);
      70             :     }
      71           0 :     sz = hhdr -> hb_sz;
      72           0 :     if (sz > MAXOBJBYTES) {
      73           0 :       base = (ptr_t)HBLKPTR(p);
      74           0 :       limit = base + sz;
      75           0 :       if ((word)p >= (word)limit) {
      76           0 :         goto fail;
      77             :       }
      78             :     } else {
      79             :       size_t offset;
      80           0 :       size_t pdispl = HBLKDISPL(p);
      81             : 
      82           0 :       offset = pdispl % sz;
      83           0 :       if (HBLKPTR(p) != HBLKPTR(q)) goto fail;
      84             :                 /* W/o this check, we might miss an error if    */
      85             :                 /* q points to the first object on a page, and  */
      86             :                 /* points just before the page.                 */
      87           0 :       base = (ptr_t)p - offset;
      88           0 :       limit = base + sz;
      89             :     }
      90             :     /* [base, limit) delimits the object containing p, if any.  */
      91             :     /* If p is not inside a valid object, then either q is      */
      92             :     /* also outside any valid object, or it is outside          */
      93             :     /* [base, limit).                                           */
      94           0 :     if ((word)q >= (word)limit || (word)q < (word)base) {
      95             :         goto fail;
      96             :     }
      97           0 :     return(p);
      98             : fail:
      99           0 :     (*GC_same_obj_print_proc)((ptr_t)p, (ptr_t)q);
     100           0 :     return(p);
     101             : }
     102             : 
     103           0 : STATIC void GC_CALLBACK GC_default_is_valid_displacement_print_proc (void *p)
     104             : {
     105           0 :     ABORT_ARG1("GC_is_valid_displacement test failed", ": %p not valid", p);
     106             : }
     107             : 
     108             : void (GC_CALLBACK *GC_is_valid_displacement_print_proc)(void *) =
     109             :         GC_default_is_valid_displacement_print_proc;
     110             : 
     111             : /* Check that if p is a pointer to a heap page, then it points to       */
     112             : /* a valid displacement within a heap object.                           */
     113             : /* Uninteresting with GC_all_interior_pointers.                         */
     114             : /* Always returns its argument.                                         */
     115             : /* Note that we don't lock, since nothing relevant about the header     */
     116             : /* should change while we have a valid object pointer to the block.     */
     117           0 : GC_API void * GC_CALL GC_is_valid_displacement(void *p)
     118             : {
     119             :     hdr *hhdr;
     120             :     word pdispl;
     121             :     word offset;
     122             :     struct hblk *h;
     123             :     word sz;
     124             : 
     125           0 :     if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
     126           0 :     hhdr = HDR((word)p);
     127           0 :     if (hhdr == 0) return(p);
     128           0 :     h = HBLKPTR(p);
     129           0 :     if (GC_all_interior_pointers) {
     130           0 :         while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
     131           0 :            h = FORWARDED_ADDR(h, hhdr);
     132           0 :            hhdr = HDR(h);
     133             :         }
     134             :     }
     135           0 :     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
     136           0 :         goto fail;
     137             :     }
     138           0 :     sz = hhdr -> hb_sz;
     139           0 :     pdispl = HBLKDISPL(p);
     140           0 :     offset = pdispl % sz;
     141           0 :     if ((sz > MAXOBJBYTES && (word)p >= (word)h + sz)
     142           0 :         || !GC_valid_offsets[offset]
     143           0 :         || (word)p - offset + sz > (word)(h + 1)) {
     144             :         goto fail;
     145             :     }
     146           0 :     return(p);
     147             : fail:
     148           0 :     (*GC_is_valid_displacement_print_proc)((ptr_t)p);
     149           0 :     return(p);
     150             : }
     151             : 
     152           0 : STATIC void GC_CALLBACK GC_default_is_visible_print_proc(void * p)
     153             : {
     154           0 :     ABORT_ARG1("GC_is_visible test failed", ": %p not GC-visible", p);
     155             : }
     156             : 
     157             : void (GC_CALLBACK *GC_is_visible_print_proc)(void * p) =
     158             :                 GC_default_is_visible_print_proc;
     159             : 
     160             : #ifndef THREADS
     161             : /* Could p be a stack address? */
     162             :    STATIC GC_bool GC_on_stack(ptr_t p)
     163             :    {
     164             : #    ifdef STACK_GROWS_DOWN
     165             :        if ((word)p >= (word)GC_approx_sp()
     166             :            && (word)p < (word)GC_stackbottom) {
     167             :          return(TRUE);
     168             :        }
     169             : #    else
     170             :        if ((word)p <= (word)GC_approx_sp()
     171             :            && (word)p > (word)GC_stackbottom) {
     172             :          return(TRUE);
     173             :        }
     174             : #    endif
     175             :      return(FALSE);
     176             :    }
     177             : #endif
     178             : 
     179             : /* Check that p is visible                                              */
     180             : /* to the collector as a possibly pointer containing location.          */
     181             : /* If it isn't invoke *GC_is_visible_print_proc.                        */
     182             : /* Returns the argument in all cases.  May erroneously succeed          */
     183             : /* in hard cases.  (This is intended for debugging use with             */
     184             : /* untyped allocations.  The idea is that it should be possible, though */
     185             : /* slow, to add such a call to all indirect pointer stores.)            */
     186             : /* Currently useless for the multi-threaded worlds.                     */
     187           0 : GC_API void * GC_CALL GC_is_visible(void *p)
     188             : {
     189             :     hdr *hhdr;
     190             : 
     191           0 :     if ((word)p & (ALIGNMENT - 1)) goto fail;
     192           0 :     if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
     193             : #   ifdef THREADS
     194           0 :         hhdr = HDR((word)p);
     195           0 :         if (hhdr != 0 && GC_base(p) == 0) {
     196             :             goto fail;
     197             :         } else {
     198             :             /* May be inside thread stack.  We can't do much. */
     199           0 :             return(p);
     200             :         }
     201             : #   else
     202             :         /* Check stack first: */
     203             :           if (GC_on_stack(p)) return(p);
     204             :         hhdr = HDR((word)p);
     205             :         if (hhdr == 0) {
     206             :             if (GC_is_static_root(p)) return(p);
     207             :             /* Else do it again correctly:      */
     208             : #           if defined(DYNAMIC_LOADING) || defined(MSWIN32) \
     209             :                 || defined(MSWINCE) || defined(CYGWIN32) || defined(PCR)
     210             :               GC_register_dynamic_libraries();
     211             :               if (GC_is_static_root(p))
     212             :                 return(p);
     213             : #           endif
     214             :             goto fail;
     215             :         } else {
     216             :             /* p points to the heap. */
     217             :             word descr;
     218             :             ptr_t base = GC_base(p);    /* Should be manually inlined? */
     219             : 
     220             :             if (base == 0) goto fail;
     221             :             if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
     222             :             descr = hhdr -> hb_descr;
     223             :     retry:
     224             :             switch(descr & GC_DS_TAGS) {
     225             :                 case GC_DS_LENGTH:
     226             :                     if ((word)p - (word)base > descr) goto fail;
     227             :                     break;
     228             :                 case GC_DS_BITMAP:
     229             :                     if ((word)p - (word)base >= WORDS_TO_BYTES(BITMAP_BITS)
     230             :                         || ((word)p & (sizeof(word) - 1))) goto fail;
     231             :                     if (!(((word)1 << (WORDSZ - ((ptr_t)p - (ptr_t)base) - 1))
     232             :                           & descr)) goto fail;
     233             :                     break;
     234             :                 case GC_DS_PROC:
     235             :                     /* We could try to decipher this partially.         */
     236             :                     /* For now we just punt.                            */
     237             :                     break;
     238             :                 case GC_DS_PER_OBJECT:
     239             :                     if ((signed_word)descr >= 0) {
     240             :                       descr = *(word *)((ptr_t)base + (descr & ~GC_DS_TAGS));
     241             :                     } else {
     242             :                       ptr_t type_descr = *(ptr_t *)base;
     243             :                       descr = *(word *)(type_descr
     244             :                                         - (descr - (word)(GC_DS_PER_OBJECT
     245             :                                            - GC_INDIR_PER_OBJ_BIAS)));
     246             :                     }
     247             :                     goto retry;
     248             :             }
     249             :             return(p);
     250             :         }
     251             : #   endif
     252             : fail:
     253           0 :     (*GC_is_visible_print_proc)((ptr_t)p);
     254           0 :     return(p);
     255             : }
     256             : 
     257           0 : GC_API void * GC_CALL GC_pre_incr (void **p, ptrdiff_t how_much)
     258             : {
     259           0 :     void * initial = *p;
     260           0 :     void * result = GC_same_obj((void *)((ptr_t)initial + how_much), initial);
     261             : 
     262           0 :     if (!GC_all_interior_pointers) {
     263           0 :         (void) GC_is_valid_displacement(result);
     264             :     }
     265           0 :     return (*p = result);
     266             : }
     267             : 
     268           0 : GC_API void * GC_CALL GC_post_incr (void **p, ptrdiff_t how_much)
     269             : {
     270           0 :     void * initial = *p;
     271           0 :     void * result = GC_same_obj((void *)((ptr_t)initial + how_much), initial);
     272             : 
     273           0 :     if (!GC_all_interior_pointers) {
     274           0 :         (void) GC_is_valid_displacement(result);
     275             :     }
     276           0 :     *p = result;
     277           0 :     return(initial);
     278             : }

Generated by: LCOV version 1.11