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