LCOV - code coverage report
Current view: top level - mm/boehm-gc - ptr_chck.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 85 0.0 %
Date: 2015-06-10 18:10:59 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 :     GC_err_printf("%p and %p are not in the same object\n", p, q);
      24           0 :     ABORT("GC_same_obj test failed");
      25           0 : }
      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 (!GC_is_initialized) 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 ((ptr_t)p >= limit || (ptr_t)q >= limit || (ptr_t)q < (ptr_t)h ) {
      66             :             goto fail;
      67             :         }
      68           0 :         return(p);
      69             :     }
      70           0 :     sz = hhdr -> hb_sz;
      71           0 :     if (sz > MAXOBJBYTES) {
      72           0 :       base = (ptr_t)HBLKPTR(p);
      73           0 :       limit = base + sz;
      74           0 :       if ((ptr_t)p >= limit) {
      75           0 :         goto fail;
      76             :       }
      77             :     } else {
      78             :       size_t offset;
      79           0 :       size_t pdispl = HBLKDISPL(p);
      80             : 
      81           0 :       offset = pdispl % sz;
      82           0 :       if (HBLKPTR(p) != HBLKPTR(q)) goto fail;
      83             :                 /* W/o this check, we might miss an error if    */
      84             :                 /* q points to the first object on a page, and  */
      85             :                 /* points just before the page.                 */
      86           0 :       base = (ptr_t)p - offset;
      87           0 :       limit = base + sz;
      88             :     }
      89             :     /* [base, limit) delimits the object containing p, if any.  */
      90             :     /* If p is not inside a valid object, then either q is      */
      91             :     /* also outside any valid object, or it is outside          */
      92             :     /* [base, limit).                                           */
      93           0 :     if ((ptr_t)q >= limit || (ptr_t)q < base) {
      94             :         goto fail;
      95             :     }
      96           0 :     return(p);
      97             : fail:
      98           0 :     (*GC_same_obj_print_proc)((ptr_t)p, (ptr_t)q);
      99           0 :     return(p);
     100             : }
     101             : 
     102           0 : STATIC void GC_CALLBACK GC_default_is_valid_displacement_print_proc (void *p)
     103             : {
     104           0 :     GC_err_printf("%p does not point to valid object displacement\n", p);
     105           0 :     ABORT("GC_is_valid_displacement test failed");
     106           0 : }
     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 (!GC_is_initialized) 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 && (ptr_t)p >= (ptr_t)h + sz)
     142           0 :         || !GC_valid_offsets[offset]
     143           0 :         || (ptr_t)p - offset + sz > (ptr_t)(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 :     GC_err_printf("%p is not a GC visible pointer location\n", p);
     155           0 :     ABORT("GC_is_visible test failed");
     156           0 : }
     157             : 
     158             : void (GC_CALLBACK *GC_is_visible_print_proc)(void * p) =
     159             :                 GC_default_is_visible_print_proc;
     160             : 
     161             : #ifndef THREADS
     162             : /* Could p be a stack address? */
     163             :    STATIC GC_bool GC_on_stack(ptr_t p)
     164             :    {
     165             : #       ifdef STACK_GROWS_DOWN
     166             :             if ((ptr_t)p >= GC_approx_sp() && (ptr_t)p < GC_stackbottom) {
     167             :                 return(TRUE);
     168             :             }
     169             : #       else
     170             :             if ((ptr_t)p <= GC_approx_sp() && (ptr_t)p > GC_stackbottom) {
     171             :                 return(TRUE);
     172             :             }
     173             : #       endif
     174             :         return(FALSE);
     175             :    }
     176             : #endif
     177             : 
     178             : /* Check that p is visible                                              */
     179             : /* to the collector as a possibly pointer containing location.          */
     180             : /* If it isn't invoke *GC_is_visible_print_proc.                        */
     181             : /* Returns the argument in all cases.  May erroneously succeed          */
     182             : /* in hard cases.  (This is intended for debugging use with             */
     183             : /* untyped allocations.  The idea is that it should be possible, though */
     184             : /* slow, to add such a call to all indirect pointer stores.)            */
     185             : /* Currently useless for multithreaded worlds.                          */
     186           0 : GC_API void * GC_CALL GC_is_visible(void *p)
     187             : {
     188             :     hdr *hhdr;
     189             : 
     190           0 :     if ((word)p & (ALIGNMENT - 1)) goto fail;
     191           0 :     if (!GC_is_initialized) GC_init();
     192             : #   ifdef THREADS
     193           0 :         hhdr = HDR((word)p);
     194           0 :         if (hhdr != 0 && GC_base(p) == 0) {
     195             :             goto fail;
     196             :         } else {
     197             :             /* May be inside thread stack.  We can't do much. */
     198           0 :             return(p);
     199             :         }
     200             : #   else
     201             :         /* Check stack first: */
     202             :           if (GC_on_stack(p)) return(p);
     203             :         hhdr = HDR((word)p);
     204             :         if (hhdr == 0) {
     205             :             if (GC_is_static_root(p)) return(p);
     206             :             /* Else do it again correctly:      */
     207             : #           if defined(DYNAMIC_LOADING) || defined(MSWIN32) \
     208             :                 || defined(MSWINCE) || defined(CYGWIN32) || defined(PCR)
     209             :               GC_register_dynamic_libraries();
     210             :               if (GC_is_static_root(p))
     211             :                 return(p);
     212             : #           endif
     213             :             goto fail;
     214             :         } else {
     215             :             /* p points to the heap. */
     216             :             word descr;
     217             :             ptr_t base = GC_base(p);    /* Should be manually inlined? */
     218             : 
     219             :             if (base == 0) goto fail;
     220             :             if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
     221             :             descr = hhdr -> hb_descr;
     222             :     retry:
     223             :             switch(descr & GC_DS_TAGS) {
     224             :                 case GC_DS_LENGTH:
     225             :                     if ((word)((ptr_t)p - (ptr_t)base) > (word)descr) goto fail;
     226             :                     break;
     227             :                 case GC_DS_BITMAP:
     228             :                     if ((word)((ptr_t)p - (ptr_t)base)
     229             :                          >= 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