NEWS: Update
[valgrind.git] / shared / vg_replace_strmem.c
blob005b6795a1839aef7dd2b313e3d54bc34c96f27c
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-2015 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, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
29 The GNU General Public License is contained in the file COPYING.
32 #include "pub_tool_basics.h"
33 #include "pub_tool_poolalloc.h"
34 #include "pub_tool_hashtable.h"
35 #include "pub_tool_redir.h"
36 #include "pub_tool_tooliface.h"
37 #include "pub_tool_clreq.h"
39 /* ---------------------------------------------------------------------
40 We have our own versions of these functions for two reasons:
41 (a) it allows us to do overlap checking
42 (b) some of the normal versions are hyper-optimised, which fools
43 Memcheck and cause spurious value warnings. Our versions are
44 simpler.
45 (c) the glibc SSE-variants can read past the end of the input data
46 ranges. This can cause false-positive Memcheck / Helgrind / DRD
47 reports.
49 Note that overenthusiastic use of PLT bypassing by the glibc people also
50 means that we need to patch multiple versions of some of the functions to
51 our own implementations.
53 THEY RUN ON THE SIMD CPU!
54 ------------------------------------------------------------------ */
56 /* Assignment of behavioural equivalence class tags: 2NNNP is intended
57 to be reserved for str/mem intercepts. Current usage:
59 20010 STRRCHR
60 20020 STRCHR
61 20030 STRCAT
62 20040 STRNCAT
63 20050 STRLCAT
64 20060 STRNLEN
65 20070 STRLEN
66 20080 STRCPY
67 20090 STRNCPY
68 20100 STRLCPY
69 20110 STRNCMP
70 20120 STRCASECMP
71 20130 STRNCASECMP
72 20140 STRCASECMP_L
73 20150 STRNCASECMP_L
74 20160 STRCMP
75 20170 MEMCHR
77 20180 MEMCPY if there's a conflict between memcpy and
78 20181 MEMMOVE memmove, prefer memmove
80 20190 MEMCMP
81 20200 STPCPY
82 20210 MEMSET
83 2022P unused (was previously MEMMOVE)
84 20230 BCOPY
85 20240 GLIBC25___MEMMOVE_CHK
86 20250 GLIBC232_STRCHRNUL
87 20260 GLIBC232_RAWMEMCHR
88 20270 GLIBC25___STRCPY_CHK
89 20280 GLIBC25___STPCPY_CHK
90 20290 GLIBC25_MEMPCPY
91 20300 GLIBC26___MEMCPY_CHK
92 20310 STRSTR
93 20320 STRPBRK
94 20330 STRCSPN
95 20340 STRSPN
96 20350 STRCASESTR
97 20360 MEMRCHR
98 20370 WCSLEN
99 20380 WCSCMP
100 20390 WCSCPY
101 20400 WCSCHR
102 20410 WCSRCHR
103 20420 STPNCPY
106 #if defined(VGO_solaris)
108 Detour functions in the libc and the runtime linker. If a function isn't
109 much optimized (and no overlap checking is necessary) then redir the
110 function only in the libc. This way we can keep stacktraces in the tests
111 consistent.
113 #endif
116 /* Figure out if [dst .. dst+dstlen-1] overlaps with
117 [src .. src+srclen-1].
118 We assume that the address ranges do not wrap around
119 (which is safe since on Linux addresses >= 0xC0000000
120 are not accessible and the program will segfault in this
121 circumstance, presumably).
123 static inline
124 Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
126 Addr loS, hiS, loD, hiD;
128 if (dstlen == 0 || srclen == 0)
129 return False;
131 loS = (Addr)src;
132 loD = (Addr)dst;
133 hiS = loS + srclen - 1;
134 hiD = loD + dstlen - 1;
136 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
137 if (loS < loD) {
138 return !(hiS < loD);
140 else if (loD < loS) {
141 return !(hiD < loS);
143 else {
144 /* They start at same place. Since we know neither of them has
145 zero length, they must overlap. */
146 return True;
151 /* Call here to exit if we can't continue. On Android we can't call
152 _exit for some reason, so we have to blunt-instrument it. */
153 __attribute__ ((__noreturn__))
154 static inline void my_exit ( int x )
156 # if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \
157 || defined(VGPV_arm64_linux_android)
158 __asm__ __volatile__(".word 0xFFFFFFFF");
159 while (1) {}
160 # elif defined(VGPV_x86_linux_android)
161 __asm__ __volatile__("ud2");
162 while (1) {}
163 # else
164 extern __attribute__ ((__noreturn__)) void _exit(int status);
165 _exit(x);
166 # endif
170 // This is a macro rather than a function because we don't want to have an
171 // extra function in the stack trace.
172 #ifndef RECORD_OVERLAP_ERROR
173 #define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0)
174 #endif
175 #ifndef VALGRIND_CHECK_VALUE_IS_DEFINED
176 #define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1
177 #endif
180 /*---------------------- strrchr ----------------------*/
182 #define STRRCHR(soname, fnname) \
183 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
184 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
186 HChar ch = (HChar)c; \
187 const HChar* p = s; \
188 const HChar* last = NULL; \
189 while (True) { \
190 if (*p == ch) last = p; \
191 if (*p == 0) return CONST_CAST(HChar *,last); \
192 p++; \
196 // Apparently rindex() is the same thing as strrchr()
197 #if defined(VGO_linux)
198 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
199 STRRCHR(VG_Z_LIBC_SONAME, rindex)
200 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
201 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2)
202 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2_no_bsf)
203 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse42)
204 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
205 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
206 || defined(VGPV_mips32_linux_android)
207 STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */
208 #endif
210 #elif defined(VGO_darwin)
211 //STRRCHR(VG_Z_LIBC_SONAME, strrchr)
212 //STRRCHR(VG_Z_LIBC_SONAME, rindex)
213 //STRRCHR(VG_Z_DYLD, strrchr)
214 //STRRCHR(VG_Z_DYLD, rindex)
215 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
216 # if DARWIN_VERS >= DARWIN_10_9
217 STRRCHR(libsystemZucZddylib, strrchr)
218 # endif
220 #elif defined(VGO_solaris)
221 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
222 STRRCHR(VG_Z_LIBC_SONAME, rindex)
223 STRRCHR(VG_Z_LD_SO_1, strrchr)
225 #endif
228 /*---------------------- strchr ----------------------*/
230 #define STRCHR(soname, fnname) \
231 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
232 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
234 HChar ch = (HChar)c ; \
235 const HChar* p = s; \
236 while (True) { \
237 if (*p == ch) return CONST_CAST(HChar *,p); \
238 if (*p == 0) return NULL; \
239 p++; \
243 // Apparently index() is the same thing as strchr()
244 #if defined(VGO_linux)
245 STRCHR(VG_Z_LIBC_SONAME, strchr)
246 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
247 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2)
248 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2_no_bsf)
249 STRCHR(VG_Z_LIBC_SONAME, index)
250 # if !defined(VGP_x86_linux)
251 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
252 STRCHR(VG_Z_LD_LINUX_SO_2, index)
253 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
254 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
255 # endif
257 #elif defined(VGO_darwin)
258 STRCHR(VG_Z_LIBC_SONAME, strchr)
259 # if DARWIN_VERS == DARWIN_10_9
260 STRCHR(libsystemZuplatformZddylib, _platform_strchr)
261 # endif
262 # if DARWIN_VERS >= DARWIN_10_10
263 /* _platform_strchr$VARIANT$Generic */
264 STRCHR(libsystemZuplatformZddylib, _platform_strchr$VARIANT$Generic)
265 /* _platform_strchr$VARIANT$Haswell */
266 STRCHR(libsystemZuplatformZddylib, _platform_strchr$VARIANT$Haswell)
267 # endif
269 #elif defined(VGO_solaris)
270 STRCHR(VG_Z_LIBC_SONAME, strchr)
271 STRCHR(VG_Z_LIBC_SONAME, index)
272 STRCHR(VG_Z_LD_SO_1, strchr)
274 #endif
277 /*---------------------- strcat ----------------------*/
279 #define STRCAT(soname, fnname) \
280 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
281 ( char* dst, const char* src ); \
282 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
283 ( char* dst, const char* src ) \
285 const HChar* src_orig = src; \
286 HChar* dst_orig = dst; \
287 while (*dst) dst++; \
288 while (*src) *dst++ = *src++; \
289 *dst = 0; \
291 /* This is a bit redundant, I think; any overlap and the strcat will */ \
292 /* go forever... or until a seg fault occurs. */ \
293 if (is_overlap(dst_orig, \
294 src_orig, \
295 (Addr)dst-(Addr)dst_orig+1, \
296 (Addr)src-(Addr)src_orig+1)) \
297 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
299 return dst_orig; \
302 #if defined(VGO_linux)
303 STRCAT(VG_Z_LIBC_SONAME, strcat)
304 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
306 #elif defined(VGO_darwin)
307 //STRCAT(VG_Z_LIBC_SONAME, strcat)
309 #elif defined(VGO_solaris)
310 STRCAT(VG_Z_LIBC_SONAME, strcat)
311 STRCAT(VG_Z_LD_SO_1, strcat)
313 #endif
316 /*---------------------- strncat ----------------------*/
318 #define STRNCAT(soname, fnname) \
319 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
320 ( char* dst, const char* src, SizeT n ); \
321 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
322 ( char* dst, const char* src, SizeT n ) \
324 const HChar* src_orig = src; \
325 HChar* dst_orig = dst; \
326 SizeT m = 0; \
328 while (*dst) dst++; \
329 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
330 *dst = 0; /* always add null */ \
332 /* This checks for overlap after copying, unavoidable without */ \
333 /* pre-counting lengths... should be ok */ \
334 if (is_overlap(dst_orig, \
335 src_orig, \
336 (Addr)dst-(Addr)dst_orig+1, \
337 (Addr)src-(Addr)src_orig+1)) \
338 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
340 return dst_orig; \
343 #if defined(VGO_linux)
344 STRNCAT(VG_Z_LIBC_SONAME, strncat)
346 #elif defined(VGO_darwin)
347 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
348 //STRNCAT(VG_Z_DYLD, strncat)
350 #elif defined(VGO_solaris)
351 STRNCAT(VG_Z_LIBC_SONAME, strncat)
353 #endif
356 /*---------------------- strlcat ----------------------*/
358 /* Append src to dst. n is the size of dst's buffer. dst is guaranteed
359 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
360 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
361 Truncation occurred if retval >= n.
363 #define STRLCAT(soname, fnname) \
364 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
365 ( char* dst, const char* src, SizeT n ); \
366 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
367 ( char* dst, const char* src, SizeT n ) \
369 const HChar* src_orig = src; \
370 HChar* dst_orig = dst; \
371 SizeT m = 0; \
373 while (m < n && *dst) { m++; dst++; } \
374 if (m < n) { \
375 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
376 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
377 *dst = 0; \
378 } else { \
379 /* No space to copy anything to dst. m == n */ \
381 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
382 while (*src) { m++; src++; } \
383 /* This checks for overlap after copying, unavoidable without */ \
384 /* pre-counting lengths... should be ok */ \
385 if (is_overlap(dst_orig, \
386 src_orig, \
387 (Addr)dst-(Addr)dst_orig+1, \
388 (Addr)src-(Addr)src_orig+1)) \
389 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
391 return m; \
394 #if defined(VGO_linux)
396 #elif defined(VGO_darwin)
397 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
398 //STRLCAT(VG_Z_DYLD, strlcat)
399 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
401 #elif defined(VGO_solaris)
402 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
404 #endif
407 /*---------------------- strnlen ----------------------*/
409 #define STRNLEN(soname, fnname) \
410 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
411 ( const char* str, SizeT n ); \
412 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
413 ( const char* str, SizeT n ) \
415 SizeT i = 0; \
416 while (i < n && str[i] != 0) i++; \
417 return i; \
420 #if defined(VGO_linux)
421 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
422 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
424 #elif defined(VGO_darwin)
425 # if DARWIN_VERS == DARWIN_10_9
426 STRNLEN(libsystemZucZddylib, strnlen)
427 # endif
429 #elif defined(VGO_solaris)
430 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
432 #endif
435 /*---------------------- strlen ----------------------*/
437 // Note that this replacement often doesn't get used because gcc inlines
438 // calls to strlen() with its own built-in version. This can be very
439 // confusing if you aren't expecting it. Other small functions in
440 // this file may also be inline by gcc.
442 #define STRLEN(soname, fnname) \
443 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
444 ( const char* str ); \
445 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
446 ( const char* str ) \
448 SizeT i = 0; \
449 while (str[i] != 0) i++; \
450 return i; \
453 #if defined(VGO_linux)
454 STRLEN(VG_Z_LIBC_SONAME, strlen)
455 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
456 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2)
457 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2_no_bsf)
458 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse42)
459 STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
460 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
461 # if defined(VGPV_arm_linux_android) \
462 || defined(VGPV_x86_linux_android) \
463 || defined(VGPV_mips32_linux_android)
464 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
465 # endif
467 #elif defined(VGO_darwin)
468 STRLEN(VG_Z_LIBC_SONAME, strlen)
469 # if DARWIN_VERS >= DARWIN_10_9
470 STRLEN(libsystemZucZddylib, strlen)
471 # endif
473 #elif defined(VGO_solaris)
474 STRLEN(VG_Z_LIBC_SONAME, strlen)
475 STRLEN(VG_Z_LD_SO_1, strlen)
477 #endif
480 /*---------------------- strcpy ----------------------*/
482 #define STRCPY(soname, fnname) \
483 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
484 ( char* dst, const char* src ); \
485 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
486 ( char* dst, const char* src ) \
488 const HChar* src_orig = src; \
489 HChar* dst_orig = dst; \
491 while (*src) *dst++ = *src++; \
492 *dst = 0; \
494 /* This checks for overlap after copying, unavoidable without */ \
495 /* pre-counting length... should be ok */ \
496 if (is_overlap(dst_orig, \
497 src_orig, \
498 (Addr)dst-(Addr)dst_orig+1, \
499 (Addr)src-(Addr)src_orig+1)) \
500 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
502 return dst_orig; \
505 #if defined(VGO_linux)
506 STRCPY(VG_Z_LIBC_SONAME, strcpy)
507 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
509 #elif defined(VGO_darwin)
510 STRCPY(VG_Z_LIBC_SONAME, strcpy)
511 # if DARWIN_VERS == DARWIN_10_9
512 STRCPY(libsystemZucZddylib, strcpy)
513 # endif
515 #elif defined(VGO_solaris)
516 STRCPY(VG_Z_LIBC_SONAME, strcpy)
517 STRCPY(VG_Z_LD_SO_1, strcpy)
519 #endif
522 /*---------------------- strncpy ----------------------*/
524 #define STRNCPY(soname, fnname) \
525 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
526 ( char* dst, const char* src, SizeT n ); \
527 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
528 ( char* dst, const char* src, SizeT n ) \
530 const HChar* src_orig = src; \
531 HChar* dst_orig = dst; \
532 SizeT m = 0; \
534 while (m < n && *src) { m++; *dst++ = *src++; } \
535 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
536 /* but only m+1 bytes of src if terminator was found */ \
537 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
538 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
539 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
541 return dst_orig; \
544 #if defined(VGO_linux)
545 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
546 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
547 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2)
548 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned)
550 #elif defined(VGO_darwin)
551 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
552 # if DARWIN_VERS >= DARWIN_10_9
553 STRNCPY(libsystemZucZddylib, strncpy)
554 # endif
556 #elif defined(VGO_solaris)
557 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
558 STRNCPY(VG_Z_LD_SO_1, strncpy)
560 #endif
563 /*---------------------- strlcpy ----------------------*/
565 /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
566 Returns strlen(src). Does not zero-fill the remainder of dst. */
567 #define STRLCPY(soname, fnname) \
568 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
569 ( char* dst, const char* src, SizeT n ); \
570 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
571 ( char* dst, const char* src, SizeT n ) \
573 const HChar* src_orig = src; \
574 HChar* dst_orig = dst; \
575 SizeT m = 0; \
577 STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
579 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
580 /* m non-nul bytes have now been copied, and m <= n-1. */ \
581 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
582 /* but only m+1 bytes of src if terminator was found */ \
583 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
584 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
585 /* Nul-terminate dst. */ \
586 if (n > 0) *dst = 0; \
587 /* Finish counting strlen(src). */ \
588 while (*src) src++; \
589 return src - src_orig; \
592 #if defined(VGO_linux)
594 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
595 || defined(VGPV_mips32_linux_android)
596 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
597 STRLCPY(VG_Z_LIBC_SONAME, strlcpy);
598 #endif
600 #elif defined(VGO_darwin)
601 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
602 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
603 //STRLCPY(VG_Z_DYLD, strlcpy)
604 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
606 #elif defined(VGO_solaris)
607 /* special case for n == 0 which is undocumented but heavily used */
608 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
609 if (n == 0) { \
610 while (*src) src++; \
611 return src - src_orig; \
614 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
616 #endif
619 /*---------------------- strncmp ----------------------*/
621 #define STRNCMP(soname, fnname) \
622 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
623 ( const char* s1, const char* s2, SizeT nmax ); \
624 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
625 ( const char* s1, const char* s2, SizeT nmax ) \
627 SizeT n = 0; \
628 while (True) { \
629 if (n >= nmax) return 0; \
630 if (*s1 == 0 && *s2 == 0) return 0; \
631 if (*s1 == 0) return -1; \
632 if (*s2 == 0) return 1; \
634 if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \
635 if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \
637 s1++; s2++; n++; \
641 #if defined(VGO_linux)
642 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
643 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
644 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2)
645 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42)
647 #elif defined(VGO_darwin)
648 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
649 # if DARWIN_VERS >= DARWIN_10_9
650 STRNCMP(libsystemZuplatformZddylib, _platform_strncmp)
651 # endif
653 #elif defined(VGO_solaris)
654 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
656 #endif
659 /*---------------------- strcasecmp ----------------------*/
661 #define STRCASECMP(soname, fnname) \
662 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
663 ( const char* s1, const char* s2 ); \
664 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
665 ( const char* s1, const char* s2 ) \
667 extern int tolower(int); \
668 register UChar c1; \
669 register UChar c2; \
670 while (True) { \
671 c1 = tolower(*(const UChar *)s1); \
672 c2 = tolower(*(const UChar *)s2); \
673 if (c1 != c2) break; \
674 if (c1 == 0) break; \
675 s1++; s2++; \
677 if ((UChar)c1 < (UChar)c2) return -1; \
678 if ((UChar)c1 > (UChar)c2) return 1; \
679 return 0; \
682 #if defined(VGO_linux)
683 # if !defined(VGPV_arm_linux_android) \
684 && !defined(VGPV_x86_linux_android) \
685 && !defined(VGPV_mips32_linux_android) \
686 && !defined(VGPV_arm64_linux_android)
687 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
688 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
689 # endif
691 #elif defined(VGO_darwin)
692 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
694 #elif defined(VGO_solaris)
695 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
697 #endif
700 /*---------------------- strncasecmp ----------------------*/
702 #define STRNCASECMP(soname, fnname) \
703 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
704 ( const char* s1, const char* s2, SizeT nmax ); \
705 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
706 ( const char* s1, const char* s2, SizeT nmax ) \
708 extern int tolower(int); \
709 SizeT n = 0; \
710 while (True) { \
711 if (n >= nmax) return 0; \
712 if (*s1 == 0 && *s2 == 0) return 0; \
713 if (*s1 == 0) return -1; \
714 if (*s2 == 0) return 1; \
716 if (tolower(*(const UChar *)s1) \
717 < tolower(*(const UChar*)s2)) return -1; \
718 if (tolower(*(const UChar *)s1) \
719 > tolower(*(const UChar *)s2)) return 1; \
721 s1++; s2++; n++; \
725 #if defined(VGO_linux)
726 # if !defined(VGPV_arm_linux_android) \
727 && !defined(VGPV_x86_linux_android) \
728 && !defined(VGPV_mips32_linux_android) \
729 && !defined(VGPV_arm64_linux_android)
730 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
731 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
732 # endif
734 #elif defined(VGO_darwin)
735 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
736 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
738 #elif defined(VGO_solaris)
739 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
741 #endif
744 /*---------------------- strcasecmp_l ----------------------*/
746 #define STRCASECMP_L(soname, fnname) \
747 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
748 ( const char* s1, const char* s2, void* locale ); \
749 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
750 ( const char* s1, const char* s2, void* locale ) \
752 extern int tolower_l(int, void*) __attribute__((weak)); \
753 register UChar c1; \
754 register UChar c2; \
755 while (True) { \
756 c1 = tolower_l(*(const UChar *)s1, locale); \
757 c2 = tolower_l(*(const UChar *)s2, locale); \
758 if (c1 != c2) break; \
759 if (c1 == 0) break; \
760 s1++; s2++; \
762 if ((UChar)c1 < (UChar)c2) return -1; \
763 if ((UChar)c1 > (UChar)c2) return 1; \
764 return 0; \
767 #if defined(VGO_linux)
768 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
769 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
770 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
772 #elif defined(VGO_darwin)
773 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
775 #elif defined(VGO_solaris)
777 #endif
780 /*---------------------- strncasecmp_l ----------------------*/
782 #define STRNCASECMP_L(soname, fnname) \
783 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
784 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
785 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
786 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
788 extern int tolower_l(int, void*) __attribute__((weak)); \
789 SizeT n = 0; \
790 while (True) { \
791 if (n >= nmax) return 0; \
792 if (*s1 == 0 && *s2 == 0) return 0; \
793 if (*s1 == 0) return -1; \
794 if (*s2 == 0) return 1; \
796 if (tolower_l(*(const UChar *)s1, locale) \
797 < tolower_l(*(const UChar *)s2, locale)) return -1; \
798 if (tolower_l(*(const UChar *)s1, locale) \
799 > tolower_l(*(const UChar *)s2, locale)) return 1; \
801 s1++; s2++; n++; \
805 #if defined(VGO_linux)
806 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
807 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
808 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l)
810 #elif defined(VGO_darwin)
811 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
812 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
814 #elif defined(VGO_solaris)
816 #endif
819 /*---------------------- strcmp ----------------------*/
821 #define STRCMP(soname, fnname) \
822 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
823 ( const char* s1, const char* s2 ); \
824 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
825 ( const char* s1, const char* s2 ) \
827 register UChar c1; \
828 register UChar c2; \
829 while (True) { \
830 c1 = *(const UChar *)s1; \
831 c2 = *(const UChar *)s2; \
832 if (c1 != c2) break; \
833 if (c1 == 0) break; \
834 s1++; s2++; \
836 if ((UChar)c1 < (UChar)c2) return -1; \
837 if ((UChar)c1 > (UChar)c2) return 1; \
838 return 0; \
841 #if defined(VGO_linux)
842 STRCMP(VG_Z_LIBC_SONAME, strcmp)
843 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
844 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse2)
845 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse42)
846 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
847 STRCMP(VG_Z_LD64_SO_1, strcmp)
848 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
849 || defined(VGPV_mips32_linux_android)
850 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
851 # endif
853 #elif defined(VGO_darwin)
854 STRCMP(VG_Z_LIBC_SONAME, strcmp)
855 # if DARWIN_VERS >= DARWIN_10_9
856 STRCMP(libsystemZuplatformZddylib, _platform_strcmp)
857 # endif
859 #elif defined(VGO_solaris)
860 STRCMP(VG_Z_LIBC_SONAME, strcmp)
861 STRCMP(VG_Z_LD_SO_1, strcmp)
863 #endif
866 /*---------------------- memchr ----------------------*/
868 #define MEMCHR(soname, fnname) \
869 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
870 (const void *s, int c, SizeT n); \
871 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
872 (const void *s, int c, SizeT n) \
874 SizeT i; \
875 UChar c0 = (UChar)c; \
876 const UChar* p = s; \
877 for (i = 0; i < n; i++) \
878 if (p[i] == c0) return CONST_CAST(void *,&p[i]); \
879 return NULL; \
882 #if defined(VGO_linux)
883 MEMCHR(VG_Z_LIBC_SONAME, memchr)
884 MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr)
886 #elif defined(VGO_darwin)
887 # if DARWIN_VERS == DARWIN_10_9
888 MEMCHR(VG_Z_DYLD, memchr)
889 MEMCHR(libsystemZuplatformZddylib, _platform_memchr)
890 # endif
891 # if DARWIN_VERS >= DARWIN_10_10
892 MEMCHR(VG_Z_DYLD, memchr)
893 /* _platform_memchr$VARIANT$Generic */
894 MEMCHR(libsystemZuplatformZddylib, _platform_memchr$VARIANT$Generic)
895 /* _platform_memchr$VARIANT$Haswell */
896 MEMCHR(libsystemZuplatformZddylib, _platform_memchr$VARIANT$Haswell)
897 # endif
899 #elif defined(VGO_solaris)
900 MEMCHR(VG_Z_LIBC_SONAME, memchr)
902 #endif
905 /*---------------------- memrchr ----------------------*/
907 #define MEMRCHR(soname, fnname) \
908 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
909 (const void *s, int c, SizeT n); \
910 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
911 (const void *s, int c, SizeT n) \
913 SizeT i; \
914 UChar c0 = (UChar)c; \
915 const UChar* p = s; \
916 for (i = 0; i < n; i++) \
917 if (p[n-1-i] == c0) return CONST_CAST(void *,&p[n-1-i]); \
918 return NULL; \
921 #if defined(VGO_linux)
922 MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
924 #elif defined(VGO_darwin)
925 //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
926 //MEMRCHR(VG_Z_DYLD, memrchr)
928 #elif defined(VGO_solaris)
930 #endif
933 /*---------------------- memcpy ----------------------*/
935 #define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
936 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
937 ( void *dst, const void *src, SizeT len ); \
938 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
939 ( void *dst, const void *src, SizeT len ) \
941 if (do_ol_check && is_overlap(dst, src, len, len)) \
942 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
944 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
945 const Addr WM = WS - 1; /* 7 or 3 */ \
947 if (len > 0) { \
948 if (dst < src || !is_overlap(dst, src, len, len)) { \
950 /* Copying backwards. */ \
951 SizeT n = len; \
952 Addr d = (Addr)dst; \
953 Addr s = (Addr)src; \
955 if (((s^d) & WM) == 0) { \
956 /* s and d have same UWord alignment. */ \
957 /* Pull up to a UWord boundary. */ \
958 while ((s & WM) != 0 && n >= 1) \
959 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
960 /* Copy UWords. */ \
961 while (n >= WS) \
962 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
963 if (n == 0) \
964 return dst; \
966 if (((s|d) & 1) == 0) { \
967 /* Both are 16-aligned; copy what we can thusly. */ \
968 while (n >= 2) \
969 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
971 /* Copy leftovers, or everything if misaligned. */ \
972 while (n >= 1) \
973 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
975 } else if (dst > src) { \
977 SizeT n = len; \
978 Addr d = ((Addr)dst) + n; \
979 Addr s = ((Addr)src) + n; \
981 /* Copying forwards. */ \
982 if (((s^d) & WM) == 0) { \
983 /* s and d have same UWord alignment. */ \
984 /* Back down to a UWord boundary. */ \
985 while ((s & WM) != 0 && n >= 1) \
986 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
987 /* Copy UWords. */ \
988 while (n >= WS) \
989 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
990 if (n == 0) \
991 return dst; \
993 if (((s|d) & 1) == 0) { \
994 /* Both are 16-aligned; copy what we can thusly. */ \
995 while (n >= 2) \
996 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
998 /* Copy leftovers, or everything if misaligned. */ \
999 while (n >= 1) \
1000 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
1005 return dst; \
1008 #define MEMMOVE(soname, fnname) \
1009 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
1011 #define MEMCPY(soname, fnname) \
1012 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
1014 #if defined(VGO_linux)
1015 /* For older memcpy we have to use memmove-like semantics and skip
1016 the overlap check; sigh; see #275284. */
1017 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
1018 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
1019 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
1020 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy)
1021 MEMCPY(VG_Z_LIBC_SONAME, __memcpy_sse2)
1022 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
1023 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
1024 /* icc9 blats these around all over the place. Not only in the main
1025 executable but various .so's. They are highly tuned and read
1026 memory beyond the source boundary (although work correctly and
1027 never go across page boundaries), so give errors when run
1028 natively, at least for misaligned source arg. Just intercepting
1029 in the exe only until we understand more about the problem. See
1030 http://bugs.kde.org/show_bug.cgi?id=139776
1032 MEMCPY(NONE, ZuintelZufastZumemcpy)
1034 #elif defined(VGO_darwin)
1035 # if DARWIN_VERS <= DARWIN_10_6
1036 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
1037 # endif
1038 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
1039 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
1041 #elif defined(VGO_solaris)
1042 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
1043 MEMCPY(VG_Z_LD_SO_1, memcpy)
1045 #endif
1048 /*---------------------- memcmp ----------------------*/
1050 #define MEMCMP(soname, fnname) \
1051 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1052 ( const void *s1V, const void *s2V, SizeT n ); \
1053 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1054 ( const void *s1V, const void *s2V, SizeT n ) \
1056 const SizeT WS = sizeof(UWord); /* 8 or 4 */ \
1057 const SizeT WM = WS - 1; /* 7 or 3 */ \
1058 Addr s1A = (Addr)s1V; \
1059 Addr s2A = (Addr)s2V; \
1061 if (((s1A | s2A) & WM) == 0) { \
1062 /* Both areas are word aligned. Skip over the */ \
1063 /* equal prefix as fast as possible. */ \
1064 while (n >= WS) { \
1065 UWord w1 = *(UWord*)s1A; \
1066 UWord w2 = *(UWord*)s2A; \
1067 if (w1 != w2) break; \
1068 s1A += WS; \
1069 s2A += WS; \
1070 n -= WS; \
1074 const UChar* s1 = (const UChar*) s1A; \
1075 const UChar* s2 = (const UChar*) s2A; \
1077 while (n != 0) { \
1078 UChar a0 = s1[0]; \
1079 UChar b0 = s2[0]; \
1080 s1 += 1; \
1081 s2 += 1; \
1082 int res = ((int)a0) - ((int)b0); \
1083 if (res != 0) \
1084 return res; \
1085 n -= 1; \
1087 return 0; \
1090 #if defined(VGO_linux)
1091 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
1092 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
1093 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse2)
1094 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse4_1)
1095 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
1096 MEMCMP(VG_Z_LD_SO_1, bcmp)
1098 #elif defined(VGO_darwin)
1099 # if DARWIN_VERS >= DARWIN_10_9
1100 MEMCMP(libsystemZuplatformZddylib, _platform_memcmp)
1101 # endif
1103 #elif defined(VGO_solaris)
1104 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
1105 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
1106 MEMCMP(VG_Z_LD_SO_1, memcmp)
1108 #endif
1111 /*---------------------- stpcpy ----------------------*/
1113 /* Copy SRC to DEST, returning the address of the terminating '\0' in
1114 DEST. (minor variant of strcpy) */
1115 #define STPCPY(soname, fnname) \
1116 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1117 ( char* dst, const char* src ); \
1118 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1119 ( char* dst, const char* src ) \
1121 const HChar* src_orig = src; \
1122 HChar* dst_orig = dst; \
1124 while (*src) *dst++ = *src++; \
1125 *dst = 0; \
1127 /* This checks for overlap after copying, unavoidable without */ \
1128 /* pre-counting length... should be ok */ \
1129 if (is_overlap(dst_orig, \
1130 src_orig, \
1131 (Addr)dst-(Addr)dst_orig+1, \
1132 (Addr)src-(Addr)src_orig+1)) \
1133 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
1135 return dst; \
1138 #if defined(VGO_linux)
1139 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1140 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
1141 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2)
1142 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2_unaligned)
1143 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
1144 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
1146 #elif defined(VGO_darwin)
1147 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1148 //STPCPY(VG_Z_DYLD, stpcpy)
1150 #elif defined(VGO_solaris)
1151 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1153 #endif
1156 /*---------------------- stpncpy ----------------------*/
1158 #define STPNCPY(soname, fnname) \
1159 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1160 ( char* dst, const char* src, SizeT n ); \
1161 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1162 ( char* dst, const char* src, SizeT n ) \
1164 const HChar* src_orig = src; \
1165 HChar* dst_str = dst; \
1166 SizeT m = 0; \
1168 while (m < n && *src) { m++; *dst++ = *src++; } \
1169 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
1170 /* but only m+1 bytes of src if terminator was found */ \
1171 if (is_overlap(dst_str, src_orig, n, (m < n) ? m+1 : n)) \
1172 RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \
1173 dst_str = dst; \
1174 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
1176 return dst_str; \
1179 #if defined(VGO_linux)
1180 STPNCPY(VG_Z_LIBC_SONAME, stpncpy)
1181 #endif
1184 /*---------------------- memset ----------------------*/
1186 /* Why are we bothering to intercept this? It seems entirely
1187 pointless. */
1189 #define MEMSET(soname, fnname) \
1190 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1191 (void *s, Int c, SizeT n); \
1192 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1193 (void *s, Int c, SizeT n) \
1195 if (sizeof(void*) == 8) { \
1196 Addr a = (Addr)s; \
1197 ULong c8 = (c & 0xFF); \
1198 c8 = (c8 << 8) | c8; \
1199 c8 = (c8 << 16) | c8; \
1200 c8 = (c8 << 32) | c8; \
1201 while ((a & 7) != 0 && n >= 1) \
1202 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1203 while (n >= 8) \
1204 { *(ULong*)a = c8; a += 8; n -= 8; } \
1205 while (n >= 1) \
1206 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1207 return s; \
1208 } else { \
1209 Addr a = (Addr)s; \
1210 UInt c4 = (c & 0xFF); \
1211 c4 = (c4 << 8) | c4; \
1212 c4 = (c4 << 16) | c4; \
1213 while ((a & 3) != 0 && n >= 1) \
1214 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1215 while (n >= 4) \
1216 { *(UInt*)a = c4; a += 4; n -= 4; } \
1217 while (n >= 1) \
1218 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1219 return s; \
1223 #if defined(VGO_linux)
1224 MEMSET(VG_Z_LIBC_SONAME, memset)
1226 #elif defined(VGO_darwin)
1227 //MEMSET(VG_Z_LIBC_SONAME, memset)
1228 //MEMSET(VG_Z_DYLD, memset)
1229 MEMSET(VG_Z_LIBC_SONAME, memset)
1231 #elif defined(VGO_solaris)
1232 MEMSET(VG_Z_LIBC_SONAME, memset)
1234 #endif
1237 /*---------------------- memmove ----------------------*/
1239 /* memmove -- use the MEMMOVE defn above. */
1241 #if defined(VGO_linux)
1242 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1243 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove)
1244 /* See bug #349828 Override for ld64.so.1 like memcpy, because for some
1245 arches MEMCPY_OK_FOR_FORWARD_MEMMOVE is set, which might cause memmove
1246 to call memcpy. */
1247 MEMMOVE(VG_Z_LD64_SO_1, memmove)
1249 #elif defined(VGO_darwin)
1250 # if DARWIN_VERS <= DARWIN_10_6
1251 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1252 # endif
1253 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
1254 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
1255 # if DARWIN_VERS >= DARWIN_10_9
1256 /* _platform_memmove$VARIANT$Ivybridge */
1257 MEMMOVE(libsystemZuplatformZddylib, ZuplatformZumemmoveZDVARIANTZDIvybridge)
1258 # endif
1260 #elif defined(VGO_solaris)
1261 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1262 MEMMOVE(VG_Z_LD_SO_1, memmove)
1264 #endif
1267 /*---------------------- bcopy ----------------------*/
1269 #define BCOPY(soname, fnname) \
1270 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1271 (const void *srcV, void *dstV, SizeT n); \
1272 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1273 (const void *srcV, void *dstV, SizeT n) \
1275 SizeT i; \
1276 HChar* dst = dstV; \
1277 const HChar* src = srcV; \
1278 if (dst < src) { \
1279 for (i = 0; i < n; i++) \
1280 dst[i] = src[i]; \
1282 else \
1283 if (dst > src) { \
1284 for (i = 0; i < n; i++) \
1285 dst[n-i-1] = src[n-i-1]; \
1289 #if defined(VGO_linux)
1290 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1292 #elif defined(VGO_darwin)
1293 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1294 //BCOPY(VG_Z_DYLD, bcopy)
1296 #elif defined(VGO_darwin)
1297 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1299 #endif
1302 /*-------------------- memmove_chk --------------------*/
1304 /* glibc 2.5 variant of memmove which checks the dest is big enough.
1305 There is no specific part of glibc that this is copied from. */
1306 #define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1307 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1308 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1309 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1310 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1312 SizeT i; \
1313 HChar* dst = dstV; \
1314 const HChar* src = srcV; \
1315 if (destlen < n) \
1316 goto badness; \
1317 if (dst < src) { \
1318 for (i = 0; i < n; i++) \
1319 dst[i] = src[i]; \
1321 else \
1322 if (dst > src) { \
1323 for (i = 0; i < n; i++) \
1324 dst[n-i-1] = src[n-i-1]; \
1326 return dst; \
1327 badness: \
1328 VALGRIND_PRINTF_BACKTRACE( \
1329 "*** memmove_chk: buffer overflow detected ***: " \
1330 "program terminated\n"); \
1331 my_exit(1); \
1332 /*NOTREACHED*/ \
1333 return NULL; \
1336 #if defined(VGO_linux)
1337 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
1339 #elif defined(VGO_darwin)
1341 #elif defined(VGO_solaris)
1343 #endif
1346 /*-------------------- strchrnul --------------------*/
1348 /* Find the first occurrence of C in S or the final NUL byte. */
1349 #define GLIBC232_STRCHRNUL(soname, fnname) \
1350 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1351 (const char* s, int c_in); \
1352 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1353 (const char* s, int c_in) \
1355 HChar c = (HChar) c_in; \
1356 const HChar* char_ptr = s; \
1357 while (1) { \
1358 if (*char_ptr == 0) return CONST_CAST(HChar *,char_ptr); \
1359 if (*char_ptr == c) return CONST_CAST(HChar *,char_ptr); \
1360 char_ptr++; \
1364 #if defined(VGO_linux)
1365 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1367 #elif defined(VGO_darwin)
1369 #elif defined(VGO_solaris)
1371 #endif
1374 /*---------------------- rawmemchr ----------------------*/
1376 /* Find the first occurrence of C in S. */
1377 #define GLIBC232_RAWMEMCHR(soname, fnname) \
1378 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1379 (const void* s, int c_in); \
1380 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1381 (const void* s, int c_in) \
1383 UChar c = (UChar) c_in; \
1384 const UChar* char_ptr = s; \
1385 while (1) { \
1386 if (*char_ptr == c) return CONST_CAST(void *,char_ptr); \
1387 char_ptr++; \
1391 #if defined (VGO_linux)
1392 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1393 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1395 #elif defined(VGO_darwin)
1397 #elif defined(VGO_solaris)
1399 #endif
1402 /*---------------------- strcpy_chk ----------------------*/
1404 /* glibc variant of strcpy that checks the dest is big enough.
1405 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1406 #define GLIBC25___STRCPY_CHK(soname,fnname) \
1407 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1408 (char* dst, const char* src, SizeT len); \
1409 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1410 (char* dst, const char* src, SizeT len) \
1412 HChar* ret = dst; \
1413 if (! len) \
1414 goto badness; \
1415 while ((*dst++ = *src++) != '\0') \
1416 if (--len == 0) \
1417 goto badness; \
1418 return ret; \
1419 badness: \
1420 VALGRIND_PRINTF_BACKTRACE( \
1421 "*** strcpy_chk: buffer overflow detected ***: " \
1422 "program terminated\n"); \
1423 my_exit(1); \
1424 /*NOTREACHED*/ \
1425 return NULL; \
1428 #if defined(VGO_linux)
1429 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1431 #elif defined(VGO_darwin)
1433 #elif defined(VGO_solaris)
1435 #endif
1438 /*---------------------- stpcpy_chk ----------------------*/
1440 /* glibc variant of stpcpy that checks the dest is big enough.
1441 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1442 #define GLIBC25___STPCPY_CHK(soname,fnname) \
1443 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1444 (char* dst, const char* src, SizeT len); \
1445 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1446 (char* dst, const char* src, SizeT len) \
1448 if (! len) \
1449 goto badness; \
1450 while ((*dst++ = *src++) != '\0') \
1451 if (--len == 0) \
1452 goto badness; \
1453 return dst - 1; \
1454 badness: \
1455 VALGRIND_PRINTF_BACKTRACE( \
1456 "*** stpcpy_chk: buffer overflow detected ***: " \
1457 "program terminated\n"); \
1458 my_exit(1); \
1459 /*NOTREACHED*/ \
1460 return NULL; \
1463 #if defined(VGO_linux)
1464 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1466 #elif defined(VGO_darwin)
1468 #elif defined(VGO_solaris)
1470 #endif
1473 /*---------------------- mempcpy ----------------------*/
1475 /* mempcpy */
1476 #define GLIBC25_MEMPCPY(soname, fnname) \
1477 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1478 ( void *dst, const void *src, SizeT len ); \
1479 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1480 ( void *dst, const void *src, SizeT len ) \
1482 SizeT len_saved = len; \
1484 if (len == 0) \
1485 return dst; \
1487 if (is_overlap(dst, src, len, len)) \
1488 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1490 if ( dst > src ) { \
1491 register HChar *d = (char *)dst + len - 1; \
1492 register const HChar *s = (const char *)src + len - 1; \
1493 while ( len-- ) { \
1494 *d-- = *s--; \
1496 } else if ( dst < src ) { \
1497 register HChar *d = dst; \
1498 register const HChar *s = src; \
1499 while ( len-- ) { \
1500 *d++ = *s++; \
1503 return (void*)( ((char*)dst) + len_saved ); \
1506 #if defined(VGO_linux)
1507 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1508 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, __GI_mempcpy)
1509 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
1510 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */
1511 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */
1513 #elif defined(VGO_darwin)
1514 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1516 #elif defined(VGO_solaris)
1518 #endif
1521 /*-------------------- memcpy_chk --------------------*/
1523 #define GLIBC26___MEMCPY_CHK(soname, fnname) \
1524 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1525 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1526 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1527 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1529 register HChar *d; \
1530 register const HChar *s; \
1532 if (dstlen < len) goto badness; \
1534 if (len == 0) \
1535 return dst; \
1537 if (is_overlap(dst, src, len, len)) \
1538 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1540 if ( dst > src ) { \
1541 d = (HChar *)dst + len - 1; \
1542 s = (const HChar *)src + len - 1; \
1543 while ( len-- ) { \
1544 *d-- = *s--; \
1546 } else if ( dst < src ) { \
1547 d = (HChar *)dst; \
1548 s = (const HChar *)src; \
1549 while ( len-- ) { \
1550 *d++ = *s++; \
1553 return dst; \
1554 badness: \
1555 VALGRIND_PRINTF_BACKTRACE( \
1556 "*** memcpy_chk: buffer overflow detected ***: " \
1557 "program terminated\n"); \
1558 my_exit(1); \
1559 /*NOTREACHED*/ \
1560 return NULL; \
1563 #if defined(VGO_linux)
1564 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1566 #elif defined(VGO_darwin)
1568 #elif defined(VGO_solaris)
1570 #endif
1573 /*---------------------- strstr ----------------------*/
1575 #define STRSTR(soname, fnname) \
1576 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1577 (const char* haystack, const char* needle); \
1578 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1579 (const char* haystack, const char* needle) \
1581 const HChar* h = haystack; \
1582 const HChar* n = needle; \
1584 /* find the length of n, not including terminating zero */ \
1585 UWord nlen = 0; \
1586 while (n[nlen]) nlen++; \
1588 /* if n is the empty string, match immediately. */ \
1589 if (nlen == 0) return CONST_CAST(HChar *,h); \
1591 /* assert(nlen >= 1); */ \
1592 HChar n0 = n[0]; \
1594 while (1) { \
1595 const HChar hh = *h; \
1596 if (hh == 0) return NULL; \
1597 if (hh != n0) { h++; continue; } \
1599 UWord i; \
1600 for (i = 0; i < nlen; i++) { \
1601 if (n[i] != h[i]) \
1602 break; \
1604 /* assert(i >= 0 && i <= nlen); */ \
1605 if (i == nlen) \
1606 return CONST_CAST(HChar *,h); \
1608 h++; \
1612 #if defined(VGO_linux)
1613 STRSTR(VG_Z_LIBC_SONAME, strstr)
1614 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse2)
1615 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse42)
1617 #elif defined(VGO_darwin)
1619 #elif defined(VGO_solaris)
1620 STRSTR(VG_Z_LIBC_SONAME, strstr)
1622 #endif
1625 /*---------------------- strpbrk ----------------------*/
1627 #define STRPBRK(soname, fnname) \
1628 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1629 (const char* sV, const char* acceptV); \
1630 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1631 (const char* sV, const char* acceptV) \
1633 const HChar* s = sV; \
1634 const HChar* accept = acceptV; \
1636 /* find the length of 'accept', not including terminating zero */ \
1637 UWord nacc = 0; \
1638 while (accept[nacc]) nacc++; \
1640 /* if n is the empty string, fail immediately. */ \
1641 if (nacc == 0) return NULL; \
1643 /* assert(nacc >= 1); */ \
1644 while (1) { \
1645 UWord i; \
1646 HChar sc = *s; \
1647 if (sc == 0) \
1648 break; \
1649 for (i = 0; i < nacc; i++) { \
1650 if (sc == accept[i]) \
1651 return CONST_CAST(HChar *,s); \
1653 s++; \
1656 return NULL; \
1659 #if defined(VGO_linux)
1660 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1662 #elif defined(VGO_darwin)
1664 #elif defined(VGO_solaris)
1665 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1667 #endif
1670 /*---------------------- strcspn ----------------------*/
1672 #define STRCSPN(soname, fnname) \
1673 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1674 (const char* sV, const char* rejectV); \
1675 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1676 (const char* sV, const char* rejectV) \
1678 const HChar* s = sV; \
1679 const HChar* reject = rejectV; \
1681 /* find the length of 'reject', not including terminating zero */ \
1682 UWord nrej = 0; \
1683 while (reject[nrej]) nrej++; \
1685 UWord len = 0; \
1686 while (1) { \
1687 UWord i; \
1688 HChar sc = *s; \
1689 if (sc == 0) \
1690 break; \
1691 for (i = 0; i < nrej; i++) { \
1692 if (sc == reject[i]) \
1693 break; \
1695 /* assert(i >= 0 && i <= nrej); */ \
1696 if (i < nrej) \
1697 break; \
1698 s++; \
1699 len++; \
1702 return len; \
1705 #if defined(VGO_linux)
1706 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1708 #elif defined(VGO_darwin)
1710 #elif defined(VGO_solaris)
1711 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1713 #endif
1716 /*---------------------- strspn ----------------------*/
1718 #define STRSPN(soname, fnname) \
1719 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1720 (const char* sV, const char* acceptV); \
1721 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1722 (const char* sV, const char* acceptV) \
1724 const UChar* s = (const UChar *)sV; \
1725 const UChar* accept = (const UChar *)acceptV; \
1727 /* find the length of 'accept', not including terminating zero */ \
1728 UWord nacc = 0; \
1729 while (accept[nacc]) nacc++; \
1730 if (nacc == 0) return 0; \
1732 UWord len = 0; \
1733 while (1) { \
1734 UWord i; \
1735 HChar sc = *s; \
1736 if (sc == 0) \
1737 break; \
1738 for (i = 0; i < nacc; i++) { \
1739 if (sc == accept[i]) \
1740 break; \
1742 /* assert(i >= 0 && i <= nacc); */ \
1743 if (i == nacc) \
1744 break; \
1745 s++; \
1746 len++; \
1749 return len; \
1752 #if defined(VGO_linux)
1753 STRSPN(VG_Z_LIBC_SONAME, strspn)
1755 #elif defined(VGO_darwin)
1757 #elif defined(VGO_solaris)
1758 STRSPN(VG_Z_LIBC_SONAME, strspn)
1760 #endif
1763 /*---------------------- strcasestr ----------------------*/
1765 #define STRCASESTR(soname, fnname) \
1766 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1767 (const char* haystack, const char* needle); \
1768 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1769 (const char* haystack, const char* needle) \
1771 extern int tolower(int); \
1772 const HChar* h = haystack; \
1773 const HChar* n = needle; \
1775 /* find the length of n, not including terminating zero */ \
1776 UWord nlen = 0; \
1777 while (n[nlen]) nlen++; \
1779 /* if n is the empty string, match immediately. */ \
1780 if (nlen == 0) return CONST_CAST(HChar *,h); \
1782 /* assert(nlen >= 1); */ \
1783 UChar n0 = tolower(n[0]); \
1785 while (1) { \
1786 UChar hh = tolower(*h); \
1787 if (hh == 0) return NULL; \
1788 if (hh != n0) { h++; continue; } \
1790 UWord i; \
1791 for (i = 0; i < nlen; i++) { \
1792 if (tolower(n[i]) != tolower(h[i])) \
1793 break; \
1795 /* assert(i >= 0 && i <= nlen); */ \
1796 if (i == nlen) \
1797 return CONST_CAST(HChar *,h); \
1799 h++; \
1803 #if defined(VGO_linux)
1804 # if !defined(VGPV_arm_linux_android) \
1805 && !defined(VGPV_x86_linux_android) \
1806 && !defined(VGPV_mips32_linux_android) \
1807 && !defined(VGPV_arm64_linux_android)
1808 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1809 # endif
1811 #elif defined(VGO_darwin)
1813 #elif defined(VGO_solaris)
1814 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1816 #endif
1819 /*---------------------- wcslen ----------------------*/
1821 // This is a wchar_t equivalent to strlen. Unfortunately
1822 // we don't have wchar_t available here, but it looks like
1823 // a 32 bit int on Linux. I don't know if that is also
1824 // valid on MacOSX.
1826 #define WCSLEN(soname, fnname) \
1827 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1828 ( const UInt* str ); \
1829 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1830 ( const UInt* str ) \
1832 SizeT i = 0; \
1833 while (str[i] != 0) i++; \
1834 return i; \
1837 #if defined(VGO_linux)
1838 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
1840 #elif defined(VGO_darwin)
1842 #elif defined(VGO_solaris)
1843 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
1845 #endif
1847 /*---------------------- wcscmp ----------------------*/
1849 // This is a wchar_t equivalent to strcmp. We don't
1850 // have wchar_t available here, but in the GNU C Library
1851 // wchar_t is always 32 bits wide and wcscmp uses signed
1852 // comparison, not unsigned as in strcmp function.
1854 #define WCSCMP(soname, fnname) \
1855 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1856 ( const Int* s1, const Int* s2 ); \
1857 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1858 ( const Int* s1, const Int* s2 ) \
1860 register Int c1; \
1861 register Int c2; \
1862 while (True) { \
1863 c1 = *s1; \
1864 c2 = *s2; \
1865 if (c1 != c2) break; \
1866 if (c1 == 0) break; \
1867 s1++; s2++; \
1869 if (c1 < c2) return -1; \
1870 if (c1 > c2) return 1; \
1871 return 0; \
1874 #if defined(VGO_linux)
1875 WCSCMP(VG_Z_LIBC_SONAME, wcscmp)
1876 #endif
1878 /*---------------------- wcscpy ----------------------*/
1880 // This is a wchar_t equivalent to strcpy. We don't
1881 // have wchar_t available here, but in the GNU C Library
1882 // wchar_t is always 32 bits wide.
1884 #define WCSCPY(soname, fnname) \
1885 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1886 ( Int* dst, const Int* src ); \
1887 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1888 ( Int* dst, const Int* src ) \
1890 const Int* src_orig = src; \
1891 Int* dst_orig = dst; \
1893 while (*src) *dst++ = *src++; \
1894 *dst = 0; \
1896 /* This checks for overlap after copying, unavoidable without */ \
1897 /* pre-counting length... should be ok */ \
1898 if (is_overlap(dst_orig, \
1899 src_orig, \
1900 (Addr)dst-(Addr)dst_orig+1, \
1901 (Addr)src-(Addr)src_orig+1)) \
1902 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
1904 return dst_orig; \
1907 #if defined(VGO_linux)
1908 WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
1909 #endif
1912 /*---------------------- wcschr ----------------------*/
1914 // This is a wchar_t equivalent to strchr. We don't
1915 // have wchar_t available here, but in the GNU C Library
1916 // wchar_t is always 32 bits wide.
1918 #define WCSCHR(soname, fnname) \
1919 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
1920 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
1922 const Int* p = s; \
1923 while (True) { \
1924 if (*p == c) return CONST_CAST(Int *,p); \
1925 if (*p == 0) return NULL; \
1926 p++; \
1930 #if defined(VGO_linux)
1931 WCSCHR(VG_Z_LIBC_SONAME, wcschr)
1932 #endif
1933 /*---------------------- wcsrchr ----------------------*/
1935 // This is a wchar_t equivalent to strrchr. We don't
1936 // have wchar_t available here, but in the GNU C Library
1937 // wchar_t is always 32 bits wide.
1939 #define WCSRCHR(soname, fnname) \
1940 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
1941 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
1943 const Int* p = s; \
1944 const Int* last = NULL; \
1945 while (True) { \
1946 if (*p == c) last = p; \
1947 if (*p == 0) return CONST_CAST(Int *,last); \
1948 p++; \
1952 #if defined(VGO_linux)
1953 WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
1954 #endif
1956 /*------------------------------------------------------------*/
1957 /*--- Improve definedness checking of process environment ---*/
1958 /*------------------------------------------------------------*/
1960 #if defined(VGO_linux)
1962 /* If these wind up getting generated via a macro, so that multiple
1963 versions of each function exist (as above), use the _EZU variants
1964 to assign equivalance class tags. */
1966 /*---------------------- putenv ----------------------*/
1968 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1969 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
1971 OrigFn fn;
1972 Word result;
1973 const HChar* p = string;
1974 VALGRIND_GET_ORIG_FN(fn);
1975 /* Now by walking over the string we magically produce
1976 traces when hitting undefined memory. */
1977 if (p)
1978 while (*p++)
1979 __asm__ __volatile__("" ::: "memory");
1980 CALL_FN_W_W(result, fn, string);
1981 return result;
1985 /*---------------------- unsetenv ----------------------*/
1987 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1988 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
1990 OrigFn fn;
1991 Word result;
1992 const HChar* p = name;
1993 VALGRIND_GET_ORIG_FN(fn);
1994 /* Now by walking over the string we magically produce
1995 traces when hitting undefined memory. */
1996 if (p)
1997 while (*p++)
1998 __asm__ __volatile__("" ::: "memory");
1999 CALL_FN_W_W(result, fn, name);
2000 return result;
2004 /*---------------------- setenv ----------------------*/
2006 /* setenv */
2007 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
2008 (const char* name, const char* value, int overwrite);
2009 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
2010 (const char* name, const char* value, int overwrite)
2012 OrigFn fn;
2013 Word result;
2014 const HChar* p;
2015 VALGRIND_GET_ORIG_FN(fn);
2016 /* Now by walking over the string we magically produce
2017 traces when hitting undefined memory. */
2018 if (name)
2019 for (p = name; *p; p++)
2020 __asm__ __volatile__("" ::: "memory");
2021 if (value)
2022 for (p = value; *p; p++)
2023 __asm__ __volatile__("" ::: "memory");
2024 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
2025 CALL_FN_W_WWW(result, fn, name, value, overwrite);
2026 return result;
2029 #endif /* defined(VGO_linux) */
2031 /*--------------------------------------------------------------------*/
2032 /*--- end ---*/
2033 /*--------------------------------------------------------------------*/