2 /*--------------------------------------------------------------------*/
3 /*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/
4 /*--- simulated CPU. ---*/
5 /*--- vg_replace_strmem.c ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of Valgrind.
11 Copyright (C) 2000-2017 Julian Seward
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #include "pub_tool_basics.h"
31 #include "pub_tool_poolalloc.h"
32 #include "pub_tool_hashtable.h"
33 #include "pub_tool_redir.h"
34 #include "pub_tool_tooliface.h"
35 #include "pub_tool_clreq.h"
37 /* ---------------------------------------------------------------------
38 We have our own versions of these functions for multiple reasons:
39 (a) it allows us to do overlap checking
40 (b) it allows us to do copy tracking
41 (c) some of the normal versions are hyper-optimised, which fools
42 Memcheck and cause spurious value warnings. Our versions are
44 (d) the glibc SSE-variants can read past the end of the input data
45 ranges. This can cause false-positive Memcheck / Helgrind / DRD
48 Note that overenthusiastic use of PLT bypassing by the glibc people also
49 means that we need to patch multiple versions of some of the functions to
50 our own implementations.
52 THEY RUN ON THE SIMD CPU!
53 ------------------------------------------------------------------ */
55 /* Assignment of behavioural equivalence class tags: 2NNNP is intended
56 to be reserved for str/mem intercepts. Current usage:
76 20180 MEMCPY if there's a conflict between memcpy and
77 20181 MEMMOVE memmove, prefer memmove
82 2022P unused (was previously MEMMOVE)
84 20240 GLIBC25___MEMMOVE_CHK
85 20250 GLIBC232_STRCHRNUL
86 20260 GLIBC232_RAWMEMCHR
87 20270 GLIBC25___STRCPY_CHK
88 20280 GLIBC25___STPCPY_CHK
90 20300 GLIBC26___MEMCPY_CHK
108 #if defined(VGO_solaris)
110 Detour functions in the libc and the runtime linker. If a function isn't
111 much optimized (and no overlap checking is necessary) then redir the
112 function only in the libc. This way we can keep stacktraces in the tests
118 /* Figure out if [dst .. dst+dstlen-1] overlaps with
119 [src .. src+srclen-1].
120 We assume that the address ranges do not wrap around
121 (which is safe since on Linux addresses >= 0xC0000000
122 are not accessible and the program will segfault in this
123 circumstance, presumably).
126 Bool
is_overlap ( void* dst
, const void* src
, SizeT dstlen
, SizeT srclen
)
128 Addr loS
, hiS
, loD
, hiD
;
130 if (dstlen
== 0 || srclen
== 0)
135 hiS
= loS
+ srclen
- 1;
136 hiD
= loD
+ dstlen
- 1;
138 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
142 else if (loD
< loS
) {
146 /* They start at same place. Since we know neither of them has
147 zero length, they must overlap. */
153 /* Call here to exit if we can't continue. On Android we can't call
154 _exit for some reason, so we have to blunt-instrument it. */
155 __attribute__ ((__noreturn__
))
156 static inline void my_exit ( int x
)
158 # if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \
159 || defined(VGPV_arm64_linux_android)
160 __asm__
__volatile__(".word 0xFFFFFFFF");
162 # elif defined(VGPV_x86_linux_android)
163 __asm__
__volatile__("ud2");
166 extern __attribute__ ((__noreturn__
)) void _exit(int status
);
172 // This is a macro rather than a function because we don't want to have an
173 // extra function in the stack trace.
174 #ifndef RECORD_OVERLAP_ERROR
175 #define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0)
178 // Used for tools that record bulk copies: memcpy, strcpy, etc.
180 #define RECORD_COPY(len) do { } while (0)
183 #define FOR_COPY(x) x
186 #ifndef VALGRIND_CHECK_VALUE_IS_DEFINED
187 #define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1
191 /*---------------------- strrchr ----------------------*/
193 #define STRRCHR(soname, fnname) \
194 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
195 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
197 HChar ch = (HChar)c; \
198 const HChar* p = s; \
199 const HChar* last = NULL; \
201 if (*p == ch) last = p; \
202 if (*p == 0) return CONST_CAST(HChar *,last); \
207 // Apparently rindex() is the same thing as strrchr()
208 #if defined(VGO_linux)
209 STRRCHR(VG_Z_LIBC_SONAME
, strrchr
)
210 STRRCHR(VG_Z_LIBC_SONAME
, rindex
)
211 STRRCHR(VG_Z_LIBC_SONAME
, __GI_strrchr
)
212 STRRCHR(VG_Z_LIBC_SONAME
, __strrchr_sse2
)
213 STRRCHR(VG_Z_LIBC_SONAME
, __strrchr_sse2_no_bsf
)
214 STRRCHR(VG_Z_LIBC_SONAME
, __strrchr_sse42
)
215 STRRCHR(VG_Z_LD_LINUX_SO_2
, rindex
)
216 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
217 || defined(VGPV_mips32_linux_android)
218 STRRCHR(NONE
, __dl_strrchr
); /* in /system/bin/linker */
221 #elif defined(VGO_darwin)
222 //STRRCHR(VG_Z_LIBC_SONAME, strrchr)
223 //STRRCHR(VG_Z_LIBC_SONAME, rindex)
224 //STRRCHR(VG_Z_DYLD, strrchr)
225 //STRRCHR(VG_Z_DYLD, rindex)
226 STRRCHR(VG_Z_LIBC_SONAME
, strrchr
)
227 # if DARWIN_VERS >= DARWIN_10_9
228 STRRCHR(libsystemZucZddylib
, strrchr
)
231 #elif defined(VGO_solaris)
232 STRRCHR(VG_Z_LIBC_SONAME
, strrchr
)
233 STRRCHR(VG_Z_LIBC_SONAME
, rindex
)
234 STRRCHR(VG_Z_LD_SO_1
, strrchr
)
239 /*---------------------- strchr ----------------------*/
241 #define STRCHR(soname, fnname) \
242 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
243 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
245 HChar ch = (HChar)c ; \
246 const HChar* p = s; \
248 if (*p == ch) return CONST_CAST(HChar *,p); \
249 if (*p == 0) return NULL; \
254 // Apparently index() is the same thing as strchr()
255 #if defined(VGO_linux)
256 STRCHR(VG_Z_LIBC_SONAME
, strchr
)
257 STRCHR(VG_Z_LIBC_SONAME
, __GI_strchr
)
258 STRCHR(VG_Z_LIBC_SONAME
, __strchr_sse2
)
259 STRCHR(VG_Z_LIBC_SONAME
, __strchr_sse2_no_bsf
)
260 STRCHR(VG_Z_LIBC_SONAME
, index
)
261 # if !defined(VGP_x86_linux) && !defined(VGP_amd64_linux)
262 STRCHR(VG_Z_LD_LINUX_SO_2
, strchr
)
263 STRCHR(VG_Z_LD_LINUX_SO_2
, index
)
264 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2
, strchr
)
265 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2
, index
)
268 #if defined(VGPV_mips32_linux_android)
269 STRCHR(NONE
, __dl_strchr
)
272 #elif defined(VGO_darwin)
273 STRCHR(VG_Z_LIBC_SONAME
, strchr
)
274 # if DARWIN_VERS == DARWIN_10_9
275 STRCHR(libsystemZuplatformZddylib
, _platform_strchr
)
277 # if DARWIN_VERS >= DARWIN_10_10
278 /* _platform_strchr$VARIANT$Generic */
279 STRCHR(libsystemZuplatformZddylib
, _platform_strchr$VARIANT$Generic
)
280 /* _platform_strchr$VARIANT$Haswell */
281 STRCHR(libsystemZuplatformZddylib
, _platform_strchr$VARIANT$Haswell
)
284 #elif defined(VGO_solaris)
285 STRCHR(VG_Z_LIBC_SONAME
, strchr
)
286 STRCHR(VG_Z_LIBC_SONAME
, index
)
287 STRCHR(VG_Z_LD_SO_1
, strchr
)
292 /*---------------------- strcat ----------------------*/
294 #define STRCAT(soname, fnname) \
295 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
296 ( char* dst, const char* src ); \
297 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
298 ( char* dst, const char* src ) \
300 const HChar* src_orig = src; \
301 HChar* dst_orig = dst; \
302 while (*dst) dst++; \
303 while (*src) *dst++ = *src++; \
306 /* This is a bit redundant, I think; any overlap and the strcat will */ \
307 /* go forever... or until a seg fault occurs. */ \
308 if (is_overlap(dst_orig, \
310 (Addr)dst-(Addr)dst_orig+1, \
311 (Addr)src-(Addr)src_orig+1)) \
312 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
317 #if defined(VGO_linux)
318 STRCAT(VG_Z_LIBC_SONAME
, strcat
)
319 STRCAT(VG_Z_LIBC_SONAME
, __GI_strcat
)
321 #elif defined(VGO_darwin)
322 //STRCAT(VG_Z_LIBC_SONAME, strcat)
324 #elif defined(VGO_solaris)
325 STRCAT(VG_Z_LIBC_SONAME
, strcat
)
326 STRCAT(VG_Z_LD_SO_1
, strcat
)
331 /*---------------------- strncat ----------------------*/
333 #define STRNCAT(soname, fnname) \
334 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
335 ( char* dst, const char* src, SizeT n ); \
336 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
337 ( char* dst, const char* src, SizeT n ) \
339 const HChar* src_orig = src; \
340 HChar* dst_orig = dst; \
343 while (*dst) dst++; \
344 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
345 *dst = 0; /* always add null */ \
347 /* This checks for overlap after copying, unavoidable without */ \
348 /* pre-counting lengths... should be ok */ \
349 if (is_overlap(dst_orig, \
351 (Addr)dst-(Addr)dst_orig+1, \
352 (Addr)src-(Addr)src_orig+1)) \
353 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
358 #if defined(VGO_linux)
359 STRNCAT(VG_Z_LIBC_SONAME
, strncat
)
361 #elif defined(VGO_darwin)
362 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
363 //STRNCAT(VG_Z_DYLD, strncat)
365 #elif defined(VGO_solaris)
366 STRNCAT(VG_Z_LIBC_SONAME
, strncat
)
371 /*---------------------- strlcat ----------------------*/
373 /* Append src to dst. n is the size of dst's buffer. dst is guaranteed
374 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
375 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
376 Truncation occurred if retval >= n.
378 #define STRLCAT(soname, fnname) \
379 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
380 ( char* dst, const char* src, SizeT n ); \
381 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
382 ( char* dst, const char* src, SizeT n ) \
384 const HChar* src_orig = src; \
385 HChar* dst_orig = dst; \
388 while (m < n && *dst) { m++; dst++; } \
390 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
391 while (m+1 < n && *src) { m++; *dst++ = *src++; } \
394 /* No space to copy anything to dst. m == n */ \
396 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
397 while (*src) { m++; src++; } \
398 /* This checks for overlap after copying, unavoidable without */ \
399 /* pre-counting lengths... should be ok */ \
400 if (is_overlap(dst_orig, \
402 (Addr)dst-(Addr)dst_orig+1, \
403 (Addr)src-(Addr)src_orig+1)) \
404 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
409 #if defined(VGO_linux)
411 #elif defined(VGO_darwin)
412 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
413 //STRLCAT(VG_Z_DYLD, strlcat)
414 STRLCAT(VG_Z_LIBC_SONAME
, strlcat
)
416 #elif defined(VGO_solaris)
417 STRLCAT(VG_Z_LIBC_SONAME
, strlcat
)
422 /*---------------------- strnlen ----------------------*/
424 #define STRNLEN(soname, fnname) \
425 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
426 ( const char* str, SizeT n ); \
427 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
428 ( const char* str, SizeT n ) \
431 while (i < n && str[i] != 0) i++; \
435 #if defined(VGO_linux)
436 STRNLEN(VG_Z_LIBC_SONAME
, strnlen
)
437 STRNLEN(VG_Z_LIBC_SONAME
, __GI_strnlen
)
439 #elif defined(VGO_darwin)
440 # if DARWIN_VERS == DARWIN_10_9
441 STRNLEN(libsystemZucZddylib
, strnlen
)
444 #elif defined(VGO_solaris)
445 STRNLEN(VG_Z_LIBC_SONAME
, strnlen
)
450 /*---------------------- strlen ----------------------*/
452 // Note that this replacement often doesn't get used because gcc inlines
453 // calls to strlen() with its own built-in version. This can be very
454 // confusing if you aren't expecting it. Other small functions in
455 // this file may also be inline by gcc.
457 #define STRLEN(soname, fnname) \
458 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
459 ( const char* str ); \
460 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
461 ( const char* str ) \
464 while (str[i] != 0) i++; \
468 #if defined(VGO_linux)
469 STRLEN(VG_Z_LIBC_SONAME
, strlen
)
470 STRLEN(VG_Z_LIBC_SONAME
, __GI_strlen
)
471 STRLEN(VG_Z_LIBC_SONAME
, __strlen_sse2
)
472 STRLEN(VG_Z_LIBC_SONAME
, __strlen_sse2_no_bsf
)
473 STRLEN(VG_Z_LIBC_SONAME
, __strlen_sse42
)
474 STRLEN(VG_Z_LD_LINUX_SO_2
, strlen
)
475 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2
, strlen
)
476 # if defined(VGPV_arm_linux_android) \
477 || defined(VGPV_x86_linux_android) \
478 || defined(VGPV_mips32_linux_android)
479 STRLEN(NONE
, __dl_strlen
); /* in /system/bin/linker */
482 #elif defined(VGO_darwin)
483 STRLEN(VG_Z_LIBC_SONAME
, strlen
)
484 # if DARWIN_VERS >= DARWIN_10_9
485 STRLEN(libsystemZucZddylib
, strlen
)
488 #elif defined(VGO_solaris)
489 STRLEN(VG_Z_LIBC_SONAME
, strlen
)
490 STRLEN(VG_Z_LD_SO_1
, strlen
)
495 /*---------------------- strcpy ----------------------*/
497 #define STRCPY(soname, fnname) \
498 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
499 ( char* dst, const char* src ); \
500 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
501 ( char* dst, const char* src ) \
503 const HChar* src_orig = src; \
504 HChar* dst_orig = dst; \
506 while (*src) *dst++ = *src++; \
509 /* This happens after copying, unavoidable without */ \
510 /* pre-counting length... should be ok */ \
511 SizeT srclen = (Addr)src-(Addr)src_orig+1; \
512 RECORD_COPY(srclen); \
513 if (is_overlap(dst_orig, \
515 (Addr)dst-(Addr)dst_orig+1, \
517 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
522 #if defined(VGO_linux)
523 STRCPY(VG_Z_LIBC_SONAME
, strcpy
)
524 STRCPY(VG_Z_LIBC_SONAME
, __GI_strcpy
)
526 #elif defined(VGO_darwin)
527 STRCPY(VG_Z_LIBC_SONAME
, strcpy
)
528 # if DARWIN_VERS == DARWIN_10_9
529 STRCPY(libsystemZucZddylib
, strcpy
)
532 #elif defined(VGO_solaris)
533 STRCPY(VG_Z_LIBC_SONAME
, strcpy
)
534 STRCPY(VG_Z_LD_SO_1
, strcpy
)
539 /*---------------------- strncpy ----------------------*/
541 #define STRNCPY(soname, fnname) \
542 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
543 ( char* dst, const char* src, SizeT n ); \
544 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
545 ( char* dst, const char* src, SizeT n ) \
547 const HChar* src_orig = src; \
548 HChar* dst_orig = dst; \
551 while (m < n && *src) { m++; *dst++ = *src++; } \
552 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
553 /* but only m+1 bytes of src if terminator was found */ \
554 SizeT srclen = (m < n) ? m+1 : n; \
555 RECORD_COPY(srclen); \
556 if (is_overlap(dst_orig, src_orig, n, srclen)) \
557 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
558 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
563 #if defined(VGO_linux)
564 STRNCPY(VG_Z_LIBC_SONAME
, strncpy
)
565 STRNCPY(VG_Z_LIBC_SONAME
, __GI_strncpy
)
566 STRNCPY(VG_Z_LIBC_SONAME
, __strncpy_sse2
)
567 STRNCPY(VG_Z_LIBC_SONAME
, __strncpy_sse2_unaligned
)
569 #elif defined(VGO_darwin)
570 STRNCPY(VG_Z_LIBC_SONAME
, strncpy
)
571 # if DARWIN_VERS >= DARWIN_10_9
572 STRNCPY(libsystemZucZddylib
, strncpy
)
575 #elif defined(VGO_solaris)
576 STRNCPY(VG_Z_LIBC_SONAME
, strncpy
)
577 STRNCPY(VG_Z_LD_SO_1
, strncpy
)
582 /*---------------------- strlcpy ----------------------*/
584 /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
585 Returns strlen(src). Does not zero-fill the remainder of dst. */
586 #define STRLCPY(soname, fnname) \
587 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
588 ( char* dst, const char* src, SizeT n ); \
589 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
590 ( char* dst, const char* src, SizeT n ) \
592 const HChar* src_orig = src; \
593 HChar* dst_orig = dst; \
596 STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
598 while (m+1 < n && *src) { m++; *dst++ = *src++; } \
599 /* m non-nul bytes have now been copied, and m <= n-1. */ \
600 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
601 /* but only m+1 bytes of src if terminator was found */ \
602 SizeT srclen = (m < n) ? m+1 : n; \
603 RECORD_COPY(srclen); \
604 if (is_overlap(dst_orig, src_orig, n, srclen)) \
605 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
606 /* Nul-terminate dst. */ \
607 if (n > 0) *dst = 0; \
608 /* Finish counting strlen(src). */ \
609 while (*src) src++; \
610 return src - src_orig; \
613 #if defined(VGO_linux)
615 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
616 || defined(VGPV_mips32_linux_android)
617 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
618 STRLCPY(VG_Z_LIBC_SONAME
, strlcpy
);
621 #elif defined(VGO_darwin)
622 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
623 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
624 //STRLCPY(VG_Z_DYLD, strlcpy)
625 STRLCPY(VG_Z_LIBC_SONAME
, strlcpy
)
627 #elif defined(VGO_solaris)
628 /* special case for n == 0 which is undocumented but heavily used */
629 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
631 while (*src) src++; \
632 return src - src_orig; \
635 STRLCPY(VG_Z_LIBC_SONAME
, strlcpy
)
640 /*---------------------- strncmp ----------------------*/
642 #define STRNCMP(soname, fnname) \
643 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
644 ( const char* s1, const char* s2, SizeT nmax ); \
645 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
646 ( const char* s1, const char* s2, SizeT nmax ) \
650 if (n >= nmax) return 0; \
651 if (*s1 == 0 && *s2 == 0) return 0; \
652 if (*s1 == 0) return -1; \
653 if (*s2 == 0) return 1; \
655 if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \
656 if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \
662 #if defined(VGO_linux)
663 STRNCMP(VG_Z_LIBC_SONAME
, strncmp
)
664 STRNCMP(VG_Z_LIBC_SONAME
, __GI_strncmp
)
665 STRNCMP(VG_Z_LIBC_SONAME
, __strncmp_sse2
)
666 STRNCMP(VG_Z_LIBC_SONAME
, __strncmp_sse42
)
668 #elif defined(VGO_darwin)
669 STRNCMP(VG_Z_LIBC_SONAME
, strncmp
)
670 # if DARWIN_VERS >= DARWIN_10_9
671 STRNCMP(libsystemZuplatformZddylib
, _platform_strncmp
)
674 #elif defined(VGO_solaris)
675 STRNCMP(VG_Z_LIBC_SONAME
, strncmp
)
680 /*---------------------- strcasecmp ----------------------*/
682 #define STRCASECMP(soname, fnname) \
683 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
684 ( const char* s1, const char* s2 ); \
685 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
686 ( const char* s1, const char* s2 ) \
688 extern int tolower(int); \
692 c1 = tolower(*(const UChar *)s1); \
693 c2 = tolower(*(const UChar *)s2); \
694 if (c1 != c2) break; \
695 if (c1 == 0) break; \
698 if ((UChar)c1 < (UChar)c2) return -1; \
699 if ((UChar)c1 > (UChar)c2) return 1; \
703 #if defined(VGO_linux)
704 # if !defined(VGPV_arm_linux_android) \
705 && !defined(VGPV_x86_linux_android) \
706 && !defined(VGPV_mips32_linux_android) \
707 && !defined(VGPV_arm64_linux_android)
708 STRCASECMP(VG_Z_LIBC_SONAME
, strcasecmp
)
709 STRCASECMP(VG_Z_LIBC_SONAME
, __GI_strcasecmp
)
712 #elif defined(VGO_darwin)
713 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
715 #elif defined(VGO_solaris)
716 STRCASECMP(VG_Z_LIBC_SONAME
, strcasecmp
)
721 /*---------------------- strncasecmp ----------------------*/
723 #define STRNCASECMP(soname, fnname) \
724 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
725 ( const char* s1, const char* s2, SizeT nmax ); \
726 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
727 ( const char* s1, const char* s2, SizeT nmax ) \
729 extern int tolower(int); \
732 if (n >= nmax) return 0; \
733 if (*s1 == 0 && *s2 == 0) return 0; \
734 if (*s1 == 0) return -1; \
735 if (*s2 == 0) return 1; \
737 if (tolower(*(const UChar *)s1) \
738 < tolower(*(const UChar*)s2)) return -1; \
739 if (tolower(*(const UChar *)s1) \
740 > tolower(*(const UChar *)s2)) return 1; \
746 #if defined(VGO_linux)
747 # if !defined(VGPV_arm_linux_android) \
748 && !defined(VGPV_x86_linux_android) \
749 && !defined(VGPV_mips32_linux_android) \
750 && !defined(VGPV_arm64_linux_android)
751 STRNCASECMP(VG_Z_LIBC_SONAME
, strncasecmp
)
752 STRNCASECMP(VG_Z_LIBC_SONAME
, __GI_strncasecmp
)
755 #elif defined(VGO_darwin)
756 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
757 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
759 #elif defined(VGO_solaris)
760 STRNCASECMP(VG_Z_LIBC_SONAME
, strncasecmp
)
765 /*---------------------- strcasecmp_l ----------------------*/
767 #define STRCASECMP_L(soname, fnname) \
768 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
769 ( const char* s1, const char* s2, void* locale ); \
770 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
771 ( const char* s1, const char* s2, void* locale ) \
773 extern int tolower_l(int, void*) __attribute__((weak)); \
777 c1 = tolower_l(*(const UChar *)s1, locale); \
778 c2 = tolower_l(*(const UChar *)s2, locale); \
779 if (c1 != c2) break; \
780 if (c1 == 0) break; \
783 if ((UChar)c1 < (UChar)c2) return -1; \
784 if ((UChar)c1 > (UChar)c2) return 1; \
788 #if defined(VGO_linux)
789 STRCASECMP_L(VG_Z_LIBC_SONAME
, strcasecmp_l
)
790 STRCASECMP_L(VG_Z_LIBC_SONAME
, __GI_strcasecmp_l
)
791 STRCASECMP_L(VG_Z_LIBC_SONAME
, __GI___strcasecmp_l
)
793 #elif defined(VGO_darwin)
794 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
796 #elif defined(VGO_solaris)
801 /*---------------------- strncasecmp_l ----------------------*/
803 #define STRNCASECMP_L(soname, fnname) \
804 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
805 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
806 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
807 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
809 extern int tolower_l(int, void*) __attribute__((weak)); \
812 if (n >= nmax) return 0; \
813 if (*s1 == 0 && *s2 == 0) return 0; \
814 if (*s1 == 0) return -1; \
815 if (*s2 == 0) return 1; \
817 if (tolower_l(*(const UChar *)s1, locale) \
818 < tolower_l(*(const UChar *)s2, locale)) return -1; \
819 if (tolower_l(*(const UChar *)s1, locale) \
820 > tolower_l(*(const UChar *)s2, locale)) return 1; \
826 #if defined(VGO_linux)
827 STRNCASECMP_L(VG_Z_LIBC_SONAME
, strncasecmp_l
)
828 STRNCASECMP_L(VG_Z_LIBC_SONAME
, __GI_strncasecmp_l
)
829 STRNCASECMP_L(VG_Z_LIBC_SONAME
, __GI___strncasecmp_l
)
831 #elif defined(VGO_darwin)
832 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
833 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
835 #elif defined(VGO_solaris)
840 /*---------------------- strcmp ----------------------*/
842 #define STRCMP(soname, fnname) \
843 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
844 ( const char* s1, const char* s2 ); \
845 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
846 ( const char* s1, const char* s2 ) \
851 c1 = *(const UChar *)s1; \
852 c2 = *(const UChar *)s2; \
853 if (c1 != c2) break; \
854 if (c1 == 0) break; \
857 if ((UChar)c1 < (UChar)c2) return -1; \
858 if ((UChar)c1 > (UChar)c2) return 1; \
862 #if defined(VGO_linux)
863 STRCMP(VG_Z_LIBC_SONAME
, strcmp
)
864 STRCMP(VG_Z_LIBC_SONAME
, __GI_strcmp
)
865 STRCMP(VG_Z_LIBC_SONAME
, __strcmp_sse2
)
866 STRCMP(VG_Z_LIBC_SONAME
, __strcmp_sse42
)
867 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2
, strcmp
)
868 STRCMP(VG_Z_LD64_SO_1
, strcmp
)
869 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
870 || defined(VGPV_mips32_linux_android)
871 STRCMP(NONE
, __dl_strcmp
); /* in /system/bin/linker */
874 #elif defined(VGO_darwin)
875 STRCMP(VG_Z_LIBC_SONAME
, strcmp
)
876 # if DARWIN_VERS >= DARWIN_10_9
877 STRCMP(libsystemZuplatformZddylib
, _platform_strcmp
)
880 #elif defined(VGO_solaris)
881 STRCMP(VG_Z_LIBC_SONAME
, strcmp
)
882 STRCMP(VG_Z_LD_SO_1
, strcmp
)
887 /*---------------------- memchr ----------------------*/
889 #define MEMCHR(soname, fnname) \
890 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
891 (const void *s, int c, SizeT n); \
892 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
893 (const void *s, int c, SizeT n) \
896 UChar c0 = (UChar)c; \
897 const UChar* p = s; \
898 for (i = 0; i < n; i++) \
899 if (p[i] == c0) return CONST_CAST(void *,&p[i]); \
903 #if defined(VGO_linux)
904 MEMCHR(VG_Z_LIBC_SONAME
, memchr
)
905 MEMCHR(VG_Z_LIBC_SONAME
, __GI_memchr
)
907 #elif defined(VGO_darwin)
908 # if DARWIN_VERS == DARWIN_10_9
909 MEMCHR(VG_Z_DYLD
, memchr
)
910 MEMCHR(libsystemZuplatformZddylib
, _platform_memchr
)
912 # if DARWIN_VERS >= DARWIN_10_10
913 MEMCHR(VG_Z_DYLD
, memchr
)
914 /* _platform_memchr$VARIANT$Generic */
915 MEMCHR(libsystemZuplatformZddylib
, _platform_memchr$VARIANT$Generic
)
916 /* _platform_memchr$VARIANT$Haswell */
917 MEMCHR(libsystemZuplatformZddylib
, _platform_memchr$VARIANT$Haswell
)
920 #elif defined(VGO_solaris)
921 MEMCHR(VG_Z_LIBC_SONAME
, memchr
)
926 /*---------------------- memrchr ----------------------*/
928 #define MEMRCHR(soname, fnname) \
929 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
930 (const void *s, int c, SizeT n); \
931 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
932 (const void *s, int c, SizeT n) \
935 UChar c0 = (UChar)c; \
936 const UChar* p = s; \
937 for (i = 0; i < n; i++) \
938 if (p[n-1-i] == c0) return CONST_CAST(void *,&p[n-1-i]); \
942 #if defined(VGO_linux)
943 MEMRCHR(VG_Z_LIBC_SONAME
, memrchr
)
945 #elif defined(VGO_darwin)
946 //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
947 //MEMRCHR(VG_Z_DYLD, memrchr)
949 #elif defined(VGO_solaris)
954 /*---------------------- memcpy ----------------------*/
956 #define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
957 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
958 ( void *dst, const void *src, SizeT len ); \
959 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
960 ( void *dst, const void *src, SizeT len ) \
963 if (do_ol_check && is_overlap(dst, src, len, len)) \
964 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
966 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
967 const Addr WM = WS - 1; /* 7 or 3 */ \
970 if (dst < src || !is_overlap(dst, src, len, len)) { \
972 /* Copying backwards. */ \
974 Addr d = (Addr)dst; \
975 Addr s = (Addr)src; \
977 if (((s^d) & WM) == 0) { \
978 /* s and d have same UWord alignment. */ \
979 /* Pull up to a UWord boundary. */ \
980 while ((s & WM) != 0 && n >= 1) \
981 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
983 while (n >= WS * 4) \
984 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
985 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
986 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
987 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
989 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
993 if (((s|d) & 1) == 0) { \
994 /* Both are 16-aligned; copy what we can thusly. */ \
996 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
998 /* Copy leftovers, or everything if misaligned. */ \
1000 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
1002 } else if (dst > src) { \
1005 Addr d = ((Addr)dst) + n; \
1006 Addr s = ((Addr)src) + n; \
1008 /* Copying forwards. */ \
1009 if (((s^d) & WM) == 0) { \
1010 /* s and d have same UWord alignment. */ \
1011 /* Back down to a UWord boundary. */ \
1012 while ((s & WM) != 0 && n >= 1) \
1013 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
1014 /* Copy UWords. */ \
1015 while (n >= WS * 4) \
1016 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1017 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1018 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1019 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
1021 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
1025 if (((s|d) & 1) == 0) { \
1026 /* Both are 16-aligned; copy what we can thusly. */ \
1028 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
1030 /* Copy leftovers, or everything if misaligned. */ \
1032 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
1040 #define MEMMOVE(soname, fnname) \
1041 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
1043 #define MEMCPY(soname, fnname) \
1044 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
1046 #if defined(VGO_linux)
1047 /* For older memcpy we have to use memmove-like semantics and skip
1048 the overlap check; sigh; see #275284. */
1049 MEMMOVE(VG_Z_LIBC_SONAME
, memcpyZAGLIBCZu2Zd2Zd5
) /* memcpy@GLIBC_2.2.5 */
1050 MEMCPY(VG_Z_LIBC_SONAME
, memcpyZAZAGLIBCZu2Zd14
) /* memcpy@@GLIBC_2.14 */
1051 MEMCPY(VG_Z_LIBC_SONAME
, memcpy
) /* fallback case */
1052 MEMCPY(VG_Z_LIBC_SONAME
, __GI_memcpy
)
1053 MEMCPY(VG_Z_LIBC_SONAME
, __memcpy_sse2
)
1054 MEMCPY(VG_Z_LIBC_SONAME
, __memcpy_avx_unaligned_erms
)
1055 MEMCPY(VG_Z_LD_SO_1
, memcpy
) /* ld.so.1 */
1056 MEMCPY(VG_Z_LD64_SO_1
, memcpy
) /* ld64.so.1 */
1057 /* icc9 blats these around all over the place. Not only in the main
1058 executable but various .so's. They are highly tuned and read
1059 memory beyond the source boundary (although work correctly and
1060 never go across page boundaries), so give errors when run
1061 natively, at least for misaligned source arg. Just intercepting
1062 in the exe only until we understand more about the problem. See
1063 http://bugs.kde.org/show_bug.cgi?id=139776
1065 MEMCPY(NONE
, ZuintelZufastZumemcpy
)
1067 #elif defined(VGO_darwin)
1068 # if DARWIN_VERS <= DARWIN_10_6
1069 MEMCPY(VG_Z_LIBC_SONAME
, memcpy
)
1071 MEMCPY(VG_Z_LIBC_SONAME
, memcpyZDVARIANTZDsse3x
) /* memcpy$VARIANT$sse3x */
1072 MEMCPY(VG_Z_LIBC_SONAME
, memcpyZDVARIANTZDsse42
) /* memcpy$VARIANT$sse42 */
1074 #elif defined(VGO_solaris)
1075 MEMCPY(VG_Z_LIBC_SONAME
, memcpy
)
1076 MEMCPY(VG_Z_LIBC_SONAME
, memcpyZPZa
)
1077 MEMCPY(VG_Z_LD_SO_1
, memcpy
)
1082 /*---------------------- memcmp ----------------------*/
1084 #define MEMCMP(soname, fnname) \
1085 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1086 ( const void *s1V, const void *s2V, SizeT n ); \
1087 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1088 ( const void *s1V, const void *s2V, SizeT n ) \
1090 const SizeT WS = sizeof(UWord); /* 8 or 4 */ \
1091 const SizeT WM = WS - 1; /* 7 or 3 */ \
1092 Addr s1A = (Addr)s1V; \
1093 Addr s2A = (Addr)s2V; \
1095 if (((s1A | s2A) & WM) == 0) { \
1096 /* Both areas are word aligned. Skip over the */ \
1097 /* equal prefix as fast as possible. */ \
1099 UWord w1 = *(UWord*)s1A; \
1100 UWord w2 = *(UWord*)s2A; \
1101 if (w1 != w2) break; \
1108 const UChar* s1 = (const UChar*) s1A; \
1109 const UChar* s2 = (const UChar*) s2A; \
1116 int res = ((int)a0) - ((int)b0); \
1124 #if defined(VGO_linux)
1125 MEMCMP(VG_Z_LIBC_SONAME
, memcmp
)
1126 MEMCMP(VG_Z_LIBC_SONAME
, __GI_memcmp
)
1127 MEMCMP(VG_Z_LIBC_SONAME
, __memcmp_sse2
)
1128 MEMCMP(VG_Z_LIBC_SONAME
, __memcmp_sse4_1
)
1129 MEMCMP(VG_Z_LIBC_SONAME
, bcmp
)
1130 MEMCMP(VG_Z_LD_SO_1
, bcmp
)
1132 #elif defined(VGO_darwin)
1133 # if DARWIN_VERS >= DARWIN_10_9
1134 MEMCMP(libsystemZuplatformZddylib
, _platform_memcmp
)
1137 #elif defined(VGO_solaris)
1138 MEMCMP(VG_Z_LIBC_SONAME
, memcmp
)
1139 MEMCMP(VG_Z_LIBC_SONAME
, bcmp
)
1140 MEMCMP(VG_Z_LD_SO_1
, memcmp
)
1145 /*---------------------- stpcpy ----------------------*/
1147 /* Copy SRC to DEST, returning the address of the terminating '\0' in
1148 DEST. (minor variant of strcpy) */
1149 #define STPCPY(soname, fnname) \
1150 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1151 ( char* dst, const char* src ); \
1152 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1153 ( char* dst, const char* src ) \
1155 const HChar* src_orig = src; \
1156 HChar* dst_orig = dst; \
1158 while (*src) *dst++ = *src++; \
1161 /* This checks for overlap after copying, unavoidable without */ \
1162 /* pre-counting length... should be ok */ \
1163 SizeT srclen = (Addr)src-(Addr)src_orig+1; \
1164 RECORD_COPY(srclen); \
1165 if (is_overlap(dst_orig, \
1167 (Addr)dst-(Addr)dst_orig+1, \
1169 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
1174 #if defined(VGO_linux)
1175 STPCPY(VG_Z_LIBC_SONAME
, stpcpy
)
1176 STPCPY(VG_Z_LIBC_SONAME
, __GI_stpcpy
)
1177 STPCPY(VG_Z_LIBC_SONAME
, __stpcpy_sse2
)
1178 STPCPY(VG_Z_LIBC_SONAME
, __stpcpy_sse2_unaligned
)
1179 STPCPY(VG_Z_LD_LINUX_SO_2
, stpcpy
)
1180 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2
, stpcpy
)
1181 STPCPY(VG_Z_LD_LINUX_AARCH64_SO_1
,stpcpy
)
1183 #elif defined(VGO_darwin)
1184 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1185 //STPCPY(VG_Z_DYLD, stpcpy)
1187 #elif defined(VGO_solaris)
1188 STPCPY(VG_Z_LIBC_SONAME
, stpcpy
)
1193 /*---------------------- stpncpy ----------------------*/
1195 #define STPNCPY(soname, fnname) \
1196 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1197 ( char* dst, const char* src, SizeT n ); \
1198 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1199 ( char* dst, const char* src, SizeT n ) \
1201 const HChar* src_orig = src; \
1202 HChar* dst_str = dst; \
1205 while (m < n && *src) { m++; *dst++ = *src++; } \
1206 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
1207 /* but only m+1 bytes of src if terminator was found */ \
1208 SizeT srclen = (m < n) ? m+1 : n; \
1209 RECORD_COPY(srclen); \
1210 if (is_overlap(dst_str, src_orig, n, srclen)) \
1211 RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \
1213 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
1218 #if defined(VGO_linux)
1219 STPNCPY(VG_Z_LIBC_SONAME
, stpncpy
)
1223 /*---------------------- memset ----------------------*/
1225 #define MEMSET(soname, fnname) \
1226 void* VG_REPLACE_FUNCTION_EZZ(20210,soname,fnname) \
1227 (void *s, Int c, SizeT n); \
1228 void* VG_REPLACE_FUNCTION_EZZ(20210,soname,fnname) \
1229 (void *s, Int c, SizeT n) \
1231 if (sizeof(void*) == 8) { \
1233 ULong c8 = (c & 0xFF); \
1234 c8 = (c8 << 8) | c8; \
1235 c8 = (c8 << 16) | c8; \
1236 c8 = (c8 << 32) | c8; \
1237 while ((a & 7) != 0 && n >= 1) \
1238 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1240 { *(ULong*)a = c8; a += 8; n -= 8; \
1241 *(ULong*)a = c8; a += 8; n -= 8; \
1242 *(ULong*)a = c8; a += 8; n -= 8; \
1243 *(ULong*)a = c8; a += 8; n -= 8; } \
1245 { *(ULong*)a = c8; a += 8; n -= 8; } \
1247 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1251 UInt c4 = (c & 0xFF); \
1252 c4 = (c4 << 8) | c4; \
1253 c4 = (c4 << 16) | c4; \
1254 while ((a & 3) != 0 && n >= 1) \
1255 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1257 { *(UInt*)a = c4; a += 4; n -= 4; \
1258 *(UInt*)a = c4; a += 4; n -= 4; \
1259 *(UInt*)a = c4; a += 4; n -= 4; \
1260 *(UInt*)a = c4; a += 4; n -= 4; } \
1262 { *(UInt*)a = c4; a += 4; n -= 4; } \
1264 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1269 #if defined(VGO_linux)
1270 MEMSET(VG_Z_LIBC_SONAME
, memset
)
1272 #elif defined(VGO_darwin)
1273 //MEMSET(VG_Z_LIBC_SONAME, memset)
1274 //MEMSET(VG_Z_DYLD, memset)
1275 MEMSET(VG_Z_LIBC_SONAME
, memset
)
1277 #elif defined(VGO_solaris)
1278 MEMSET(VG_Z_LIBC_SONAME
, memset
)
1279 MEMSET(VG_Z_LIBC_SONAME
, memsetZPZa
)
1284 /*---------------------- memmove ----------------------*/
1286 /* memmove -- use the MEMMOVE defn above. */
1288 #if defined(VGO_linux)
1289 MEMMOVE(VG_Z_LIBC_SONAME
, memmove
)
1290 MEMMOVE(VG_Z_LIBC_SONAME
, __GI_memmove
)
1291 /* See bug #349828 Override for ld64.so.1 like memcpy, because for some
1292 arches MEMCPY_OK_FOR_FORWARD_MEMMOVE is set, which might cause memmove
1294 MEMMOVE(VG_Z_LD64_SO_1
, memmove
)
1296 #elif defined(VGO_darwin)
1297 # if DARWIN_VERS <= DARWIN_10_6
1298 MEMMOVE(VG_Z_LIBC_SONAME
, memmove
)
1300 MEMMOVE(VG_Z_LIBC_SONAME
, memmoveZDVARIANTZDsse3x
) /* memmove$VARIANT$sse3x */
1301 MEMMOVE(VG_Z_LIBC_SONAME
, memmoveZDVARIANTZDsse42
) /* memmove$VARIANT$sse42 */
1302 # if DARWIN_VERS >= DARWIN_10_9
1303 /* _platform_memmove$VARIANT$Ivybridge */
1304 MEMMOVE(libsystemZuplatformZddylib
, ZuplatformZumemmoveZDVARIANTZDIvybridge
)
1307 #elif defined(VGO_solaris)
1308 MEMMOVE(VG_Z_LIBC_SONAME
, memmove
)
1309 MEMMOVE(VG_Z_LIBC_SONAME
, memmoveZPZa
)
1310 MEMMOVE(VG_Z_LD_SO_1
, memmove
)
1315 /*---------------------- bcopy ----------------------*/
1317 #define BCOPY(soname, fnname) \
1318 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1319 (const void *srcV, void *dstV, SizeT n); \
1320 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1321 (const void *srcV, void *dstV, SizeT n) \
1325 HChar* dst = dstV; \
1326 const HChar* src = srcV; \
1328 for (i = 0; i < n; i++) \
1333 for (i = 0; i < n; i++) \
1334 dst[n-i-1] = src[n-i-1]; \
1338 #if defined(VGO_linux)
1339 BCOPY(VG_Z_LIBC_SONAME
, bcopy
)
1341 #elif defined(VGO_darwin)
1342 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1343 //BCOPY(VG_Z_DYLD, bcopy)
1345 #elif defined(VGO_darwin)
1346 BCOPY(VG_Z_LIBC_SONAME
, bcopy
)
1351 /*-------------------- memmove_chk --------------------*/
1353 /* glibc 2.5 variant of memmove which checks the dest is big enough.
1354 There is no specific part of glibc that this is copied from. */
1355 #define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1356 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1357 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1358 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1359 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1363 HChar* dst = dstV; \
1364 const HChar* src = srcV; \
1368 for (i = 0; i < n; i++) \
1373 for (i = 0; i < n; i++) \
1374 dst[n-i-1] = src[n-i-1]; \
1378 VALGRIND_PRINTF_BACKTRACE( \
1379 "*** memmove_chk: buffer overflow detected ***: " \
1380 "program terminated\n"); \
1386 #if defined(VGO_linux)
1387 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME
, __memmove_chk
)
1389 #elif defined(VGO_darwin)
1391 #elif defined(VGO_solaris)
1396 /*-------------------- strchrnul --------------------*/
1398 /* Find the first occurrence of C in S or the final NUL byte. */
1399 #define GLIBC232_STRCHRNUL(soname, fnname) \
1400 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1401 (const char* s, int c_in); \
1402 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1403 (const char* s, int c_in) \
1405 HChar c = (HChar) c_in; \
1406 const HChar* char_ptr = s; \
1408 if (*char_ptr == 0) return CONST_CAST(HChar *,char_ptr); \
1409 if (*char_ptr == c) return CONST_CAST(HChar *,char_ptr); \
1414 #if defined(VGO_linux)
1415 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME
, strchrnul
)
1417 #elif defined(VGO_darwin)
1419 #elif defined(VGO_solaris)
1424 /*---------------------- rawmemchr ----------------------*/
1426 /* Find the first occurrence of C in S. */
1427 #define GLIBC232_RAWMEMCHR(soname, fnname) \
1428 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1429 (const void* s, int c_in); \
1430 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1431 (const void* s, int c_in) \
1433 UChar c = (UChar) c_in; \
1434 const UChar* char_ptr = s; \
1436 if (*char_ptr == c) return CONST_CAST(void *,char_ptr); \
1441 #if defined (VGO_linux)
1442 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME
, rawmemchr
)
1443 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME
, __GI___rawmemchr
)
1445 #elif defined(VGO_darwin)
1447 #elif defined(VGO_solaris)
1452 /*---------------------- strcpy_chk ----------------------*/
1454 /* glibc variant of strcpy that checks the dest is big enough.
1455 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1456 #define GLIBC25___STRCPY_CHK(soname,fnname) \
1457 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1458 (char* dst, const char* src, SizeT len); \
1459 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1460 (char* dst, const char* src, SizeT len) \
1462 FOR_COPY(const HChar* src_orig = src); \
1466 while ((*dst++ = *src++) != '\0') \
1469 RECORD_COPY((Addr)src-(Addr)src_orig); \
1472 VALGRIND_PRINTF_BACKTRACE( \
1473 "*** strcpy_chk: buffer overflow detected ***: " \
1474 "program terminated\n"); \
1480 #if defined(VGO_linux)
1481 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME
, __strcpy_chk
)
1483 #elif defined(VGO_darwin)
1485 #elif defined(VGO_solaris)
1490 /*---------------------- stpcpy_chk ----------------------*/
1492 /* glibc variant of stpcpy that checks the dest is big enough.
1493 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1494 #define GLIBC25___STPCPY_CHK(soname,fnname) \
1495 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1496 (char* dst, const char* src, SizeT len); \
1497 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1498 (char* dst, const char* src, SizeT len) \
1500 FOR_COPY(const HChar* src_orig = src); \
1503 while ((*dst++ = *src++) != '\0') \
1506 RECORD_COPY((Addr)src-(Addr)src_orig); \
1509 VALGRIND_PRINTF_BACKTRACE( \
1510 "*** stpcpy_chk: buffer overflow detected ***: " \
1511 "program terminated\n"); \
1517 #if defined(VGO_linux)
1518 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME
, __stpcpy_chk
)
1520 #elif defined(VGO_darwin)
1522 #elif defined(VGO_solaris)
1527 /*---------------------- mempcpy ----------------------*/
1530 #define GLIBC25_MEMPCPY(soname, fnname) \
1531 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1532 ( void *dst, const void *src, SizeT len ); \
1533 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1534 ( void *dst, const void *src, SizeT len ) \
1537 SizeT len_saved = len; \
1542 if (is_overlap(dst, src, len, len)) \
1543 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1545 if ( dst > src ) { \
1546 register HChar *d = (char *)dst + len - 1; \
1547 register const HChar *s = (const char *)src + len - 1; \
1551 } else if ( dst < src ) { \
1552 register HChar *d = dst; \
1553 register const HChar *s = src; \
1558 return (void*)( ((char*)dst) + len_saved ); \
1561 #if defined(VGO_linux)
1562 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME
, mempcpy
)
1563 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME
, __GI_mempcpy
)
1564 GLIBC25_MEMPCPY(VG_Z_LD_SO_1
, mempcpy
) /* ld.so.1 */
1565 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3
, mempcpy
) /* ld-linux.so.3 */
1566 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2
, mempcpy
) /* ld-linux-x86-64.so.2 */
1568 #elif defined(VGO_darwin)
1569 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1571 #elif defined(VGO_solaris)
1576 /*-------------------- memcpy_chk --------------------*/
1578 #define GLIBC26___MEMCPY_CHK(soname, fnname) \
1579 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1580 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1581 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1582 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1584 register HChar *d; \
1585 register const HChar *s; \
1591 if (is_overlap(dst, src, len, len)) \
1592 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1593 if ( dst > src ) { \
1594 d = (HChar *)dst + len - 1; \
1595 s = (const HChar *)src + len - 1; \
1599 } else if ( dst < src ) { \
1601 s = (const HChar *)src; \
1608 VALGRIND_PRINTF_BACKTRACE( \
1609 "*** memcpy_chk: buffer overflow detected ***: " \
1610 "program terminated\n"); \
1616 #if defined(VGO_linux)
1617 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME
, __memcpy_chk
)
1619 #elif defined(VGO_darwin)
1621 #elif defined(VGO_solaris)
1626 /*---------------------- strstr ----------------------*/
1628 #define STRSTR(soname, fnname) \
1629 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1630 (const char* haystack, const char* needle); \
1631 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1632 (const char* haystack, const char* needle) \
1634 const HChar* h = haystack; \
1635 const HChar* n = needle; \
1637 /* find the length of n, not including terminating zero */ \
1639 while (n[nlen]) nlen++; \
1641 /* if n is the empty string, match immediately. */ \
1642 if (nlen == 0) return CONST_CAST(HChar *,h); \
1644 /* assert(nlen >= 1); */ \
1648 const HChar hh = *h; \
1649 if (hh == 0) return NULL; \
1650 if (hh != n0) { h++; continue; } \
1653 for (i = 0; i < nlen; i++) { \
1657 /* assert(i >= 0 && i <= nlen); */ \
1659 return CONST_CAST(HChar *,h); \
1665 #if defined(VGO_linux)
1666 STRSTR(VG_Z_LIBC_SONAME
, strstr
)
1667 STRSTR(VG_Z_LIBC_SONAME
, __strstr_sse2
)
1668 STRSTR(VG_Z_LIBC_SONAME
, __strstr_sse42
)
1670 #elif defined(VGO_darwin)
1672 #elif defined(VGO_solaris)
1673 STRSTR(VG_Z_LIBC_SONAME
, strstr
)
1678 /*---------------------- strpbrk ----------------------*/
1680 #define STRPBRK(soname, fnname) \
1681 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1682 (const char* sV, const char* acceptV); \
1683 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1684 (const char* sV, const char* acceptV) \
1686 const HChar* s = sV; \
1687 const HChar* accept = acceptV; \
1689 /* find the length of 'accept', not including terminating zero */ \
1691 while (accept[nacc]) nacc++; \
1693 /* if n is the empty string, fail immediately. */ \
1694 if (nacc == 0) return NULL; \
1696 /* assert(nacc >= 1); */ \
1702 for (i = 0; i < nacc; i++) { \
1703 if (sc == accept[i]) \
1704 return CONST_CAST(HChar *,s); \
1712 #if defined(VGO_linux)
1713 STRPBRK(VG_Z_LIBC_SONAME
, strpbrk
)
1715 #elif defined(VGO_darwin)
1717 #elif defined(VGO_solaris)
1718 STRPBRK(VG_Z_LIBC_SONAME
, strpbrk
)
1723 /*---------------------- strcspn ----------------------*/
1725 #define STRCSPN(soname, fnname) \
1726 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1727 (const char* sV, const char* rejectV); \
1728 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1729 (const char* sV, const char* rejectV) \
1731 const HChar* s = sV; \
1732 const HChar* reject = rejectV; \
1734 /* find the length of 'reject', not including terminating zero */ \
1736 while (reject[nrej]) nrej++; \
1744 for (i = 0; i < nrej; i++) { \
1745 if (sc == reject[i]) \
1748 /* assert(i >= 0 && i <= nrej); */ \
1758 #if defined(VGO_linux)
1759 STRCSPN(VG_Z_LIBC_SONAME
, strcspn
)
1760 STRCSPN(VG_Z_LIBC_SONAME
, __GI_strcspn
)
1762 #elif defined(VGO_darwin)
1764 #elif defined(VGO_solaris)
1765 STRCSPN(VG_Z_LIBC_SONAME
, strcspn
)
1770 /*---------------------- strspn ----------------------*/
1772 #define STRSPN(soname, fnname) \
1773 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1774 (const char* sV, const char* acceptV); \
1775 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1776 (const char* sV, const char* acceptV) \
1778 const UChar* s = (const UChar *)sV; \
1779 const UChar* accept = (const UChar *)acceptV; \
1781 /* find the length of 'accept', not including terminating zero */ \
1783 while (accept[nacc]) nacc++; \
1784 if (nacc == 0) return 0; \
1792 for (i = 0; i < nacc; i++) { \
1793 if (sc == accept[i]) \
1796 /* assert(i >= 0 && i <= nacc); */ \
1806 #if defined(VGO_linux)
1807 STRSPN(VG_Z_LIBC_SONAME
, strspn
)
1809 #elif defined(VGO_darwin)
1811 #elif defined(VGO_solaris)
1812 STRSPN(VG_Z_LIBC_SONAME
, strspn
)
1817 /*---------------------- strcasestr ----------------------*/
1819 #define STRCASESTR(soname, fnname) \
1820 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1821 (const char* haystack, const char* needle); \
1822 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1823 (const char* haystack, const char* needle) \
1825 extern int tolower(int); \
1826 const HChar* h = haystack; \
1827 const HChar* n = needle; \
1829 /* find the length of n, not including terminating zero */ \
1831 while (n[nlen]) nlen++; \
1833 /* if n is the empty string, match immediately. */ \
1834 if (nlen == 0) return CONST_CAST(HChar *,h); \
1836 /* assert(nlen >= 1); */ \
1837 UChar n0 = tolower(n[0]); \
1840 UChar hh = tolower(*h); \
1841 if (hh == 0) return NULL; \
1842 if (hh != n0) { h++; continue; } \
1845 for (i = 0; i < nlen; i++) { \
1846 if (tolower(n[i]) != tolower(h[i])) \
1849 /* assert(i >= 0 && i <= nlen); */ \
1851 return CONST_CAST(HChar *,h); \
1857 #if defined(VGO_linux)
1858 # if !defined(VGPV_arm_linux_android) \
1859 && !defined(VGPV_x86_linux_android) \
1860 && !defined(VGPV_mips32_linux_android) \
1861 && !defined(VGPV_arm64_linux_android)
1862 STRCASESTR(VG_Z_LIBC_SONAME
, strcasestr
)
1865 #elif defined(VGO_darwin)
1867 #elif defined(VGO_solaris)
1868 STRCASESTR(VG_Z_LIBC_SONAME
, strcasestr
)
1873 /*---------------------- wcslen ----------------------*/
1875 // This is a wchar_t equivalent to strlen. Unfortunately
1876 // we don't have wchar_t available here, but it looks like
1877 // a 32 bit int on Linux. I don't know if that is also
1880 #define WCSLEN(soname, fnname) \
1881 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1882 ( const Int* str ); \
1883 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1884 ( const Int* str ) \
1887 while (str[i] != 0) i++; \
1891 #if defined(VGO_linux)
1892 WCSLEN(VG_Z_LIBC_SONAME
, wcslen
)
1894 #elif defined(VGO_darwin)
1896 #elif defined(VGO_solaris)
1897 WCSLEN(VG_Z_LIBC_SONAME
, wcslen
)
1901 /*---------------------- wcsnlen ----------------------*/
1903 #define WCSNLEN(soname, fnname) \
1904 SizeT VG_REPLACE_FUNCTION_EZU(20440,soname,fnname) \
1905 ( const Int *s, SizeT n ); \
1906 SizeT VG_REPLACE_FUNCTION_EZU(20440,soname,fnname) \
1907 ( const Int *s, SizeT n ) \
1911 while (i < n && *p != 0) { \
1918 #if defined(VGO_linux)
1919 WCSNLEN(VG_Z_LIBC_SONAME
, wcsnlen
)
1920 WCSNLEN(VG_Z_LIBC_SONAME
, __GI_wcsnlen
)
1923 /*---------------------- wcscmp ----------------------*/
1925 // This is a wchar_t equivalent to strcmp. We don't
1926 // have wchar_t available here, but in the GNU C Library
1927 // wchar_t is always 32 bits wide and wcscmp uses signed
1928 // comparison, not unsigned as in strcmp function.
1930 #define WCSCMP(soname, fnname) \
1931 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1932 ( const Int* s1, const Int* s2 ); \
1933 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1934 ( const Int* s1, const Int* s2 ) \
1941 if (c1 != c2) break; \
1942 if (c1 == 0) break; \
1945 if (c1 < c2) return -1; \
1946 if (c1 > c2) return 1; \
1950 #if defined(VGO_linux)
1951 WCSCMP(VG_Z_LIBC_SONAME
, wcscmp
)
1954 /*---------------------- wcsncmp ----------------------*/
1956 // This is a wchar_t equivalent to strncmp. We don't
1957 // have wchar_t available here, but in the GNU C Library
1958 // wchar_t is always 32 bits wide and wcsncmp uses signed
1959 // comparison, not unsigned as in strncmp function.
1961 #define WCSNCMP(soname, fnname) \
1962 int VG_REPLACE_FUNCTION_EZU(20450,soname,fnname) \
1963 ( const Int* s1, const Int* s2, SizeT nmax ); \
1964 int VG_REPLACE_FUNCTION_EZU(20450,soname,fnname) \
1965 ( const Int* s1, const Int* s2, SizeT nmax ) \
1969 if (n >= nmax) return 0; \
1970 if (*s1 == 0 && *s2 == 0) return 0; \
1971 if (*s1 == 0) return -1; \
1972 if (*s2 == 0) return 1; \
1974 if (*s1 < *s2) return -1; \
1975 if (*s1 > *s2) return 1; \
1980 #if defined(VGO_linux)
1981 WCSNCMP(VG_Z_LIBC_SONAME
, wcsncmp
)
1984 /*---------------------- wcscpy ----------------------*/
1986 // This is a wchar_t equivalent to strcpy. We don't
1987 // have wchar_t available here, but in the GNU C Library
1988 // wchar_t is always 32 bits wide.
1990 #define WCSCPY(soname, fnname) \
1991 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1992 ( Int* dst, const Int* src ); \
1993 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1994 ( Int* dst, const Int* src ) \
1996 const Int* src_orig = src; \
1997 Int* dst_orig = dst; \
1999 while (*src) *dst++ = *src++; \
2002 /* This checks for overlap after copying, unavoidable without */ \
2003 /* pre-counting length... should be ok */ \
2004 /* +4 because sizeof(wchar_t) == 4 */ \
2005 SizeT srclen = (Addr)src-(Addr)src_orig+4; \
2006 RECORD_COPY(srclen); \
2007 if (is_overlap(dst_orig, \
2009 /* +4 because sizeof(wchar_t) == 4 */ \
2010 (Addr)dst-(Addr)dst_orig+4, \
2012 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
2017 #if defined(VGO_linux) || defined(VGO_solaris)
2018 WCSCPY(VG_Z_LIBC_SONAME
, wcscpy
)
2022 /*---------------------- wcschr ----------------------*/
2024 // This is a wchar_t equivalent to strchr. We don't
2025 // have wchar_t available here, but in the GNU C Library
2026 // wchar_t is always 32 bits wide.
2028 #define WCSCHR(soname, fnname) \
2029 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
2030 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
2034 if (*p == c) return CONST_CAST(Int *,p); \
2035 if (*p == 0) return NULL; \
2040 #if defined(VGO_linux)
2041 WCSCHR(VG_Z_LIBC_SONAME
, wcschr
)
2043 /*---------------------- wcsrchr ----------------------*/
2045 // This is a wchar_t equivalent to strrchr. We don't
2046 // have wchar_t available here, but in the GNU C Library
2047 // wchar_t is always 32 bits wide.
2049 #define WCSRCHR(soname, fnname) \
2050 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
2051 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
2054 const Int* last = NULL; \
2056 if (*p == c) last = p; \
2057 if (*p == 0) return CONST_CAST(Int *,last); \
2062 #if defined(VGO_linux)
2063 WCSRCHR(VG_Z_LIBC_SONAME
, wcsrchr
)
2066 /*---------------------- wmemchr ----------------------*/
2068 // This is a wchar_t equivalent to memchr. We don't
2069 // have wchar_t available here, but in the GNU C Library
2070 // wchar_t is always 32 bits wide.
2072 #define WMEMCHR(soname, fnname) \
2073 Int* VG_REPLACE_FUNCTION_EZU(20430,soname,fnname) \
2074 (const Int *s, Int c, SizeT n); \
2075 Int* VG_REPLACE_FUNCTION_EZU(20430,soname,fnname) \
2076 (const Int *s, Int c, SizeT n) \
2080 for (i = 0; i < n; i++) { \
2081 if (*p == c) return CONST_CAST(Int *,p); \
2087 #if defined(VGO_linux)
2088 WMEMCHR(VG_Z_LIBC_SONAME
, wmemchr
)
2089 WMEMCHR(VG_Z_LIBC_SONAME
, __GI_wmemchr
)
2092 /*------------------------------------------------------------*/
2093 /*--- Improve definedness checking of process environment ---*/
2094 /*------------------------------------------------------------*/
2096 #if defined(VGO_linux)
2098 /* If these wind up getting generated via a macro, so that multiple
2099 versions of each function exist (as above), use the _EZU variants
2100 to assign equivalance class tags. */
2102 /*---------------------- putenv ----------------------*/
2104 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME
, putenv
) (char* string
);
2105 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME
, putenv
) (char* string
)
2109 const HChar
* p
= string
;
2110 VALGRIND_GET_ORIG_FN(fn
);
2111 /* Now by walking over the string we magically produce
2112 traces when hitting undefined memory. */
2115 __asm__
__volatile__("" ::: "memory");
2116 CALL_FN_W_W(result
, fn
, string
);
2121 /*---------------------- unsetenv ----------------------*/
2123 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME
, unsetenv
) (const char* name
);
2124 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME
, unsetenv
) (const char* name
)
2128 const HChar
* p
= name
;
2129 VALGRIND_GET_ORIG_FN(fn
);
2130 /* Now by walking over the string we magically produce
2131 traces when hitting undefined memory. */
2134 __asm__
__volatile__("" ::: "memory");
2135 CALL_FN_W_W(result
, fn
, name
);
2140 /*---------------------- setenv ----------------------*/
2143 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME
, setenv
)
2144 (const char* name
, const char* value
, int overwrite
);
2145 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME
, setenv
)
2146 (const char* name
, const char* value
, int overwrite
)
2151 VALGRIND_GET_ORIG_FN(fn
);
2152 /* Now by walking over the string we magically produce
2153 traces when hitting undefined memory. */
2155 for (p
= name
; *p
; p
++)
2156 __asm__
__volatile__("" ::: "memory");
2158 for (p
= value
; *p
; p
++)
2159 __asm__
__volatile__("" ::: "memory");
2160 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite
);
2161 CALL_FN_W_WWW(result
, fn
, name
, value
, overwrite
);
2165 #endif /* defined(VGO_linux) */
2167 /*--------------------------------------------------------------------*/
2169 /*--------------------------------------------------------------------*/