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-2013 Nicholas Nethercote 11 njn@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 (HChar *)last; \ 58 p++; \ 59 } \ 60 } 61 62// Apparently rindex() is the same thing as strrchr() 63STRRCHR(VG_Z_LIBC_SONAME, strrchr) 64STRRCHR(VG_Z_LIBC_SONAME, rindex) 65#if defined(VGO_linux) 66STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr) 67STRRCHR(VG_Z_LD_LINUX_SO_2, rindex) 68#elif defined(VGO_darwin) 69STRRCHR(VG_Z_DYLD, strrchr) 70STRRCHR(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 HChar ch = (HChar)c ; \ 79 const HChar* p = s; \ 80 while (True) { \ 81 if (*p == ch) return (HChar *)p; \ 82 if (*p == 0) return NULL; \ 83 p++; \ 84 } \ 85 } 86 87// Apparently index() is the same thing as strchr() 88STRCHR(VG_Z_LIBC_SONAME, strchr) 89STRCHR(VG_Z_LIBC_SONAME, index) 90#if defined(VGO_linux) 91STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) 92STRCHR(VG_Z_LD_LINUX_SO_2, strchr) 93STRCHR(VG_Z_LD_LINUX_SO_2, index) 94STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr) 95STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) 96#elif defined(VGO_darwin) 97STRCHR(VG_Z_DYLD, strchr) 98STRCHR(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 111STRNLEN(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 127STRLEN(VG_Z_LIBC_SONAME, strlen) 128#if defined(VGO_linux) 129STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) 130STRLEN(VG_Z_LD_LINUX_SO_2, strlen) 131STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen) 132STRLEN(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 HChar* dst_orig = dst; \ 141 \ 142 while (*src) *dst++ = *src++; \ 143 *dst = 0; \ 144 \ 145 return dst_orig; \ 146 } 147 148STRCPY(VG_Z_LIBC_SONAME, strcpy) 149#if defined(VGO_linux) 150STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) 151#elif defined(VGO_darwin) 152STRCPY(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 (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \ 170 if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \ 171 \ 172 s1++; s2++; n++; \ 173 } \ 174 } 175 176STRNCMP(VG_Z_LIBC_SONAME, strncmp) 177#if defined(VGO_linux) 178STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) 179#elif defined(VGO_darwin) 180STRNCMP(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 UChar c1; \ 191 register UChar c2; \ 192 while (True) { \ 193 c1 = *(const UChar *)s1; \ 194 c2 = *(const UChar *)s2; \ 195 if (c1 != c2) break; \ 196 if (c1 == 0) break; \ 197 s1++; s2++; \ 198 } \ 199 if ((UChar)c1 < (UChar)c2) return -1; \ 200 if ((UChar)c1 > (UChar)c2) return 1; \ 201 return 0; \ 202 } 203 204STRCMP(VG_Z_LIBC_SONAME, strcmp) 205#if defined(VGO_linux) 206STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) 207STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp) 208STRCMP(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 const UChar* p = (const UChar*)s; \ 219 for (i = 0; i < n; i++) \ 220 if (p[i] == c0) return (void*)(&p[i]); \ 221 return NULL; \ 222 } 223 224MEMCHR(VG_Z_LIBC_SONAME, memchr) 225#if defined(VGO_darwin) 226MEMCHR(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 len ); \ 233 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 234 ( void *dst, const void *src, SizeT len ) \ 235 { \ 236 const Addr WS = sizeof(UWord); /* 8 or 4 */ \ 237 const Addr WM = WS - 1; /* 7 or 3 */ \ 238 \ 239 if (len > 0) { \ 240 if (dst < src) { \ 241 \ 242 /* Copying backwards. */ \ 243 SizeT n = len; \ 244 Addr d = (Addr)dst; \ 245 Addr s = (Addr)src; \ 246 \ 247 if (((s^d) & WM) == 0) { \ 248 /* s and d have same UWord alignment. */ \ 249 /* Pull up to a UWord boundary. */ \ 250 while ((s & WM) != 0 && n >= 1) \ 251 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 252 /* Copy UWords. */ \ 253 while (n >= WS) \ 254 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \ 255 if (n == 0) \ 256 return dst; \ 257 } \ 258 if (((s|d) & 1) == 0) { \ 259 /* Both are 16-aligned; copy what we can thusly. */ \ 260 while (n >= 2) \ 261 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \ 262 } \ 263 /* Copy leftovers, or everything if misaligned. */ \ 264 while (n >= 1) \ 265 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 266 \ 267 } else if (dst > src) { \ 268 \ 269 SizeT n = len; \ 270 Addr d = ((Addr)dst) + n; \ 271 Addr s = ((Addr)src) + n; \ 272 \ 273 /* Copying forwards. */ \ 274 if (((s^d) & WM) == 0) { \ 275 /* s and d have same UWord alignment. */ \ 276 /* Back down to a UWord boundary. */ \ 277 while ((s & WM) != 0 && n >= 1) \ 278 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 279 /* Copy UWords. */ \ 280 while (n >= WS) \ 281 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \ 282 if (n == 0) \ 283 return dst; \ 284 } \ 285 if (((s|d) & 1) == 0) { \ 286 /* Both are 16-aligned; copy what we can thusly. */ \ 287 while (n >= 2) \ 288 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \ 289 } \ 290 /* Copy leftovers, or everything if misaligned. */ \ 291 while (n >= 1) \ 292 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 293 \ 294 } \ 295 } \ 296 \ 297 return dst; \ 298 } 299 300MEMCPY(VG_Z_LIBC_SONAME, memcpy) 301#if defined(VGO_linux) 302MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ 303MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ 304#endif 305 306 307/* Copy SRC to DEST, returning the address of the terminating '\0' in 308 DEST. (minor variant of strcpy) */ 309#define STPCPY(soname, fnname) \ 310 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \ 311 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \ 312 { \ 313 while (*src) *dst++ = *src++; \ 314 *dst = 0; \ 315 \ 316 return dst; \ 317 } 318 319STPCPY(VG_Z_LIBC_SONAME, stpcpy) 320#if defined(VGO_linux) 321STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) 322STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) 323#endif 324 325 326/* Find the first occurrence of C in S. */ 327#define GLIBC232_RAWMEMCHR(soname, fnname) \ 328 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in); \ 329 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in) \ 330 { \ 331 UChar c = (UChar)c_in; \ 332 const UChar* char_ptr = s; \ 333 while (1) { \ 334 if (*char_ptr == c) return (void *)char_ptr; \ 335 char_ptr++; \ 336 } \ 337 } 338 339GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr) 340#if defined (VGO_linux) 341GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) 342#endif 343 344 345#define STRSTR(soname, fnname) \ 346 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 347 (const char* haystack, const char* needle); \ 348 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 349 (const char* haystack, const char* needle) \ 350 { \ 351 const HChar* h = haystack; \ 352 const HChar* n = needle; \ 353 \ 354 /* find the length of n, not including terminating zero */ \ 355 UWord nlen = 0; \ 356 while (n[nlen]) nlen++; \ 357 \ 358 /* if n is the empty string, match immediately. */ \ 359 if (nlen == 0) return (HChar *)h; \ 360 \ 361 /* assert(nlen >= 1); */ \ 362 HChar n0 = n[0]; \ 363 \ 364 while (1) { \ 365 const HChar hh = *h; \ 366 if (hh == 0) return NULL; \ 367 if (hh != n0) { h++; continue; } \ 368 \ 369 UWord i; \ 370 for (i = 0; i < nlen; i++) { \ 371 if (n[i] != h[i]) \ 372 break; \ 373 } \ 374 /* assert(i >= 0 && i <= nlen); */ \ 375 if (i == nlen) \ 376 return (HChar *)h; \ 377 \ 378 h++; \ 379 } \ 380 } 381 382#if defined(VGO_linux) 383STRSTR(VG_Z_LIBC_SONAME, strstr) 384#endif 385 386 387#define STRPBRK(soname, fnname) \ 388 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 389 (const char* sV, const char* acceptV); \ 390 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 391 (const char* sV, const char* acceptV) \ 392 { \ 393 const HChar* s = sV; \ 394 const HChar* accept = acceptV; \ 395 \ 396 /* find the length of 'accept', not including terminating zero */ \ 397 UWord nacc = 0; \ 398 while (accept[nacc]) nacc++; \ 399 \ 400 /* if n is the empty string, fail immediately. */ \ 401 if (nacc == 0) return NULL; \ 402 \ 403 /* assert(nacc >= 1); */ \ 404 while (1) { \ 405 UWord i; \ 406 HChar sc = *s; \ 407 if (sc == 0) \ 408 break; \ 409 for (i = 0; i < nacc; i++) { \ 410 if (sc == accept[i]) \ 411 return (HChar *)s; \ 412 } \ 413 s++; \ 414 } \ 415 \ 416 return NULL; \ 417 } 418 419#if defined(VGO_linux) 420STRPBRK(VG_Z_LIBC_SONAME, strpbrk) 421#endif 422 423 424/*--------------------------------------------------------------------*/ 425/*--- end pc_intercepts.c ---*/ 426/*--------------------------------------------------------------------*/ 427