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@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