1 2 /*--------------------------------------------------------------------*/ 3 /*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/ 4 /*--- simulated CPU. ---*/ 5 /*--- mc_replace_strmem.c ---*/ 6 /*--------------------------------------------------------------------*/ 7 8 /* 9 This file is part of Valgrind. 10 11 Copyright (C) 2000-2013 Julian Seward 12 jseward (at) acm.org 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 02111-1307, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30 */ 31 32 #include "pub_tool_basics.h" 33 #include "pub_tool_poolalloc.h" 34 #include "pub_tool_hashtable.h" 35 #include "pub_tool_redir.h" 36 #include "pub_tool_tooliface.h" 37 #include "pub_tool_clreq.h" 38 39 /* --------------------------------------------------------------------- 40 We have our own versions of these functions for two reasons: 41 (a) it allows us to do overlap checking 42 (b) some of the normal versions are hyper-optimised, which fools 43 Memcheck and cause spurious value warnings. Our versions are 44 simpler. 45 (c) the glibc SSE-variants can read past the end of the input data 46 ranges. This can cause false-positive Memcheck / Helgrind / DRD 47 reports. 48 49 Note that overenthusiastic use of PLT bypassing by the glibc people also 50 means that we need to patch multiple versions of some of the functions to 51 our own implementations. 52 53 THEY RUN ON THE SIMD CPU! 54 ------------------------------------------------------------------ */ 55 56 /* Assignment of behavioural equivalence class tags: 2NNNP is intended 57 to be reserved for str/mem intercepts. Current usage: 58 59 20010 STRRCHR 60 20020 STRCHR 61 20030 STRCAT 62 20040 STRNCAT 63 20050 STRLCAT 64 20060 STRNLEN 65 20070 STRLEN 66 20080 STRCPY 67 20090 STRNCPY 68 20100 STRLCPY 69 20110 STRNCMP 70 20120 STRCASECMP 71 20130 STRNCASECMP 72 20140 STRCASECMP_L 73 20150 STRNCASECMP_L 74 20160 STRCMP 75 20170 MEMCHR 76 77 20180 MEMCPY if there's a conflict between memcpy and 78 20181 MEMMOVE memmove, prefer memmove 79 80 20190 MEMCMP 81 20200 STPCPY 82 20210 MEMSET 83 2022P unused (was previously MEMMOVE) 84 20230 BCOPY 85 20240 GLIBC25___MEMMOVE_CHK 86 20250 GLIBC232_STRCHRNUL 87 20260 GLIBC232_RAWMEMCHR 88 20270 GLIBC25___STRCPY_CHK 89 20280 GLIBC25___STPCPY_CHK 90 20290 GLIBC25_MEMPCPY 91 20300 GLIBC26___MEMCPY_CHK 92 20310 STRSTR 93 20320 STRPBRK 94 20330 STRCSPN 95 20340 STRSPN 96 20350 STRCASESTR 97 20360 MEMRCHR 98 20370 WCSLEN 99 20380 WCSCMP 100 20390 WCSCPY 101 20400 WCSCHR 102 20410 WCSRCHR 103 20420 STPNCPY 104 */ 105 106 107 /* Figure out if [dst .. dst+dstlen-1] overlaps with 108 [src .. src+srclen-1]. 109 We assume that the address ranges do not wrap around 110 (which is safe since on Linux addresses >= 0xC0000000 111 are not accessible and the program will segfault in this 112 circumstance, presumably). 113 */ 114 static inline 115 Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen ) 116 { 117 Addr loS, hiS, loD, hiD; 118 119 if (dstlen == 0 || srclen == 0) 120 return False; 121 122 loS = (Addr)src; 123 loD = (Addr)dst; 124 hiS = loS + srclen - 1; 125 hiD = loD + dstlen - 1; 126 127 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */ 128 if (loS < loD) { 129 return !(hiS < loD); 130 } 131 else if (loD < loS) { 132 return !(hiD < loS); 133 } 134 else { 135 /* They start at same place. Since we know neither of them has 136 zero length, they must overlap. */ 137 return True; 138 } 139 } 140 141 142 /* Call here to exit if we can't continue. On Android we can't call 143 _exit for some reason, so we have to blunt-instrument it. */ 144 __attribute__ ((__noreturn__)) 145 static inline void my_exit ( int x ) 146 { 147 # if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \ 148 || defined(VGPV_mips32_linux_android) 149 __asm__ __volatile__(".word 0xFFFFFFFF"); 150 while (1) {} 151 # elif defined(VGPV_x86_linux_android) 152 __asm__ __volatile__("ud2"); 153 while (1) {} 154 # else 155 extern __attribute__ ((__noreturn__)) void _exit(int status); 156 _exit(x); 157 # endif 158 } 159 160 161 // This is a macro rather than a function because we don't want to have an 162 // extra function in the stack trace. 163 #ifndef RECORD_OVERLAP_ERROR 164 #define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0) 165 #endif 166 #ifndef VALGRIND_CHECK_VALUE_IS_DEFINED 167 #define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1 168 #endif 169 170 171 /*---------------------- strrchr ----------------------*/ 172 173 #define STRRCHR(soname, fnname) \ 174 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \ 175 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \ 176 { \ 177 HChar ch = (HChar)c; \ 178 const HChar* p = s; \ 179 const HChar* last = NULL; \ 180 while (True) { \ 181 if (*p == ch) last = p; \ 182 if (*p == 0) return (HChar *)last; \ 183 p++; \ 184 } \ 185 } 186 187 // Apparently rindex() is the same thing as strrchr() 188 #if defined(VGO_linux) 189 STRRCHR(VG_Z_LIBC_SONAME, strrchr) 190 STRRCHR(VG_Z_LIBC_SONAME, rindex) 191 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr) 192 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2) 193 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2_no_bsf) 194 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse42) 195 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex) 196 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \ 197 || defined(VGPV_mips32_linux_android) 198 STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */ 199 #endif 200 201 #elif defined(VGO_darwin) 202 //STRRCHR(VG_Z_LIBC_SONAME, strrchr) 203 //STRRCHR(VG_Z_LIBC_SONAME, rindex) 204 //STRRCHR(VG_Z_DYLD, strrchr) 205 //STRRCHR(VG_Z_DYLD, rindex) 206 STRRCHR(VG_Z_LIBC_SONAME, strrchr) 207 208 #endif 209 210 211 /*---------------------- strchr ----------------------*/ 212 213 #define STRCHR(soname, fnname) \ 214 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \ 215 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \ 216 { \ 217 HChar ch = (HChar)c ; \ 218 const HChar* p = s; \ 219 while (True) { \ 220 if (*p == ch) return (HChar *)p; \ 221 if (*p == 0) return NULL; \ 222 p++; \ 223 } \ 224 } 225 226 // Apparently index() is the same thing as strchr() 227 #if defined(VGO_linux) 228 STRCHR(VG_Z_LIBC_SONAME, strchr) 229 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) 230 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2) 231 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2_no_bsf) 232 STRCHR(VG_Z_LIBC_SONAME, index) 233 # if !defined(VGP_x86_linux) 234 STRCHR(VG_Z_LD_LINUX_SO_2, strchr) 235 STRCHR(VG_Z_LD_LINUX_SO_2, index) 236 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr) 237 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) 238 # endif 239 240 #elif defined(VGO_darwin) 241 //STRCHR(VG_Z_LIBC_SONAME, strchr) 242 //STRCHR(VG_Z_LIBC_SONAME, index) 243 //STRCHR(VG_Z_DYLD, strchr) 244 //STRCHR(VG_Z_DYLD, index) 245 STRCHR(VG_Z_LIBC_SONAME, strchr) 246 247 #endif 248 249 250 /*---------------------- strcat ----------------------*/ 251 252 #define STRCAT(soname, fnname) \ 253 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ 254 ( char* dst, const char* src ); \ 255 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ 256 ( char* dst, const char* src ) \ 257 { \ 258 const HChar* src_orig = src; \ 259 HChar* dst_orig = dst; \ 260 while (*dst) dst++; \ 261 while (*src) *dst++ = *src++; \ 262 *dst = 0; \ 263 \ 264 /* This is a bit redundant, I think; any overlap and the strcat will */ \ 265 /* go forever... or until a seg fault occurs. */ \ 266 if (is_overlap(dst_orig, \ 267 src_orig, \ 268 (Addr)dst-(Addr)dst_orig+1, \ 269 (Addr)src-(Addr)src_orig+1)) \ 270 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \ 271 \ 272 return dst_orig; \ 273 } 274 275 #if defined(VGO_linux) 276 STRCAT(VG_Z_LIBC_SONAME, strcat) 277 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) 278 279 #elif defined(VGO_darwin) 280 //STRCAT(VG_Z_LIBC_SONAME, strcat) 281 282 #endif 283 284 285 /*---------------------- strncat ----------------------*/ 286 287 #define STRNCAT(soname, fnname) \ 288 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ 289 ( char* dst, const char* src, SizeT n ); \ 290 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ 291 ( char* dst, const char* src, SizeT n ) \ 292 { \ 293 const HChar* src_orig = src; \ 294 HChar* dst_orig = dst; \ 295 SizeT m = 0; \ 296 \ 297 while (*dst) dst++; \ 298 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \ 299 *dst = 0; /* always add null */ \ 300 \ 301 /* This checks for overlap after copying, unavoidable without */ \ 302 /* pre-counting lengths... should be ok */ \ 303 if (is_overlap(dst_orig, \ 304 src_orig, \ 305 (Addr)dst-(Addr)dst_orig+1, \ 306 (Addr)src-(Addr)src_orig+1)) \ 307 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \ 308 \ 309 return dst_orig; \ 310 } 311 312 #if defined(VGO_linux) 313 STRNCAT(VG_Z_LIBC_SONAME, strncat) 314 315 #elif defined(VGO_darwin) 316 //STRNCAT(VG_Z_LIBC_SONAME, strncat) 317 //STRNCAT(VG_Z_DYLD, strncat) 318 319 #endif 320 321 322 /*---------------------- strlcat ----------------------*/ 323 324 /* Append src to dst. n is the size of dst's buffer. dst is guaranteed 325 to be nul-terminated after the copy, unless n <= strlen(dst_orig). 326 Returns min(n, strlen(dst_orig)) + strlen(src_orig). 327 Truncation occurred if retval >= n. 328 */ 329 #define STRLCAT(soname, fnname) \ 330 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ 331 ( char* dst, const char* src, SizeT n ); \ 332 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ 333 ( char* dst, const char* src, SizeT n ) \ 334 { \ 335 const HChar* src_orig = src; \ 336 HChar* dst_orig = dst; \ 337 SizeT m = 0; \ 338 \ 339 while (m < n && *dst) { m++; dst++; } \ 340 if (m < n) { \ 341 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \ 342 while (m < n-1 && *src) { m++; *dst++ = *src++; } \ 343 *dst = 0; \ 344 } else { \ 345 /* No space to copy anything to dst. m == n */ \ 346 } \ 347 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \ 348 while (*src) { m++; src++; } \ 349 /* This checks for overlap after copying, unavoidable without */ \ 350 /* pre-counting lengths... should be ok */ \ 351 if (is_overlap(dst_orig, \ 352 src_orig, \ 353 (Addr)dst-(Addr)dst_orig+1, \ 354 (Addr)src-(Addr)src_orig+1)) \ 355 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \ 356 \ 357 return m; \ 358 } 359 360 #if defined(VGO_linux) 361 362 #elif defined(VGO_darwin) 363 //STRLCAT(VG_Z_LIBC_SONAME, strlcat) 364 //STRLCAT(VG_Z_DYLD, strlcat) 365 STRLCAT(VG_Z_LIBC_SONAME, strlcat) 366 367 #endif 368 369 370 /*---------------------- strnlen ----------------------*/ 371 372 #define STRNLEN(soname, fnname) \ 373 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ 374 ( const char* str, SizeT n ); \ 375 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ 376 ( const char* str, SizeT n ) \ 377 { \ 378 SizeT i = 0; \ 379 while (i < n && str[i] != 0) i++; \ 380 return i; \ 381 } 382 383 #if defined(VGO_linux) 384 STRNLEN(VG_Z_LIBC_SONAME, strnlen) 385 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen) 386 387 #elif defined(VGO_darwin) 388 //STRNLEN(VG_Z_LIBC_SONAME, strnlen) 389 390 #endif 391 392 393 /*---------------------- strlen ----------------------*/ 394 395 // Note that this replacement often doesn't get used because gcc inlines 396 // calls to strlen() with its own built-in version. This can be very 397 // confusing if you aren't expecting it. Other small functions in 398 // this file may also be inline by gcc. 399 400 #define STRLEN(soname, fnname) \ 401 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ 402 ( const char* str ); \ 403 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ 404 ( const char* str ) \ 405 { \ 406 SizeT i = 0; \ 407 while (str[i] != 0) i++; \ 408 return i; \ 409 } 410 411 #if defined(VGO_linux) 412 STRLEN(VG_Z_LIBC_SONAME, strlen) 413 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) 414 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2) 415 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2_no_bsf) 416 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse42) 417 STRLEN(VG_Z_LD_LINUX_SO_2, strlen) 418 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen) 419 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \ 420 || defined(VGPV_mips32_linux_android) 421 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */ 422 # endif 423 424 #elif defined(VGO_darwin) 425 //STRLEN(VG_Z_LIBC_SONAME, strlen) 426 STRLEN(VG_Z_LIBC_SONAME, strlen) 427 428 #endif 429 430 431 /*---------------------- strcpy ----------------------*/ 432 433 #define STRCPY(soname, fnname) \ 434 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ 435 ( char* dst, const char* src ); \ 436 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ 437 ( char* dst, const char* src ) \ 438 { \ 439 const HChar* src_orig = src; \ 440 HChar* dst_orig = dst; \ 441 \ 442 while (*src) *dst++ = *src++; \ 443 *dst = 0; \ 444 \ 445 /* This checks for overlap after copying, unavoidable without */ \ 446 /* pre-counting length... should be ok */ \ 447 if (is_overlap(dst_orig, \ 448 src_orig, \ 449 (Addr)dst-(Addr)dst_orig+1, \ 450 (Addr)src-(Addr)src_orig+1)) \ 451 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \ 452 \ 453 return dst_orig; \ 454 } 455 456 #if defined(VGO_linux) 457 STRCPY(VG_Z_LIBC_SONAME, strcpy) 458 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) 459 460 #elif defined(VGO_darwin) 461 //STRCPY(VG_Z_LIBC_SONAME, strcpy) 462 //STRCPY(VG_Z_DYLD, strcpy) 463 STRCPY(VG_Z_LIBC_SONAME, strcpy) 464 465 #endif 466 467 468 /*---------------------- strncpy ----------------------*/ 469 470 #define STRNCPY(soname, fnname) \ 471 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ 472 ( char* dst, const char* src, SizeT n ); \ 473 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ 474 ( char* dst, const char* src, SizeT n ) \ 475 { \ 476 const HChar* src_orig = src; \ 477 HChar* dst_orig = dst; \ 478 SizeT m = 0; \ 479 \ 480 while (m < n && *src) { m++; *dst++ = *src++; } \ 481 /* Check for overlap after copying; all n bytes of dst are relevant, */ \ 482 /* but only m+1 bytes of src if terminator was found */ \ 483 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ 484 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \ 485 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \ 486 \ 487 return dst_orig; \ 488 } 489 490 #if defined(VGO_linux) 491 STRNCPY(VG_Z_LIBC_SONAME, strncpy) 492 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy) 493 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2) 494 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned) 495 496 #elif defined(VGO_darwin) 497 //STRNCPY(VG_Z_LIBC_SONAME, strncpy) 498 //STRNCPY(VG_Z_DYLD, strncpy) 499 STRNCPY(VG_Z_LIBC_SONAME, strncpy) 500 501 #endif 502 503 504 /*---------------------- strlcpy ----------------------*/ 505 506 /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0. 507 Returns strlen(src). Does not zero-fill the remainder of dst. */ 508 #define STRLCPY(soname, fnname) \ 509 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ 510 ( char* dst, const char* src, SizeT n ); \ 511 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ 512 ( char* dst, const char* src, SizeT n ) \ 513 { \ 514 const HChar* src_orig = src; \ 515 HChar* dst_orig = dst; \ 516 SizeT m = 0; \ 517 \ 518 while (m < n-1 && *src) { m++; *dst++ = *src++; } \ 519 /* m non-nul bytes have now been copied, and m <= n-1. */ \ 520 /* Check for overlap after copying; all n bytes of dst are relevant, */ \ 521 /* but only m+1 bytes of src if terminator was found */ \ 522 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ 523 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \ 524 /* Nul-terminate dst. */ \ 525 if (n > 0) *dst = 0; \ 526 /* Finish counting strlen(src). */ \ 527 while (*src) src++; \ 528 return src - src_orig; \ 529 } 530 531 #if defined(VGO_linux) 532 533 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \ 534 || defined(VGPV_mips32_linux_android) 535 STRLCPY(VG_Z_LIBC_SONAME, strlcpy); 536 #endif 537 538 #elif defined(VGO_darwin) 539 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy) 540 //STRLCPY(VG_Z_DYLD, strlcpy) 541 STRLCPY(VG_Z_LIBC_SONAME, strlcpy) 542 543 #endif 544 545 546 /*---------------------- strncmp ----------------------*/ 547 548 #define STRNCMP(soname, fnname) \ 549 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ 550 ( const char* s1, const char* s2, SizeT nmax ); \ 551 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ 552 ( const char* s1, const char* s2, SizeT nmax ) \ 553 { \ 554 SizeT n = 0; \ 555 while (True) { \ 556 if (n >= nmax) return 0; \ 557 if (*s1 == 0 && *s2 == 0) return 0; \ 558 if (*s1 == 0) return -1; \ 559 if (*s2 == 0) return 1; \ 560 \ 561 if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \ 562 if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \ 563 \ 564 s1++; s2++; n++; \ 565 } \ 566 } 567 568 #if defined(VGO_linux) 569 STRNCMP(VG_Z_LIBC_SONAME, strncmp) 570 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) 571 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2) 572 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42) 573 574 #elif defined(VGO_darwin) 575 //STRNCMP(VG_Z_LIBC_SONAME, strncmp) 576 //STRNCMP(VG_Z_DYLD, strncmp) 577 STRNCMP(VG_Z_LIBC_SONAME, strncmp) 578 579 #endif 580 581 582 /*---------------------- strcasecmp ----------------------*/ 583 584 #define STRCASECMP(soname, fnname) \ 585 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ 586 ( const char* s1, const char* s2 ); \ 587 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ 588 ( const char* s1, const char* s2 ) \ 589 { \ 590 extern int tolower(int); \ 591 register UChar c1; \ 592 register UChar c2; \ 593 while (True) { \ 594 c1 = tolower(*(const UChar *)s1); \ 595 c2 = tolower(*(const UChar *)s2); \ 596 if (c1 != c2) break; \ 597 if (c1 == 0) break; \ 598 s1++; s2++; \ 599 } \ 600 if ((UChar)c1 < (UChar)c2) return -1; \ 601 if ((UChar)c1 > (UChar)c2) return 1; \ 602 return 0; \ 603 } 604 605 #if defined(VGO_linux) 606 # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \ 607 && !defined(VGPV_mips32_linux_android) 608 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) 609 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp) 610 # endif 611 612 #elif defined(VGO_darwin) 613 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) 614 615 #endif 616 617 618 /*---------------------- strncasecmp ----------------------*/ 619 620 #define STRNCASECMP(soname, fnname) \ 621 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ 622 ( const char* s1, const char* s2, SizeT nmax ); \ 623 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ 624 ( const char* s1, const char* s2, SizeT nmax ) \ 625 { \ 626 extern int tolower(int); \ 627 SizeT n = 0; \ 628 while (True) { \ 629 if (n >= nmax) return 0; \ 630 if (*s1 == 0 && *s2 == 0) return 0; \ 631 if (*s1 == 0) return -1; \ 632 if (*s2 == 0) return 1; \ 633 \ 634 if (tolower(*(const UChar *)s1) \ 635 < tolower(*(const UChar*)s2)) return -1; \ 636 if (tolower(*(const UChar *)s1) \ 637 > tolower(*(const UChar *)s2)) return 1; \ 638 \ 639 s1++; s2++; n++; \ 640 } \ 641 } 642 643 #if defined(VGO_linux) 644 # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \ 645 && !defined(VGPV_mips32_linux_android) 646 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) 647 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp) 648 # endif 649 650 #elif defined(VGO_darwin) 651 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) 652 //STRNCASECMP(VG_Z_DYLD, strncasecmp) 653 654 #endif 655 656 657 /*---------------------- strcasecmp_l ----------------------*/ 658 659 #define STRCASECMP_L(soname, fnname) \ 660 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ 661 ( const char* s1, const char* s2, void* locale ); \ 662 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ 663 ( const char* s1, const char* s2, void* locale ) \ 664 { \ 665 extern int tolower_l(int, void*) __attribute__((weak)); \ 666 register UChar c1; \ 667 register UChar c2; \ 668 while (True) { \ 669 c1 = tolower_l(*(const UChar *)s1, locale); \ 670 c2 = tolower_l(*(const UChar *)s2, locale); \ 671 if (c1 != c2) break; \ 672 if (c1 == 0) break; \ 673 s1++; s2++; \ 674 } \ 675 if ((UChar)c1 < (UChar)c2) return -1; \ 676 if ((UChar)c1 > (UChar)c2) return 1; \ 677 return 0; \ 678 } 679 680 #if defined(VGO_linux) 681 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) 682 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l) 683 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l) 684 685 #elif defined(VGO_darwin) 686 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) 687 688 #endif 689 690 691 /*---------------------- strncasecmp_l ----------------------*/ 692 693 #define STRNCASECMP_L(soname, fnname) \ 694 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ 695 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \ 696 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ 697 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \ 698 { \ 699 extern int tolower_l(int, void*) __attribute__((weak)); \ 700 SizeT n = 0; \ 701 while (True) { \ 702 if (n >= nmax) return 0; \ 703 if (*s1 == 0 && *s2 == 0) return 0; \ 704 if (*s1 == 0) return -1; \ 705 if (*s2 == 0) return 1; \ 706 \ 707 if (tolower_l(*(const UChar *)s1, locale) \ 708 < tolower_l(*(const UChar *)s2, locale)) return -1; \ 709 if (tolower_l(*(const UChar *)s1, locale) \ 710 > tolower_l(*(const UChar *)s2, locale)) return 1; \ 711 \ 712 s1++; s2++; n++; \ 713 } \ 714 } 715 716 #if defined(VGO_linux) 717 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) 718 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l) 719 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l) 720 721 #elif defined(VGO_darwin) 722 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) 723 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l) 724 725 #endif 726 727 728 /*---------------------- strcmp ----------------------*/ 729 730 #define STRCMP(soname, fnname) \ 731 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ 732 ( const char* s1, const char* s2 ); \ 733 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ 734 ( const char* s1, const char* s2 ) \ 735 { \ 736 register UChar c1; \ 737 register UChar c2; \ 738 while (True) { \ 739 c1 = *(const UChar *)s1; \ 740 c2 = *(const UChar *)s2; \ 741 if (c1 != c2) break; \ 742 if (c1 == 0) break; \ 743 s1++; s2++; \ 744 } \ 745 if ((UChar)c1 < (UChar)c2) return -1; \ 746 if ((UChar)c1 > (UChar)c2) return 1; \ 747 return 0; \ 748 } 749 750 #if defined(VGO_linux) 751 STRCMP(VG_Z_LIBC_SONAME, strcmp) 752 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) 753 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse2) 754 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse42) 755 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp) 756 STRCMP(VG_Z_LD64_SO_1, strcmp) 757 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \ 758 || defined(VGPV_mips32_linux_android) 759 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */ 760 # endif 761 762 #elif defined(VGO_darwin) 763 //STRCMP(VG_Z_LIBC_SONAME, strcmp) 764 STRCMP(VG_Z_LIBC_SONAME, strcmp) 765 766 #endif 767 768 769 /*---------------------- memchr ----------------------*/ 770 771 #define MEMCHR(soname, fnname) \ 772 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ 773 (const void *s, int c, SizeT n); \ 774 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ 775 (const void *s, int c, SizeT n) \ 776 { \ 777 SizeT i; \ 778 UChar c0 = (UChar)c; \ 779 UChar* p = (UChar*)s; \ 780 for (i = 0; i < n; i++) \ 781 if (p[i] == c0) return (void*)(&p[i]); \ 782 return NULL; \ 783 } 784 785 #if defined(VGO_linux) 786 MEMCHR(VG_Z_LIBC_SONAME, memchr) 787 MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr) 788 789 #elif defined(VGO_darwin) 790 //MEMCHR(VG_Z_LIBC_SONAME, memchr) 791 //MEMCHR(VG_Z_DYLD, memchr) 792 793 #endif 794 795 796 /*---------------------- memrchr ----------------------*/ 797 798 #define MEMRCHR(soname, fnname) \ 799 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \ 800 (const void *s, int c, SizeT n); \ 801 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \ 802 (const void *s, int c, SizeT n) \ 803 { \ 804 SizeT i; \ 805 UChar c0 = (UChar)c; \ 806 UChar* p = (UChar*)s; \ 807 for (i = 0; i < n; i++) \ 808 if (p[n-1-i] == c0) return (void*)(&p[n-1-i]); \ 809 return NULL; \ 810 } 811 812 #if defined(VGO_linux) 813 MEMRCHR(VG_Z_LIBC_SONAME, memrchr) 814 815 #elif defined(VGO_darwin) 816 //MEMRCHR(VG_Z_LIBC_SONAME, memrchr) 817 //MEMRCHR(VG_Z_DYLD, memrchr) 818 819 #endif 820 821 822 /*---------------------- memcpy ----------------------*/ 823 824 #define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \ 825 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ 826 ( void *dst, const void *src, SizeT len ); \ 827 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ 828 ( void *dst, const void *src, SizeT len ) \ 829 { \ 830 if (do_ol_check && is_overlap(dst, src, len, len)) \ 831 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \ 832 \ 833 const Addr WS = sizeof(UWord); /* 8 or 4 */ \ 834 const Addr WM = WS - 1; /* 7 or 3 */ \ 835 \ 836 if (len > 0) { \ 837 if (dst < src || !is_overlap(dst, src, len, len)) { \ 838 \ 839 /* Copying backwards. */ \ 840 SizeT n = len; \ 841 Addr d = (Addr)dst; \ 842 Addr s = (Addr)src; \ 843 \ 844 if (((s^d) & WM) == 0) { \ 845 /* s and d have same UWord alignment. */ \ 846 /* Pull up to a UWord boundary. */ \ 847 while ((s & WM) != 0 && n >= 1) \ 848 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 849 /* Copy UWords. */ \ 850 while (n >= WS) \ 851 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \ 852 if (n == 0) \ 853 return dst; \ 854 } \ 855 if (((s|d) & 1) == 0) { \ 856 /* Both are 16-aligned; copy what we can thusly. */ \ 857 while (n >= 2) \ 858 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \ 859 } \ 860 /* Copy leftovers, or everything if misaligned. */ \ 861 while (n >= 1) \ 862 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 863 \ 864 } else if (dst > src) { \ 865 \ 866 SizeT n = len; \ 867 Addr d = ((Addr)dst) + n; \ 868 Addr s = ((Addr)src) + n; \ 869 \ 870 /* Copying forwards. */ \ 871 if (((s^d) & WM) == 0) { \ 872 /* s and d have same UWord alignment. */ \ 873 /* Back down to a UWord boundary. */ \ 874 while ((s & WM) != 0 && n >= 1) \ 875 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 876 /* Copy UWords. */ \ 877 while (n >= WS) \ 878 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \ 879 if (n == 0) \ 880 return dst; \ 881 } \ 882 if (((s|d) & 1) == 0) { \ 883 /* Both are 16-aligned; copy what we can thusly. */ \ 884 while (n >= 2) \ 885 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \ 886 } \ 887 /* Copy leftovers, or everything if misaligned. */ \ 888 while (n >= 1) \ 889 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 890 \ 891 } \ 892 } \ 893 \ 894 return dst; \ 895 } 896 897 #define MEMMOVE(soname, fnname) \ 898 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0) 899 900 #define MEMCPY(soname, fnname) \ 901 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1) 902 903 #if defined(VGO_linux) 904 /* For older memcpy we have to use memmove-like semantics and skip 905 the overlap check; sigh; see #275284. */ 906 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy (at) GLIBC_2.2.5 */ 907 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */ 908 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */ 909 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy) 910 MEMCPY(VG_Z_LIBC_SONAME, __memcpy_sse2) 911 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ 912 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ 913 /* icc9 blats these around all over the place. Not only in the main 914 executable but various .so's. They are highly tuned and read 915 memory beyond the source boundary (although work correctly and 916 never go across page boundaries), so give errors when run 917 natively, at least for misaligned source arg. Just intercepting 918 in the exe only until we understand more about the problem. See 919 http://bugs.kde.org/show_bug.cgi?id=139776 920 */ 921 MEMCPY(NONE, ZuintelZufastZumemcpy) 922 923 #elif defined(VGO_darwin) 924 # if DARWIN_VERS <= DARWIN_10_6 925 MEMCPY(VG_Z_LIBC_SONAME, memcpy) 926 # endif 927 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */ 928 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */ 929 930 #endif 931 932 933 /*---------------------- memcmp ----------------------*/ 934 935 #define MEMCMP(soname, fnname) \ 936 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ 937 ( const void *s1V, const void *s2V, SizeT n ); \ 938 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ 939 ( const void *s1V, const void *s2V, SizeT n ) \ 940 { \ 941 int res; \ 942 UChar a0; \ 943 UChar b0; \ 944 const UChar* s1 = s1V; \ 945 const UChar* s2 = s2V; \ 946 \ 947 while (n != 0) { \ 948 a0 = s1[0]; \ 949 b0 = s2[0]; \ 950 s1 += 1; \ 951 s2 += 1; \ 952 res = ((int)a0) - ((int)b0); \ 953 if (res != 0) \ 954 return res; \ 955 n -= 1; \ 956 } \ 957 return 0; \ 958 } 959 960 #if defined(VGO_linux) 961 MEMCMP(VG_Z_LIBC_SONAME, memcmp) 962 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp) 963 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse2) 964 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse4_1) 965 MEMCMP(VG_Z_LIBC_SONAME, bcmp) 966 MEMCMP(VG_Z_LD_SO_1, bcmp) 967 968 #elif defined(VGO_darwin) 969 //MEMCMP(VG_Z_LIBC_SONAME, memcmp) 970 //MEMCMP(VG_Z_LIBC_SONAME, bcmp) 971 //MEMCMP(VG_Z_DYLD, memcmp) 972 //MEMCMP(VG_Z_DYLD, bcmp) 973 974 #endif 975 976 977 /*---------------------- stpcpy ----------------------*/ 978 979 /* Copy SRC to DEST, returning the address of the terminating '\0' in 980 DEST. (minor variant of strcpy) */ 981 #define STPCPY(soname, fnname) \ 982 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ 983 ( char* dst, const char* src ); \ 984 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ 985 ( char* dst, const char* src ) \ 986 { \ 987 const HChar* src_orig = src; \ 988 HChar* dst_orig = dst; \ 989 \ 990 while (*src) *dst++ = *src++; \ 991 *dst = 0; \ 992 \ 993 /* This checks for overlap after copying, unavoidable without */ \ 994 /* pre-counting length... should be ok */ \ 995 if (is_overlap(dst_orig, \ 996 src_orig, \ 997 (Addr)dst-(Addr)dst_orig+1, \ 998 (Addr)src-(Addr)src_orig+1)) \ 999 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \ 1000 \ 1001 return dst; \ 1002 } 1003 1004 #if defined(VGO_linux) 1005 STPCPY(VG_Z_LIBC_SONAME, stpcpy) 1006 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy) 1007 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2) 1008 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2_unaligned) 1009 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) 1010 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) 1011 1012 #elif defined(VGO_darwin) 1013 //STPCPY(VG_Z_LIBC_SONAME, stpcpy) 1014 //STPCPY(VG_Z_DYLD, stpcpy) 1015 1016 #endif 1017 1018 1019 /*---------------------- stpncpy ----------------------*/ 1020 1021 #define STPNCPY(soname, fnname) \ 1022 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \ 1023 ( char* dst, const char* src, SizeT n ); \ 1024 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \ 1025 ( char* dst, const char* src, SizeT n ) \ 1026 { \ 1027 const HChar* src_orig = src; \ 1028 HChar* dst_str = dst; \ 1029 SizeT m = 0; \ 1030 \ 1031 while (m < n && *src) { m++; *dst++ = *src++; } \ 1032 /* Check for overlap after copying; all n bytes of dst are relevant, */ \ 1033 /* but only m+1 bytes of src if terminator was found */ \ 1034 if (is_overlap(dst_str, src_orig, n, (m < n) ? m+1 : n)) \ 1035 RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \ 1036 dst_str = dst; \ 1037 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \ 1038 \ 1039 return dst_str; \ 1040 } 1041 1042 #if defined(VGO_linux) 1043 STPNCPY(VG_Z_LIBC_SONAME, stpncpy) 1044 #endif 1045 1046 1047 /*---------------------- memset ----------------------*/ 1048 1049 /* Why are we bothering to intercept this? It seems entirely 1050 pointless. */ 1051 1052 #define MEMSET(soname, fnname) \ 1053 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ 1054 (void *s, Int c, SizeT n); \ 1055 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ 1056 (void *s, Int c, SizeT n) \ 1057 { \ 1058 if (sizeof(void*) == 8) { \ 1059 Addr a = (Addr)s; \ 1060 ULong c8 = (c & 0xFF); \ 1061 c8 = (c8 << 8) | c8; \ 1062 c8 = (c8 << 16) | c8; \ 1063 c8 = (c8 << 32) | c8; \ 1064 while ((a & 7) != 0 && n >= 1) \ 1065 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 1066 while (n >= 8) \ 1067 { *(ULong*)a = c8; a += 8; n -= 8; } \ 1068 while (n >= 1) \ 1069 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 1070 return s; \ 1071 } else { \ 1072 Addr a = (Addr)s; \ 1073 UInt c4 = (c & 0xFF); \ 1074 c4 = (c4 << 8) | c4; \ 1075 c4 = (c4 << 16) | c4; \ 1076 while ((a & 3) != 0 && n >= 1) \ 1077 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 1078 while (n >= 4) \ 1079 { *(UInt*)a = c4; a += 4; n -= 4; } \ 1080 while (n >= 1) \ 1081 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 1082 return s; \ 1083 } \ 1084 } 1085 1086 #if defined(VGO_linux) 1087 MEMSET(VG_Z_LIBC_SONAME, memset) 1088 1089 #elif defined(VGO_darwin) 1090 //MEMSET(VG_Z_LIBC_SONAME, memset) 1091 //MEMSET(VG_Z_DYLD, memset) 1092 MEMSET(VG_Z_LIBC_SONAME, memset) 1093 1094 #endif 1095 1096 1097 /*---------------------- memmove ----------------------*/ 1098 1099 /* memmove -- use the MEMMOVE defn above. */ 1100 1101 #if defined(VGO_linux) 1102 MEMMOVE(VG_Z_LIBC_SONAME, memmove) 1103 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove) 1104 1105 #elif defined(VGO_darwin) 1106 # if DARWIN_VERS <= DARWIN_10_6 1107 MEMMOVE(VG_Z_LIBC_SONAME, memmove) 1108 # endif 1109 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */ 1110 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */ 1111 1112 #endif 1113 1114 1115 /*---------------------- bcopy ----------------------*/ 1116 1117 #define BCOPY(soname, fnname) \ 1118 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ 1119 (const void *srcV, void *dstV, SizeT n); \ 1120 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ 1121 (const void *srcV, void *dstV, SizeT n) \ 1122 { \ 1123 SizeT i; \ 1124 HChar* dst = dstV; \ 1125 const HChar* src = srcV; \ 1126 if (dst < src) { \ 1127 for (i = 0; i < n; i++) \ 1128 dst[i] = src[i]; \ 1129 } \ 1130 else \ 1131 if (dst > src) { \ 1132 for (i = 0; i < n; i++) \ 1133 dst[n-i-1] = src[n-i-1]; \ 1134 } \ 1135 } 1136 1137 #if defined(VGO_linux) 1138 BCOPY(VG_Z_LIBC_SONAME, bcopy) 1139 1140 #elif defined(VGO_darwin) 1141 //BCOPY(VG_Z_LIBC_SONAME, bcopy) 1142 //BCOPY(VG_Z_DYLD, bcopy) 1143 1144 #endif 1145 1146 1147 /*-------------------- memmove_chk --------------------*/ 1148 1149 /* glibc 2.5 variant of memmove which checks the dest is big enough. 1150 There is no specific part of glibc that this is copied from. */ 1151 #define GLIBC25___MEMMOVE_CHK(soname, fnname) \ 1152 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ 1153 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \ 1154 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ 1155 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \ 1156 { \ 1157 SizeT i; \ 1158 HChar* dst = dstV; \ 1159 const HChar* src = srcV; \ 1160 if (destlen < n) \ 1161 goto badness; \ 1162 if (dst < src) { \ 1163 for (i = 0; i < n; i++) \ 1164 dst[i] = src[i]; \ 1165 } \ 1166 else \ 1167 if (dst > src) { \ 1168 for (i = 0; i < n; i++) \ 1169 dst[n-i-1] = src[n-i-1]; \ 1170 } \ 1171 return dst; \ 1172 badness: \ 1173 VALGRIND_PRINTF_BACKTRACE( \ 1174 "*** memmove_chk: buffer overflow detected ***: " \ 1175 "program terminated\n"); \ 1176 my_exit(127); \ 1177 /*NOTREACHED*/ \ 1178 return NULL; \ 1179 } 1180 1181 #if defined(VGO_linux) 1182 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk) 1183 1184 #elif defined(VGO_darwin) 1185 1186 #endif 1187 1188 1189 /*-------------------- strchrnul --------------------*/ 1190 1191 /* Find the first occurrence of C in S or the final NUL byte. */ 1192 #define GLIBC232_STRCHRNUL(soname, fnname) \ 1193 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ 1194 (const char* s, int c_in); \ 1195 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ 1196 (const char* s, int c_in) \ 1197 { \ 1198 UChar c = (UChar) c_in; \ 1199 UChar* char_ptr = (UChar *)s; \ 1200 while (1) { \ 1201 if (*char_ptr == 0) return (HChar *)char_ptr; \ 1202 if (*char_ptr == c) return (HChar *)char_ptr; \ 1203 char_ptr++; \ 1204 } \ 1205 } 1206 1207 #if defined(VGO_linux) 1208 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul) 1209 1210 #elif defined(VGO_darwin) 1211 1212 #endif 1213 1214 1215 /*---------------------- rawmemchr ----------------------*/ 1216 1217 /* Find the first occurrence of C in S. */ 1218 #define GLIBC232_RAWMEMCHR(soname, fnname) \ 1219 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ 1220 (const char* s, int c_in); \ 1221 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ 1222 (const char* s, int c_in) \ 1223 { \ 1224 UChar c = (UChar) c_in; \ 1225 UChar* char_ptr = (UChar *)s; \ 1226 while (1) { \ 1227 if (*char_ptr == c) return (HChar *)char_ptr; \ 1228 char_ptr++; \ 1229 } \ 1230 } 1231 1232 #if defined (VGO_linux) 1233 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr) 1234 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) 1235 1236 #elif defined(VGO_darwin) 1237 1238 #endif 1239 1240 1241 /*---------------------- strcpy_chk ----------------------*/ 1242 1243 /* glibc variant of strcpy that checks the dest is big enough. 1244 Copied from glibc-2.5/debug/test-strcpy_chk.c. */ 1245 #define GLIBC25___STRCPY_CHK(soname,fnname) \ 1246 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ 1247 (char* dst, const char* src, SizeT len); \ 1248 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ 1249 (char* dst, const char* src, SizeT len) \ 1250 { \ 1251 HChar* ret = dst; \ 1252 if (! len) \ 1253 goto badness; \ 1254 while ((*dst++ = *src++) != '\0') \ 1255 if (--len == 0) \ 1256 goto badness; \ 1257 return ret; \ 1258 badness: \ 1259 VALGRIND_PRINTF_BACKTRACE( \ 1260 "*** strcpy_chk: buffer overflow detected ***: " \ 1261 "program terminated\n"); \ 1262 my_exit(127); \ 1263 /*NOTREACHED*/ \ 1264 return NULL; \ 1265 } 1266 1267 #if defined(VGO_linux) 1268 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk) 1269 1270 #elif defined(VGO_darwin) 1271 1272 #endif 1273 1274 1275 /*---------------------- stpcpy_chk ----------------------*/ 1276 1277 /* glibc variant of stpcpy that checks the dest is big enough. 1278 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */ 1279 #define GLIBC25___STPCPY_CHK(soname,fnname) \ 1280 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ 1281 (char* dst, const char* src, SizeT len); \ 1282 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ 1283 (char* dst, const char* src, SizeT len) \ 1284 { \ 1285 if (! len) \ 1286 goto badness; \ 1287 while ((*dst++ = *src++) != '\0') \ 1288 if (--len == 0) \ 1289 goto badness; \ 1290 return dst - 1; \ 1291 badness: \ 1292 VALGRIND_PRINTF_BACKTRACE( \ 1293 "*** stpcpy_chk: buffer overflow detected ***: " \ 1294 "program terminated\n"); \ 1295 my_exit(127); \ 1296 /*NOTREACHED*/ \ 1297 return NULL; \ 1298 } 1299 1300 #if defined(VGO_linux) 1301 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk) 1302 1303 #elif defined(VGO_darwin) 1304 1305 #endif 1306 1307 1308 /*---------------------- mempcpy ----------------------*/ 1309 1310 /* mempcpy */ 1311 #define GLIBC25_MEMPCPY(soname, fnname) \ 1312 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ 1313 ( void *dst, const void *src, SizeT len ); \ 1314 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ 1315 ( void *dst, const void *src, SizeT len ) \ 1316 { \ 1317 register HChar *d; \ 1318 register HChar *s; \ 1319 SizeT len_saved = len; \ 1320 \ 1321 if (len == 0) \ 1322 return dst; \ 1323 \ 1324 if (is_overlap(dst, src, len, len)) \ 1325 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \ 1326 \ 1327 if ( dst > src ) { \ 1328 d = (char *)dst + len - 1; \ 1329 s = (char *)src + len - 1; \ 1330 while ( len-- ) { \ 1331 *d-- = *s--; \ 1332 } \ 1333 } else if ( dst < src ) { \ 1334 d = (char *)dst; \ 1335 s = (char *)src; \ 1336 while ( len-- ) { \ 1337 *d++ = *s++; \ 1338 } \ 1339 } \ 1340 return (void*)( ((char*)dst) + len_saved ); \ 1341 } 1342 1343 #if defined(VGO_linux) 1344 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) 1345 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */ 1346 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */ 1347 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */ 1348 1349 #elif defined(VGO_darwin) 1350 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) 1351 1352 #endif 1353 1354 1355 /*-------------------- memcpy_chk --------------------*/ 1356 1357 #define GLIBC26___MEMCPY_CHK(soname, fnname) \ 1358 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ 1359 (void* dst, const void* src, SizeT len, SizeT dstlen ); \ 1360 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ 1361 (void* dst, const void* src, SizeT len, SizeT dstlen ) \ 1362 { \ 1363 register HChar *d; \ 1364 register const HChar *s; \ 1365 \ 1366 if (dstlen < len) goto badness; \ 1367 \ 1368 if (len == 0) \ 1369 return dst; \ 1370 \ 1371 if (is_overlap(dst, src, len, len)) \ 1372 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \ 1373 \ 1374 if ( dst > src ) { \ 1375 d = (HChar *)dst + len - 1; \ 1376 s = (const HChar *)src + len - 1; \ 1377 while ( len-- ) { \ 1378 *d-- = *s--; \ 1379 } \ 1380 } else if ( dst < src ) { \ 1381 d = (HChar *)dst; \ 1382 s = (const HChar *)src; \ 1383 while ( len-- ) { \ 1384 *d++ = *s++; \ 1385 } \ 1386 } \ 1387 return dst; \ 1388 badness: \ 1389 VALGRIND_PRINTF_BACKTRACE( \ 1390 "*** memcpy_chk: buffer overflow detected ***: " \ 1391 "program terminated\n"); \ 1392 my_exit(127); \ 1393 /*NOTREACHED*/ \ 1394 return NULL; \ 1395 } 1396 1397 #if defined(VGO_linux) 1398 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk) 1399 1400 #elif defined(VGO_darwin) 1401 1402 #endif 1403 1404 1405 /*---------------------- strstr ----------------------*/ 1406 1407 #define STRSTR(soname, fnname) \ 1408 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ 1409 (const char* haystack, const char* needle); \ 1410 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ 1411 (const char* haystack, const char* needle) \ 1412 { \ 1413 const HChar* h = haystack; \ 1414 const HChar* n = needle; \ 1415 \ 1416 /* find the length of n, not including terminating zero */ \ 1417 UWord nlen = 0; \ 1418 while (n[nlen]) nlen++; \ 1419 \ 1420 /* if n is the empty string, match immediately. */ \ 1421 if (nlen == 0) return (HChar *)h; \ 1422 \ 1423 /* assert(nlen >= 1); */ \ 1424 HChar n0 = n[0]; \ 1425 \ 1426 while (1) { \ 1427 const HChar hh = *h; \ 1428 if (hh == 0) return NULL; \ 1429 if (hh != n0) { h++; continue; } \ 1430 \ 1431 UWord i; \ 1432 for (i = 0; i < nlen; i++) { \ 1433 if (n[i] != h[i]) \ 1434 break; \ 1435 } \ 1436 /* assert(i >= 0 && i <= nlen); */ \ 1437 if (i == nlen) \ 1438 return (HChar *)h; \ 1439 \ 1440 h++; \ 1441 } \ 1442 } 1443 1444 #if defined(VGO_linux) 1445 STRSTR(VG_Z_LIBC_SONAME, strstr) 1446 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse2) 1447 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse42) 1448 1449 #elif defined(VGO_darwin) 1450 1451 #endif 1452 1453 1454 /*---------------------- strpbrk ----------------------*/ 1455 1456 #define STRPBRK(soname, fnname) \ 1457 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ 1458 (const char* sV, const char* acceptV); \ 1459 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ 1460 (const char* sV, const char* acceptV) \ 1461 { \ 1462 const HChar* s = sV; \ 1463 const HChar* accept = acceptV; \ 1464 \ 1465 /* find the length of 'accept', not including terminating zero */ \ 1466 UWord nacc = 0; \ 1467 while (accept[nacc]) nacc++; \ 1468 \ 1469 /* if n is the empty string, fail immediately. */ \ 1470 if (nacc == 0) return NULL; \ 1471 \ 1472 /* assert(nacc >= 1); */ \ 1473 while (1) { \ 1474 UWord i; \ 1475 HChar sc = *s; \ 1476 if (sc == 0) \ 1477 break; \ 1478 for (i = 0; i < nacc; i++) { \ 1479 if (sc == accept[i]) \ 1480 return (HChar *)s; \ 1481 } \ 1482 s++; \ 1483 } \ 1484 \ 1485 return NULL; \ 1486 } 1487 1488 #if defined(VGO_linux) 1489 STRPBRK(VG_Z_LIBC_SONAME, strpbrk) 1490 1491 #elif defined(VGO_darwin) 1492 1493 #endif 1494 1495 1496 /*---------------------- strcspn ----------------------*/ 1497 1498 #define STRCSPN(soname, fnname) \ 1499 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ 1500 (const char* sV, const char* rejectV); \ 1501 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ 1502 (const char* sV, const char* rejectV) \ 1503 { \ 1504 const HChar* s = sV; \ 1505 const HChar* reject = rejectV; \ 1506 \ 1507 /* find the length of 'reject', not including terminating zero */ \ 1508 UWord nrej = 0; \ 1509 while (reject[nrej]) nrej++; \ 1510 \ 1511 UWord len = 0; \ 1512 while (1) { \ 1513 UWord i; \ 1514 HChar sc = *s; \ 1515 if (sc == 0) \ 1516 break; \ 1517 for (i = 0; i < nrej; i++) { \ 1518 if (sc == reject[i]) \ 1519 break; \ 1520 } \ 1521 /* assert(i >= 0 && i <= nrej); */ \ 1522 if (i < nrej) \ 1523 break; \ 1524 s++; \ 1525 len++; \ 1526 } \ 1527 \ 1528 return len; \ 1529 } 1530 1531 #if defined(VGO_linux) 1532 STRCSPN(VG_Z_LIBC_SONAME, strcspn) 1533 1534 #elif defined(VGO_darwin) 1535 1536 #endif 1537 1538 1539 /*---------------------- strspn ----------------------*/ 1540 1541 #define STRSPN(soname, fnname) \ 1542 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ 1543 (const char* sV, const char* acceptV); \ 1544 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ 1545 (const char* sV, const char* acceptV) \ 1546 { \ 1547 const UChar* s = (const UChar *)sV; \ 1548 const UChar* accept = (const UChar *)acceptV; \ 1549 \ 1550 /* find the length of 'accept', not including terminating zero */ \ 1551 UWord nacc = 0; \ 1552 while (accept[nacc]) nacc++; \ 1553 if (nacc == 0) return 0; \ 1554 \ 1555 UWord len = 0; \ 1556 while (1) { \ 1557 UWord i; \ 1558 HChar sc = *s; \ 1559 if (sc == 0) \ 1560 break; \ 1561 for (i = 0; i < nacc; i++) { \ 1562 if (sc == accept[i]) \ 1563 break; \ 1564 } \ 1565 /* assert(i >= 0 && i <= nacc); */ \ 1566 if (i == nacc) \ 1567 break; \ 1568 s++; \ 1569 len++; \ 1570 } \ 1571 \ 1572 return len; \ 1573 } 1574 1575 #if defined(VGO_linux) 1576 STRSPN(VG_Z_LIBC_SONAME, strspn) 1577 1578 #elif defined(VGO_darwin) 1579 1580 #endif 1581 1582 1583 /*---------------------- strcasestr ----------------------*/ 1584 1585 #define STRCASESTR(soname, fnname) \ 1586 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ 1587 (const char* haystack, const char* needle); \ 1588 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ 1589 (const char* haystack, const char* needle) \ 1590 { \ 1591 extern int tolower(int); \ 1592 const HChar* h = haystack; \ 1593 const HChar* n = needle; \ 1594 \ 1595 /* find the length of n, not including terminating zero */ \ 1596 UWord nlen = 0; \ 1597 while (n[nlen]) nlen++; \ 1598 \ 1599 /* if n is the empty string, match immediately. */ \ 1600 if (nlen == 0) return (HChar *)h; \ 1601 \ 1602 /* assert(nlen >= 1); */ \ 1603 UChar n0 = tolower(n[0]); \ 1604 \ 1605 while (1) { \ 1606 UChar hh = tolower(*h); \ 1607 if (hh == 0) return NULL; \ 1608 if (hh != n0) { h++; continue; } \ 1609 \ 1610 UWord i; \ 1611 for (i = 0; i < nlen; i++) { \ 1612 if (tolower(n[i]) != tolower(h[i])) \ 1613 break; \ 1614 } \ 1615 /* assert(i >= 0 && i <= nlen); */ \ 1616 if (i == nlen) \ 1617 return (HChar *)h; \ 1618 \ 1619 h++; \ 1620 } \ 1621 } 1622 1623 #if defined(VGO_linux) 1624 # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \ 1625 && !defined(VGPV_mips32_linux_android) 1626 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr) 1627 # endif 1628 1629 #elif defined(VGO_darwin) 1630 1631 #endif 1632 1633 1634 /*---------------------- wcslen ----------------------*/ 1635 1636 // This is a wchar_t equivalent to strlen. Unfortunately 1637 // we don't have wchar_t available here, but it looks like 1638 // a 32 bit int on Linux. I don't know if that is also 1639 // valid on MacOSX. 1640 1641 #define WCSLEN(soname, fnname) \ 1642 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \ 1643 ( const UInt* str ); \ 1644 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \ 1645 ( const UInt* str ) \ 1646 { \ 1647 SizeT i = 0; \ 1648 while (str[i] != 0) i++; \ 1649 return i; \ 1650 } 1651 1652 #if defined(VGO_linux) 1653 WCSLEN(VG_Z_LIBC_SONAME, wcslen) 1654 1655 #elif defined(VGO_darwin) 1656 1657 #endif 1658 1659 /*---------------------- wcscmp ----------------------*/ 1660 1661 // This is a wchar_t equivalent to strcmp. We don't 1662 // have wchar_t available here, but in the GNU C Library 1663 // wchar_t is always 32 bits wide and wcscmp uses signed 1664 // comparison, not unsigned as in strcmp function. 1665 1666 #define WCSCMP(soname, fnname) \ 1667 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \ 1668 ( const Int* s1, const Int* s2 ); \ 1669 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \ 1670 ( const Int* s1, const Int* s2 ) \ 1671 { \ 1672 register Int c1; \ 1673 register Int c2; \ 1674 while (True) { \ 1675 c1 = *s1; \ 1676 c2 = *s2; \ 1677 if (c1 != c2) break; \ 1678 if (c1 == 0) break; \ 1679 s1++; s2++; \ 1680 } \ 1681 if (c1 < c2) return -1; \ 1682 if (c1 > c2) return 1; \ 1683 return 0; \ 1684 } 1685 1686 #if defined(VGO_linux) 1687 WCSCMP(VG_Z_LIBC_SONAME, wcscmp) 1688 #endif 1689 1690 /*---------------------- wcscpy ----------------------*/ 1691 1692 // This is a wchar_t equivalent to strcpy. We don't 1693 // have wchar_t available here, but in the GNU C Library 1694 // wchar_t is always 32 bits wide. 1695 1696 #define WCSCPY(soname, fnname) \ 1697 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \ 1698 ( Int* dst, const Int* src ); \ 1699 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \ 1700 ( Int* dst, const Int* src ) \ 1701 { \ 1702 const Int* src_orig = src; \ 1703 Int* dst_orig = dst; \ 1704 \ 1705 while (*src) *dst++ = *src++; \ 1706 *dst = 0; \ 1707 \ 1708 /* This checks for overlap after copying, unavoidable without */ \ 1709 /* pre-counting length... should be ok */ \ 1710 if (is_overlap(dst_orig, \ 1711 src_orig, \ 1712 (Addr)dst-(Addr)dst_orig+1, \ 1713 (Addr)src-(Addr)src_orig+1)) \ 1714 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \ 1715 \ 1716 return dst_orig; \ 1717 } 1718 1719 #if defined(VGO_linux) 1720 WCSCPY(VG_Z_LIBC_SONAME, wcscpy) 1721 #endif 1722 1723 1724 /*---------------------- wcschr ----------------------*/ 1725 1726 // This is a wchar_t equivalent to strchr. We don't 1727 // have wchar_t available here, but in the GNU C Library 1728 // wchar_t is always 32 bits wide. 1729 1730 #define WCSCHR(soname, fnname) \ 1731 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \ 1732 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \ 1733 { \ 1734 Int* p = (Int*)s; \ 1735 while (True) { \ 1736 if (*p == c) return p; \ 1737 if (*p == 0) return NULL; \ 1738 p++; \ 1739 } \ 1740 } 1741 1742 #if defined(VGO_linux) 1743 WCSCHR(VG_Z_LIBC_SONAME, wcschr) 1744 #endif 1745 /*---------------------- wcsrchr ----------------------*/ 1746 1747 // This is a wchar_t equivalent to strrchr. We don't 1748 // have wchar_t available here, but in the GNU C Library 1749 // wchar_t is always 32 bits wide. 1750 1751 #define WCSRCHR(soname, fnname) \ 1752 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \ 1753 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \ 1754 { \ 1755 Int* p = (Int*) s; \ 1756 Int* last = NULL; \ 1757 while (True) { \ 1758 if (*p == c) last = p; \ 1759 if (*p == 0) return last; \ 1760 p++; \ 1761 } \ 1762 } 1763 1764 #if defined(VGO_linux) 1765 WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr) 1766 #endif 1767 1768 /*------------------------------------------------------------*/ 1769 /*--- Improve definedness checking of process environment ---*/ 1770 /*------------------------------------------------------------*/ 1771 1772 #if defined(VGO_linux) 1773 1774 /* If these wind up getting generated via a macro, so that multiple 1775 versions of each function exist (as above), use the _EZU variants 1776 to assign equivalance class tags. */ 1777 1778 /*---------------------- putenv ----------------------*/ 1779 1780 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string); 1781 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string) 1782 { 1783 OrigFn fn; 1784 Word result; 1785 const HChar* p = string; 1786 VALGRIND_GET_ORIG_FN(fn); 1787 /* Now by walking over the string we magically produce 1788 traces when hitting undefined memory. */ 1789 if (p) 1790 while (*p++) 1791 __asm__ __volatile__("" ::: "memory"); 1792 CALL_FN_W_W(result, fn, string); 1793 return result; 1794 } 1795 1796 1797 /*---------------------- unsetenv ----------------------*/ 1798 1799 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name); 1800 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name) 1801 { 1802 OrigFn fn; 1803 Word result; 1804 const HChar* p = name; 1805 VALGRIND_GET_ORIG_FN(fn); 1806 /* Now by walking over the string we magically produce 1807 traces when hitting undefined memory. */ 1808 if (p) 1809 while (*p++) 1810 __asm__ __volatile__("" ::: "memory"); 1811 CALL_FN_W_W(result, fn, name); 1812 return result; 1813 } 1814 1815 1816 /*---------------------- setenv ----------------------*/ 1817 1818 /* setenv */ 1819 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) 1820 (const char* name, const char* value, int overwrite); 1821 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) 1822 (const char* name, const char* value, int overwrite) 1823 { 1824 OrigFn fn; 1825 Word result; 1826 const HChar* p; 1827 VALGRIND_GET_ORIG_FN(fn); 1828 /* Now by walking over the string we magically produce 1829 traces when hitting undefined memory. */ 1830 if (name) 1831 for (p = name; *p; p++) 1832 __asm__ __volatile__("" ::: "memory"); 1833 if (value) 1834 for (p = value; *p; p++) 1835 __asm__ __volatile__("" ::: "memory"); 1836 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite); 1837 CALL_FN_W_WWW(result, fn, name, value, overwrite); 1838 return result; 1839 } 1840 1841 #endif /* defined(VGO_linux) */ 1842 1843 /*--------------------------------------------------------------------*/ 1844 /*--- end ---*/ 1845 /*--------------------------------------------------------------------*/ 1846