Hook up statx syscall for s390x-linux
[valgrind.git] / shared / vg_replace_strmem.c
blobd6927f08e0da1f22c5ebb63990ad38c6024b42bc
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, 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
104 20430 WMEMCHR
105 20440 WCSNLEN
108 #if defined(VGO_solaris)
110 Detour functions in the libc and the runtime linker. If a function isn't
111 much optimized (and no overlap checking is necessary) then redir the
112 function only in the libc. This way we can keep stacktraces in the tests
113 consistent.
115 #endif
118 /* Figure out if [dst .. dst+dstlen-1] overlaps with
119 [src .. src+srclen-1].
120 We assume that the address ranges do not wrap around
121 (which is safe since on Linux addresses >= 0xC0000000
122 are not accessible and the program will segfault in this
123 circumstance, presumably).
125 static inline
126 Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
128 Addr loS, hiS, loD, hiD;
130 if (dstlen == 0 || srclen == 0)
131 return False;
133 loS = (Addr)src;
134 loD = (Addr)dst;
135 hiS = loS + srclen - 1;
136 hiD = loD + dstlen - 1;
138 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
139 if (loS < loD) {
140 return !(hiS < loD);
142 else if (loD < loS) {
143 return !(hiD < loS);
145 else {
146 /* They start at same place. Since we know neither of them has
147 zero length, they must overlap. */
148 return True;
153 /* Call here to exit if we can't continue. On Android we can't call
154 _exit for some reason, so we have to blunt-instrument it. */
155 __attribute__ ((__noreturn__))
156 static inline void my_exit ( int x )
158 # if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \
159 || defined(VGPV_arm64_linux_android)
160 __asm__ __volatile__(".word 0xFFFFFFFF");
161 while (1) {}
162 # elif defined(VGPV_x86_linux_android)
163 __asm__ __volatile__("ud2");
164 while (1) {}
165 # else
166 extern __attribute__ ((__noreturn__)) void _exit(int status);
167 _exit(x);
168 # endif
172 // This is a macro rather than a function because we don't want to have an
173 // extra function in the stack trace.
174 #ifndef RECORD_OVERLAP_ERROR
175 #define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0)
176 #endif
177 #ifndef VALGRIND_CHECK_VALUE_IS_DEFINED
178 #define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1
179 #endif
182 /*---------------------- strrchr ----------------------*/
184 #define STRRCHR(soname, fnname) \
185 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
186 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
188 HChar ch = (HChar)c; \
189 const HChar* p = s; \
190 const HChar* last = NULL; \
191 while (True) { \
192 if (*p == ch) last = p; \
193 if (*p == 0) return CONST_CAST(HChar *,last); \
194 p++; \
198 // Apparently rindex() is the same thing as strrchr()
199 #if defined(VGO_linux)
200 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
201 STRRCHR(VG_Z_LIBC_SONAME, rindex)
202 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
203 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2)
204 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2_no_bsf)
205 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse42)
206 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
207 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
208 || defined(VGPV_mips32_linux_android)
209 STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */
210 #endif
212 #elif defined(VGO_darwin)
213 //STRRCHR(VG_Z_LIBC_SONAME, strrchr)
214 //STRRCHR(VG_Z_LIBC_SONAME, rindex)
215 //STRRCHR(VG_Z_DYLD, strrchr)
216 //STRRCHR(VG_Z_DYLD, rindex)
217 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
218 # if DARWIN_VERS >= DARWIN_10_9
219 STRRCHR(libsystemZucZddylib, strrchr)
220 # endif
222 #elif defined(VGO_solaris)
223 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
224 STRRCHR(VG_Z_LIBC_SONAME, rindex)
225 STRRCHR(VG_Z_LD_SO_1, strrchr)
227 #endif
230 /*---------------------- strchr ----------------------*/
232 #define STRCHR(soname, fnname) \
233 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
234 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
236 HChar ch = (HChar)c ; \
237 const HChar* p = s; \
238 while (True) { \
239 if (*p == ch) return CONST_CAST(HChar *,p); \
240 if (*p == 0) return NULL; \
241 p++; \
245 // Apparently index() is the same thing as strchr()
246 #if defined(VGO_linux)
247 STRCHR(VG_Z_LIBC_SONAME, strchr)
248 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
249 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2)
250 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2_no_bsf)
251 STRCHR(VG_Z_LIBC_SONAME, index)
252 # if !defined(VGP_x86_linux) && !defined(VGP_amd64_linux)
253 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
254 STRCHR(VG_Z_LD_LINUX_SO_2, index)
255 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
256 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
257 # endif
259 #if defined(VGPV_mips32_linux_android)
260 STRCHR(NONE, __dl_strchr)
261 #endif
263 #elif defined(VGO_darwin)
264 STRCHR(VG_Z_LIBC_SONAME, strchr)
265 # if DARWIN_VERS == DARWIN_10_9
266 STRCHR(libsystemZuplatformZddylib, _platform_strchr)
267 # endif
268 # if DARWIN_VERS >= DARWIN_10_10
269 /* _platform_strchr$VARIANT$Generic */
270 STRCHR(libsystemZuplatformZddylib, _platform_strchr$VARIANT$Generic)
271 /* _platform_strchr$VARIANT$Haswell */
272 STRCHR(libsystemZuplatformZddylib, _platform_strchr$VARIANT$Haswell)
273 # endif
275 #elif defined(VGO_solaris)
276 STRCHR(VG_Z_LIBC_SONAME, strchr)
277 STRCHR(VG_Z_LIBC_SONAME, index)
278 STRCHR(VG_Z_LD_SO_1, strchr)
280 #endif
283 /*---------------------- strcat ----------------------*/
285 #define STRCAT(soname, fnname) \
286 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
287 ( char* dst, const char* src ); \
288 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
289 ( char* dst, const char* src ) \
291 const HChar* src_orig = src; \
292 HChar* dst_orig = dst; \
293 while (*dst) dst++; \
294 while (*src) *dst++ = *src++; \
295 *dst = 0; \
297 /* This is a bit redundant, I think; any overlap and the strcat will */ \
298 /* go forever... or until a seg fault occurs. */ \
299 if (is_overlap(dst_orig, \
300 src_orig, \
301 (Addr)dst-(Addr)dst_orig+1, \
302 (Addr)src-(Addr)src_orig+1)) \
303 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
305 return dst_orig; \
308 #if defined(VGO_linux)
309 STRCAT(VG_Z_LIBC_SONAME, strcat)
310 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
312 #elif defined(VGO_darwin)
313 //STRCAT(VG_Z_LIBC_SONAME, strcat)
315 #elif defined(VGO_solaris)
316 STRCAT(VG_Z_LIBC_SONAME, strcat)
317 STRCAT(VG_Z_LD_SO_1, strcat)
319 #endif
322 /*---------------------- strncat ----------------------*/
324 #define STRNCAT(soname, fnname) \
325 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
326 ( char* dst, const char* src, SizeT n ); \
327 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
328 ( char* dst, const char* src, SizeT n ) \
330 const HChar* src_orig = src; \
331 HChar* dst_orig = dst; \
332 SizeT m = 0; \
334 while (*dst) dst++; \
335 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
336 *dst = 0; /* always add null */ \
338 /* This checks for overlap after copying, unavoidable without */ \
339 /* pre-counting lengths... should be ok */ \
340 if (is_overlap(dst_orig, \
341 src_orig, \
342 (Addr)dst-(Addr)dst_orig+1, \
343 (Addr)src-(Addr)src_orig+1)) \
344 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
346 return dst_orig; \
349 #if defined(VGO_linux)
350 STRNCAT(VG_Z_LIBC_SONAME, strncat)
352 #elif defined(VGO_darwin)
353 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
354 //STRNCAT(VG_Z_DYLD, strncat)
356 #elif defined(VGO_solaris)
357 STRNCAT(VG_Z_LIBC_SONAME, strncat)
359 #endif
362 /*---------------------- strlcat ----------------------*/
364 /* Append src to dst. n is the size of dst's buffer. dst is guaranteed
365 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
366 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
367 Truncation occurred if retval >= n.
369 #define STRLCAT(soname, fnname) \
370 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
371 ( char* dst, const char* src, SizeT n ); \
372 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
373 ( char* dst, const char* src, SizeT n ) \
375 const HChar* src_orig = src; \
376 HChar* dst_orig = dst; \
377 SizeT m = 0; \
379 while (m < n && *dst) { m++; dst++; } \
380 if (m < n) { \
381 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
382 while (m+1 < n && *src) { m++; *dst++ = *src++; } \
383 *dst = 0; \
384 } else { \
385 /* No space to copy anything to dst. m == n */ \
387 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
388 while (*src) { m++; src++; } \
389 /* This checks for overlap after copying, unavoidable without */ \
390 /* pre-counting lengths... should be ok */ \
391 if (is_overlap(dst_orig, \
392 src_orig, \
393 (Addr)dst-(Addr)dst_orig+1, \
394 (Addr)src-(Addr)src_orig+1)) \
395 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
397 return m; \
400 #if defined(VGO_linux)
402 #elif defined(VGO_darwin)
403 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
404 //STRLCAT(VG_Z_DYLD, strlcat)
405 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
407 #elif defined(VGO_solaris)
408 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
410 #endif
413 /*---------------------- strnlen ----------------------*/
415 #define STRNLEN(soname, fnname) \
416 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
417 ( const char* str, SizeT n ); \
418 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
419 ( const char* str, SizeT n ) \
421 SizeT i = 0; \
422 while (i < n && str[i] != 0) i++; \
423 return i; \
426 #if defined(VGO_linux)
427 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
428 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
430 #elif defined(VGO_darwin)
431 # if DARWIN_VERS == DARWIN_10_9
432 STRNLEN(libsystemZucZddylib, strnlen)
433 # endif
435 #elif defined(VGO_solaris)
436 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
438 #endif
441 /*---------------------- strlen ----------------------*/
443 // Note that this replacement often doesn't get used because gcc inlines
444 // calls to strlen() with its own built-in version. This can be very
445 // confusing if you aren't expecting it. Other small functions in
446 // this file may also be inline by gcc.
448 #define STRLEN(soname, fnname) \
449 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
450 ( const char* str ); \
451 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
452 ( const char* str ) \
454 SizeT i = 0; \
455 while (str[i] != 0) i++; \
456 return i; \
459 #if defined(VGO_linux)
460 STRLEN(VG_Z_LIBC_SONAME, strlen)
461 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
462 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2)
463 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2_no_bsf)
464 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse42)
465 STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
466 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
467 # if defined(VGPV_arm_linux_android) \
468 || defined(VGPV_x86_linux_android) \
469 || defined(VGPV_mips32_linux_android)
470 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
471 # endif
473 #elif defined(VGO_darwin)
474 STRLEN(VG_Z_LIBC_SONAME, strlen)
475 # if DARWIN_VERS >= DARWIN_10_9
476 STRLEN(libsystemZucZddylib, strlen)
477 # endif
479 #elif defined(VGO_solaris)
480 STRLEN(VG_Z_LIBC_SONAME, strlen)
481 STRLEN(VG_Z_LD_SO_1, strlen)
483 #endif
486 /*---------------------- strcpy ----------------------*/
488 #define STRCPY(soname, fnname) \
489 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
490 ( char* dst, const char* src ); \
491 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
492 ( char* dst, const char* src ) \
494 const HChar* src_orig = src; \
495 HChar* dst_orig = dst; \
497 while (*src) *dst++ = *src++; \
498 *dst = 0; \
500 /* This checks for overlap after copying, unavoidable without */ \
501 /* pre-counting length... should be ok */ \
502 if (is_overlap(dst_orig, \
503 src_orig, \
504 (Addr)dst-(Addr)dst_orig+1, \
505 (Addr)src-(Addr)src_orig+1)) \
506 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
508 return dst_orig; \
511 #if defined(VGO_linux)
512 STRCPY(VG_Z_LIBC_SONAME, strcpy)
513 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
515 #elif defined(VGO_darwin)
516 STRCPY(VG_Z_LIBC_SONAME, strcpy)
517 # if DARWIN_VERS == DARWIN_10_9
518 STRCPY(libsystemZucZddylib, strcpy)
519 # endif
521 #elif defined(VGO_solaris)
522 STRCPY(VG_Z_LIBC_SONAME, strcpy)
523 STRCPY(VG_Z_LD_SO_1, strcpy)
525 #endif
528 /*---------------------- strncpy ----------------------*/
530 #define STRNCPY(soname, fnname) \
531 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
532 ( char* dst, const char* src, SizeT n ); \
533 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
534 ( char* dst, const char* src, SizeT n ) \
536 const HChar* src_orig = src; \
537 HChar* dst_orig = dst; \
538 SizeT m = 0; \
540 while (m < n && *src) { m++; *dst++ = *src++; } \
541 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
542 /* but only m+1 bytes of src if terminator was found */ \
543 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
544 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
545 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
547 return dst_orig; \
550 #if defined(VGO_linux)
551 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
552 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
553 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2)
554 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned)
556 #elif defined(VGO_darwin)
557 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
558 # if DARWIN_VERS >= DARWIN_10_9
559 STRNCPY(libsystemZucZddylib, strncpy)
560 # endif
562 #elif defined(VGO_solaris)
563 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
564 STRNCPY(VG_Z_LD_SO_1, strncpy)
566 #endif
569 /*---------------------- strlcpy ----------------------*/
571 /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
572 Returns strlen(src). Does not zero-fill the remainder of dst. */
573 #define STRLCPY(soname, fnname) \
574 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
575 ( char* dst, const char* src, SizeT n ); \
576 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
577 ( char* dst, const char* src, SizeT n ) \
579 const HChar* src_orig = src; \
580 HChar* dst_orig = dst; \
581 SizeT m = 0; \
583 STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
585 while (m+1 < n && *src) { m++; *dst++ = *src++; } \
586 /* m non-nul bytes have now been copied, and m <= n-1. */ \
587 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
588 /* but only m+1 bytes of src if terminator was found */ \
589 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
590 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
591 /* Nul-terminate dst. */ \
592 if (n > 0) *dst = 0; \
593 /* Finish counting strlen(src). */ \
594 while (*src) src++; \
595 return src - src_orig; \
598 #if defined(VGO_linux)
600 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
601 || defined(VGPV_mips32_linux_android)
602 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
603 STRLCPY(VG_Z_LIBC_SONAME, strlcpy);
604 #endif
606 #elif defined(VGO_darwin)
607 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO
608 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
609 //STRLCPY(VG_Z_DYLD, strlcpy)
610 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
612 #elif defined(VGO_solaris)
613 /* special case for n == 0 which is undocumented but heavily used */
614 #define STRLCPY_CHECK_FOR_DSTSIZE_ZERO \
615 if (n == 0) { \
616 while (*src) src++; \
617 return src - src_orig; \
620 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
622 #endif
625 /*---------------------- strncmp ----------------------*/
627 #define STRNCMP(soname, fnname) \
628 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
629 ( const char* s1, const char* s2, SizeT nmax ); \
630 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
631 ( const char* s1, const char* s2, SizeT nmax ) \
633 SizeT n = 0; \
634 while (True) { \
635 if (n >= nmax) return 0; \
636 if (*s1 == 0 && *s2 == 0) return 0; \
637 if (*s1 == 0) return -1; \
638 if (*s2 == 0) return 1; \
640 if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \
641 if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \
643 s1++; s2++; n++; \
647 #if defined(VGO_linux)
648 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
649 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
650 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2)
651 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42)
653 #elif defined(VGO_darwin)
654 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
655 # if DARWIN_VERS >= DARWIN_10_9
656 STRNCMP(libsystemZuplatformZddylib, _platform_strncmp)
657 # endif
659 #elif defined(VGO_solaris)
660 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
662 #endif
665 /*---------------------- strcasecmp ----------------------*/
667 #define STRCASECMP(soname, fnname) \
668 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
669 ( const char* s1, const char* s2 ); \
670 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
671 ( const char* s1, const char* s2 ) \
673 extern int tolower(int); \
674 register UChar c1; \
675 register UChar c2; \
676 while (True) { \
677 c1 = tolower(*(const UChar *)s1); \
678 c2 = tolower(*(const UChar *)s2); \
679 if (c1 != c2) break; \
680 if (c1 == 0) break; \
681 s1++; s2++; \
683 if ((UChar)c1 < (UChar)c2) return -1; \
684 if ((UChar)c1 > (UChar)c2) return 1; \
685 return 0; \
688 #if defined(VGO_linux)
689 # if !defined(VGPV_arm_linux_android) \
690 && !defined(VGPV_x86_linux_android) \
691 && !defined(VGPV_mips32_linux_android) \
692 && !defined(VGPV_arm64_linux_android)
693 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
694 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
695 # endif
697 #elif defined(VGO_darwin)
698 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
700 #elif defined(VGO_solaris)
701 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
703 #endif
706 /*---------------------- strncasecmp ----------------------*/
708 #define STRNCASECMP(soname, fnname) \
709 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
710 ( const char* s1, const char* s2, SizeT nmax ); \
711 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
712 ( const char* s1, const char* s2, SizeT nmax ) \
714 extern int tolower(int); \
715 SizeT n = 0; \
716 while (True) { \
717 if (n >= nmax) return 0; \
718 if (*s1 == 0 && *s2 == 0) return 0; \
719 if (*s1 == 0) return -1; \
720 if (*s2 == 0) return 1; \
722 if (tolower(*(const UChar *)s1) \
723 < tolower(*(const UChar*)s2)) return -1; \
724 if (tolower(*(const UChar *)s1) \
725 > tolower(*(const UChar *)s2)) return 1; \
727 s1++; s2++; n++; \
731 #if defined(VGO_linux)
732 # if !defined(VGPV_arm_linux_android) \
733 && !defined(VGPV_x86_linux_android) \
734 && !defined(VGPV_mips32_linux_android) \
735 && !defined(VGPV_arm64_linux_android)
736 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
737 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
738 # endif
740 #elif defined(VGO_darwin)
741 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
742 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
744 #elif defined(VGO_solaris)
745 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
747 #endif
750 /*---------------------- strcasecmp_l ----------------------*/
752 #define STRCASECMP_L(soname, fnname) \
753 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
754 ( const char* s1, const char* s2, void* locale ); \
755 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
756 ( const char* s1, const char* s2, void* locale ) \
758 extern int tolower_l(int, void*) __attribute__((weak)); \
759 register UChar c1; \
760 register UChar c2; \
761 while (True) { \
762 c1 = tolower_l(*(const UChar *)s1, locale); \
763 c2 = tolower_l(*(const UChar *)s2, locale); \
764 if (c1 != c2) break; \
765 if (c1 == 0) break; \
766 s1++; s2++; \
768 if ((UChar)c1 < (UChar)c2) return -1; \
769 if ((UChar)c1 > (UChar)c2) return 1; \
770 return 0; \
773 #if defined(VGO_linux)
774 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
775 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
776 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
778 #elif defined(VGO_darwin)
779 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
781 #elif defined(VGO_solaris)
783 #endif
786 /*---------------------- strncasecmp_l ----------------------*/
788 #define STRNCASECMP_L(soname, fnname) \
789 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
790 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
791 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
792 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
794 extern int tolower_l(int, void*) __attribute__((weak)); \
795 SizeT n = 0; \
796 while (True) { \
797 if (n >= nmax) return 0; \
798 if (*s1 == 0 && *s2 == 0) return 0; \
799 if (*s1 == 0) return -1; \
800 if (*s2 == 0) return 1; \
802 if (tolower_l(*(const UChar *)s1, locale) \
803 < tolower_l(*(const UChar *)s2, locale)) return -1; \
804 if (tolower_l(*(const UChar *)s1, locale) \
805 > tolower_l(*(const UChar *)s2, locale)) return 1; \
807 s1++; s2++; n++; \
811 #if defined(VGO_linux)
812 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
813 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
814 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l)
816 #elif defined(VGO_darwin)
817 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
818 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
820 #elif defined(VGO_solaris)
822 #endif
825 /*---------------------- strcmp ----------------------*/
827 #define STRCMP(soname, fnname) \
828 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
829 ( const char* s1, const char* s2 ); \
830 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
831 ( const char* s1, const char* s2 ) \
833 register UChar c1; \
834 register UChar c2; \
835 while (True) { \
836 c1 = *(const UChar *)s1; \
837 c2 = *(const UChar *)s2; \
838 if (c1 != c2) break; \
839 if (c1 == 0) break; \
840 s1++; s2++; \
842 if ((UChar)c1 < (UChar)c2) return -1; \
843 if ((UChar)c1 > (UChar)c2) return 1; \
844 return 0; \
847 #if defined(VGO_linux)
848 STRCMP(VG_Z_LIBC_SONAME, strcmp)
849 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
850 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse2)
851 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse42)
852 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
853 STRCMP(VG_Z_LD64_SO_1, strcmp)
854 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
855 || defined(VGPV_mips32_linux_android)
856 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
857 # endif
859 #elif defined(VGO_darwin)
860 STRCMP(VG_Z_LIBC_SONAME, strcmp)
861 # if DARWIN_VERS >= DARWIN_10_9
862 STRCMP(libsystemZuplatformZddylib, _platform_strcmp)
863 # endif
865 #elif defined(VGO_solaris)
866 STRCMP(VG_Z_LIBC_SONAME, strcmp)
867 STRCMP(VG_Z_LD_SO_1, strcmp)
869 #endif
872 /*---------------------- memchr ----------------------*/
874 #define MEMCHR(soname, fnname) \
875 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
876 (const void *s, int c, SizeT n); \
877 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
878 (const void *s, int c, SizeT n) \
880 SizeT i; \
881 UChar c0 = (UChar)c; \
882 const UChar* p = s; \
883 for (i = 0; i < n; i++) \
884 if (p[i] == c0) return CONST_CAST(void *,&p[i]); \
885 return NULL; \
888 #if defined(VGO_linux)
889 MEMCHR(VG_Z_LIBC_SONAME, memchr)
890 MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr)
892 #elif defined(VGO_darwin)
893 # if DARWIN_VERS == DARWIN_10_9
894 MEMCHR(VG_Z_DYLD, memchr)
895 MEMCHR(libsystemZuplatformZddylib, _platform_memchr)
896 # endif
897 # if DARWIN_VERS >= DARWIN_10_10
898 MEMCHR(VG_Z_DYLD, memchr)
899 /* _platform_memchr$VARIANT$Generic */
900 MEMCHR(libsystemZuplatformZddylib, _platform_memchr$VARIANT$Generic)
901 /* _platform_memchr$VARIANT$Haswell */
902 MEMCHR(libsystemZuplatformZddylib, _platform_memchr$VARIANT$Haswell)
903 # endif
905 #elif defined(VGO_solaris)
906 MEMCHR(VG_Z_LIBC_SONAME, memchr)
908 #endif
911 /*---------------------- memrchr ----------------------*/
913 #define MEMRCHR(soname, fnname) \
914 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
915 (const void *s, int c, SizeT n); \
916 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
917 (const void *s, int c, SizeT n) \
919 SizeT i; \
920 UChar c0 = (UChar)c; \
921 const UChar* p = s; \
922 for (i = 0; i < n; i++) \
923 if (p[n-1-i] == c0) return CONST_CAST(void *,&p[n-1-i]); \
924 return NULL; \
927 #if defined(VGO_linux)
928 MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
930 #elif defined(VGO_darwin)
931 //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
932 //MEMRCHR(VG_Z_DYLD, memrchr)
934 #elif defined(VGO_solaris)
936 #endif
939 /*---------------------- memcpy ----------------------*/
941 #define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
942 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
943 ( void *dst, const void *src, SizeT len ); \
944 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
945 ( void *dst, const void *src, SizeT len ) \
947 if (do_ol_check && is_overlap(dst, src, len, len)) \
948 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
950 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
951 const Addr WM = WS - 1; /* 7 or 3 */ \
953 if (len > 0) { \
954 if (dst < src || !is_overlap(dst, src, len, len)) { \
956 /* Copying backwards. */ \
957 SizeT n = len; \
958 Addr d = (Addr)dst; \
959 Addr s = (Addr)src; \
961 if (((s^d) & WM) == 0) { \
962 /* s and d have same UWord alignment. */ \
963 /* Pull up to a UWord boundary. */ \
964 while ((s & WM) != 0 && n >= 1) \
965 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
966 /* Copy UWords. */ \
967 while (n >= WS * 4) \
968 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
969 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
970 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; \
971 *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
972 while (n >= WS) \
973 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
974 if (n == 0) \
975 return dst; \
977 if (((s|d) & 1) == 0) { \
978 /* Both are 16-aligned; copy what we can thusly. */ \
979 while (n >= 2) \
980 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
982 /* Copy leftovers, or everything if misaligned. */ \
983 while (n >= 1) \
984 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
986 } else if (dst > src) { \
988 SizeT n = len; \
989 Addr d = ((Addr)dst) + n; \
990 Addr s = ((Addr)src) + n; \
992 /* Copying forwards. */ \
993 if (((s^d) & WM) == 0) { \
994 /* s and d have same UWord alignment. */ \
995 /* Back down to a UWord boundary. */ \
996 while ((s & WM) != 0 && n >= 1) \
997 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
998 /* Copy UWords. */ \
999 while (n >= WS * 4) \
1000 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1001 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1002 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; \
1003 s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
1004 while (n >= WS) \
1005 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
1006 if (n == 0) \
1007 return dst; \
1009 if (((s|d) & 1) == 0) { \
1010 /* Both are 16-aligned; copy what we can thusly. */ \
1011 while (n >= 2) \
1012 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
1014 /* Copy leftovers, or everything if misaligned. */ \
1015 while (n >= 1) \
1016 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
1021 return dst; \
1024 #define MEMMOVE(soname, fnname) \
1025 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
1027 #define MEMCPY(soname, fnname) \
1028 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
1030 #if defined(VGO_linux)
1031 /* For older memcpy we have to use memmove-like semantics and skip
1032 the overlap check; sigh; see #275284. */
1033 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
1034 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
1035 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
1036 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy)
1037 MEMCPY(VG_Z_LIBC_SONAME, __memcpy_sse2)
1038 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
1039 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
1040 /* icc9 blats these around all over the place. Not only in the main
1041 executable but various .so's. They are highly tuned and read
1042 memory beyond the source boundary (although work correctly and
1043 never go across page boundaries), so give errors when run
1044 natively, at least for misaligned source arg. Just intercepting
1045 in the exe only until we understand more about the problem. See
1046 http://bugs.kde.org/show_bug.cgi?id=139776
1048 MEMCPY(NONE, ZuintelZufastZumemcpy)
1050 #elif defined(VGO_darwin)
1051 # if DARWIN_VERS <= DARWIN_10_6
1052 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
1053 # endif
1054 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
1055 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
1057 #elif defined(VGO_solaris)
1058 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
1059 MEMCPY(VG_Z_LIBC_SONAME, memcpyZPZa)
1060 MEMCPY(VG_Z_LD_SO_1, memcpy)
1062 #endif
1065 /*---------------------- memcmp ----------------------*/
1067 #define MEMCMP(soname, fnname) \
1068 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1069 ( const void *s1V, const void *s2V, SizeT n ); \
1070 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
1071 ( const void *s1V, const void *s2V, SizeT n ) \
1073 const SizeT WS = sizeof(UWord); /* 8 or 4 */ \
1074 const SizeT WM = WS - 1; /* 7 or 3 */ \
1075 Addr s1A = (Addr)s1V; \
1076 Addr s2A = (Addr)s2V; \
1078 if (((s1A | s2A) & WM) == 0) { \
1079 /* Both areas are word aligned. Skip over the */ \
1080 /* equal prefix as fast as possible. */ \
1081 while (n >= WS) { \
1082 UWord w1 = *(UWord*)s1A; \
1083 UWord w2 = *(UWord*)s2A; \
1084 if (w1 != w2) break; \
1085 s1A += WS; \
1086 s2A += WS; \
1087 n -= WS; \
1091 const UChar* s1 = (const UChar*) s1A; \
1092 const UChar* s2 = (const UChar*) s2A; \
1094 while (n != 0) { \
1095 UChar a0 = s1[0]; \
1096 UChar b0 = s2[0]; \
1097 s1 += 1; \
1098 s2 += 1; \
1099 int res = ((int)a0) - ((int)b0); \
1100 if (res != 0) \
1101 return res; \
1102 n -= 1; \
1104 return 0; \
1107 #if defined(VGO_linux)
1108 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
1109 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
1110 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse2)
1111 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse4_1)
1112 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
1113 MEMCMP(VG_Z_LD_SO_1, bcmp)
1115 #elif defined(VGO_darwin)
1116 # if DARWIN_VERS >= DARWIN_10_9
1117 MEMCMP(libsystemZuplatformZddylib, _platform_memcmp)
1118 # endif
1120 #elif defined(VGO_solaris)
1121 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
1122 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
1123 MEMCMP(VG_Z_LD_SO_1, memcmp)
1125 #endif
1128 /*---------------------- stpcpy ----------------------*/
1130 /* Copy SRC to DEST, returning the address of the terminating '\0' in
1131 DEST. (minor variant of strcpy) */
1132 #define STPCPY(soname, fnname) \
1133 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1134 ( char* dst, const char* src ); \
1135 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
1136 ( char* dst, const char* src ) \
1138 const HChar* src_orig = src; \
1139 HChar* dst_orig = dst; \
1141 while (*src) *dst++ = *src++; \
1142 *dst = 0; \
1144 /* This checks for overlap after copying, unavoidable without */ \
1145 /* pre-counting length... should be ok */ \
1146 if (is_overlap(dst_orig, \
1147 src_orig, \
1148 (Addr)dst-(Addr)dst_orig+1, \
1149 (Addr)src-(Addr)src_orig+1)) \
1150 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
1152 return dst; \
1155 #if defined(VGO_linux)
1156 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1157 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
1158 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2)
1159 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2_unaligned)
1160 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
1161 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
1163 #elif defined(VGO_darwin)
1164 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1165 //STPCPY(VG_Z_DYLD, stpcpy)
1167 #elif defined(VGO_solaris)
1168 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1170 #endif
1173 /*---------------------- stpncpy ----------------------*/
1175 #define STPNCPY(soname, fnname) \
1176 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1177 ( char* dst, const char* src, SizeT n ); \
1178 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1179 ( char* dst, const char* src, SizeT n ) \
1181 const HChar* src_orig = src; \
1182 HChar* dst_str = dst; \
1183 SizeT m = 0; \
1185 while (m < n && *src) { m++; *dst++ = *src++; } \
1186 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
1187 /* but only m+1 bytes of src if terminator was found */ \
1188 if (is_overlap(dst_str, src_orig, n, (m < n) ? m+1 : n)) \
1189 RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \
1190 dst_str = dst; \
1191 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
1193 return dst_str; \
1196 #if defined(VGO_linux)
1197 STPNCPY(VG_Z_LIBC_SONAME, stpncpy)
1198 #endif
1201 /*---------------------- memset ----------------------*/
1203 /* Why are we bothering to intercept this? It seems entirely
1204 pointless. */
1206 #define MEMSET(soname, fnname) \
1207 void* VG_REPLACE_FUNCTION_EZZ(20210,soname,fnname) \
1208 (void *s, Int c, SizeT n); \
1209 void* VG_REPLACE_FUNCTION_EZZ(20210,soname,fnname) \
1210 (void *s, Int c, SizeT n) \
1212 if (sizeof(void*) == 8) { \
1213 Addr a = (Addr)s; \
1214 ULong c8 = (c & 0xFF); \
1215 c8 = (c8 << 8) | c8; \
1216 c8 = (c8 << 16) | c8; \
1217 c8 = (c8 << 32) | c8; \
1218 while ((a & 7) != 0 && n >= 1) \
1219 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1220 while (n >= 32) \
1221 { *(ULong*)a = c8; a += 8; n -= 8; \
1222 *(ULong*)a = c8; a += 8; n -= 8; \
1223 *(ULong*)a = c8; a += 8; n -= 8; \
1224 *(ULong*)a = c8; a += 8; n -= 8; } \
1225 while (n >= 8) \
1226 { *(ULong*)a = c8; a += 8; n -= 8; } \
1227 while (n >= 1) \
1228 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1229 return s; \
1230 } else { \
1231 Addr a = (Addr)s; \
1232 UInt c4 = (c & 0xFF); \
1233 c4 = (c4 << 8) | c4; \
1234 c4 = (c4 << 16) | c4; \
1235 while ((a & 3) != 0 && n >= 1) \
1236 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1237 while (n >= 16) \
1238 { *(UInt*)a = c4; a += 4; n -= 4; \
1239 *(UInt*)a = c4; a += 4; n -= 4; \
1240 *(UInt*)a = c4; a += 4; n -= 4; \
1241 *(UInt*)a = c4; a += 4; n -= 4; } \
1242 while (n >= 4) \
1243 { *(UInt*)a = c4; a += 4; n -= 4; } \
1244 while (n >= 1) \
1245 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1246 return s; \
1250 #if defined(VGO_linux)
1251 MEMSET(VG_Z_LIBC_SONAME, memset)
1253 #elif defined(VGO_darwin)
1254 //MEMSET(VG_Z_LIBC_SONAME, memset)
1255 //MEMSET(VG_Z_DYLD, memset)
1256 MEMSET(VG_Z_LIBC_SONAME, memset)
1258 #elif defined(VGO_solaris)
1259 MEMSET(VG_Z_LIBC_SONAME, memset)
1260 MEMSET(VG_Z_LIBC_SONAME, memsetZPZa)
1262 #endif
1265 /*---------------------- memmove ----------------------*/
1267 /* memmove -- use the MEMMOVE defn above. */
1269 #if defined(VGO_linux)
1270 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1271 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove)
1272 /* See bug #349828 Override for ld64.so.1 like memcpy, because for some
1273 arches MEMCPY_OK_FOR_FORWARD_MEMMOVE is set, which might cause memmove
1274 to call memcpy. */
1275 MEMMOVE(VG_Z_LD64_SO_1, memmove)
1277 #elif defined(VGO_darwin)
1278 # if DARWIN_VERS <= DARWIN_10_6
1279 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1280 # endif
1281 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
1282 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
1283 # if DARWIN_VERS >= DARWIN_10_9
1284 /* _platform_memmove$VARIANT$Ivybridge */
1285 MEMMOVE(libsystemZuplatformZddylib, ZuplatformZumemmoveZDVARIANTZDIvybridge)
1286 # endif
1288 #elif defined(VGO_solaris)
1289 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1290 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZPZa)
1291 MEMMOVE(VG_Z_LD_SO_1, memmove)
1293 #endif
1296 /*---------------------- bcopy ----------------------*/
1298 #define BCOPY(soname, fnname) \
1299 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1300 (const void *srcV, void *dstV, SizeT n); \
1301 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1302 (const void *srcV, void *dstV, SizeT n) \
1304 SizeT i; \
1305 HChar* dst = dstV; \
1306 const HChar* src = srcV; \
1307 if (dst < src) { \
1308 for (i = 0; i < n; i++) \
1309 dst[i] = src[i]; \
1311 else \
1312 if (dst > src) { \
1313 for (i = 0; i < n; i++) \
1314 dst[n-i-1] = src[n-i-1]; \
1318 #if defined(VGO_linux)
1319 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1321 #elif defined(VGO_darwin)
1322 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1323 //BCOPY(VG_Z_DYLD, bcopy)
1325 #elif defined(VGO_darwin)
1326 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1328 #endif
1331 /*-------------------- memmove_chk --------------------*/
1333 /* glibc 2.5 variant of memmove which checks the dest is big enough.
1334 There is no specific part of glibc that this is copied from. */
1335 #define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1336 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1337 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1338 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1339 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1341 SizeT i; \
1342 HChar* dst = dstV; \
1343 const HChar* src = srcV; \
1344 if (destlen < n) \
1345 goto badness; \
1346 if (dst < src) { \
1347 for (i = 0; i < n; i++) \
1348 dst[i] = src[i]; \
1350 else \
1351 if (dst > src) { \
1352 for (i = 0; i < n; i++) \
1353 dst[n-i-1] = src[n-i-1]; \
1355 return dst; \
1356 badness: \
1357 VALGRIND_PRINTF_BACKTRACE( \
1358 "*** memmove_chk: buffer overflow detected ***: " \
1359 "program terminated\n"); \
1360 my_exit(1); \
1361 /*NOTREACHED*/ \
1362 return NULL; \
1365 #if defined(VGO_linux)
1366 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
1368 #elif defined(VGO_darwin)
1370 #elif defined(VGO_solaris)
1372 #endif
1375 /*-------------------- strchrnul --------------------*/
1377 /* Find the first occurrence of C in S or the final NUL byte. */
1378 #define GLIBC232_STRCHRNUL(soname, fnname) \
1379 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1380 (const char* s, int c_in); \
1381 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1382 (const char* s, int c_in) \
1384 HChar c = (HChar) c_in; \
1385 const HChar* char_ptr = s; \
1386 while (1) { \
1387 if (*char_ptr == 0) return CONST_CAST(HChar *,char_ptr); \
1388 if (*char_ptr == c) return CONST_CAST(HChar *,char_ptr); \
1389 char_ptr++; \
1393 #if defined(VGO_linux)
1394 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1396 #elif defined(VGO_darwin)
1398 #elif defined(VGO_solaris)
1400 #endif
1403 /*---------------------- rawmemchr ----------------------*/
1405 /* Find the first occurrence of C in S. */
1406 #define GLIBC232_RAWMEMCHR(soname, fnname) \
1407 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1408 (const void* s, int c_in); \
1409 void* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1410 (const void* s, int c_in) \
1412 UChar c = (UChar) c_in; \
1413 const UChar* char_ptr = s; \
1414 while (1) { \
1415 if (*char_ptr == c) return CONST_CAST(void *,char_ptr); \
1416 char_ptr++; \
1420 #if defined (VGO_linux)
1421 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1422 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1424 #elif defined(VGO_darwin)
1426 #elif defined(VGO_solaris)
1428 #endif
1431 /*---------------------- strcpy_chk ----------------------*/
1433 /* glibc variant of strcpy that checks the dest is big enough.
1434 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1435 #define GLIBC25___STRCPY_CHK(soname,fnname) \
1436 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1437 (char* dst, const char* src, SizeT len); \
1438 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1439 (char* dst, const char* src, SizeT len) \
1441 HChar* ret = dst; \
1442 if (! len) \
1443 goto badness; \
1444 while ((*dst++ = *src++) != '\0') \
1445 if (--len == 0) \
1446 goto badness; \
1447 return ret; \
1448 badness: \
1449 VALGRIND_PRINTF_BACKTRACE( \
1450 "*** strcpy_chk: buffer overflow detected ***: " \
1451 "program terminated\n"); \
1452 my_exit(1); \
1453 /*NOTREACHED*/ \
1454 return NULL; \
1457 #if defined(VGO_linux)
1458 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1460 #elif defined(VGO_darwin)
1462 #elif defined(VGO_solaris)
1464 #endif
1467 /*---------------------- stpcpy_chk ----------------------*/
1469 /* glibc variant of stpcpy that checks the dest is big enough.
1470 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1471 #define GLIBC25___STPCPY_CHK(soname,fnname) \
1472 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1473 (char* dst, const char* src, SizeT len); \
1474 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1475 (char* dst, const char* src, SizeT len) \
1477 if (! len) \
1478 goto badness; \
1479 while ((*dst++ = *src++) != '\0') \
1480 if (--len == 0) \
1481 goto badness; \
1482 return dst - 1; \
1483 badness: \
1484 VALGRIND_PRINTF_BACKTRACE( \
1485 "*** stpcpy_chk: buffer overflow detected ***: " \
1486 "program terminated\n"); \
1487 my_exit(1); \
1488 /*NOTREACHED*/ \
1489 return NULL; \
1492 #if defined(VGO_linux)
1493 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1495 #elif defined(VGO_darwin)
1497 #elif defined(VGO_solaris)
1499 #endif
1502 /*---------------------- mempcpy ----------------------*/
1504 /* mempcpy */
1505 #define GLIBC25_MEMPCPY(soname, fnname) \
1506 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1507 ( void *dst, const void *src, SizeT len ); \
1508 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1509 ( void *dst, const void *src, SizeT len ) \
1511 SizeT len_saved = len; \
1513 if (len == 0) \
1514 return dst; \
1516 if (is_overlap(dst, src, len, len)) \
1517 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1519 if ( dst > src ) { \
1520 register HChar *d = (char *)dst + len - 1; \
1521 register const HChar *s = (const char *)src + len - 1; \
1522 while ( len-- ) { \
1523 *d-- = *s--; \
1525 } else if ( dst < src ) { \
1526 register HChar *d = dst; \
1527 register const HChar *s = src; \
1528 while ( len-- ) { \
1529 *d++ = *s++; \
1532 return (void*)( ((char*)dst) + len_saved ); \
1535 #if defined(VGO_linux)
1536 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1537 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, __GI_mempcpy)
1538 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
1539 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */
1540 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */
1542 #elif defined(VGO_darwin)
1543 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1545 #elif defined(VGO_solaris)
1547 #endif
1550 /*-------------------- memcpy_chk --------------------*/
1552 #define GLIBC26___MEMCPY_CHK(soname, fnname) \
1553 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1554 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1555 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1556 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1558 register HChar *d; \
1559 register const HChar *s; \
1561 if (dstlen < len) goto badness; \
1563 if (len == 0) \
1564 return dst; \
1566 if (is_overlap(dst, src, len, len)) \
1567 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1569 if ( dst > src ) { \
1570 d = (HChar *)dst + len - 1; \
1571 s = (const HChar *)src + len - 1; \
1572 while ( len-- ) { \
1573 *d-- = *s--; \
1575 } else if ( dst < src ) { \
1576 d = (HChar *)dst; \
1577 s = (const HChar *)src; \
1578 while ( len-- ) { \
1579 *d++ = *s++; \
1582 return dst; \
1583 badness: \
1584 VALGRIND_PRINTF_BACKTRACE( \
1585 "*** memcpy_chk: buffer overflow detected ***: " \
1586 "program terminated\n"); \
1587 my_exit(1); \
1588 /*NOTREACHED*/ \
1589 return NULL; \
1592 #if defined(VGO_linux)
1593 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1595 #elif defined(VGO_darwin)
1597 #elif defined(VGO_solaris)
1599 #endif
1602 /*---------------------- strstr ----------------------*/
1604 #define STRSTR(soname, fnname) \
1605 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1606 (const char* haystack, const char* needle); \
1607 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1608 (const char* haystack, const char* needle) \
1610 const HChar* h = haystack; \
1611 const HChar* n = needle; \
1613 /* find the length of n, not including terminating zero */ \
1614 UWord nlen = 0; \
1615 while (n[nlen]) nlen++; \
1617 /* if n is the empty string, match immediately. */ \
1618 if (nlen == 0) return CONST_CAST(HChar *,h); \
1620 /* assert(nlen >= 1); */ \
1621 HChar n0 = n[0]; \
1623 while (1) { \
1624 const HChar hh = *h; \
1625 if (hh == 0) return NULL; \
1626 if (hh != n0) { h++; continue; } \
1628 UWord i; \
1629 for (i = 0; i < nlen; i++) { \
1630 if (n[i] != h[i]) \
1631 break; \
1633 /* assert(i >= 0 && i <= nlen); */ \
1634 if (i == nlen) \
1635 return CONST_CAST(HChar *,h); \
1637 h++; \
1641 #if defined(VGO_linux)
1642 STRSTR(VG_Z_LIBC_SONAME, strstr)
1643 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse2)
1644 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse42)
1646 #elif defined(VGO_darwin)
1648 #elif defined(VGO_solaris)
1649 STRSTR(VG_Z_LIBC_SONAME, strstr)
1651 #endif
1654 /*---------------------- strpbrk ----------------------*/
1656 #define STRPBRK(soname, fnname) \
1657 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1658 (const char* sV, const char* acceptV); \
1659 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1660 (const char* sV, const char* acceptV) \
1662 const HChar* s = sV; \
1663 const HChar* accept = acceptV; \
1665 /* find the length of 'accept', not including terminating zero */ \
1666 UWord nacc = 0; \
1667 while (accept[nacc]) nacc++; \
1669 /* if n is the empty string, fail immediately. */ \
1670 if (nacc == 0) return NULL; \
1672 /* assert(nacc >= 1); */ \
1673 while (1) { \
1674 UWord i; \
1675 HChar sc = *s; \
1676 if (sc == 0) \
1677 break; \
1678 for (i = 0; i < nacc; i++) { \
1679 if (sc == accept[i]) \
1680 return CONST_CAST(HChar *,s); \
1682 s++; \
1685 return NULL; \
1688 #if defined(VGO_linux)
1689 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1691 #elif defined(VGO_darwin)
1693 #elif defined(VGO_solaris)
1694 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1696 #endif
1699 /*---------------------- strcspn ----------------------*/
1701 #define STRCSPN(soname, fnname) \
1702 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1703 (const char* sV, const char* rejectV); \
1704 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1705 (const char* sV, const char* rejectV) \
1707 const HChar* s = sV; \
1708 const HChar* reject = rejectV; \
1710 /* find the length of 'reject', not including terminating zero */ \
1711 UWord nrej = 0; \
1712 while (reject[nrej]) nrej++; \
1714 UWord len = 0; \
1715 while (1) { \
1716 UWord i; \
1717 HChar sc = *s; \
1718 if (sc == 0) \
1719 break; \
1720 for (i = 0; i < nrej; i++) { \
1721 if (sc == reject[i]) \
1722 break; \
1724 /* assert(i >= 0 && i <= nrej); */ \
1725 if (i < nrej) \
1726 break; \
1727 s++; \
1728 len++; \
1731 return len; \
1734 #if defined(VGO_linux)
1735 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1736 STRCSPN(VG_Z_LIBC_SONAME, __GI_strcspn)
1738 #elif defined(VGO_darwin)
1740 #elif defined(VGO_solaris)
1741 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1743 #endif
1746 /*---------------------- strspn ----------------------*/
1748 #define STRSPN(soname, fnname) \
1749 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1750 (const char* sV, const char* acceptV); \
1751 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1752 (const char* sV, const char* acceptV) \
1754 const UChar* s = (const UChar *)sV; \
1755 const UChar* accept = (const UChar *)acceptV; \
1757 /* find the length of 'accept', not including terminating zero */ \
1758 UWord nacc = 0; \
1759 while (accept[nacc]) nacc++; \
1760 if (nacc == 0) return 0; \
1762 UWord len = 0; \
1763 while (1) { \
1764 UWord i; \
1765 UChar sc = *s; \
1766 if (sc == 0) \
1767 break; \
1768 for (i = 0; i < nacc; i++) { \
1769 if (sc == accept[i]) \
1770 break; \
1772 /* assert(i >= 0 && i <= nacc); */ \
1773 if (i == nacc) \
1774 break; \
1775 s++; \
1776 len++; \
1779 return len; \
1782 #if defined(VGO_linux)
1783 STRSPN(VG_Z_LIBC_SONAME, strspn)
1785 #elif defined(VGO_darwin)
1787 #elif defined(VGO_solaris)
1788 STRSPN(VG_Z_LIBC_SONAME, strspn)
1790 #endif
1793 /*---------------------- strcasestr ----------------------*/
1795 #define STRCASESTR(soname, fnname) \
1796 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1797 (const char* haystack, const char* needle); \
1798 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1799 (const char* haystack, const char* needle) \
1801 extern int tolower(int); \
1802 const HChar* h = haystack; \
1803 const HChar* n = needle; \
1805 /* find the length of n, not including terminating zero */ \
1806 UWord nlen = 0; \
1807 while (n[nlen]) nlen++; \
1809 /* if n is the empty string, match immediately. */ \
1810 if (nlen == 0) return CONST_CAST(HChar *,h); \
1812 /* assert(nlen >= 1); */ \
1813 UChar n0 = tolower(n[0]); \
1815 while (1) { \
1816 UChar hh = tolower(*h); \
1817 if (hh == 0) return NULL; \
1818 if (hh != n0) { h++; continue; } \
1820 UWord i; \
1821 for (i = 0; i < nlen; i++) { \
1822 if (tolower(n[i]) != tolower(h[i])) \
1823 break; \
1825 /* assert(i >= 0 && i <= nlen); */ \
1826 if (i == nlen) \
1827 return CONST_CAST(HChar *,h); \
1829 h++; \
1833 #if defined(VGO_linux)
1834 # if !defined(VGPV_arm_linux_android) \
1835 && !defined(VGPV_x86_linux_android) \
1836 && !defined(VGPV_mips32_linux_android) \
1837 && !defined(VGPV_arm64_linux_android)
1838 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1839 # endif
1841 #elif defined(VGO_darwin)
1843 #elif defined(VGO_solaris)
1844 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1846 #endif
1849 /*---------------------- wcslen ----------------------*/
1851 // This is a wchar_t equivalent to strlen. Unfortunately
1852 // we don't have wchar_t available here, but it looks like
1853 // a 32 bit int on Linux. I don't know if that is also
1854 // valid on MacOSX.
1856 #define WCSLEN(soname, fnname) \
1857 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1858 ( const Int* str ); \
1859 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1860 ( const Int* str ) \
1862 SizeT i = 0; \
1863 while (str[i] != 0) i++; \
1864 return i; \
1867 #if defined(VGO_linux)
1868 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
1870 #elif defined(VGO_darwin)
1872 #elif defined(VGO_solaris)
1873 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
1875 #endif
1877 /*---------------------- wcsnlen ----------------------*/
1879 #define WCSNLEN(soname, fnname) \
1880 SizeT VG_REPLACE_FUNCTION_EZU(20440,soname,fnname) \
1881 ( const Int *s, SizeT n ); \
1882 SizeT VG_REPLACE_FUNCTION_EZU(20440,soname,fnname) \
1883 ( const Int *s, SizeT n ) \
1885 SizeT i = 0; \
1886 const Int* p = s; \
1887 while (i < n && *p != 0) { \
1888 i++; \
1889 p++; \
1891 return i; \
1894 #if defined(VGO_linux)
1895 WCSNLEN(VG_Z_LIBC_SONAME, wcsnlen)
1896 WCSNLEN(VG_Z_LIBC_SONAME, __GI_wcsnlen)
1897 #endif
1899 /*---------------------- wcscmp ----------------------*/
1901 // This is a wchar_t equivalent to strcmp. We don't
1902 // have wchar_t available here, but in the GNU C Library
1903 // wchar_t is always 32 bits wide and wcscmp uses signed
1904 // comparison, not unsigned as in strcmp function.
1906 #define WCSCMP(soname, fnname) \
1907 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1908 ( const Int* s1, const Int* s2 ); \
1909 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1910 ( const Int* s1, const Int* s2 ) \
1912 register Int c1; \
1913 register Int c2; \
1914 while (True) { \
1915 c1 = *s1; \
1916 c2 = *s2; \
1917 if (c1 != c2) break; \
1918 if (c1 == 0) break; \
1919 s1++; s2++; \
1921 if (c1 < c2) return -1; \
1922 if (c1 > c2) return 1; \
1923 return 0; \
1926 #if defined(VGO_linux)
1927 WCSCMP(VG_Z_LIBC_SONAME, wcscmp)
1928 #endif
1930 /*---------------------- wcscpy ----------------------*/
1932 // This is a wchar_t equivalent to strcpy. We don't
1933 // have wchar_t available here, but in the GNU C Library
1934 // wchar_t is always 32 bits wide.
1936 #define WCSCPY(soname, fnname) \
1937 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1938 ( Int* dst, const Int* src ); \
1939 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1940 ( Int* dst, const Int* src ) \
1942 const Int* src_orig = src; \
1943 Int* dst_orig = dst; \
1945 while (*src) *dst++ = *src++; \
1946 *dst = 0; \
1948 /* This checks for overlap after copying, unavoidable without */ \
1949 /* pre-counting length... should be ok */ \
1950 if (is_overlap(dst_orig, \
1951 src_orig, \
1952 (Addr)dst-(Addr)dst_orig+1, \
1953 (Addr)src-(Addr)src_orig+1)) \
1954 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
1956 return dst_orig; \
1959 #if defined(VGO_linux)
1960 WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
1961 #endif
1964 /*---------------------- wcschr ----------------------*/
1966 // This is a wchar_t equivalent to strchr. We don't
1967 // have wchar_t available here, but in the GNU C Library
1968 // wchar_t is always 32 bits wide.
1970 #define WCSCHR(soname, fnname) \
1971 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
1972 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
1974 const Int* p = s; \
1975 while (True) { \
1976 if (*p == c) return CONST_CAST(Int *,p); \
1977 if (*p == 0) return NULL; \
1978 p++; \
1982 #if defined(VGO_linux)
1983 WCSCHR(VG_Z_LIBC_SONAME, wcschr)
1984 #endif
1985 /*---------------------- wcsrchr ----------------------*/
1987 // This is a wchar_t equivalent to strrchr. We don't
1988 // have wchar_t available here, but in the GNU C Library
1989 // wchar_t is always 32 bits wide.
1991 #define WCSRCHR(soname, fnname) \
1992 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
1993 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
1995 const Int* p = s; \
1996 const Int* last = NULL; \
1997 while (True) { \
1998 if (*p == c) last = p; \
1999 if (*p == 0) return CONST_CAST(Int *,last); \
2000 p++; \
2004 #if defined(VGO_linux)
2005 WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
2006 #endif
2008 /*---------------------- wmemchr ----------------------*/
2010 // This is a wchar_t equivalent to memchr. We don't
2011 // have wchar_t available here, but in the GNU C Library
2012 // wchar_t is always 32 bits wide.
2014 #define WMEMCHR(soname, fnname) \
2015 Int* VG_REPLACE_FUNCTION_EZU(20430,soname,fnname) \
2016 (const Int *s, Int c, SizeT n); \
2017 Int* VG_REPLACE_FUNCTION_EZU(20430,soname,fnname) \
2018 (const Int *s, Int c, SizeT n) \
2020 SizeT i; \
2021 const Int* p = s; \
2022 for (i = 0; i < n; i++) { \
2023 if (*p == c) return CONST_CAST(Int *,p); \
2024 p++; \
2026 return NULL; \
2029 #if defined(VGO_linux)
2030 WMEMCHR(VG_Z_LIBC_SONAME, wmemchr)
2031 WMEMCHR(VG_Z_LIBC_SONAME, __GI_wmemchr)
2032 #endif
2034 /*------------------------------------------------------------*/
2035 /*--- Improve definedness checking of process environment ---*/
2036 /*------------------------------------------------------------*/
2038 #if defined(VGO_linux)
2040 /* If these wind up getting generated via a macro, so that multiple
2041 versions of each function exist (as above), use the _EZU variants
2042 to assign equivalance class tags. */
2044 /*---------------------- putenv ----------------------*/
2046 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
2047 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
2049 OrigFn fn;
2050 Word result;
2051 const HChar* p = string;
2052 VALGRIND_GET_ORIG_FN(fn);
2053 /* Now by walking over the string we magically produce
2054 traces when hitting undefined memory. */
2055 if (p)
2056 while (*p++)
2057 __asm__ __volatile__("" ::: "memory");
2058 CALL_FN_W_W(result, fn, string);
2059 return result;
2063 /*---------------------- unsetenv ----------------------*/
2065 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
2066 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
2068 OrigFn fn;
2069 Word result;
2070 const HChar* p = name;
2071 VALGRIND_GET_ORIG_FN(fn);
2072 /* Now by walking over the string we magically produce
2073 traces when hitting undefined memory. */
2074 if (p)
2075 while (*p++)
2076 __asm__ __volatile__("" ::: "memory");
2077 CALL_FN_W_W(result, fn, name);
2078 return result;
2082 /*---------------------- setenv ----------------------*/
2084 /* setenv */
2085 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
2086 (const char* name, const char* value, int overwrite);
2087 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
2088 (const char* name, const char* value, int overwrite)
2090 OrigFn fn;
2091 Word result;
2092 const HChar* p;
2093 VALGRIND_GET_ORIG_FN(fn);
2094 /* Now by walking over the string we magically produce
2095 traces when hitting undefined memory. */
2096 if (name)
2097 for (p = name; *p; p++)
2098 __asm__ __volatile__("" ::: "memory");
2099 if (value)
2100 for (p = value; *p; p++)
2101 __asm__ __volatile__("" ::: "memory");
2102 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
2103 CALL_FN_W_WWW(result, fn, name, value, overwrite);
2104 return result;
2107 #endif /* defined(VGO_linux) */
2109 /*--------------------------------------------------------------------*/
2110 /*--- end ---*/
2111 /*--------------------------------------------------------------------*/