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-2011 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 "valgrind.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 UChar ch = (UChar)((UInt)c); \ 53 UChar* p = (UChar*)s; \ 54 UChar* last = NULL; \ 55 while (True) { \ 56 if (*p == ch) last = p; \ 57 if (*p == 0) return 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 #endif 72 73 74 #define STRCHR(soname, fnname) \ 75 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \ 76 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \ 77 { \ 78 UChar ch = (UChar)((UInt)c); \ 79 UChar* p = (UChar*)s; \ 80 while (True) { \ 81 if (*p == ch) return p; \ 82 if (*p == 0) return NULL; \ 83 p++; \ 84 } \ 85 } 86 87 // Apparently index() is the same thing as strchr() 88 STRCHR(VG_Z_LIBC_SONAME, strchr) 89 STRCHR(VG_Z_LIBC_SONAME, index) 90 #if defined(VGO_linux) 91 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) 92 STRCHR(VG_Z_LD_LINUX_SO_2, strchr) 93 STRCHR(VG_Z_LD_LINUX_SO_2, index) 94 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr) 95 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) 96 #elif defined(VGO_darwin) 97 STRCHR(VG_Z_DYLD, strchr) 98 STRCHR(VG_Z_DYLD, index) 99 #endif 100 101 102 #define STRNLEN(soname, fnname) \ 103 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \ 104 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \ 105 { \ 106 SizeT i = 0; \ 107 while (i < n && str[i] != 0) i++; \ 108 return i; \ 109 } 110 111 STRNLEN(VG_Z_LIBC_SONAME, strnlen) 112 113 114 // Note that this replacement often doesn't get used because gcc inlines 115 // calls to strlen() with its own built-in version. This can be very 116 // confusing if you aren't expecting it. Other small functions in this file 117 // may also be inline by gcc. 118 #define STRLEN(soname, fnname) \ 119 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \ 120 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \ 121 { \ 122 SizeT i = 0; \ 123 while (str[i] != 0) i++; \ 124 return i; \ 125 } 126 127 STRLEN(VG_Z_LIBC_SONAME, strlen) 128 #if defined(VGO_linux) 129 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) 130 STRLEN(VG_Z_LD_LINUX_SO_2, strlen) 131 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen) 132 STRLEN(VG_Z_LD_SO_1, strlen) 133 #endif 134 135 136 #define STRCPY(soname, fnname) \ 137 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \ 138 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \ 139 { \ 140 Char* dst_orig = dst; \ 141 \ 142 while (*src) *dst++ = *src++; \ 143 *dst = 0; \ 144 \ 145 return dst_orig; \ 146 } 147 148 STRCPY(VG_Z_LIBC_SONAME, strcpy) 149 #if defined(VGO_linux) 150 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) 151 #elif defined(VGO_darwin) 152 STRCPY(VG_Z_DYLD, strcpy) 153 #endif 154 155 156 #define STRNCMP(soname, fnname) \ 157 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 158 ( const char* s1, const char* s2, SizeT nmax ); \ 159 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 160 ( const char* s1, const char* s2, SizeT nmax ) \ 161 { \ 162 SizeT n = 0; \ 163 while (True) { \ 164 if (n >= nmax) return 0; \ 165 if (*s1 == 0 && *s2 == 0) return 0; \ 166 if (*s1 == 0) return -1; \ 167 if (*s2 == 0) return 1; \ 168 \ 169 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \ 170 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \ 171 \ 172 s1++; s2++; n++; \ 173 } \ 174 } 175 176 STRNCMP(VG_Z_LIBC_SONAME, strncmp) 177 #if defined(VGO_linux) 178 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) 179 #elif defined(VGO_darwin) 180 STRNCMP(VG_Z_DYLD, strncmp) 181 #endif 182 183 184 #define STRCMP(soname, fnname) \ 185 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 186 ( const char* s1, const char* s2 ); \ 187 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 188 ( const char* s1, const char* s2 ) \ 189 { \ 190 register unsigned char c1; \ 191 register unsigned char c2; \ 192 while (True) { \ 193 c1 = *(unsigned char *)s1; \ 194 c2 = *(unsigned char *)s2; \ 195 if (c1 != c2) break; \ 196 if (c1 == 0) break; \ 197 s1++; s2++; \ 198 } \ 199 if ((unsigned char)c1 < (unsigned char)c2) return -1; \ 200 if ((unsigned char)c1 > (unsigned char)c2) return 1; \ 201 return 0; \ 202 } 203 204 STRCMP(VG_Z_LIBC_SONAME, strcmp) 205 #if defined(VGO_linux) 206 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) 207 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp) 208 STRCMP(VG_Z_LD64_SO_1, strcmp) 209 #endif 210 211 212 #define MEMCHR(soname, fnname) \ 213 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \ 214 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \ 215 { \ 216 SizeT i; \ 217 UChar c0 = (UChar)c; \ 218 UChar* p = (UChar*)s; \ 219 for (i = 0; i < n; i++) \ 220 if (p[i] == c0) return (void*)(&p[i]); \ 221 return NULL; \ 222 } 223 224 MEMCHR(VG_Z_LIBC_SONAME, memchr) 225 #if defined(VGO_darwin) 226 MEMCHR(VG_Z_DYLD, memchr) 227 #endif 228 229 230 #define MEMCPY(soname, fnname) \ 231 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 232 ( void *dst, const void *src, SizeT sz ); \ 233 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 234 ( void *dest, const void *src, SizeT sz ) \ 235 { \ 236 const UChar* s = (const UChar*)src; \ 237 UChar* d = (UChar*)dest; \ 238 const UWord* sW = (const UWord*)src; \ 239 UWord* dW = (UWord*)dest; \ 240 const UWord al = sizeof(UWord)-1; \ 241 \ 242 if (0 == (((UWord)dW) & al) && 0 == (((UWord)sW) & al)) { \ 243 while (sz >= 4 * sizeof(UWord)) { \ 244 dW[0] = sW[0]; \ 245 dW[1] = sW[1]; \ 246 dW[2] = sW[2]; \ 247 dW[3] = sW[3]; \ 248 sz -= 4 * sizeof(UWord); \ 249 dW += 4; \ 250 sW += 4; \ 251 } \ 252 if (sz == 0) \ 253 return dest; \ 254 while (sz >= 1 * sizeof(UWord)) { \ 255 dW[0] = sW[0]; \ 256 sz -= 1 * sizeof(UWord); \ 257 dW += 1; \ 258 sW += 1; \ 259 } \ 260 if (sz == 0) \ 261 return dest; \ 262 s = (const UChar*)sW; \ 263 d = (UChar*)dW; \ 264 } \ 265 \ 266 while (sz--) \ 267 *d++ = *s++; \ 268 \ 269 return dest; \ 270 } 271 272 MEMCPY(VG_Z_LIBC_SONAME, memcpy) 273 #if defined(VGO_linux) 274 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ 275 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ 276 #endif 277 278 279 /* Copy SRC to DEST, returning the address of the terminating '\0' in 280 DEST. (minor variant of strcpy) */ 281 #define STPCPY(soname, fnname) \ 282 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \ 283 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \ 284 { \ 285 while (*src) *dst++ = *src++; \ 286 *dst = 0; \ 287 \ 288 return dst; \ 289 } 290 291 STPCPY(VG_Z_LIBC_SONAME, stpcpy) 292 #if defined(VGO_linux) 293 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) 294 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) 295 #endif 296 297 298 /* Find the first occurrence of C in S. */ 299 #define GLIBC232_RAWMEMCHR(soname, fnname) \ 300 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \ 301 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \ 302 { \ 303 unsigned char c = (unsigned char) c_in; \ 304 unsigned char* char_ptr = (unsigned char *)s; \ 305 while (1) { \ 306 if (*char_ptr == c) return char_ptr; \ 307 char_ptr++; \ 308 } \ 309 } 310 311 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr) 312 #if defined (VGO_linux) 313 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) 314 #endif 315 316 317 #define STRSTR(soname, fnname) \ 318 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 319 (void* haystack, void* needle); \ 320 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 321 (void* haystack, void* needle) \ 322 { \ 323 UChar* h = (UChar*)haystack; \ 324 UChar* n = (UChar*)needle; \ 325 \ 326 /* find the length of n, not including terminating zero */ \ 327 UWord nlen = 0; \ 328 while (n[nlen]) nlen++; \ 329 \ 330 /* if n is the empty string, match immediately. */ \ 331 if (nlen == 0) return h; \ 332 \ 333 /* assert(nlen >= 1); */ \ 334 UChar n0 = n[0]; \ 335 \ 336 while (1) { \ 337 UChar hh = *h; \ 338 if (hh == 0) return NULL; \ 339 if (hh != n0) { h++; continue; } \ 340 \ 341 UWord i; \ 342 for (i = 0; i < nlen; i++) { \ 343 if (n[i] != h[i]) \ 344 break; \ 345 } \ 346 /* assert(i >= 0 && i <= nlen); */ \ 347 if (i == nlen) \ 348 return h; \ 349 \ 350 h++; \ 351 } \ 352 } 353 354 #if defined(VGO_linux) 355 STRSTR(VG_Z_LIBC_SONAME, strstr) 356 #endif 357 358 359 #define STRPBRK(soname, fnname) \ 360 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 361 (void* sV, void* acceptV); \ 362 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 363 (void* sV, void* acceptV) \ 364 { \ 365 UChar* s = (UChar*)sV; \ 366 UChar* accept = (UChar*)acceptV; \ 367 \ 368 /* find the length of 'accept', not including terminating zero */ \ 369 UWord nacc = 0; \ 370 while (accept[nacc]) nacc++; \ 371 \ 372 /* if n is the empty string, fail immediately. */ \ 373 if (nacc == 0) return NULL; \ 374 \ 375 /* assert(nacc >= 1); */ \ 376 while (1) { \ 377 UWord i; \ 378 UChar sc = *s; \ 379 if (sc == 0) \ 380 break; \ 381 for (i = 0; i < nacc; i++) { \ 382 if (sc == accept[i]) \ 383 return s; \ 384 } \ 385 s++; \ 386 } \ 387 \ 388 return NULL; \ 389 } 390 391 #if defined(VGO_linux) 392 STRPBRK(VG_Z_LIBC_SONAME, strpbrk) 393 #endif 394 395 396 /*--------------------------------------------------------------------*/ 397 /*--- end pc_intercepts.c ---*/ 398 /*--------------------------------------------------------------------*/ 399