Home | History | Annotate | Download | only in exp-sgcheck
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Ptrcheck: a pointer-use checker.             pc_intercepts.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Ptrcheck, a Valgrind tool for checking pointer
      8    use in programs.
      9 
     10    Copyright (C) 2003-2015 Nicholas Nethercote
     11       njn (at) valgrind.org
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     26    02111-1307, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 /* Nothing actually in here.  However it appears this file is needed
     32    to make malloc intercepting work. (jrs, 2 july 08 -- not sure about
     33    that).
     34 */
     35 
     36 #include "pub_tool_basics.h"
     37 #include "pub_tool_hashtable.h"
     38 #include "pub_tool_redir.h"
     39 #include "pub_tool_tooliface.h"
     40 #include "pub_tool_clreq.h"
     41 
     42 
     43 /* The following intercepts are copied verbatim from
     44    memcheck/mc_replace_strmem.c.  If you copy more in, please keep
     45    them in the same order as in mc_replace_strmem.c. */
     46 
     47 
     48 #define STRRCHR(soname, fnname) \
     49    char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
     50    char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
     51    { \
     52       HChar ch = (HChar)c;   \
     53       const HChar* p = s;       \
     54       const HChar* last = NULL; \
     55       while (True) { \
     56          if (*p == ch) last = p; \
     57          if (*p == 0) return CONST_CAST(HChar *,last);    \
     58          p++; \
     59       } \
     60    }
     61 
     62 // Apparently rindex() is the same thing as strrchr()
     63 STRRCHR(VG_Z_LIBC_SONAME,   strrchr)
     64 STRRCHR(VG_Z_LIBC_SONAME,   rindex)
     65 #if defined(VGO_linux)
     66 STRRCHR(VG_Z_LIBC_SONAME,   __GI_strrchr)
     67 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
     68 #elif defined(VGO_darwin)
     69 STRRCHR(VG_Z_DYLD,          strrchr)
     70 STRRCHR(VG_Z_DYLD,          rindex)
     71 #elif defined(VGO_solaris)
     72 STRRCHR(VG_Z_LD_SO_1,       strrchr)
     73 #endif
     74 
     75 
     76 #define STRCHR(soname, fnname) \
     77    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
     78    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
     79    { \
     80       HChar  ch = (HChar)c ; \
     81       const HChar* p  = s;   \
     82       while (True) { \
     83          if (*p == ch) return CONST_CAST(HChar *,p);       \
     84          if (*p == 0) return NULL; \
     85          p++; \
     86       } \
     87    }
     88 
     89 // Apparently index() is the same thing as strchr()
     90 STRCHR(VG_Z_LIBC_SONAME,          strchr)
     91 STRCHR(VG_Z_LIBC_SONAME,          index)
     92 #if defined(VGO_linux)
     93 STRCHR(VG_Z_LIBC_SONAME,          __GI_strchr)
     94 STRCHR(VG_Z_LD_LINUX_SO_2,        strchr)
     95 STRCHR(VG_Z_LD_LINUX_SO_2,        index)
     96 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
     97 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
     98 #elif defined(VGO_darwin)
     99 STRCHR(VG_Z_DYLD,                 strchr)
    100 STRCHR(VG_Z_DYLD,                 index)
    101 #elif defined(VGO_solaris)
    102 STRCHR(VG_Z_LD_SO_1,              strchr)
    103 #endif
    104 
    105 
    106 #define STRNLEN(soname, fnname) \
    107    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
    108    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
    109    { \
    110       SizeT i = 0; \
    111       while (i < n && str[i] != 0) i++; \
    112       return i; \
    113    }
    114 
    115 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
    116 
    117 
    118 // Note that this replacement often doesn't get used because gcc inlines
    119 // calls to strlen() with its own built-in version.  This can be very
    120 // confusing if you aren't expecting it.  Other small functions in this file
    121 // may also be inline by gcc.
    122 #define STRLEN(soname, fnname) \
    123    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
    124    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
    125    { \
    126       SizeT i = 0; \
    127       while (str[i] != 0) i++; \
    128       return i; \
    129    }
    130 
    131 STRLEN(VG_Z_LIBC_SONAME,          strlen)
    132 #if defined(VGO_linux)
    133 STRLEN(VG_Z_LIBC_SONAME,          __GI_strlen)
    134 STRLEN(VG_Z_LD_LINUX_SO_2,        strlen)
    135 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
    136 STRLEN(VG_Z_LD_SO_1,              strlen)
    137 #elif defined(VGO_solaris)
    138 STRLEN(VG_Z_LD_SO_1,              strlen)
    139 #endif
    140 
    141 
    142 #define STRCPY(soname, fnname) \
    143    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
    144    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
    145    { \
    146       HChar* dst_orig = dst; \
    147       \
    148       while (*src) *dst++ = *src++; \
    149       *dst = 0; \
    150       \
    151       return dst_orig; \
    152    }
    153 
    154 STRCPY(VG_Z_LIBC_SONAME, strcpy)
    155 #if defined(VGO_linux)
    156 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
    157 #elif defined(VGO_darwin)
    158 STRCPY(VG_Z_DYLD,        strcpy)
    159 #elif defined(VGO_solaris)
    160 STRCPY(VG_Z_LD_SO_1,     strcpy)
    161 #endif
    162 
    163 
    164 #define STRNCMP(soname, fnname) \
    165    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    166           ( const char* s1, const char* s2, SizeT nmax ); \
    167    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    168           ( const char* s1, const char* s2, SizeT nmax ) \
    169    { \
    170       SizeT n = 0; \
    171       while (True) { \
    172          if (n >= nmax) return 0; \
    173          if (*s1 == 0 && *s2 == 0) return 0; \
    174          if (*s1 == 0) return -1; \
    175          if (*s2 == 0) return 1; \
    176          \
    177          if (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \
    178          if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \
    179          \
    180          s1++; s2++; n++; \
    181       } \
    182    }
    183 
    184 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
    185 #if defined(VGO_linux)
    186 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
    187 #elif defined(VGO_darwin)
    188 STRNCMP(VG_Z_DYLD,        strncmp)
    189 #endif
    190 
    191 
    192 #define STRCMP(soname, fnname) \
    193    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    194           ( const char* s1, const char* s2 ); \
    195    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    196           ( const char* s1, const char* s2 ) \
    197    { \
    198       register UChar c1; \
    199       register UChar c2; \
    200       while (True) { \
    201          c1 = *(const UChar *)s1; \
    202          c2 = *(const UChar *)s2; \
    203          if (c1 != c2) break; \
    204          if (c1 == 0) break; \
    205          s1++; s2++; \
    206       } \
    207       if ((UChar)c1 < (UChar)c2) return -1; \
    208       if ((UChar)c1 > (UChar)c2) return 1; \
    209       return 0; \
    210    }
    211 
    212 STRCMP(VG_Z_LIBC_SONAME,          strcmp)
    213 #if defined(VGO_linux)
    214 STRCMP(VG_Z_LIBC_SONAME,          __GI_strcmp)
    215 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
    216 STRCMP(VG_Z_LD64_SO_1,            strcmp)
    217 #elif defined(VGO_solaris)
    218 STRCMP(VG_Z_LD_SO_1,              strcmp)
    219 #endif
    220 
    221 
    222 #define MEMCHR(soname, fnname) \
    223    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
    224    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
    225    { \
    226       SizeT i; \
    227       UChar c0 = (UChar)c; \
    228       const UChar* p = s; \
    229       for (i = 0; i < n; i++) \
    230          if (p[i] == c0) return CONST_CAST(void *,&p[i]);  \
    231       return NULL; \
    232    }
    233 
    234 MEMCHR(VG_Z_LIBC_SONAME, memchr)
    235 #if defined(VGO_darwin)
    236 MEMCHR(VG_Z_DYLD,        memchr)
    237 #endif
    238 
    239 
    240 #define MEMCPY(soname, fnname) \
    241    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    242             ( void *dst, const void *src, SizeT len ); \
    243    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    244             ( void *dst, const void *src, SizeT len ) \
    245    { \
    246       const Addr WS = sizeof(UWord); /* 8 or 4 */ \
    247       const Addr WM = WS - 1;        /* 7 or 3 */ \
    248       \
    249       if (len > 0) { \
    250          if (dst < src) { \
    251          \
    252             /* Copying backwards. */ \
    253             SizeT n = len; \
    254             Addr  d = (Addr)dst; \
    255             Addr  s = (Addr)src; \
    256             \
    257             if (((s^d) & WM) == 0) { \
    258                /* s and d have same UWord alignment. */ \
    259                /* Pull up to a UWord boundary. */ \
    260                while ((s & WM) != 0 && n >= 1) \
    261                   { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
    262                /* Copy UWords. */ \
    263                while (n >= WS) \
    264                   { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
    265                if (n == 0) \
    266                   return dst; \
    267             } \
    268             if (((s|d) & 1) == 0) { \
    269                /* Both are 16-aligned; copy what we can thusly. */ \
    270                while (n >= 2) \
    271                   { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
    272             } \
    273             /* Copy leftovers, or everything if misaligned. */ \
    274             while (n >= 1) \
    275                { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
    276          \
    277          } else if (dst > src) { \
    278          \
    279             SizeT n = len; \
    280             Addr  d = ((Addr)dst) + n; \
    281             Addr  s = ((Addr)src) + n; \
    282             \
    283             /* Copying forwards. */ \
    284             if (((s^d) & WM) == 0) { \
    285                /* s and d have same UWord alignment. */ \
    286                /* Back down to a UWord boundary. */ \
    287                while ((s & WM) != 0 && n >= 1) \
    288                   { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
    289                /* Copy UWords. */ \
    290                while (n >= WS) \
    291                   { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
    292                if (n == 0) \
    293                   return dst; \
    294             } \
    295             if (((s|d) & 1) == 0) { \
    296                /* Both are 16-aligned; copy what we can thusly. */ \
    297                while (n >= 2) \
    298                   { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
    299             } \
    300             /* Copy leftovers, or everything if misaligned. */ \
    301             while (n >= 1) \
    302                { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
    303             \
    304          } \
    305       } \
    306       \
    307       return dst; \
    308    }
    309 
    310 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
    311 #if defined(VGO_linux)
    312 MEMCPY(VG_Z_LD_SO_1,     memcpy) /* ld.so.1 */
    313 MEMCPY(VG_Z_LD64_SO_1,   memcpy) /* ld64.so.1 */
    314 #elif defined(VGO_solaris)
    315 MEMCPY(VG_Z_LD_SO_1,      memcpy)
    316 #endif
    317 
    318 
    319 /* Copy SRC to DEST, returning the address of the terminating '\0' in
    320    DEST. (minor variant of strcpy) */
    321 #define STPCPY(soname, fnname) \
    322    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
    323    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
    324    { \
    325       while (*src) *dst++ = *src++; \
    326       *dst = 0; \
    327       \
    328       return dst; \
    329    }
    330 
    331 STPCPY(VG_Z_LIBC_SONAME,          stpcpy)
    332 #if defined(VGO_linux)
    333 STPCPY(VG_Z_LD_LINUX_SO_2,        stpcpy)
    334 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
    335 #endif
    336 
    337 
    338 /* Find the first occurrence of C in S.  */
    339 #define GLIBC232_RAWMEMCHR(soname, fnname) \
    340    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in); \
    341    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in) \
    342    { \
    343       UChar c = (UChar)c_in; \
    344       const UChar* char_ptr = s; \
    345       while (1) { \
    346          if (*char_ptr == c) return CONST_CAST(void *,char_ptr);   \
    347          char_ptr++; \
    348       } \
    349    }
    350 
    351 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
    352 #if defined (VGO_linux)
    353 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
    354 #endif
    355 
    356 
    357 #define STRSTR(soname, fnname) \
    358    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    359          (const char* haystack, const char* needle); \
    360    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    361          (const char* haystack, const char* needle) \
    362    { \
    363       const HChar* h = haystack; \
    364       const HChar* n = needle; \
    365       \
    366       /* find the length of n, not including terminating zero */ \
    367       UWord nlen = 0; \
    368       while (n[nlen]) nlen++; \
    369       \
    370       /* if n is the empty string, match immediately. */ \
    371       if (nlen == 0) return CONST_CAST(HChar *,h);         \
    372       \
    373       /* assert(nlen >= 1); */ \
    374       HChar n0 = n[0]; \
    375       \
    376       while (1) { \
    377          const HChar hh = *h; \
    378          if (hh == 0) return NULL; \
    379          if (hh != n0) { h++; continue; } \
    380          \
    381          UWord i; \
    382          for (i = 0; i < nlen; i++) { \
    383             if (n[i] != h[i]) \
    384                break; \
    385          } \
    386          /* assert(i >= 0 && i <= nlen); */ \
    387          if (i == nlen) \
    388             return CONST_CAST(HChar *,h);          \
    389          \
    390          h++; \
    391       } \
    392    }
    393 
    394 #if defined(VGO_linux)
    395 STRSTR(VG_Z_LIBC_SONAME,          strstr)
    396 #elif defined(VGO_solaris)
    397 STRSTR(VG_Z_LIBC_SONAME,          strstr)
    398 #endif
    399 
    400 
    401 #define STRPBRK(soname, fnname) \
    402    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    403          (const char* sV, const char* acceptV); \
    404    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
    405          (const char* sV, const char* acceptV) \
    406    { \
    407       const HChar* s = sV; \
    408       const HChar* accept = acceptV; \
    409       \
    410       /*  find the length of 'accept', not including terminating zero */ \
    411       UWord nacc = 0; \
    412       while (accept[nacc]) nacc++; \
    413       \
    414       /* if n is the empty string, fail immediately. */ \
    415       if (nacc == 0) return NULL; \
    416       \
    417       /* assert(nacc >= 1); */ \
    418       while (1) { \
    419          UWord i; \
    420          HChar sc = *s; \
    421          if (sc == 0) \
    422             break; \
    423          for (i = 0; i < nacc; i++) { \
    424             if (sc == accept[i]) \
    425                return CONST_CAST(HChar *,s);       \
    426          } \
    427          s++; \
    428       } \
    429       \
    430       return NULL; \
    431    }
    432 
    433 #if defined(VGO_linux)
    434 STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
    435 #elif defined(VGO_solaris)
    436 STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
    437 #endif
    438 
    439 
    440 /*--------------------------------------------------------------------*/
    441 /*--- end                                          pc_intercepts.c ---*/
    442 /*--------------------------------------------------------------------*/
    443