2 /*--------------------------------------------------------------------*/
3 /*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/
4 /*--- simulated CPU. ---*/
5 /*--- vg_replace_strmem.c ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of Valgrind.
11 Copyright (C) 2000-2017 Julian Seward
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
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
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
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:
77 20180 MEMCPY if there's a conflict between memcpy and
78 20181 MEMMOVE memmove, prefer memmove
83 2022P unused (was previously MEMMOVE)
85 20240 GLIBC25___MEMMOVE_CHK
86 20250 GLIBC232_STRCHRNUL
87 20260 GLIBC232_RAWMEMCHR
88 20270 GLIBC25___STRCPY_CHK
89 20280 GLIBC25___STPCPY_CHK
91 20300 GLIBC26___MEMCPY_CHK
108 #if defined(VGO_solaris)
110 Detour functions in the libc and the runtime linker. If a function isn't
111 much optimized (and no overlap checking is necessary) then redir the
112 function only in the libc. This way we can keep stacktraces in the tests
118 /* Figure out if [dst .. dst+dstlen-1] overlaps with
119 [src .. src+srclen-1].
120 We assume that the address ranges do not wrap around
121 (which is safe since on Linux addresses >= 0xC0000000
122 are not accessible and the program will segfault in this
123 circumstance, presumably).
126 Bool
is_overlap ( void* dst
, const void* src
, SizeT dstlen
, SizeT srclen
)
128 Addr loS
, hiS
, loD
, hiD
;
130 if (dstlen
== 0 || srclen
== 0)
135 hiS
= loS
+ srclen
- 1;
136 hiD
= loD
+ dstlen
- 1;
138 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
142 else if (loD
< loS
) {
146 /* They start at same place. Since we know neither of them has
147 zero length, they must overlap. */
153 /* Call here to exit if we can't continue. On Android we can't call
154 _exit for some reason, so we have to blunt-instrument it. */
155 __attribute__ ((__noreturn__
))
156 static inline void my_exit ( int x
)
158 # if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \
159 || defined(VGPV_arm64_linux_android)
160 __asm__
__volatile__(".word 0xFFFFFFFF");
162 # elif defined(VGPV_x86_linux_android)
163 __asm__
__volatile__("ud2");
166 extern __attribute__ ((__noreturn__
)) void _exit(int status
);
172 // This is a macro rather than a function because we don't want to have an
173 // extra function in the stack trace.
174 #ifndef RECORD_OVERLAP_ERROR
175 #define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0)
177 #ifndef VALGRIND_CHECK_VALUE_IS_DEFINED
178 #define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1
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; \
192 if (*p == ch) last = p; \
193 if (*p == 0) return CONST_CAST(HChar *,last); \
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 */
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
)
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
)
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; \
239 if (*p == ch) return CONST_CAST(HChar *,p); \
240 if (*p == 0) return NULL; \
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
)
259 #if defined(VGPV_mips32_linux_android)
260 STRCHR(NONE
, __dl_strchr
)
263 #elif defined(VGO_darwin)
264 STRCHR(VG_Z_LIBC_SONAME
, strchr
)
265 # if DARWIN_VERS == DARWIN_10_9
266 STRCHR(libsystemZuplatformZddylib
, _platform_strchr
)
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
)
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
)
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++; \
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, \
301 (Addr)dst-(Addr)dst_orig+1, \
302 (Addr)src-(Addr)src_orig+1)) \
303 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
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
)
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; \
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, \
342 (Addr)dst-(Addr)dst_orig+1, \
343 (Addr)src-(Addr)src_orig+1)) \
344 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
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
)
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; \
379 while (m < n && *dst) { m++; dst++; } \
381 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
382 while (m+1 < n && *src) { m++; *dst++ = *src++; } \
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, \
393 (Addr)dst-(Addr)dst_orig+1, \
394 (Addr)src-(Addr)src_orig+1)) \
395 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
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
)
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 ) \
422 while (i < n && str[i] != 0) 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
)
435 #elif defined(VGO_solaris)
436 STRNLEN(VG_Z_LIBC_SONAME
, strnlen
)
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 ) \
455 while (str[i] != 0) 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 */
473 #elif defined(VGO_darwin)
474 STRLEN(VG_Z_LIBC_SONAME
, strlen
)
475 # if DARWIN_VERS >= DARWIN_10_9
476 STRLEN(libsystemZucZddylib
, strlen
)
479 #elif defined(VGO_solaris)
480 STRLEN(VG_Z_LIBC_SONAME
, strlen
)
481 STRLEN(VG_Z_LD_SO_1
, strlen
)
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++; \
500 /* This checks for overlap after copying, unavoidable without */ \
501 /* pre-counting length... should be ok */ \
502 if (is_overlap(dst_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); \
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
)
521 #elif defined(VGO_solaris)
522 STRCPY(VG_Z_LIBC_SONAME
, strcpy
)
523 STRCPY(VG_Z_LD_SO_1
, strcpy
)
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; \
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 */ \
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
)
562 #elif defined(VGO_solaris)
563 STRNCPY(VG_Z_LIBC_SONAME
, strncpy
)
564 STRNCPY(VG_Z_LD_SO_1
, strncpy
)
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; \
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
);
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 \
616 while (*src) src++; \
617 return src - src_orig; \
620 STRLCPY(VG_Z_LIBC_SONAME
, strlcpy
)
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 ) \
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; \
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
)
659 #elif defined(VGO_solaris)
660 STRNCMP(VG_Z_LIBC_SONAME
, strncmp
)
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); \
677 c1 = tolower(*(const UChar *)s1); \
678 c2 = tolower(*(const UChar *)s2); \
679 if (c1 != c2) break; \
680 if (c1 == 0) break; \
683 if ((UChar)c1 < (UChar)c2) return -1; \
684 if ((UChar)c1 > (UChar)c2) return 1; \
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
)
697 #elif defined(VGO_darwin)
698 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
700 #elif defined(VGO_solaris)
701 STRCASECMP(VG_Z_LIBC_SONAME
, strcasecmp
)
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); \
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; \
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
)
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
)
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)); \
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; \
768 if ((UChar)c1 < (UChar)c2) return -1; \
769 if ((UChar)c1 > (UChar)c2) return 1; \
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)
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)); \
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; \
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)
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 ) \
836 c1 = *(const UChar *)s1; \
837 c2 = *(const UChar *)s2; \
838 if (c1 != c2) break; \
839 if (c1 == 0) break; \
842 if ((UChar)c1 < (UChar)c2) return -1; \
843 if ((UChar)c1 > (UChar)c2) return 1; \
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 */
859 #elif defined(VGO_darwin)
860 STRCMP(VG_Z_LIBC_SONAME
, strcmp
)
861 # if DARWIN_VERS >= DARWIN_10_9
862 STRCMP(libsystemZuplatformZddylib
, _platform_strcmp
)
865 #elif defined(VGO_solaris)
866 STRCMP(VG_Z_LIBC_SONAME
, strcmp
)
867 STRCMP(VG_Z_LD_SO_1
, strcmp
)
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) \
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]); \
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
)
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
)
905 #elif defined(VGO_solaris)
906 MEMCHR(VG_Z_LIBC_SONAME
, memchr
)
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) \
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]); \
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)
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 */ \
954 if (dst < src || !is_overlap(dst, src, len, len)) { \
956 /* Copying backwards. */ \
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; } \
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; } \
973 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
977 if (((s|d) & 1) == 0) { \
978 /* Both are 16-aligned; copy what we can thusly. */ \
980 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
982 /* Copy leftovers, or everything if misaligned. */ \
984 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
986 } else if (dst > src) { \
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; } \
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; } \
1005 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
1009 if (((s|d) & 1) == 0) { \
1010 /* Both are 16-aligned; copy what we can thusly. */ \
1012 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
1014 /* Copy leftovers, or everything if misaligned. */ \
1016 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
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
)
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
)
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. */ \
1082 UWord w1 = *(UWord*)s1A; \
1083 UWord w2 = *(UWord*)s2A; \
1084 if (w1 != w2) break; \
1091 const UChar* s1 = (const UChar*) s1A; \
1092 const UChar* s2 = (const UChar*) s2A; \
1099 int res = ((int)a0) - ((int)b0); \
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
)
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
)
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++; \
1144 /* This checks for overlap after copying, unavoidable without */ \
1145 /* pre-counting length... should be ok */ \
1146 if (is_overlap(dst_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); \
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
)
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; \
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); \
1191 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
1196 #if defined(VGO_linux)
1197 STPNCPY(VG_Z_LIBC_SONAME
, stpncpy
)
1201 /*---------------------- memset ----------------------*/
1203 /* Why are we bothering to intercept this? It seems entirely
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) { \
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; } \
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; } \
1226 { *(ULong*)a = c8; a += 8; n -= 8; } \
1228 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
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; } \
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; } \
1243 { *(UInt*)a = c4; a += 4; n -= 4; } \
1245 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
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
)
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
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
)
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
)
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
)
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) \
1305 HChar* dst = dstV; \
1306 const HChar* src = srcV; \
1308 for (i = 0; i < n; i++) \
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
)
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) \
1342 HChar* dst = dstV; \
1343 const HChar* src = srcV; \
1347 for (i = 0; i < n; i++) \
1352 for (i = 0; i < n; i++) \
1353 dst[n-i-1] = src[n-i-1]; \
1357 VALGRIND_PRINTF_BACKTRACE( \
1358 "*** memmove_chk: buffer overflow detected ***: " \
1359 "program terminated\n"); \
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)
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; \
1387 if (*char_ptr == 0) return CONST_CAST(HChar *,char_ptr); \
1388 if (*char_ptr == c) return CONST_CAST(HChar *,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)
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; \
1415 if (*char_ptr == c) return CONST_CAST(void *,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)
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) \
1444 while ((*dst++ = *src++) != '\0') \
1449 VALGRIND_PRINTF_BACKTRACE( \
1450 "*** strcpy_chk: buffer overflow detected ***: " \
1451 "program terminated\n"); \
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)
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) \
1479 while ((*dst++ = *src++) != '\0') \
1484 VALGRIND_PRINTF_BACKTRACE( \
1485 "*** stpcpy_chk: buffer overflow detected ***: " \
1486 "program terminated\n"); \
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)
1502 /*---------------------- 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; \
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; \
1525 } else if ( dst < src ) { \
1526 register HChar *d = dst; \
1527 register const HChar *s = src; \
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)
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; \
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; \
1575 } else if ( dst < src ) { \
1577 s = (const HChar *)src; \
1584 VALGRIND_PRINTF_BACKTRACE( \
1585 "*** memcpy_chk: buffer overflow detected ***: " \
1586 "program terminated\n"); \
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)
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 */ \
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); */ \
1624 const HChar hh = *h; \
1625 if (hh == 0) return NULL; \
1626 if (hh != n0) { h++; continue; } \
1629 for (i = 0; i < nlen; i++) { \
1633 /* assert(i >= 0 && i <= nlen); */ \
1635 return CONST_CAST(HChar *,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
)
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 */ \
1667 while (accept[nacc]) nacc++; \
1669 /* if n is the empty string, fail immediately. */ \
1670 if (nacc == 0) return NULL; \
1672 /* assert(nacc >= 1); */ \
1678 for (i = 0; i < nacc; i++) { \
1679 if (sc == accept[i]) \
1680 return CONST_CAST(HChar *,s); \
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
)
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 */ \
1712 while (reject[nrej]) nrej++; \
1720 for (i = 0; i < nrej; i++) { \
1721 if (sc == reject[i]) \
1724 /* assert(i >= 0 && i <= nrej); */ \
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
)
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 */ \
1759 while (accept[nacc]) nacc++; \
1760 if (nacc == 0) return 0; \
1768 for (i = 0; i < nacc; i++) { \
1769 if (sc == accept[i]) \
1772 /* assert(i >= 0 && i <= nacc); */ \
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
)
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 */ \
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]); \
1816 UChar hh = tolower(*h); \
1817 if (hh == 0) return NULL; \
1818 if (hh != n0) { h++; continue; } \
1821 for (i = 0; i < nlen; i++) { \
1822 if (tolower(n[i]) != tolower(h[i])) \
1825 /* assert(i >= 0 && i <= nlen); */ \
1827 return CONST_CAST(HChar *,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
)
1841 #elif defined(VGO_darwin)
1843 #elif defined(VGO_solaris)
1844 STRCASESTR(VG_Z_LIBC_SONAME
, strcasestr
)
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
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 ) \
1863 while (str[i] != 0) 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
)
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 ) \
1887 while (i < n && *p != 0) { \
1894 #if defined(VGO_linux)
1895 WCSNLEN(VG_Z_LIBC_SONAME
, wcsnlen
)
1896 WCSNLEN(VG_Z_LIBC_SONAME
, __GI_wcsnlen
)
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 ) \
1917 if (c1 != c2) break; \
1918 if (c1 == 0) break; \
1921 if (c1 < c2) return -1; \
1922 if (c1 > c2) return 1; \
1926 #if defined(VGO_linux)
1927 WCSCMP(VG_Z_LIBC_SONAME
, wcscmp
)
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++; \
1948 /* This checks for overlap after copying, unavoidable without */ \
1949 /* pre-counting length... should be ok */ \
1950 if (is_overlap(dst_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); \
1959 #if defined(VGO_linux)
1960 WCSCPY(VG_Z_LIBC_SONAME
, wcscpy
)
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 ) \
1976 if (*p == c) return CONST_CAST(Int *,p); \
1977 if (*p == 0) return NULL; \
1982 #if defined(VGO_linux)
1983 WCSCHR(VG_Z_LIBC_SONAME
, wcschr
)
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 ) \
1996 const Int* last = NULL; \
1998 if (*p == c) last = p; \
1999 if (*p == 0) return CONST_CAST(Int *,last); \
2004 #if defined(VGO_linux)
2005 WCSRCHR(VG_Z_LIBC_SONAME
, wcsrchr
)
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) \
2022 for (i = 0; i < n; i++) { \
2023 if (*p == c) return CONST_CAST(Int *,p); \
2029 #if defined(VGO_linux)
2030 WMEMCHR(VG_Z_LIBC_SONAME
, wmemchr
)
2031 WMEMCHR(VG_Z_LIBC_SONAME
, __GI_wmemchr
)
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
)
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. */
2057 __asm__
__volatile__("" ::: "memory");
2058 CALL_FN_W_W(result
, fn
, string
);
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
)
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. */
2076 __asm__
__volatile__("" ::: "memory");
2077 CALL_FN_W_W(result
, fn
, name
);
2082 /*---------------------- 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
)
2093 VALGRIND_GET_ORIG_FN(fn
);
2094 /* Now by walking over the string we magically produce
2095 traces when hitting undefined memory. */
2097 for (p
= name
; *p
; p
++)
2098 __asm__
__volatile__("" ::: "memory");
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
);
2107 #endif /* defined(VGO_linux) */
2109 /*--------------------------------------------------------------------*/
2111 /*--------------------------------------------------------------------*/