s390x: Re-implement STFLE as an extension
[valgrind.git] / shared / vg_replace_strmem.c
blobae13a2a5f87a34e704e2ceec35a2c712f7248141
2 /*--------------------------------------------------------------------*/
3 /*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/
4 /*--- simulated CPU. ---*/
5 /*--- vg_replace_strmem.c ---*/
6 /*--------------------------------------------------------------------*/
8 /*
9 This file is part of Valgrind.
11 Copyright (C) 2000-2017 Julian Seward
12 jseward@acm.org
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
43 simpler.
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
46 reports.
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:
58 20010 STRRCHR
59 20020 STRCHR
60 20030 STRCAT
61 20040 STRNCAT
62 20050 STRLCAT
63 20060 STRNLEN
64 20070 STRLEN
65 20080 STRCPY
66 20090 STRNCPY
67 20100 STRLCPY
68 20110 STRNCMP
69 20120 STRCASECMP
70 20130 STRNCASECMP
71 20140 STRCASECMP_L
72 20150 STRNCASECMP_L
73 20160 STRCMP
74 20170 MEMCHR
76 20180 MEMCPY if there's a conflict between memcpy and
77 20181 MEMMOVE memmove, prefer memmove
79 20190 MEMCMP
80 20200 STPCPY
81 20210 MEMSET
82 2022P unused (was previously MEMMOVE)
83 20230 BCOPY
84 20240 GLIBC25___MEMMOVE_CHK
85 20250 GLIBC232_STRCHRNUL
86 20260 GLIBC232_RAWMEMCHR
87 20270 GLIBC25___STRCPY_CHK
88 20280 GLIBC25___STPCPY_CHK
89 20290 GLIBC25_MEMPCPY
90 20300 GLIBC26___MEMCPY_CHK
91 20310 STRSTR
92 20320 STRPBRK
93 20330 STRCSPN
94 20340 STRSPN
95 20350 STRCASESTR
96 20360 MEMRCHR
97 20370 WCSLEN
98 20380 WCSCMP
99 20390 WCSCPY
100 20400 WCSCHR
101 20410 WCSRCHR
102 20420 STPNCPY
103 20430 WMEMCHR
104 20440 WCSNLEN
105 20450 WSTRNCMP
106 20460 MEMMEM
107 20470 WMEMCMP
108 20480 WCSNCPY
109 20490 MEMCCPY
110 20500 WCPNCPY
113 #if defined(VGO_solaris)
115 Detour functions in the libc and the runtime linker. If a function isn't
116 much optimized (and no overlap checking is necessary) then redir the
117 function only in the libc. This way we can keep stacktraces in the tests
118 consistent.
120 #endif
123 /* Figure out if [dst .. dst+dstlen-1] overlaps with
124 [src .. src+srclen-1].
125 We assume that the address ranges do not wrap around
126 (which is safe since on Linux addresses >= 0xC0000000
127 are not accessible and the program will segfault in this
128 circumstance, presumably).
130 static inline
131 Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
133 Addr loS, hiS, loD, hiD;
135 if (dstlen == 0 || srclen == 0)
136 return False;
138 loS = (Addr)src;
139 loD = (Addr)dst;
140 hiS = loS + srclen - 1;
141 hiD = loD + dstlen - 1;
143 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
144 if (loS < loD) {
145 return !(hiS < loD);
147 else if (loD < loS) {
148 return !(hiD < loS);
150 else {
151 /* They start at same place. Since we know neither of them has
152 zero length, they must overlap. */
153 return True;
157 #if defined(VGO_linux)
158 /* Call here to exit if we can't continue. On Android we can't call
159 _exit for some reason, so we have to blunt-instrument it. */
160 __attribute__ ((__noreturn__))
161 static inline void my_exit ( int x )
163 # if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \
164 || defined(VGPV_arm64_linux_android)
165 __asm__ __volatile__(".word 0xFFFFFFFF");
166 while (1) {}
167 # elif defined(VGPV_x86_linux_android)
168 __asm__ __volatile__("ud2");
169 while (1) {}
170 # else
171 extern __attribute__ ((__noreturn__)) void _exit(int status);
172 _exit(x);
173 # endif
175 #endif
177 // This is a macro rather than a function because we don't want to have an
178 // extra function in the stack trace.
179 #ifndef RECORD_OVERLAP_ERROR
180 #define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0)
181 #endif
183 // Used for tools that record bulk copies: memcpy, strcpy, etc.
184 #ifndef RECORD_COPY
185 #define RECORD_COPY(len) do { } while (0)
186 #define FOR_COPY(x)
187 #else
188 #define FOR_COPY(x) x
189 #endif
191 #ifndef VALGRIND_CHECK_VALUE_IS_DEFINED
192 #define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1
193 #endif
196 /*---------------------- strrchr ----------------------*/
198 #define STRRCHR(soname, fnname) \
199 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
200 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
202 HChar ch = (HChar)c; \
203 const HChar* p = s; \
204 const HChar* last = NULL; \
205 while (True) { \
206 if (*p == ch) last = p; \
207 if (*p == 0) return CONST_CAST(HChar *,last); \
208 p++; \
212 // Apparently rindex() is the same thing as strrchr()
213 #if defined(VGO_linux)
214 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
215 STRRCHR(VG_Z_LIBC_SONAME, rindex)
216 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
217 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2)
218 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2_no_bsf)
219 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse42)
220 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
221 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
222 || defined(VGPV_mips32_linux_android)
223 STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */
224 #endif
226 #elif defined(VGO_freebsd)
227 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
228 STRRCHR(VG_Z_LIBC_SONAME, rindex)
229 STRRCHR(VG_Z_LD_ELF_SO_1, strrchr)
230 STRRCHR(VG_Z_LD_ELF32_SO_1, strrchr)
232 #elif defined(VGO_darwin)
233 //STRRCHR(VG_Z_LIBC_SONAME, strrchr)
234 //STRRCHR(VG_Z_LIBC_SONAME, rindex)
235 //STRRCHR(VG_Z_DYLD, strrchr)
236 //STRRCHR(VG_Z_DYLD, rindex)
237 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
238 # if DARWIN_VERS >= DARWIN_10_9
239 STRRCHR(libsystemZucZddylib, strrchr)
240 # endif
242 #elif defined(VGO_solaris)
243 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
244 STRRCHR(VG_Z_LIBC_SONAME, rindex)
245 STRRCHR(VG_Z_LD_SO_1, strrchr)
247 #endif
250 /*---------------------- strchr ----------------------*/
252 #define STRCHR(soname, fnname) \
253 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
254 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
256 HChar ch = (HChar)c ; \
257 const HChar* p = s; \
258 while (True) { \
259 if (*p == ch) return CONST_CAST(HChar *,p); \
260 if (*p == 0) return NULL; \
261 p++; \
265 // Apparently index() is the same thing as strchr()
266 #if defined(VGO_linux)
267 STRCHR(VG_Z_LIBC_SONAME, strchr)
268 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
269 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2)
270 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2_no_bsf)
271 STRCHR(VG_Z_LIBC_SONAME, index)
272 # if !defined(VGP_x86_linux) && !defined(VGP_amd64_linux)
273 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
274 STRCHR(VG_Z_LD_LINUX_SO_2, index)
275 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
276 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
277 # endif
279 #if defined(VGPV_mips32_linux_android)
280 STRCHR(NONE, __dl_strchr)
281 #endif
283 #elif defined(VGO_freebsd)
284 STRCHR(VG_Z_LIBC_SONAME, strchr)
285 STRCHR(VG_Z_LIBC_SONAME, index)
286 STRCHR(VG_Z_LD_ELF_SO_1, strchr)
287 STRCHR(VG_Z_LD_ELF32_SO_1, strchr)
289 #elif defined(VGO_darwin)
290 STRCHR(VG_Z_LIBC_SONAME, strchr)
291 # if DARWIN_VERS == DARWIN_10_9
292 STRCHR(libsystemZuplatformZddylib, _platform_strchr)
293 # endif
294 # if DARWIN_VERS >= DARWIN_10_10
295 /* _platform_strchr$VARIANT$Generic */
296 STRCHR(libsystemZuplatformZddylib, _platform_strchr$VARIANT$Generic)
297 /* _platform_strchr$VARIANT$Haswell */
298 STRCHR(libsystemZuplatformZddylib, _platform_strchr$VARIANT$Haswell)
299 # endif
300 STRCHR(libsystemZuplatformZddylib, _platform_strchr$VARIANT$Base)
302 #elif defined(VGO_solaris)
303 STRCHR(VG_Z_LIBC_SONAME, strchr)
304 STRCHR(VG_Z_LIBC_SONAME, index)
305 STRCHR(VG_Z_LD_SO_1, strchr)
307 #endif
310 /*---------------------- strcat ----------------------*/
312 #define STRCAT(soname, fnname) \
313 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
314 ( char* dst, const char* src ); \
315 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
316 ( char* dst, const char* src ) \
318 const HChar* src_orig = src; \
319 HChar* dst_orig = dst; \
320 while (*dst) dst++; \
321 while (*src) *dst++ = *src++; \
322 *dst = 0; \
324 /* This is a bit redundant, I think; any overlap and the strcat will */ \
325 /* go forever... or until a seg fault occurs. */ \
326 if (is_overlap(dst_orig, \
327 src_orig, \
328 (Addr)dst-(Addr)dst_orig+1, \
329 (Addr)src-(Addr)src_orig+1)) \
330 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
332 return dst_orig; \
335 #if defined(VGO_linux)
336 STRCAT(VG_Z_LIBC_SONAME, strcat)
337 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
339 #elif defined(VGO_freebsd)
340 STRCAT(VG_Z_LIBC_SONAME, strcat)
341 STRCAT(VG_Z_LD_ELF_SO_1, strcat)
342 STRCAT(VG_Z_LD_ELF32_SO_1, strcat)
344 #elif defined(VGO_darwin)
345 //STRCAT(VG_Z_LIBC_SONAME, strcat)
347 #elif defined(VGO_solaris)
348 STRCAT(VG_Z_LIBC_SONAME, strcat)
349 STRCAT(VG_Z_LD_SO_1, strcat)
351 #endif
354 /*---------------------- strncat ----------------------*/
356 #define STRNCAT(soname, fnname) \
357 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
358 ( char* dst, const char* src, SizeT n ); \
359 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
360 ( char* dst, const char* src, SizeT n ) \
362 const HChar* src_orig = src; \
363 HChar* dst_orig = dst; \
364 SizeT m = 0; \
366 while (*dst) dst++; \
367 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
368 *dst = 0; /* always add null */ \
370 /* This checks for overlap after copying, unavoidable without */ \
371 /* pre-counting lengths... should be ok */ \
372 if (is_overlap(dst_orig, \
373 src_orig, \
374 (Addr)dst-(Addr)dst_orig+1, \
375 (Addr)src-(Addr)src_orig)) \
376 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
378 return dst_orig; \
381 #if defined(VGO_linux)
382 STRNCAT(VG_Z_LIBC_SONAME, strncat)
384 #elif defined(VGO_freebsd)
385 STRNCAT(VG_Z_LIBC_SONAME, strncat)
387 #elif defined(VGO_darwin)
388 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
389 //STRNCAT(VG_Z_DYLD, strncat)
391 #elif defined(VGO_solaris)
392 STRNCAT(VG_Z_LIBC_SONAME, strncat)
394 #endif
397 /*---------------------- strlcat ----------------------*/
399 /* Append src to dst. n is the size of dst's buffer. dst is guaranteed
400 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
401 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
402 Truncation occurred if retval >= n.
404 #define STRLCAT(soname, fnname) \
405 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
406 ( char* dst, const char* src, SizeT n ); \
407 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
408 ( char* dst, const char* src, SizeT n ) \
410 const HChar* src_orig = src; \
411 HChar* dst_orig = dst; \
412 SizeT m = 0; \
414 while (m < n && *dst) { m++; dst++; } \
415 if (m < n) { \
416 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
417 while (m+1 < n && *src) { m++; *dst++ = *src++; } \
418 *dst = 0; \
419 } else { \
420 /* No space to copy anything to dst. m == n */ \
422 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
423 while (*src) { m++; src++; } \
424 /* This checks for overlap after copying, unavoidable without */ \
425 /* pre-counting lengths... should be ok */ \
426 if (is_overlap(dst_orig, \
427 src_orig, \
428 (Addr)dst-(Addr)dst_orig+1, \
429 (Addr)src-(Addr)src_orig+1)) \
430 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
432 return m; \
435 #if defined(VGO_linux)
436 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
438 #elif defined(VGO_freebsd)
439 STRLCAT(VG_Z_LD_ELF_SO_1, strlcat)
440 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
441 STRLCAT(VG_Z_LD_ELF32_SO_1, strlcat)
443 #elif defined(VGO_darwin)
444 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
445 //STRLCAT(VG_Z_DYLD, strlcat)
446 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
448 #elif defined(VGO_solaris)
449 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
451 #endif
454 /*---------------------- strnlen ----------------------*/
456 #define STRNLEN(soname, fnname) \
457 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
458 ( const char* str, SizeT n ); \
459 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
460 ( const char* str, SizeT n ) \
462 SizeT i = 0; \
463 while (i < n && str[i] != 0) i++; \
464 return i; \
467 #if defined(VGO_linux)
468 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
469 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
471 #elif defined(VGO_freebsd)
473 STRNLEN(VG_Z_LIBC_SONAME, srtnlen)
475 #elif defined(VGO_darwin)
476 # if DARWIN_VERS == DARWIN_10_9
477 STRNLEN(libsystemZucZddylib, strnlen)
478 # endif
480 #elif defined(VGO_solaris)
481 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
483 #endif
486 /*---------------------- strlen ----------------------*/
488 // Note that this replacement often doesn't get used because gcc inlines
489 // calls to strlen() with its own built-in version. This can be very
490 // confusing if you aren't expecting it. Other small functions in
491 // this file may also be inline by gcc.
493 #define STRLEN(soname, fnname) \
494 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
495 ( const char* str ); \
496 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
497 ( const char* str ) \
499 SizeT i = 0; \
500 while (str[i] != 0) i++; \
501 return i; \
504 #if defined(VGO_linux)
505 STRLEN(VG_Z_LIBC_SONAME, strlen)
506 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
507 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2)
508 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2_no_bsf)
509 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse42)
510 STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
511 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
512 # if defined(VGPV_arm_linux_android) \
513 || defined(VGPV_x86_linux_android) \
514 || defined(VGPV_mips32_linux_android)
515 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
516 # endif
518 #elif defined(VGO_freebsd)
519 STRLEN(VG_Z_LIBC_SONAME, strlen)
520 STRLEN(VG_Z_LD_ELF_SO_1, strlen)
521 STRLEN(VG_Z_LD_ELF32_SO_1, strlen)
523 #elif defined(VGO_darwin)
524 STRLEN(VG_Z_LIBC_SONAME, strlen)
525 # if DARWIN_VERS >= DARWIN_10_9
526 STRLEN(libsystemZucZddylib, strlen)
527 # endif
529 #elif defined(VGO_solaris)
530 STRLEN(VG_Z_LIBC_SONAME, strlen)
531 STRLEN(VG_Z_LD_SO_1, strlen)
533 #endif
536 /*---------------------- strcpy ----------------------*/
538 #define STRCPY(soname, fnname) \
539 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
540 ( char* dst, const char* src ); \
541 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
542 ( char* dst, const char* src ) \
544 const HChar* src_orig = src; \
545 HChar* dst_orig = dst; \
547 while (*src) *dst++ = *src++; \
548 *dst = 0; \
550 /* This happens after copying, unavoidable without */ \
551 /* pre-counting length... should be ok */ \
552 SizeT srclen = (Addr)src-(Addr)src_orig+1; \
553 RECORD_COPY(srclen); \
554 if (is_overlap(dst_orig, \
555 src_orig, \
556 (Addr)dst-(Addr)dst_orig+1, \
557 srclen)) \
558 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
560 return dst_orig; \
563 #if defined(VGO_linux)
564 STRCPY(VG_Z_LIBC_SONAME, strcpy)
565 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
567 #elif defined(VGO_freebsd)
568 STRCPY(VG_Z_LIBC_SONAME, strcpy)
569 STRCPY(VG_Z_LD_ELF_SO_1, strcpy)
570 STRCPY(VG_Z_LD_ELF32_SO_1, strcpy)
572 #elif defined(VGO_darwin)
573 STRCPY(VG_Z_LIBC_SONAME, strcpy)
574 # if DARWIN_VERS == DARWIN_10_9
575 STRCPY(libsystemZucZddylib, strcpy)
576 # endif
578 #elif defined(VGO_solaris)
579 STRCPY(VG_Z_LIBC_SONAME, strcpy)
580 STRCPY(VG_Z_LD_SO_1, strcpy)
582 #endif
585 /*---------------------- strncpy ----------------------*/
587 #define STRNCPY(soname, fnname) \
588 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
589 ( char* dst, const char* src, SizeT n ); \
590 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
591 ( char* dst, const char* src, SizeT n ) \
593 const HChar* src_orig = src; \
594 HChar* dst_orig = dst; \
595 SizeT m = 0; \
597 while (m < n && *src) { m++; *dst++ = *src++; } \
598 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
599 /* but only m+1 bytes of src if terminator was found */ \
600 SizeT srclen = (m < n) ? m+1 : n; \
601 RECORD_COPY(srclen); \
602 if (is_overlap(dst_orig, src_orig, n, srclen)) \
603 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
604 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
606 return dst_orig; \
609 #if defined(VGO_linux)
610 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
611 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
612 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2)
613 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned)
615 #elif defined(VGO_freebsd)
616 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
617 STRNCPY(VG_Z_LD_ELF_SO_1, strncpy)
618 STRNCPY(VG_Z_LD_ELF32_SO_1, strncpy)
620 #elif defined(VGO_darwin)
621 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
622 # if DARWIN_VERS >= DARWIN_10_9
623 STRNCPY(libsystemZucZddylib, strncpy)
624 # endif
626 #elif defined(VGO_solaris)
627 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
628 STRNCPY(VG_Z_LD_SO_1, strncpy)
630 #endif
633 /*---------------------- strlcpy ----------------------*/
635 /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
636 Returns strlen(src). Does not zero-fill the remainder of dst. */
637 #define STRLCPY(soname, fnname) \
638 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
639 ( char* dst, const char* src, SizeT n ); \
640 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
641 ( char* dst, const char* src, SizeT n ) \
643 const HChar* src_orig = src; \
644 HChar* dst_orig = dst; \
645 SizeT m = 0; \
647 STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
649 while (m+1 < n && *src) { m++; *dst++ = *src++; } \
650 /* m non-nul bytes have now been copied, and m <= n-1. */ \
651 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
652 /* but only m+1 bytes of src if terminator was found */ \
653 SizeT srclen = (m < n) ? m+1 : n; \
654 RECORD_COPY(srclen); \
655 if (is_overlap(dst_orig, src_orig, n, srclen)) \
656 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
657 /* Nul-terminate dst. */ \
658 if (n > 0) *dst = 0; \
659 /* Finish counting strlen(src). */ \
660 while (*src) src++; \
661 return src - src_orig; \
664 #if defined(VGO_linux)
666 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
667 STRLCPY(VG_Z_LIBC_SONAME, strlcpy);
669 #elif defined(VGO_freebsd)
670 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
671 STRLCPY(VG_Z_LD_ELF_SO_1, strlcpy)
672 STRLCPY(VG_Z_LD_ELF32_SO_1, strlcpy)
673 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
675 #elif defined(VGO_darwin)
676 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
677 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
678 //STRLCPY(VG_Z_DYLD, strlcpy)
679 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
681 #elif defined(VGO_solaris)
682 /* special case for n == 0 which is undocumented but heavily used */
683 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
684 if (n == 0) { \
685 while (*src) src++; \
686 return src - src_orig; \
689 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
691 #endif
694 /*---------------------- strncmp ----------------------*/
696 #define STRNCMP(soname, fnname) \
697 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
698 ( const char* s1, const char* s2, SizeT nmax ); \
699 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
700 ( const char* s1, const char* s2, SizeT nmax ) \
702 SizeT n = 0; \
703 while (True) { \
704 if (n >= nmax) return 0; \
705 if (*s1 == 0 && *s2 == 0) return 0; \
706 if (*s1 == 0) return -1; \
707 if (*s2 == 0) return 1; \
709 if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \
710 if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \
712 s1++; s2++; n++; \
716 #if defined(VGO_linux)
717 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
718 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
719 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2)
720 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42)
721 STRNCMP(VG_Z_LD_LINUX_SO_2, strncmp)
722 STRNCMP(VG_Z_LD_LINUX_X86_64_SO_2, strncmp)
724 #elif defined(VGO_freebsd)
725 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
726 STRNCMP(VG_Z_LD_ELF_SO_1, strncmp)
727 STRNCMP(VG_Z_LD_ELF32_SO_1, strncmp)
729 #elif defined(VGO_darwin)
730 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
731 # if DARWIN_VERS >= DARWIN_10_9
732 STRNCMP(libsystemZuplatformZddylib, _platform_strncmp)
733 # endif
735 #elif defined(VGO_solaris)
736 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
738 #endif
741 /*---------------------- strcasecmp ----------------------*/
743 #define STRCASECMP(soname, fnname) \
744 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
745 ( const char* s1, const char* s2 ); \
746 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
747 ( const char* s1, const char* s2 ) \
749 extern int tolower(int); \
750 register UChar c1; \
751 register UChar c2; \
752 while (True) { \
753 c1 = tolower(*(const UChar *)s1); \
754 c2 = tolower(*(const UChar *)s2); \
755 if (c1 != c2) break; \
756 if (c1 == 0) break; \
757 s1++; s2++; \
759 if ((UChar)c1 < (UChar)c2) return -1; \
760 if ((UChar)c1 > (UChar)c2) return 1; \
761 return 0; \
764 #if defined(VGO_linux)
765 # if !defined(VGPV_arm_linux_android) \
766 && !defined(VGPV_x86_linux_android) \
767 && !defined(VGPV_mips32_linux_android) \
768 && !defined(VGPV_arm64_linux_android)
769 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
770 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
771 # endif
773 #elif defined(VGO_freebsd)
774 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
775 STRNCMP(VG_Z_LD_ELF_SO_1, strcasecmp)
776 STRNCMP(VG_Z_LD_ELF32_SO_1, strcasecmp)
778 #elif defined(VGO_darwin)
779 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
781 #elif defined(VGO_solaris)
782 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
784 #endif
787 /*---------------------- strncasecmp ----------------------*/
789 #define STRNCASECMP(soname, fnname) \
790 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
791 ( const char* s1, const char* s2, SizeT nmax ); \
792 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
793 ( const char* s1, const char* s2, SizeT nmax ) \
795 extern int tolower(int); \
796 SizeT n = 0; \
797 while (True) { \
798 if (n >= nmax) return 0; \
799 if (*s1 == 0 && *s2 == 0) return 0; \
800 if (*s1 == 0) return -1; \
801 if (*s2 == 0) return 1; \
803 if (tolower(*(const UChar *)s1) \
804 < tolower(*(const UChar*)s2)) return -1; \
805 if (tolower(*(const UChar *)s1) \
806 > tolower(*(const UChar *)s2)) return 1; \
808 s1++; s2++; n++; \
812 #if defined(VGO_linux)
813 # if !defined(VGPV_arm_linux_android) \
814 && !defined(VGPV_x86_linux_android) \
815 && !defined(VGPV_mips32_linux_android) \
816 && !defined(VGPV_arm64_linux_android)
817 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
818 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
819 # endif
821 #elif defined(VGO_freebsd)
822 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
823 STRNCASECMP(VG_Z_LD_ELF_SO_1, strncasecmp)
824 STRNCASECMP(VG_Z_LD_ELF32_SO_1, strncasecmp)
826 #elif defined(VGO_darwin)
827 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
828 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
830 #elif defined(VGO_solaris)
831 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
833 #endif
836 /*---------------------- strcasecmp_l ----------------------*/
838 #define STRCASECMP_L(soname, fnname) \
839 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
840 ( const char* s1, const char* s2, void* locale ); \
841 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
842 ( const char* s1, const char* s2, void* locale ) \
844 extern int tolower_l(int, void*) __attribute__((weak)); \
845 register UChar c1; \
846 register UChar c2; \
847 while (True) { \
848 c1 = tolower_l(*(const UChar *)s1, locale); \
849 c2 = tolower_l(*(const UChar *)s2, locale); \
850 if (c1 != c2) break; \
851 if (c1 == 0) break; \
852 s1++; s2++; \
854 if ((UChar)c1 < (UChar)c2) return -1; \
855 if ((UChar)c1 > (UChar)c2) return 1; \
856 return 0; \
859 #if defined(VGO_linux)
860 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
861 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
862 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
864 #elif defined(VGO_freebsd)
865 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
867 #elif defined(VGO_darwin)
868 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
870 #elif defined(VGO_solaris)
872 #endif
875 /*---------------------- strncasecmp_l ----------------------*/
877 #define STRNCASECMP_L(soname, fnname) \
878 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
879 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
880 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
881 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
883 extern int tolower_l(int, void*) __attribute__((weak)); \
884 SizeT n = 0; \
885 while (True) { \
886 if (n >= nmax) return 0; \
887 if (*s1 == 0 && *s2 == 0) return 0; \
888 if (*s1 == 0) return -1; \
889 if (*s2 == 0) return 1; \
891 if (tolower_l(*(const UChar *)s1, locale) \
892 < tolower_l(*(const UChar *)s2, locale)) return -1; \
893 if (tolower_l(*(const UChar *)s1, locale) \
894 > tolower_l(*(const UChar *)s2, locale)) return 1; \
896 s1++; s2++; n++; \
900 #if defined(VGO_linux)
901 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
902 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
903 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l)
905 #elif defined(VGO_freebsd)
906 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
908 #elif defined(VGO_darwin)
909 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
910 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
912 #elif defined(VGO_solaris)
914 #endif
917 /*---------------------- strcmp ----------------------*/
919 #define STRCMP(soname, fnname) \
920 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
921 ( const char* s1, const char* s2 ); \
922 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
923 ( const char* s1, const char* s2 ) \
925 register UChar c1; \
926 register UChar c2; \
927 while (True) { \
928 c1 = *(const UChar *)s1; \
929 c2 = *(const UChar *)s2; \
930 if (c1 != c2) break; \
931 if (c1 == 0) break; \
932 s1++; s2++; \
934 if ((UChar)c1 < (UChar)c2) return -1; \
935 if ((UChar)c1 > (UChar)c2) return 1; \
936 return 0; \
939 #if defined(VGO_linux)
940 STRCMP(VG_Z_LIBC_SONAME, strcmp)
941 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
942 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse2)
943 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse42)
944 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
945 STRCMP(VG_Z_LD64_SO_1, strcmp)
946 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
947 || defined(VGPV_mips32_linux_android)
948 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
949 # endif
951 #elif defined(VGO_freebsd)
952 STRCMP(VG_Z_LIBC_SONAME, strcmp)
953 STRCMP(VG_Z_LD_ELF_SO_1, strcmp)
954 STRCMP(VG_Z_LD_ELF32_SO_1, strcmp)
956 #elif defined(VGO_darwin)
957 STRCMP(VG_Z_LIBC_SONAME, strcmp)
958 # if DARWIN_VERS >= DARWIN_10_9
959 STRCMP(libsystemZuplatformZddylib, _platform_strcmp)
960 # endif
962 #elif defined(VGO_solaris)
963 STRCMP(VG_Z_LIBC_SONAME, strcmp)
964 STRCMP(VG_Z_LD_SO_1, strcmp)
966 #endif
969 /*---------------------- memchr ----------------------*/
971 #define MEMCHR(soname, fnname) \
972 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
973 (const void *s, int c, SizeT n); \
974 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
975 (const void *s, int c, SizeT n) \
977 SizeT i; \
978 UChar c0 = (UChar)c; \
979 const UChar* p = s; \
980 for (i = 0; i < n; i++) \
981 if (p[i] == c0) return CONST_CAST(void *,&p[i]); \
982 return NULL; \
985 #if defined(VGO_linux)
986 MEMCHR(VG_Z_LIBC_SONAME, memchr)
987 MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr)
989 #elif defined(VGO_freebsd)
990 MEMCHR(VG_Z_LIBC_SONAME, memchr)
992 #elif defined(VGO_darwin)
993 # if DARWIN_VERS == DARWIN_10_9
994 MEMCHR(VG_Z_DYLD, memchr)
995 MEMCHR(libsystemZuplatformZddylib, _platform_memchr)
996 # endif
997 # if DARWIN_VERS >= DARWIN_10_10
998 MEMCHR(VG_Z_DYLD, memchr)
999 /* _platform_memchr$VARIANT$Generic */
1000 MEMCHR(libsystemZuplatformZddylib, _platform_memchr$VARIANT$Generic)
1001 /* _platform_memchr$VARIANT$Haswell */
1002 MEMCHR(libsystemZuplatformZddylib, _platform_memchr$VARIANT$Haswell)
1003 # endif
1004 # if DARWIN_VERS >= DARWIN_10_12
1005 /* _platform_memchr$VARIANT$Base */
1006 MEMCHR(libsystemZuplatformZddylib, _platform_memchr$VARIANT$Base)
1007 #endif
1009 #elif defined(VGO_solaris)
1010 MEMCHR(VG_Z_LIBC_SONAME, memchr)
1012 #endif
1015 /*---------------------- memrchr ----------------------*/
1017 #define MEMRCHR(soname, fnname) \
1018 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
1019 (const void *s, int c, SizeT n); \
1020 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
1021 (const void *s, int c, SizeT n) \
1023 SizeT i; \
1024 UChar c0 = (UChar)c; \
1025 const UChar* p = s; \
1026 for (i = 0; i < n; i++) \
1027 if (p[n-1-i] == c0) return CONST_CAST(void *,&p[n-1-i]); \
1028 return NULL; \
1031 #if defined(VGO_linux)
1032 MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
1034 #elif defined(VGO_freebsd)
1035 MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
1037 #elif defined(VGO_darwin)
1038 //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
1039 //MEMRCHR(VG_Z_DYLD, memrchr)
1041 #elif defined(VGO_solaris)
1043 #endif
1046 /*---------------------- memcpy ----------------------*/
1048 #define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
1049 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
1050 ( void *dst, const void *src, SizeT len ); \
1051 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
1052 ( void *dst, const void *src, SizeT len ) \
1054 RECORD_COPY(len); \
1055 if (do_ol_check && is_overlap(dst, src, len, len)) \
1056 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
1058 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
1059 const Addr WM = WS - 1; /* 7 or 3 */ \
1061 if (len > 0) { \
1062 if (dst < src || !is_overlap(dst, src, len, len)) { \
1064 /* Copying backwards. */ \
1065 SizeT n = len; \
1066 Addr d = (Addr)dst; \
1067 Addr s = (Addr)src; \
1069 if (((s^d) & WM) == 0) { \
1070 /* s and d have same UWord alignment. */ \
1071 /* Pull up to a UWord boundary. */ \
1072 while ((s & WM) != 0 && n >= 1) \
1073 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
1074 /* Copy UWords. */ \
1075 while (n >= WS * 4) \
1076 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
1077 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
1078 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
1079 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
1080 while (n >= WS) \
1081 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
1082 if (n == 0) \
1083 return dst; \
1085 if (((s|d) & 1) == 0) { \
1086 /* Both are 16-aligned; copy what we can thusly. */ \
1087 while (n >= 2) \
1088 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
1090 /* Copy leftovers, or everything if misaligned. */ \
1091 while (n >= 1) \
1092 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
1094 } else if (dst > src) { \
1096 SizeT n = len; \
1097 Addr d = ((Addr)dst) + n; \
1098 Addr s = ((Addr)src) + n; \
1100 /* Copying forwards. */ \
1101 if (((s^d) & WM) == 0) { \
1102 /* s and d have same UWord alignment. */ \
1103 /* Back down to a UWord boundary. */ \
1104 while ((s & WM) != 0 && n >= 1) \
1105 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
1106 /* Copy UWords. */ \
1107 while (n >= WS * 4) \
1108 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1109 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1110 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1111 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
1112 while (n >= WS) \
1113 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
1114 if (n == 0) \
1115 return dst; \
1117 if (((s|d) & 1) == 0) { \
1118 /* Both are 16-aligned; copy what we can thusly. */ \
1119 while (n >= 2) \
1120 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
1122 /* Copy leftovers, or everything if misaligned. */ \
1123 while (n >= 1) \
1124 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
1129 return dst; \
1132 #define MEMMOVE(soname, fnname) \
1133 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
1135 /* See https://bugs.kde.org/show_bug.cgi?id=402833
1136 why we disable the overlap check on x86_64. */
1137 #if defined(VGP_amd64_linux) || defined(VGP_arm64_freebsd)
1138 #define MEMCPY(soname, fnname) \
1139 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 0)
1140 #else
1141 #define MEMCPY(soname, fnname) \
1142 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
1143 #endif
1145 #if defined(VGO_linux)
1146 /* For older memcpy we have to use memmove-like semantics and skip
1147 the overlap check; sigh; see #275284. */
1148 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
1149 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
1150 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
1151 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy)
1152 MEMCPY(VG_Z_LIBC_SONAME, __memcpy_sse2)
1153 MEMCPY(VG_Z_LIBC_SONAME, __memcpy_avx_unaligned_erms)
1154 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
1155 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
1156 /* icc9 blats these around all over the place. Not only in the main
1157 executable but various .so's. They are highly tuned and read
1158 memory beyond the source boundary (although work correctly and
1159 never go across page boundaries), so give errors when run
1160 natively, at least for misaligned source arg. Just intercepting
1161 in the exe only until we understand more about the problem. See
1162 http://bugs.kde.org/show_bug.cgi?id=139776
1164 MEMCPY(NONE, ZuintelZufastZumemcpy)
1166 #elif defined(VGO_freebsd)
1167 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
1168 MEMCPY(VG_Z_LD_ELF_SO_1, memcpy)
1169 MEMCPY(VG_Z_LD_ELF32_SO_1, memcpy)
1171 #elif defined(VGO_darwin)
1172 # if DARWIN_VERS <= DARWIN_10_6
1173 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
1174 # endif
1175 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
1176 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
1178 #elif defined(VGO_solaris)
1179 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
1180 MEMCPY(VG_Z_LIBC_SONAME, memcpyZPZa)
1181 MEMCPY(VG_Z_LD_SO_1, memcpy)
1183 #endif
1186 /*---------------------- memcmp ----------------------*/
1188 #define MEMCMP(soname, fnname) \
1189 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1190 ( const void *s1V, const void *s2V, SizeT n ); \
1191 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1192 ( const void *s1V, const void *s2V, SizeT n ) \
1194 const SizeT WS = sizeof(UWord); /* 8 or 4 */ \
1195 const SizeT WM = WS - 1; /* 7 or 3 */ \
1196 Addr s1A = (Addr)s1V; \
1197 Addr s2A = (Addr)s2V; \
1199 if (((s1A | s2A) & WM) == 0) { \
1200 /* Both areas are word aligned. Skip over the */ \
1201 /* equal prefix as fast as possible. */ \
1202 while (n >= WS) { \
1203 UWord w1 = *(UWord*)s1A; \
1204 UWord w2 = *(UWord*)s2A; \
1205 if (w1 != w2) break; \
1206 s1A += WS; \
1207 s2A += WS; \
1208 n -= WS; \
1212 const UChar* s1 = (const UChar*) s1A; \
1213 const UChar* s2 = (const UChar*) s2A; \
1215 while (n != 0) { \
1216 UChar a0 = s1[0]; \
1217 UChar b0 = s2[0]; \
1218 s1 += 1; \
1219 s2 += 1; \
1220 int res = ((int)a0) - ((int)b0); \
1221 if (res != 0) \
1222 return res; \
1223 n -= 1; \
1225 return 0; \
1228 #if defined(VGO_linux)
1229 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
1230 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
1231 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse2)
1232 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse4_1)
1233 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
1234 MEMCMP(VG_Z_LD_SO_1, bcmp)
1236 #elif defined(VGO_freebsd)
1237 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
1238 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
1239 MEMCMP(VG_Z_LIBC_SONAME, timingsafe_memcmp)
1240 MEMCMP(VG_Z_LIBC_SONAME, timingsafe_bcmp)
1242 #elif defined(VGO_darwin)
1243 # if DARWIN_VERS >= DARWIN_10_9
1244 MEMCMP(libsystemZuplatformZddylib, _platform_memcmp)
1245 # endif
1247 #elif defined(VGO_solaris)
1248 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
1249 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
1250 MEMCMP(VG_Z_LD_SO_1, memcmp)
1252 #endif
1255 /*---------------------- stpcpy ----------------------*/
1257 /* Copy SRC to DEST, returning the address of the terminating '\0' in
1258 DEST. (minor variant of strcpy) */
1259 #define STPCPY(soname, fnname) \
1260 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1261 ( char* dst, const char* src ); \
1262 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1263 ( char* dst, const char* src ) \
1265 const HChar* src_orig = src; \
1266 HChar* dst_orig = dst; \
1268 while (*src) *dst++ = *src++; \
1269 *dst = 0; \
1271 /* This checks for overlap after copying, unavoidable without */ \
1272 /* pre-counting length... should be ok */ \
1273 SizeT srclen = (Addr)src-(Addr)src_orig+1; \
1274 RECORD_COPY(srclen); \
1275 if (is_overlap(dst_orig, \
1276 src_orig, \
1277 (Addr)dst-(Addr)dst_orig+1, \
1278 srclen)) \
1279 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
1281 return dst; \
1284 #if defined(VGO_linux)
1285 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1286 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
1287 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2)
1288 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2_unaligned)
1289 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
1290 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
1291 STPCPY(VG_Z_LD_LINUX_AARCH64_SO_1,stpcpy)
1293 #elif defined(VGO_freebsd)
1294 STPCPY(VG_Z_LD_ELF_SO_1, stpcpy)
1295 STPCPY(VG_Z_LD_ELF32_SO_1, stpcpy)
1296 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1298 #elif defined(VGO_freebsd)
1299 STPCPY(VG_Z_LD_ELF_SO_1, stpcpy)
1300 STPCPY(VG_Z_LD_ELF32_SO_1, stpcpy)
1301 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1303 #elif defined(VGO_darwin)
1304 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1305 //STPCPY(VG_Z_DYLD, stpcpy)
1307 #elif defined(VGO_solaris)
1308 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1310 #endif
1313 /*---------------------- stpncpy ----------------------*/
1315 #define STPNCPY(soname, fnname) \
1316 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1317 ( char* dst, const char* src, SizeT n ); \
1318 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1319 ( char* dst, const char* src, SizeT n ) \
1321 const HChar* src_orig = src; \
1322 HChar* dst_str = dst; \
1323 SizeT m = 0; \
1325 while (m < n && *src) { m++; *dst++ = *src++; } \
1326 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
1327 /* but only m+1 bytes of src if terminator was found */ \
1328 SizeT srclen = (m < n) ? m+1 : n; \
1329 RECORD_COPY(srclen); \
1330 if (is_overlap(dst_str, src_orig, n, srclen)) \
1331 RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \
1332 dst_str = dst; \
1333 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
1335 return dst_str; \
1338 #if defined(VGO_linux) || defined(VGO_freebsd)
1339 STPNCPY(VG_Z_LIBC_SONAME, stpncpy)
1340 #endif
1343 /*---------------------- memset ----------------------*/
1345 #define MEMSET(soname, fnname) \
1346 void* VG_REPLACE_FUNCTION_EZZ(20210,soname,fnname) \
1347 (void *s, Int c, SizeT n); \
1348 void* VG_REPLACE_FUNCTION_EZZ(20210,soname,fnname) \
1349 (void *s, Int c, SizeT n) \
1351 if (sizeof(void*) == 8) { \
1352 Addr a = (Addr)s; \
1353 ULong c8 = (c & 0xFF); \
1354 c8 = (c8 << 8) | c8; \
1355 c8 = (c8 << 16) | c8; \
1356 c8 = (c8 << 32) | c8; \
1357 while ((a & 7) != 0 && n >= 1) \
1358 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1359 while (n >= 32) \
1360 { *(ULong*)a = c8; a += 8; n -= 8; \
1361 *(ULong*)a = c8; a += 8; n -= 8; \
1362 *(ULong*)a = c8; a += 8; n -= 8; \
1363 *(ULong*)a = c8; a += 8; n -= 8; } \
1364 while (n >= 8) \
1365 { *(ULong*)a = c8; a += 8; n -= 8; } \
1366 while (n >= 1) \
1367 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1368 return s; \
1369 } else { \
1370 Addr a = (Addr)s; \
1371 UInt c4 = (c & 0xFF); \
1372 c4 = (c4 << 8) | c4; \
1373 c4 = (c4 << 16) | c4; \
1374 while ((a & 3) != 0 && n >= 1) \
1375 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1376 while (n >= 16) \
1377 { *(UInt*)a = c4; a += 4; n -= 4; \
1378 *(UInt*)a = c4; a += 4; n -= 4; \
1379 *(UInt*)a = c4; a += 4; n -= 4; \
1380 *(UInt*)a = c4; a += 4; n -= 4; } \
1381 while (n >= 4) \
1382 { *(UInt*)a = c4; a += 4; n -= 4; } \
1383 while (n >= 1) \
1384 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1385 return s; \
1389 #if defined(VGO_linux)
1390 MEMSET(VG_Z_LIBC_SONAME, memset)
1392 #elif defined(VGO_freebsd)
1393 MEMSET(VG_Z_LIBC_SONAME, memset)
1394 MEMSET(VG_Z_LD_ELF_SO_1, memset)
1395 MEMSET(VG_Z_LD_ELF32_SO_1, memset)
1397 #elif defined(VGO_darwin)
1398 //MEMSET(VG_Z_LIBC_SONAME, memset)
1399 //MEMSET(VG_Z_DYLD, memset)
1400 MEMSET(VG_Z_LIBC_SONAME, memset)
1402 #elif defined(VGO_solaris)
1403 MEMSET(VG_Z_LIBC_SONAME, memset)
1404 MEMSET(VG_Z_LIBC_SONAME, memsetZPZa)
1406 #endif
1409 /*---------------------- memmove ----------------------*/
1411 /* memmove -- use the MEMMOVE defn above. */
1413 #if defined(VGO_linux)
1414 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1415 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove)
1416 /* See bug #349828 Override for ld64.so.1 like memcpy, because for some
1417 arches MEMCPY_OK_FOR_FORWARD_MEMMOVE is set, which might cause memmove
1418 to call memcpy. */
1419 MEMMOVE(VG_Z_LD64_SO_1, memmove)
1421 #elif defined(VGO_freebsd)
1422 MEMMOVE(VG_Z_LD_ELF_SO_1, memmove)
1423 MEMMOVE(VG_Z_LD_ELF32_SO_1, memmove)
1424 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1426 #elif defined(VGO_darwin)
1427 # if DARWIN_VERS <= DARWIN_10_6
1428 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1429 # endif
1430 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
1431 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
1432 # if DARWIN_VERS >= DARWIN_10_9
1433 /* _platform_memmove$VARIANT$Ivybridge */
1434 MEMMOVE(libsystemZuplatformZddylib, ZuplatformZumemmoveZDVARIANTZDIvybridge)
1435 # endif
1437 #elif defined(VGO_solaris)
1438 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1439 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZPZa)
1440 MEMMOVE(VG_Z_LD_SO_1, memmove)
1442 #endif
1445 /*---------------------- bcopy ----------------------*/
1447 #define BCOPY(soname, fnname) \
1448 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1449 (const void *srcV, void *dstV, SizeT n); \
1450 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1451 (const void *srcV, void *dstV, SizeT n) \
1453 RECORD_COPY(n); \
1454 SizeT i; \
1455 HChar* dst = dstV; \
1456 const HChar* src = srcV; \
1457 if (dst < src) { \
1458 for (i = 0; i < n; i++) \
1459 dst[i] = src[i]; \
1461 else \
1462 if (dst > src) { \
1463 for (i = 0; i < n; i++) \
1464 dst[n-i-1] = src[n-i-1]; \
1468 #if defined(VGO_linux)
1469 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1471 #elif defined(VGO_freebsd)
1472 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1473 BCOPY(VG_Z_LD_ELF_SO_1, bcopy)
1474 BCOPY(VG_Z_LD_ELF32_SO_1, bcopy)
1476 #elif defined(VGO_darwin)
1477 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1478 //BCOPY(VG_Z_DYLD, bcopy)
1480 #elif defined(VGO_darwin)
1481 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1483 #endif
1486 /*-------------------- memmove_chk --------------------*/
1488 /* glibc 2.5 variant of memmove which checks the dest is big enough.
1489 There is no specific part of glibc that this is copied from. */
1490 #define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1491 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1492 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1493 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1494 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1496 RECORD_COPY(n); \
1497 SizeT i; \
1498 HChar* dst = dstV; \
1499 const HChar* src = srcV; \
1500 if (destlen < n) \
1501 goto badness; \
1502 if (dst < src) { \
1503 for (i = 0; i < n; i++) \
1504 dst[i] = src[i]; \
1506 else \
1507 if (dst > src) { \
1508 for (i = 0; i < n; i++) \
1509 dst[n-i-1] = src[n-i-1]; \
1511 return dst; \
1512 badness: \
1513 VALGRIND_PRINTF_BACKTRACE( \
1514 "*** memmove_chk: buffer overflow detected ***: " \
1515 "program terminated\n"); \
1516 my_exit(1); \
1517 /*NOTREACHED*/ \
1518 return NULL; \
1521 #if defined(VGO_linux)
1522 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
1524 #elif defined(VGO_darwin)
1526 #elif defined(VGO_solaris)
1528 #endif
1531 /*-------------------- strchrnul --------------------*/
1533 /* Find the first occurrence of C in S or the final NUL byte. */
1534 #define GLIBC232_STRCHRNUL(soname, fnname) \
1535 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1536 (const char* s, int c_in); \
1537 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1538 (const char* s, int c_in) \
1540 HChar c = (HChar) c_in; \
1541 const HChar* char_ptr = s; \
1542 while (1) { \
1543 if (*char_ptr == 0) return CONST_CAST(HChar *,char_ptr); \
1544 if (*char_ptr == c) return CONST_CAST(HChar *,char_ptr); \
1545 char_ptr++; \
1549 #if defined(VGO_linux)
1550 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1552 #elif defined(VGO_freebsd)
1553 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1555 #elif defined(VGO_darwin)
1557 #elif defined(VGO_solaris)
1559 #endif
1562 /*---------------------- rawmemchr ----------------------*/
1564 /* Find the first occurrence of C in S. */
1565 #define GLIBC232_RAWMEMCHR(soname, fnname) \
1566 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1567 (const void* s, int c_in); \
1568 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1569 (const void* s, int c_in) \
1571 UChar c = (UChar) c_in; \
1572 const UChar* char_ptr = s; \
1573 while (1) { \
1574 if (*char_ptr == c) return CONST_CAST(void *,char_ptr); \
1575 char_ptr++; \
1579 #if defined (VGO_linux)
1580 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1581 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1583 #elif defined(VGO_darwin)
1585 #elif defined(VGO_solaris)
1587 #endif
1590 /*---------------------- strcpy_chk ----------------------*/
1592 /* glibc variant of strcpy that checks the dest is big enough.
1593 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1594 #define GLIBC25___STRCPY_CHK(soname,fnname) \
1595 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1596 (char* dst, const char* src, SizeT len); \
1597 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1598 (char* dst, const char* src, SizeT len) \
1600 FOR_COPY(const HChar* src_orig = src); \
1601 HChar* ret = dst; \
1602 if (! len) \
1603 goto badness; \
1604 while ((*dst++ = *src++) != '\0') \
1605 if (--len == 0) \
1606 goto badness; \
1607 RECORD_COPY((Addr)src-(Addr)src_orig); \
1608 return ret; \
1609 badness: \
1610 VALGRIND_PRINTF_BACKTRACE( \
1611 "*** strcpy_chk: buffer overflow detected ***: " \
1612 "program terminated\n"); \
1613 my_exit(1); \
1614 /*NOTREACHED*/ \
1615 return NULL; \
1618 #if defined(VGO_linux)
1619 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1621 #elif defined(VGO_darwin)
1623 #elif defined(VGO_solaris)
1625 #endif
1628 /*---------------------- stpcpy_chk ----------------------*/
1630 /* glibc variant of stpcpy that checks the dest is big enough.
1631 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1632 #define GLIBC25___STPCPY_CHK(soname,fnname) \
1633 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1634 (char* dst, const char* src, SizeT len); \
1635 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1636 (char* dst, const char* src, SizeT len) \
1638 FOR_COPY(const HChar* src_orig = src); \
1639 if (! len) \
1640 goto badness; \
1641 while ((*dst++ = *src++) != '\0') \
1642 if (--len == 0) \
1643 goto badness; \
1644 RECORD_COPY((Addr)src-(Addr)src_orig); \
1645 return dst - 1; \
1646 badness: \
1647 VALGRIND_PRINTF_BACKTRACE( \
1648 "*** stpcpy_chk: buffer overflow detected ***: " \
1649 "program terminated\n"); \
1650 my_exit(1); \
1651 /*NOTREACHED*/ \
1652 return NULL; \
1655 #if defined(VGO_linux)
1656 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1658 #elif defined(VGO_darwin)
1660 #elif defined(VGO_solaris)
1662 #endif
1665 /*---------------------- mempcpy ----------------------*/
1667 /* mempcpy */
1668 #define GLIBC25_MEMPCPY(soname, fnname) \
1669 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1670 ( void *dst, const void *src, SizeT len ); \
1671 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1672 ( void *dst, const void *src, SizeT len ) \
1674 RECORD_COPY(len); \
1675 SizeT len_saved = len; \
1677 if (len == 0) \
1678 return dst; \
1680 if (is_overlap(dst, src, len, len)) \
1681 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1683 if ( dst > src ) { \
1684 register HChar *d = (char *)dst + len - 1; \
1685 register const HChar *s = (const char *)src + len - 1; \
1686 while ( len-- ) { \
1687 *d-- = *s--; \
1689 } else if ( dst < src ) { \
1690 register HChar *d = dst; \
1691 register const HChar *s = src; \
1692 while ( len-- ) { \
1693 *d++ = *s++; \
1696 return (void*)( ((char*)dst) + len_saved ); \
1699 #if defined(VGO_linux)
1700 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1701 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, __GI_mempcpy)
1702 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
1703 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */
1704 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */
1706 #elif defined(VGO_freebsd)
1707 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1708 #elif defined(VGO_darwin)
1709 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1711 #elif defined(VGO_solaris)
1713 #endif
1716 /*-------------------- memcpy_chk --------------------*/
1718 /* See https://bugs.kde.org/show_bug.cgi?id=402833
1719 why we disable the overlap check on x86_64. */
1720 #if defined(VGP_amd64_linux)
1721 #define CHECK_OVERLAP 0
1722 #else
1723 #define CHECK_OVERLAP 1
1724 #endif
1726 #define GLIBC26___MEMCPY_CHK(soname, fnname) \
1727 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1728 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1729 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1730 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1732 register HChar *d; \
1733 register const HChar *s; \
1734 if (dstlen < len) \
1735 goto badness; \
1736 RECORD_COPY(len); \
1737 if (len == 0) \
1738 return dst; \
1739 if (CHECK_OVERLAP && is_overlap(dst, src, len, len)) \
1740 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1741 if ( dst > src ) { \
1742 d = (HChar *)dst + len - 1; \
1743 s = (const HChar *)src + len - 1; \
1744 while ( len-- ) { \
1745 *d-- = *s--; \
1747 } else if ( dst < src ) { \
1748 d = (HChar *)dst; \
1749 s = (const HChar *)src; \
1750 while ( len-- ) { \
1751 *d++ = *s++; \
1754 return dst; \
1755 badness: \
1756 VALGRIND_PRINTF_BACKTRACE( \
1757 "*** memcpy_chk: buffer overflow detected ***: " \
1758 "program terminated\n"); \
1759 my_exit(1); \
1760 /*NOTREACHED*/ \
1761 return NULL; \
1764 #if defined(VGO_linux)
1765 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1767 #elif defined(VGO_darwin)
1769 #elif defined(VGO_solaris)
1771 #endif
1774 /*---------------------- strstr ----------------------*/
1776 #define STRSTR(soname, fnname) \
1777 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1778 (const char* haystack, const char* needle); \
1779 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1780 (const char* haystack, const char* needle) \
1782 const HChar* h = haystack; \
1783 const HChar* n = needle; \
1785 /* find the length of n, not including terminating zero */ \
1786 UWord nlen = 0; \
1787 while (n[nlen]) nlen++; \
1789 /* if n is the empty string, match immediately. */ \
1790 if (nlen == 0) return CONST_CAST(HChar *,h); \
1792 /* assert(nlen >= 1); */ \
1793 HChar n0 = n[0]; \
1795 while (1) { \
1796 const HChar hh = *h; \
1797 if (hh == 0) return NULL; \
1798 if (hh != n0) { h++; continue; } \
1800 UWord i; \
1801 for (i = 0; i < nlen; i++) { \
1802 if (n[i] != h[i]) \
1803 break; \
1805 /* assert(i >= 0 && i <= nlen); */ \
1806 if (i == nlen) \
1807 return CONST_CAST(HChar *,h); \
1809 h++; \
1813 #if defined(VGO_linux)
1814 STRSTR(VG_Z_LIBC_SONAME, strstr)
1815 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse2)
1816 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse42)
1818 #elif defined(VGO_freebsd)
1819 STRSTR(VG_Z_LIBC_SONAME, strstr)
1821 #elif defined(VGO_darwin)
1823 #elif defined(VGO_solaris)
1824 STRSTR(VG_Z_LIBC_SONAME, strstr)
1826 #endif
1828 /*---------------------- memmem ----------------------*/
1830 #define MEMMEM(soname, fnname) \
1831 void* VG_REPLACE_FUNCTION_EZU(20460,soname,fnname) \
1832 (const void* haystack, SizeT hlen, const void* needle, SizeT nlen); \
1833 void* VG_REPLACE_FUNCTION_EZU(20460,soname,fnname) \
1834 (const void* haystack, SizeT hlen, const void* needle, SizeT nlen) \
1836 const HChar* h = haystack; \
1837 const HChar* n = needle; \
1839 /* If the needle is the empty string, match immediately. */ \
1840 if (nlen == 0) return CONST_CAST(void *,h); \
1842 HChar n0 = n[0]; \
1844 for (; hlen >= nlen; hlen--, h++) { \
1845 if (h[0] != n0) continue; \
1847 UWord i; \
1848 for (i = 1; i < nlen; i++) { \
1849 if (n[i] != h[i]) \
1850 break; \
1852 if (i == nlen) \
1853 return CONST_CAST(HChar *,h); \
1856 return NULL; \
1859 #if defined(VGP_s390x_linux)
1860 MEMMEM(VG_Z_LIBC_SONAME, memmem)
1861 #endif
1864 /*---------------------- strpbrk ----------------------*/
1866 #define STRPBRK(soname, fnname) \
1867 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1868 (const char* sV, const char* acceptV); \
1869 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1870 (const char* sV, const char* acceptV) \
1872 const HChar* s = sV; \
1873 const HChar* accept = acceptV; \
1875 /* find the length of 'accept', not including terminating zero */ \
1876 UWord nacc = 0; \
1877 while (accept[nacc]) nacc++; \
1879 /* if n is the empty string, fail immediately. */ \
1880 if (nacc == 0) return NULL; \
1882 /* assert(nacc >= 1); */ \
1883 while (1) { \
1884 UWord i; \
1885 HChar sc = *s; \
1886 if (sc == 0) \
1887 break; \
1888 for (i = 0; i < nacc; i++) { \
1889 if (sc == accept[i]) \
1890 return CONST_CAST(HChar *,s); \
1892 s++; \
1895 return NULL; \
1898 #if defined(VGO_linux)
1899 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1901 #elif defined(VGO_freebsd)
1902 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1904 #elif defined(VGO_darwin)
1906 #elif defined(VGO_solaris)
1907 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1909 #endif
1912 /*---------------------- strcspn ----------------------*/
1914 #define STRCSPN(soname, fnname) \
1915 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1916 (const char* sV, const char* rejectV); \
1917 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1918 (const char* sV, const char* rejectV) \
1920 const HChar* s = sV; \
1921 const HChar* reject = rejectV; \
1923 /* find the length of 'reject', not including terminating zero */ \
1924 UWord nrej = 0; \
1925 while (reject[nrej]) nrej++; \
1927 UWord len = 0; \
1928 while (1) { \
1929 UWord i; \
1930 HChar sc = *s; \
1931 if (sc == 0) \
1932 break; \
1933 for (i = 0; i < nrej; i++) { \
1934 if (sc == reject[i]) \
1935 break; \
1937 /* assert(i >= 0 && i <= nrej); */ \
1938 if (i < nrej) \
1939 break; \
1940 s++; \
1941 len++; \
1944 return len; \
1947 #if defined(VGO_linux)
1948 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1949 STRCSPN(VG_Z_LIBC_SONAME, __GI_strcspn)
1951 #elif defined(VGO_freebsd)
1952 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1954 #elif defined(VGO_darwin)
1956 #elif defined(VGO_solaris)
1957 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1959 #endif
1962 /*---------------------- strspn ----------------------*/
1964 #define STRSPN(soname, fnname) \
1965 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1966 (const char* sV, const char* acceptV); \
1967 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1968 (const char* sV, const char* acceptV) \
1970 const UChar* s = (const UChar *)sV; \
1971 const UChar* accept = (const UChar *)acceptV; \
1973 /* find the length of 'accept', not including terminating zero */ \
1974 UWord nacc = 0; \
1975 while (accept[nacc]) nacc++; \
1976 if (nacc == 0) return 0; \
1978 UWord len = 0; \
1979 while (1) { \
1980 UWord i; \
1981 UChar sc = *s; \
1982 if (sc == 0) \
1983 break; \
1984 for (i = 0; i < nacc; i++) { \
1985 if (sc == accept[i]) \
1986 break; \
1988 /* assert(i >= 0 && i <= nacc); */ \
1989 if (i == nacc) \
1990 break; \
1991 s++; \
1992 len++; \
1995 return len; \
1998 #if defined(VGO_linux)
1999 STRSPN(VG_Z_LIBC_SONAME, strspn)
2001 #elif defined(VGO_freebsd)
2002 STRSPN(VG_Z_LIBC_SONAME, strspn)
2004 #elif defined(VGO_darwin)
2006 #elif defined(VGO_solaris)
2007 STRSPN(VG_Z_LIBC_SONAME, strspn)
2009 #endif
2012 /*---------------------- strcasestr ----------------------*/
2014 #define STRCASESTR(soname, fnname) \
2015 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
2016 (const char* haystack, const char* needle); \
2017 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
2018 (const char* haystack, const char* needle) \
2020 extern int tolower(int); \
2021 const HChar* h = haystack; \
2022 const HChar* n = needle; \
2024 /* find the length of n, not including terminating zero */ \
2025 UWord nlen = 0; \
2026 while (n[nlen]) nlen++; \
2028 /* if n is the empty string, match immediately. */ \
2029 if (nlen == 0) return CONST_CAST(HChar *,h); \
2031 /* assert(nlen >= 1); */ \
2032 UChar n0 = tolower(n[0]); \
2034 while (1) { \
2035 UChar hh = tolower(*h); \
2036 if (hh == 0) return NULL; \
2037 if (hh != n0) { h++; continue; } \
2039 UWord i; \
2040 for (i = 0; i < nlen; i++) { \
2041 if (tolower(n[i]) != tolower(h[i])) \
2042 break; \
2044 /* assert(i >= 0 && i <= nlen); */ \
2045 if (i == nlen) \
2046 return CONST_CAST(HChar *,h); \
2048 h++; \
2052 #if defined(VGO_linux)
2053 # if !defined(VGPV_arm_linux_android) \
2054 && !defined(VGPV_x86_linux_android) \
2055 && !defined(VGPV_mips32_linux_android) \
2056 && !defined(VGPV_arm64_linux_android)
2057 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
2058 # endif
2060 #elif defined(VGO_freebsd)
2061 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
2063 #elif defined(VGO_darwin)
2065 #elif defined(VGO_solaris)
2066 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
2068 #endif
2071 /*---------------------- wcslen ----------------------*/
2073 // This is a wchar_t equivalent to strlen. Unfortunately
2074 // we don't have wchar_t available here, but it looks like
2075 // a 32 bit int on Linux. I don't know if that is also
2076 // valid on MacOSX.
2078 #define WCSLEN(soname, fnname) \
2079 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
2080 ( const Int* str ); \
2081 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
2082 ( const Int* str ) \
2084 SizeT i = 0; \
2085 while (str[i] != 0) i++; \
2086 return i; \
2089 #if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_solaris)
2090 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
2092 #endif
2094 /*---------------------- wcsnlen ----------------------*/
2096 #define WCSNLEN(soname, fnname) \
2097 SizeT VG_REPLACE_FUNCTION_EZU(20440,soname,fnname) \
2098 ( const Int *s, SizeT n ); \
2099 SizeT VG_REPLACE_FUNCTION_EZU(20440,soname,fnname) \
2100 ( const Int *s, SizeT n ) \
2102 SizeT i = 0; \
2103 const Int* p = s; \
2104 while (i < n && *p != 0) { \
2105 i++; \
2106 p++; \
2108 return i; \
2111 #if defined(VGO_linux) || defined(VGO_freebsd)
2112 WCSNLEN(VG_Z_LIBC_SONAME, wcsnlen)
2113 WCSNLEN(VG_Z_LIBC_SONAME, __GI_wcsnlen)
2114 #endif
2116 /*---------------------- wcscmp ----------------------*/
2118 // This is a wchar_t equivalent to strcmp. We don't
2119 // have wchar_t available here, but in the GNU C Library
2120 // wchar_t is always 32 bits wide and wcscmp uses signed
2121 // comparison, not unsigned as in strcmp function.
2123 #define WCSCMP(soname, fnname) \
2124 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
2125 ( const Int* s1, const Int* s2 ); \
2126 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
2127 ( const Int* s1, const Int* s2 ) \
2129 register Int c1; \
2130 register Int c2; \
2131 while (True) { \
2132 c1 = *s1; \
2133 c2 = *s2; \
2134 if (c1 != c2) break; \
2135 if (c1 == 0) break; \
2136 s1++; s2++; \
2138 if (c1 < c2) return -1; \
2139 if (c1 > c2) return 1; \
2140 return 0; \
2143 #if defined(VGO_linux) || defined(VGO_freebsd)
2144 WCSCMP(VG_Z_LIBC_SONAME, wcscmp)
2145 #endif
2147 /*---------------------- wcsncmp ----------------------*/
2149 // This is a wchar_t equivalent to strncmp. We don't
2150 // have wchar_t available here, but in the GNU C Library
2151 // wchar_t is always 32 bits wide and wcsncmp uses signed
2152 // comparison, not unsigned as in strncmp function.
2154 #define WCSNCMP(soname, fnname) \
2155 int VG_REPLACE_FUNCTION_EZU(20450,soname,fnname) \
2156 ( const Int* s1, const Int* s2, SizeT nmax ); \
2157 int VG_REPLACE_FUNCTION_EZU(20450,soname,fnname) \
2158 ( const Int* s1, const Int* s2, SizeT nmax ) \
2160 SizeT n = 0; \
2161 while (True) { \
2162 if (n >= nmax) return 0; \
2163 if (*s1 == 0 && *s2 == 0) return 0; \
2164 if (*s1 == 0) return -1; \
2165 if (*s2 == 0) return 1; \
2167 if (*s1 < *s2) return -1; \
2168 if (*s1 > *s2) return 1; \
2170 s1++; s2++; n++; \
2173 #if defined(VGO_linux) || defined(VGO_freebsd)
2174 WCSNCMP(VG_Z_LIBC_SONAME, wcsncmp)
2175 #endif
2177 /*---------------------- wcscpy ----------------------*/
2179 // This is a wchar_t equivalent to strcpy. We don't
2180 // have wchar_t available here, but in the GNU C Library
2181 // wchar_t is always 32 bits wide.
2183 #define WCSCPY(soname, fnname) \
2184 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
2185 ( Int* dst, const Int* src ); \
2186 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
2187 ( Int* dst, const Int* src ) \
2189 const Int* src_orig = src; \
2190 Int* dst_orig = dst; \
2192 while (*src) *dst++ = *src++; \
2193 *dst = 0; \
2195 /* This checks for overlap after copying, unavoidable without */ \
2196 /* pre-counting length... should be ok */ \
2197 /* +4 because sizeof(wchar_t) == 4 */ \
2198 SizeT srclen = (Addr)src-(Addr)src_orig+4; \
2199 RECORD_COPY(srclen); \
2200 if (is_overlap(dst_orig, \
2201 src_orig, \
2202 /* +4 because sizeof(wchar_t) == 4 */ \
2203 (Addr)dst-(Addr)dst_orig+4, \
2204 srclen)) \
2205 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
2207 return dst_orig; \
2210 #if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
2211 WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
2212 #endif
2215 /*---------------------- wcschr ----------------------*/
2217 // This is a wchar_t equivalent to strchr. We don't
2218 // have wchar_t available here, but in the GNU C Library
2219 // wchar_t is always 32 bits wide.
2221 #define WCSCHR(soname, fnname) \
2222 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
2223 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
2225 const Int* p = s; \
2226 while (True) { \
2227 if (*p == c) return CONST_CAST(Int *,p); \
2228 if (*p == 0) return NULL; \
2229 p++; \
2233 #if defined(VGO_linux) || defined(VGO_freebsd)
2234 WCSCHR(VG_Z_LIBC_SONAME, wcschr)
2235 #endif
2236 /*---------------------- wcsrchr ----------------------*/
2238 // This is a wchar_t equivalent to strrchr. We don't
2239 // have wchar_t available here, but in the GNU C Library
2240 // wchar_t is always 32 bits wide.
2242 #define WCSRCHR(soname, fnname) \
2243 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
2244 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
2246 const Int* p = s; \
2247 const Int* last = NULL; \
2248 while (True) { \
2249 if (*p == c) last = p; \
2250 if (*p == 0) return CONST_CAST(Int *,last); \
2251 p++; \
2255 #if defined(VGO_linux) || defined(VGO_freebsd)
2256 WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
2257 #endif
2259 /*---------------------- wmemchr ----------------------*/
2261 // This is a wchar_t equivalent to memchr. We don't
2262 // have wchar_t available here, but in the GNU C Library
2263 // wchar_t is always 32 bits wide.
2265 #define WMEMCHR(soname, fnname) \
2266 Int* VG_REPLACE_FUNCTION_EZU(20430,soname,fnname) \
2267 (const Int *s, Int c, SizeT n); \
2268 Int* VG_REPLACE_FUNCTION_EZU(20430,soname,fnname) \
2269 (const Int *s, Int c, SizeT n) \
2271 SizeT i; \
2272 const Int* p = s; \
2273 for (i = 0; i < n; i++) { \
2274 if (*p == c) return CONST_CAST(Int *,p); \
2275 p++; \
2277 return NULL; \
2280 #if defined(VGO_linux)
2281 WMEMCHR(VG_Z_LIBC_SONAME, wmemchr)
2282 WMEMCHR(VG_Z_LIBC_SONAME, __GI_wmemchr)
2283 #endif
2285 #if defined(VGO_freebsd)
2286 WMEMCHR(VG_Z_LIBC_SONAME, wmemchr)
2287 #endif
2289 /*---------------------- wmemcmp ----------------------*/
2291 #define WMEMCMP(soname, fnname) \
2292 int VG_REPLACE_FUNCTION_EZU(20470,soname,fnname) \
2293 ( const Int *b1, const Int *b2, SizeT n ); \
2294 int VG_REPLACE_FUNCTION_EZU(20470,soname,fnname) \
2295 ( const Int *b1, const Int *b2, SizeT n ) \
2297 for (SizeT i = 0U; i < n; ++i) { \
2298 if (b1[i] != b2[i]) \
2299 return b1[i] > b2[i] ? 1 : -1; \
2301 return 0; \
2304 #if defined(VGO_linux) || defined(VGO_freebsd)
2305 WMEMCMP(VG_Z_LIBC_SONAME, wmemcmp)
2306 #endif
2308 /*---------------------- wcsncpy ----------------------*/
2310 // This is a wchar_t equivalent to strncpy. We don't
2311 // have wchar_t available here, but in the GNU C Library
2312 // wchar_t is always 32 bits wide.
2314 #define WCSNCPY(soname, fnname) \
2315 Int* VG_REPLACE_FUNCTION_EZU(20480,soname,fnname) \
2316 ( Int* dst, const Int* src, SizeT n ); \
2317 Int* VG_REPLACE_FUNCTION_EZU(20480,soname,fnname) \
2318 ( Int* dst, const Int* src, SizeT n ) \
2320 const Int* src_orig = src; \
2321 Int* dst_orig = dst; \
2322 SizeT m = 0; \
2324 while (m < n && *src) { \
2325 m++; \
2326 *dst++ = *src++; \
2329 /* This checks for overlap after copying, unavoidable without */ \
2330 /* pre-counting length... should be ok */ \
2331 /* *4 because sizeof(wchar_t) == 4 */ \
2332 SizeT srclen = ((m < n) ? m+1 : n)*4; \
2333 RECORD_COPY(srclen); \
2334 if (is_overlap(dst_orig, \
2335 src_orig, \
2336 n*4, \
2337 srclen)) \
2338 RECORD_OVERLAP_ERROR("wcsncpy", dst_orig, src_orig, 0); \
2340 while (m++ < n) { \
2341 *dst++ = 0; \
2344 return dst_orig; \
2347 #if defined(VGO_linux) || defined(VGO_freebsd)
2348 WCSNCPY(VG_Z_LIBC_SONAME, wcsncpy)
2349 #endif
2351 /*---------------------- memccpy ----------------------*/
2353 /* memccpy, mostly based on GNU libc source */
2354 #define MEMCCPY(soname, fnname) \
2355 void* VG_REPLACE_FUNCTION_EZU(20490,soname,fnname) \
2356 ( void *dst, const void *src, Int c, SizeT len ); \
2357 void* VG_REPLACE_FUNCTION_EZU(20490,soname,fnname) \
2358 ( void *dst, const void *src, Int c, SizeT len ) \
2360 const char *s = src; \
2361 char *d = dst; \
2362 const char x = c; \
2363 SizeT i = len; \
2365 while (i-- > 0) \
2366 if ((*d++ = *s++) == x) { \
2367 SizeT srclen = len - i; \
2368 RECORD_COPY(srclen); \
2369 if (is_overlap(dst, src, len, srclen)) \
2370 RECORD_OVERLAP_ERROR("memccpy", dst, src, len); \
2371 return d; \
2374 if (len) { \
2375 RECORD_COPY(len); \
2376 if (is_overlap(dst, src, len, len)) \
2377 RECORD_OVERLAP_ERROR("memccpy", dst, src, len); \
2379 return NULL; \
2382 #if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_darwin) || defined(VGO_solaris)
2383 MEMCCPY(VG_Z_LIBC_SONAME, memccpy)
2384 #endif
2386 /*---------------------- wcpncpy ----------------------*/
2388 // This is a wchar_t equivalent to strncpy. We don't
2389 // have wchar_t available here, but in the GNU C Library
2390 // wchar_t is always 32 bits wide.
2392 #define WCPNCPY(soname, fnname) \
2393 Int* VG_REPLACE_FUNCTION_EZU(20500,soname,fnname) \
2394 ( Int* dst, const Int* src, SizeT n ); \
2395 Int* VG_REPLACE_FUNCTION_EZU(20500,soname,fnname) \
2396 ( Int* dst, const Int* src, SizeT n ) \
2398 const Int* src_orig = src; \
2399 Int* dst_orig = dst; \
2400 SizeT m = 0; \
2402 while (m < n && *src) { \
2403 m++; \
2404 *dst++ = *src++; \
2407 /* This checks for overlap after copying, unavoidable without */ \
2408 /* pre-counting length... should be ok */ \
2409 /* *4 because sizeof(wchar_t) == 4 */ \
2410 SizeT srclen = ((m < n) ? m+1 : n)*4; \
2411 RECORD_COPY(srclen); \
2412 if (is_overlap(dst_orig, \
2413 src_orig, \
2414 n*4, \
2415 srclen)) \
2416 RECORD_OVERLAP_ERROR("wcpncpy", dst_orig, src_orig, 0); \
2418 while (m++ < n) { \
2419 *dst++ = 0; \
2422 return dst_orig + (src - src_orig); \
2425 #if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_solaris)
2426 WCPNCPY(VG_Z_LIBC_SONAME, wcpncpy)
2427 #endif
2430 /*------------------------------------------------------------*/
2431 /*--- Improve definedness checking of process environment ---*/
2432 /*------------------------------------------------------------*/
2434 #if defined(VGO_linux) || defined(VGO_freebsd)
2436 /* If these wind up getting generated via a macro, so that multiple
2437 versions of each function exist (as above), use the _EZU variants
2438 to assign equivalance class tags. */
2440 /*---------------------- putenv ----------------------*/
2442 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
2443 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
2445 OrigFn fn;
2446 Word result;
2447 const HChar* p = string;
2448 VALGRIND_GET_ORIG_FN(fn);
2449 /* Now by walking over the string we magically produce
2450 traces when hitting undefined memory. */
2451 if (p)
2452 while (*p++)
2453 __asm__ __volatile__("" ::: "memory");
2454 CALL_FN_W_W(result, fn, string);
2455 return result;
2459 /*---------------------- unsetenv ----------------------*/
2461 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
2462 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
2464 OrigFn fn;
2465 Word result;
2466 const HChar* p = name;
2467 VALGRIND_GET_ORIG_FN(fn);
2468 /* Now by walking over the string we magically produce
2469 traces when hitting undefined memory. */
2470 if (p)
2471 while (*p++)
2472 __asm__ __volatile__("" ::: "memory");
2473 CALL_FN_W_W(result, fn, name);
2474 return result;
2478 /*---------------------- setenv ----------------------*/
2480 /* setenv */
2481 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
2482 (const char* name, const char* value, int overwrite);
2483 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
2484 (const char* name, const char* value, int overwrite)
2486 OrigFn fn;
2487 Word result;
2488 const HChar* p;
2489 VALGRIND_GET_ORIG_FN(fn);
2490 /* Now by walking over the string we magically produce
2491 traces when hitting undefined memory. */
2492 if (name)
2493 for (p = name; *p; p++)
2494 __asm__ __volatile__("" ::: "memory");
2495 if (value)
2496 for (p = value; *p; p++)
2497 __asm__ __volatile__("" ::: "memory");
2498 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
2499 CALL_FN_W_WWW(result, fn, name, value, overwrite);
2500 return result;
2503 #endif /* defined(VGO_linux) */
2505 /*--------------------------------------------------------------------*/
2506 /*--- end ---*/
2507 /*--------------------------------------------------------------------*/