• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- Replacements for strcpy(), memcpy() et al, which run on the  ---*/
4 /*--- simulated CPU.                                               ---*/
5 /*---                                          mc_replace_strmem.c ---*/
6 /*--------------------------------------------------------------------*/
7 
8 /*
9    This file is part of Valgrind.
10 
11    Copyright (C) 2000-2013 Julian Seward
12       jseward@acm.org
13 
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.
18 
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.
23 
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.
28 
29    The GNU General Public License is contained in the file COPYING.
30 */
31 
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"
38 
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.
48 
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.
52 
53    THEY RUN ON THE SIMD CPU!
54    ------------------------------------------------------------------ */
55 
56 /* Assignment of behavioural equivalence class tags: 2NNNP is intended
57    to be reserved for str/mem intercepts.  Current usage:
58 
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
76 
77    20180 MEMCPY    if there's a conflict between memcpy and
78    20181 MEMMOVE   memmove, prefer memmove
79 
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 */
105 
106 
107 /* Figure out if [dst .. dst+dstlen-1] overlaps with
108                  [src .. src+srclen-1].
109    We assume that the address ranges do not wrap around
110    (which is safe since on Linux addresses >= 0xC0000000
111    are not accessible and the program will segfault in this
112    circumstance, presumably).
113 */
114 static inline
is_overlap(void * dst,const void * src,SizeT dstlen,SizeT srclen)115 Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
116 {
117    Addr loS, hiS, loD, hiD;
118 
119    if (dstlen == 0 || srclen == 0)
120       return False;
121 
122    loS = (Addr)src;
123    loD = (Addr)dst;
124    hiS = loS + srclen - 1;
125    hiD = loD + dstlen - 1;
126 
127    /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
128    if (loS < loD) {
129       return !(hiS < loD);
130    }
131    else if (loD < loS) {
132       return !(hiD < loS);
133    }
134    else {
135       /* They start at same place.  Since we know neither of them has
136          zero length, they must overlap. */
137       return True;
138    }
139 }
140 
141 
142 /* Call here to exit if we can't continue.  On Android we can't call
143    _exit for some reason, so we have to blunt-instrument it. */
144 __attribute__ ((__noreturn__))
my_exit(int x)145 static inline void my_exit ( int x )
146 {
147 #  if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \
148       || defined(VGPV_mips32_linux_android)
149    __asm__ __volatile__(".word 0xFFFFFFFF");
150    while (1) {}
151 #  elif defined(VGPV_x86_linux_android)
152    __asm__ __volatile__("ud2");
153    while (1) {}
154 #  else
155    extern __attribute__ ((__noreturn__)) void _exit(int status);
156    _exit(x);
157 #  endif
158 }
159 
160 
161 // This is a macro rather than a function because we don't want to have an
162 // extra function in the stack trace.
163 #ifndef RECORD_OVERLAP_ERROR
164 #define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0)
165 #endif
166 #ifndef VALGRIND_CHECK_VALUE_IS_DEFINED
167 #define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1
168 #endif
169 
170 
171 /*---------------------- strrchr ----------------------*/
172 
173 #define STRRCHR(soname, fnname) \
174    char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
175    char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
176    { \
177       HChar ch = (HChar)c;   \
178       const HChar* p = s;       \
179       const HChar* last = NULL; \
180       while (True) { \
181          if (*p == ch) last = p; \
182          if (*p == 0) return (HChar *)last;     \
183          p++; \
184       } \
185    }
186 
187 // Apparently rindex() is the same thing as strrchr()
188 #if defined(VGO_linux)
189  STRRCHR(VG_Z_LIBC_SONAME,   strrchr)
190  STRRCHR(VG_Z_LIBC_SONAME,   rindex)
191  STRRCHR(VG_Z_LIBC_SONAME,   __GI_strrchr)
192  STRRCHR(VG_Z_LIBC_SONAME,   __strrchr_sse2)
193  STRRCHR(VG_Z_LIBC_SONAME,   __strrchr_sse2_no_bsf)
194  STRRCHR(VG_Z_LIBC_SONAME,   __strrchr_sse42)
195  STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
196 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
197     || defined(VGPV_mips32_linux_android)
198   STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */
199 #endif
200 
201 #elif defined(VGO_darwin)
202  //STRRCHR(VG_Z_LIBC_SONAME,   strrchr)
203  //STRRCHR(VG_Z_LIBC_SONAME,   rindex)
204  //STRRCHR(VG_Z_DYLD,          strrchr)
205  //STRRCHR(VG_Z_DYLD,          rindex)
206  STRRCHR(VG_Z_LIBC_SONAME, strrchr)
207 
208 #endif
209 
210 
211 /*---------------------- strchr ----------------------*/
212 
213 #define STRCHR(soname, fnname) \
214    char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
215    char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
216    { \
217       HChar  ch = (HChar)c ; \
218       const HChar* p  = s;   \
219       while (True) { \
220          if (*p == ch) return (HChar *)p; \
221          if (*p == 0) return NULL; \
222          p++; \
223       } \
224    }
225 
226 // Apparently index() is the same thing as strchr()
227 #if defined(VGO_linux)
228  STRCHR(VG_Z_LIBC_SONAME,          strchr)
229  STRCHR(VG_Z_LIBC_SONAME,          __GI_strchr)
230  STRCHR(VG_Z_LIBC_SONAME,          __strchr_sse2)
231  STRCHR(VG_Z_LIBC_SONAME,          __strchr_sse2_no_bsf)
232  STRCHR(VG_Z_LIBC_SONAME,          index)
233 # if !defined(VGP_x86_linux)
234   STRCHR(VG_Z_LD_LINUX_SO_2,        strchr)
235   STRCHR(VG_Z_LD_LINUX_SO_2,        index)
236   STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
237   STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
238 # endif
239 
240 #elif defined(VGO_darwin)
241  //STRCHR(VG_Z_LIBC_SONAME,          strchr)
242  //STRCHR(VG_Z_LIBC_SONAME,          index)
243  //STRCHR(VG_Z_DYLD,                 strchr)
244  //STRCHR(VG_Z_DYLD,                 index)
245  STRCHR(VG_Z_LIBC_SONAME, strchr)
246 
247 #endif
248 
249 
250 /*---------------------- strcat ----------------------*/
251 
252 #define STRCAT(soname, fnname) \
253    char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
254             ( char* dst, const char* src ); \
255    char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
256             ( char* dst, const char* src ) \
257    { \
258       const HChar* src_orig = src; \
259             HChar* dst_orig = dst; \
260       while (*dst) dst++; \
261       while (*src) *dst++ = *src++; \
262       *dst = 0; \
263       \
264       /* This is a bit redundant, I think;  any overlap and the strcat will */ \
265       /* go forever... or until a seg fault occurs. */ \
266       if (is_overlap(dst_orig,  \
267                      src_orig,  \
268                      (Addr)dst-(Addr)dst_orig+1,  \
269                      (Addr)src-(Addr)src_orig+1)) \
270          RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
271       \
272       return dst_orig; \
273    }
274 
275 #if defined(VGO_linux)
276  STRCAT(VG_Z_LIBC_SONAME, strcat)
277  STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
278 
279 #elif defined(VGO_darwin)
280  //STRCAT(VG_Z_LIBC_SONAME, strcat)
281 
282 #endif
283 
284 
285 /*---------------------- strncat ----------------------*/
286 
287 #define STRNCAT(soname, fnname) \
288    char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
289             ( char* dst, const char* src, SizeT n ); \
290    char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
291             ( char* dst, const char* src, SizeT n ) \
292    { \
293       const HChar* src_orig = src; \
294             HChar* dst_orig = dst; \
295       SizeT m = 0; \
296       \
297       while (*dst) dst++; \
298       while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
299       *dst = 0;                                       /* always add null   */ \
300       \
301       /* This checks for overlap after copying, unavoidable without */ \
302       /* pre-counting lengths... should be ok */ \
303       if (is_overlap(dst_orig,  \
304                      src_orig,  \
305                      (Addr)dst-(Addr)dst_orig+1, \
306                      (Addr)src-(Addr)src_orig+1)) \
307          RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
308       \
309       return dst_orig; \
310    }
311 
312 #if defined(VGO_linux)
313  STRNCAT(VG_Z_LIBC_SONAME, strncat)
314 
315 #elif defined(VGO_darwin)
316  //STRNCAT(VG_Z_LIBC_SONAME, strncat)
317  //STRNCAT(VG_Z_DYLD,        strncat)
318 
319 #endif
320 
321 
322 /*---------------------- strlcat ----------------------*/
323 
324 /* Append src to dst. n is the size of dst's buffer. dst is guaranteed
325    to be nul-terminated after the copy, unless n <= strlen(dst_orig).
326    Returns min(n, strlen(dst_orig)) + strlen(src_orig).
327    Truncation occurred if retval >= n.
328 */
329 #define STRLCAT(soname, fnname) \
330    SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
331         ( char* dst, const char* src, SizeT n ); \
332    SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
333         ( char* dst, const char* src, SizeT n ) \
334    { \
335       const HChar* src_orig = src; \
336       HChar* dst_orig = dst; \
337       SizeT m = 0; \
338       \
339       while (m < n && *dst) { m++; dst++; } \
340       if (m < n) { \
341          /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
342          while (m < n-1 && *src) { m++; *dst++ = *src++; } \
343          *dst = 0; \
344       } else { \
345          /* No space to copy anything to dst. m == n */ \
346       } \
347       /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
348       while (*src) { m++; src++; } \
349       /* This checks for overlap after copying, unavoidable without */ \
350       /* pre-counting lengths... should be ok */ \
351       if (is_overlap(dst_orig,  \
352                      src_orig,  \
353                      (Addr)dst-(Addr)dst_orig+1,  \
354                      (Addr)src-(Addr)src_orig+1)) \
355          RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
356       \
357       return m; \
358    }
359 
360 #if defined(VGO_linux)
361 
362 #elif defined(VGO_darwin)
363  //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
364  //STRLCAT(VG_Z_DYLD,        strlcat)
365  STRLCAT(VG_Z_LIBC_SONAME, strlcat)
366 
367 #endif
368 
369 
370 /*---------------------- strnlen ----------------------*/
371 
372 #define STRNLEN(soname, fnname) \
373    SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
374             ( const char* str, SizeT n ); \
375    SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
376             ( const char* str, SizeT n ) \
377    { \
378       SizeT i = 0; \
379       while (i < n && str[i] != 0) i++; \
380       return i; \
381    }
382 
383 #if defined(VGO_linux)
384  STRNLEN(VG_Z_LIBC_SONAME, strnlen)
385  STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
386 
387 #elif defined(VGO_darwin)
388  //STRNLEN(VG_Z_LIBC_SONAME, strnlen)
389 
390 #endif
391 
392 
393 /*---------------------- strlen ----------------------*/
394 
395 // Note that this replacement often doesn't get used because gcc inlines
396 // calls to strlen() with its own built-in version.  This can be very
397 // confusing if you aren't expecting it.  Other small functions in
398 // this file may also be inline by gcc.
399 
400 #define STRLEN(soname, fnname) \
401    SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
402       ( const char* str ); \
403    SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
404       ( const char* str )  \
405    { \
406       SizeT i = 0; \
407       while (str[i] != 0) i++; \
408       return i; \
409    }
410 
411 #if defined(VGO_linux)
412  STRLEN(VG_Z_LIBC_SONAME,          strlen)
413  STRLEN(VG_Z_LIBC_SONAME,          __GI_strlen)
414  STRLEN(VG_Z_LIBC_SONAME,          __strlen_sse2)
415  STRLEN(VG_Z_LIBC_SONAME,          __strlen_sse2_no_bsf)
416  STRLEN(VG_Z_LIBC_SONAME,          __strlen_sse42)
417  STRLEN(VG_Z_LD_LINUX_SO_2,        strlen)
418  STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
419 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
420      || defined(VGPV_mips32_linux_android)
421   STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
422 # endif
423 
424 #elif defined(VGO_darwin)
425  //STRLEN(VG_Z_LIBC_SONAME,          strlen)
426  STRLEN(VG_Z_LIBC_SONAME, strlen)
427 
428 #endif
429 
430 
431 /*---------------------- strcpy ----------------------*/
432 
433 #define STRCPY(soname, fnname) \
434    char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
435       ( char* dst, const char* src ); \
436    char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
437       ( char* dst, const char* src ) \
438    { \
439       const HChar* src_orig = src; \
440             HChar* dst_orig = dst; \
441       \
442       while (*src) *dst++ = *src++; \
443       *dst = 0; \
444       \
445       /* This checks for overlap after copying, unavoidable without */ \
446       /* pre-counting length... should be ok */ \
447       if (is_overlap(dst_orig,  \
448                      src_orig,  \
449                      (Addr)dst-(Addr)dst_orig+1, \
450                      (Addr)src-(Addr)src_orig+1)) \
451          RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
452       \
453       return dst_orig; \
454    }
455 
456 #if defined(VGO_linux)
457  STRCPY(VG_Z_LIBC_SONAME, strcpy)
458  STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
459 
460 #elif defined(VGO_darwin)
461  //STRCPY(VG_Z_LIBC_SONAME, strcpy)
462  //STRCPY(VG_Z_DYLD,        strcpy)
463  STRCPY(VG_Z_LIBC_SONAME, strcpy)
464 
465 #endif
466 
467 
468 /*---------------------- strncpy ----------------------*/
469 
470 #define STRNCPY(soname, fnname) \
471    char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
472             ( char* dst, const char* src, SizeT n ); \
473    char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
474             ( char* dst, const char* src, SizeT n ) \
475    { \
476       const HChar* src_orig = src; \
477             HChar* dst_orig = dst; \
478       SizeT m = 0; \
479       \
480       while (m   < n && *src) { m++; *dst++ = *src++; } \
481       /* Check for overlap after copying; all n bytes of dst are relevant, */ \
482       /* but only m+1 bytes of src if terminator was found */ \
483       if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
484          RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
485       while (m++ < n) *dst++ = 0;         /* must pad remainder with nulls */ \
486       \
487       return dst_orig; \
488    }
489 
490 #if defined(VGO_linux)
491  STRNCPY(VG_Z_LIBC_SONAME, strncpy)
492  STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
493  STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2)
494  STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned)
495 
496 #elif defined(VGO_darwin)
497  //STRNCPY(VG_Z_LIBC_SONAME, strncpy)
498  //STRNCPY(VG_Z_DYLD,        strncpy)
499  STRNCPY(VG_Z_LIBC_SONAME, strncpy)
500 
501 #endif
502 
503 
504 /*---------------------- strlcpy ----------------------*/
505 
506 /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
507    Returns strlen(src). Does not zero-fill the remainder of dst. */
508 #define STRLCPY(soname, fnname) \
509    SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
510        ( char* dst, const char* src, SizeT n ); \
511    SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
512        ( char* dst, const char* src, SizeT n ) \
513    { \
514       const HChar* src_orig = src; \
515       HChar* dst_orig = dst; \
516       SizeT m = 0; \
517       \
518       while (m < n-1 && *src) { m++; *dst++ = *src++; } \
519       /* m non-nul bytes have now been copied, and m <= n-1. */ \
520       /* Check for overlap after copying; all n bytes of dst are relevant, */ \
521       /* but only m+1 bytes of src if terminator was found */ \
522       if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
523           RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
524       /* Nul-terminate dst. */ \
525       if (n > 0) *dst = 0; \
526       /* Finish counting strlen(src). */ \
527       while (*src) src++; \
528       return src - src_orig; \
529    }
530 
531 #if defined(VGO_linux)
532 
533 #if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
534     || defined(VGPV_mips32_linux_android)
535  STRLCPY(VG_Z_LIBC_SONAME, strlcpy);
536 #endif
537 
538 #elif defined(VGO_darwin)
539  //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
540  //STRLCPY(VG_Z_DYLD,        strlcpy)
541  STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
542 
543 #endif
544 
545 
546 /*---------------------- strncmp ----------------------*/
547 
548 #define STRNCMP(soname, fnname) \
549    int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
550           ( const char* s1, const char* s2, SizeT nmax ); \
551    int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
552           ( const char* s1, const char* s2, SizeT nmax ) \
553    { \
554       SizeT n = 0; \
555       while (True) { \
556          if (n >= nmax) return 0; \
557          if (*s1 == 0 && *s2 == 0) return 0; \
558          if (*s1 == 0) return -1; \
559          if (*s2 == 0) return 1; \
560          \
561          if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \
562          if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \
563          \
564          s1++; s2++; n++; \
565       } \
566    }
567 
568 #if defined(VGO_linux)
569  STRNCMP(VG_Z_LIBC_SONAME, strncmp)
570  STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
571  STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2)
572  STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42)
573 
574 #elif defined(VGO_darwin)
575  //STRNCMP(VG_Z_LIBC_SONAME, strncmp)
576  //STRNCMP(VG_Z_DYLD,        strncmp)
577  STRNCMP(VG_Z_LIBC_SONAME,        strncmp)
578 
579 #endif
580 
581 
582 /*---------------------- strcasecmp ----------------------*/
583 
584 #define STRCASECMP(soname, fnname) \
585    int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
586           ( const char* s1, const char* s2 ); \
587    int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
588           ( const char* s1, const char* s2 ) \
589    { \
590       extern int tolower(int); \
591       register UChar c1; \
592       register UChar c2; \
593       while (True) { \
594          c1 = tolower(*(const UChar *)s1); \
595          c2 = tolower(*(const UChar *)s2); \
596          if (c1 != c2) break; \
597          if (c1 == 0) break; \
598          s1++; s2++; \
599       } \
600       if ((UChar)c1 < (UChar)c2) return -1; \
601       if ((UChar)c1 > (UChar)c2) return 1; \
602       return 0; \
603    }
604 
605 #if defined(VGO_linux)
606 # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
607      && !defined(VGPV_mips32_linux_android)
608   STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
609   STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
610 # endif
611 
612 #elif defined(VGO_darwin)
613  //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
614 
615 #endif
616 
617 
618 /*---------------------- strncasecmp ----------------------*/
619 
620 #define STRNCASECMP(soname, fnname) \
621    int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
622           ( const char* s1, const char* s2, SizeT nmax ); \
623    int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
624           ( const char* s1, const char* s2, SizeT nmax ) \
625    { \
626       extern int tolower(int); \
627       SizeT n = 0; \
628       while (True) { \
629          if (n >= nmax) return 0; \
630          if (*s1 == 0 && *s2 == 0) return 0; \
631          if (*s1 == 0) return -1; \
632          if (*s2 == 0) return 1; \
633          \
634          if (tolower(*(const UChar *)s1) \
635              < tolower(*(const UChar*)s2)) return -1; \
636          if (tolower(*(const UChar *)s1) \
637              > tolower(*(const UChar *)s2)) return 1; \
638          \
639          s1++; s2++; n++; \
640       } \
641    }
642 
643 #if defined(VGO_linux)
644 # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
645      && !defined(VGPV_mips32_linux_android)
646   STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
647   STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
648 # endif
649 
650 #elif defined(VGO_darwin)
651  //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
652  //STRNCASECMP(VG_Z_DYLD,        strncasecmp)
653 
654 #endif
655 
656 
657 /*---------------------- strcasecmp_l ----------------------*/
658 
659 #define STRCASECMP_L(soname, fnname) \
660    int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
661           ( const char* s1, const char* s2, void* locale ); \
662    int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
663           ( const char* s1, const char* s2, void* locale ) \
664    { \
665       extern int tolower_l(int, void*) __attribute__((weak)); \
666       register UChar c1; \
667       register UChar c2; \
668       while (True) { \
669          c1 = tolower_l(*(const UChar *)s1, locale); \
670          c2 = tolower_l(*(const UChar *)s2, locale); \
671          if (c1 != c2) break; \
672          if (c1 == 0) break; \
673          s1++; s2++; \
674       } \
675       if ((UChar)c1 < (UChar)c2) return -1; \
676       if ((UChar)c1 > (UChar)c2) return 1; \
677       return 0; \
678    }
679 
680 #if defined(VGO_linux)
681  STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
682  STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
683  STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
684 
685 #elif defined(VGO_darwin)
686  //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
687 
688 #endif
689 
690 
691 /*---------------------- strncasecmp_l ----------------------*/
692 
693 #define STRNCASECMP_L(soname, fnname) \
694    int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
695           ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
696    int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
697           ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
698    { \
699       extern int tolower_l(int, void*) __attribute__((weak));    \
700       SizeT n = 0; \
701       while (True) { \
702          if (n >= nmax) return 0; \
703          if (*s1 == 0 && *s2 == 0) return 0; \
704          if (*s1 == 0) return -1; \
705          if (*s2 == 0) return 1; \
706          \
707          if (tolower_l(*(const UChar *)s1, locale) \
708              < tolower_l(*(const UChar *)s2, locale)) return -1; \
709          if (tolower_l(*(const UChar *)s1, locale) \
710              > tolower_l(*(const UChar *)s2, locale)) return 1; \
711          \
712          s1++; s2++; n++; \
713       } \
714    }
715 
716 #if defined(VGO_linux)
717  STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
718  STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
719  STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l)
720 
721 #elif defined(VGO_darwin)
722  //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
723  //STRNCASECMP_L(VG_Z_DYLD,        strncasecmp_l)
724 
725 #endif
726 
727 
728 /*---------------------- strcmp ----------------------*/
729 
730 #define STRCMP(soname, fnname) \
731    int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
732           ( const char* s1, const char* s2 ); \
733    int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
734           ( const char* s1, const char* s2 ) \
735    { \
736       register UChar c1; \
737       register UChar c2; \
738       while (True) { \
739          c1 = *(const UChar *)s1; \
740          c2 = *(const UChar *)s2; \
741          if (c1 != c2) break; \
742          if (c1 == 0) break; \
743          s1++; s2++; \
744       } \
745       if ((UChar)c1 < (UChar)c2) return -1; \
746       if ((UChar)c1 > (UChar)c2) return 1; \
747       return 0; \
748    }
749 
750 #if defined(VGO_linux)
751  STRCMP(VG_Z_LIBC_SONAME,          strcmp)
752  STRCMP(VG_Z_LIBC_SONAME,          __GI_strcmp)
753  STRCMP(VG_Z_LIBC_SONAME,          __strcmp_sse2)
754  STRCMP(VG_Z_LIBC_SONAME,          __strcmp_sse42)
755  STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
756  STRCMP(VG_Z_LD64_SO_1,            strcmp)
757 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
758      || defined(VGPV_mips32_linux_android)
759   STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
760 # endif
761 
762 #elif defined(VGO_darwin)
763  //STRCMP(VG_Z_LIBC_SONAME,          strcmp)
764  STRCMP(VG_Z_LIBC_SONAME, strcmp)
765 
766 #endif
767 
768 
769 /*---------------------- memchr ----------------------*/
770 
771 #define MEMCHR(soname, fnname) \
772    void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
773             (const void *s, int c, SizeT n); \
774    void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
775             (const void *s, int c, SizeT n) \
776    { \
777       SizeT i; \
778       UChar c0 = (UChar)c; \
779       UChar* p = (UChar*)s; \
780       for (i = 0; i < n; i++) \
781          if (p[i] == c0) return (void*)(&p[i]); \
782       return NULL; \
783    }
784 
785 #if defined(VGO_linux)
786  MEMCHR(VG_Z_LIBC_SONAME, memchr)
787  MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr)
788 
789 #elif defined(VGO_darwin)
790  //MEMCHR(VG_Z_LIBC_SONAME, memchr)
791  //MEMCHR(VG_Z_DYLD,        memchr)
792 
793 #endif
794 
795 
796 /*---------------------- memrchr ----------------------*/
797 
798 #define MEMRCHR(soname, fnname) \
799    void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
800             (const void *s, int c, SizeT n); \
801    void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
802             (const void *s, int c, SizeT n) \
803    { \
804       SizeT i; \
805       UChar c0 = (UChar)c; \
806       UChar* p = (UChar*)s; \
807       for (i = 0; i < n; i++) \
808          if (p[n-1-i] == c0) return (void*)(&p[n-1-i]); \
809       return NULL; \
810    }
811 
812 #if defined(VGO_linux)
813  MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
814 
815 #elif defined(VGO_darwin)
816  //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
817  //MEMRCHR(VG_Z_DYLD,        memrchr)
818 
819 #endif
820 
821 
822 /*---------------------- memcpy ----------------------*/
823 
824 #define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check)  \
825    void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
826             ( void *dst, const void *src, SizeT len ); \
827    void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
828             ( void *dst, const void *src, SizeT len ) \
829    { \
830       if (do_ol_check && is_overlap(dst, src, len, len)) \
831          RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
832       \
833       const Addr WS = sizeof(UWord); /* 8 or 4 */ \
834       const Addr WM = WS - 1;        /* 7 or 3 */ \
835       \
836       if (len > 0) { \
837          if (dst < src || !is_overlap(dst, src, len, len)) { \
838          \
839             /* Copying backwards. */ \
840             SizeT n = len; \
841             Addr  d = (Addr)dst; \
842             Addr  s = (Addr)src; \
843             \
844             if (((s^d) & WM) == 0) { \
845                /* s and d have same UWord alignment. */ \
846                /* Pull up to a UWord boundary. */ \
847                while ((s & WM) != 0 && n >= 1) \
848                   { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
849                /* Copy UWords. */ \
850                while (n >= WS) \
851                   { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
852                if (n == 0) \
853                   return dst; \
854             } \
855             if (((s|d) & 1) == 0) { \
856                /* Both are 16-aligned; copy what we can thusly. */ \
857                while (n >= 2) \
858                   { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
859             } \
860             /* Copy leftovers, or everything if misaligned. */ \
861             while (n >= 1) \
862                { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
863          \
864          } else if (dst > src) { \
865          \
866             SizeT n = len; \
867             Addr  d = ((Addr)dst) + n; \
868             Addr  s = ((Addr)src) + n; \
869             \
870             /* Copying forwards. */ \
871             if (((s^d) & WM) == 0) { \
872                /* s and d have same UWord alignment. */ \
873                /* Back down to a UWord boundary. */ \
874                while ((s & WM) != 0 && n >= 1) \
875                   { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
876                /* Copy UWords. */ \
877                while (n >= WS) \
878                   { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
879                if (n == 0) \
880                   return dst; \
881             } \
882             if (((s|d) & 1) == 0) { \
883                /* Both are 16-aligned; copy what we can thusly. */ \
884                while (n >= 2) \
885                   { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
886             } \
887             /* Copy leftovers, or everything if misaligned. */ \
888             while (n >= 1) \
889                { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
890             \
891          } \
892       } \
893       \
894       return dst; \
895    }
896 
897 #define MEMMOVE(soname, fnname)  \
898    MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
899 
900 #define MEMCPY(soname, fnname) \
901    MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
902 
903 #if defined(VGO_linux)
904  /* For older memcpy we have to use memmove-like semantics and skip
905     the overlap check; sigh; see #275284. */
906  MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
907  MEMCPY(VG_Z_LIBC_SONAME,  memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
908  MEMCPY(VG_Z_LIBC_SONAME,  memcpy) /* fallback case */
909  MEMCPY(VG_Z_LIBC_SONAME,    __GI_memcpy)
910  MEMCPY(VG_Z_LIBC_SONAME,    __memcpy_sse2)
911  MEMCPY(VG_Z_LD_SO_1,      memcpy) /* ld.so.1 */
912  MEMCPY(VG_Z_LD64_SO_1,    memcpy) /* ld64.so.1 */
913  /* icc9 blats these around all over the place.  Not only in the main
914     executable but various .so's.  They are highly tuned and read
915     memory beyond the source boundary (although work correctly and
916     never go across page boundaries), so give errors when run
917     natively, at least for misaligned source arg.  Just intercepting
918     in the exe only until we understand more about the problem.  See
919     http://bugs.kde.org/show_bug.cgi?id=139776
920  */
921  MEMCPY(NONE, ZuintelZufastZumemcpy)
922 
923 #elif defined(VGO_darwin)
924 # if DARWIN_VERS <= DARWIN_10_6
925   MEMCPY(VG_Z_LIBC_SONAME,  memcpy)
926 # endif
927  MEMCPY(VG_Z_LIBC_SONAME,  memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
928  MEMCPY(VG_Z_LIBC_SONAME,  memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
929 
930 #endif
931 
932 
933 /*---------------------- memcmp ----------------------*/
934 
935 #define MEMCMP(soname, fnname) \
936    int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname)       \
937           ( const void *s1V, const void *s2V, SizeT n ); \
938    int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname)       \
939           ( const void *s1V, const void *s2V, SizeT n )  \
940    { \
941       int res; \
942       UChar a0; \
943       UChar b0; \
944       const UChar* s1 = s1V; \
945       const UChar* s2 = s2V; \
946       \
947       while (n != 0) { \
948          a0 = s1[0]; \
949          b0 = s2[0]; \
950          s1 += 1; \
951          s2 += 1; \
952          res = ((int)a0) - ((int)b0); \
953          if (res != 0) \
954             return res; \
955          n -= 1; \
956       } \
957       return 0; \
958    }
959 
960 #if defined(VGO_linux)
961  MEMCMP(VG_Z_LIBC_SONAME, memcmp)
962  MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
963  MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse2)
964  MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse4_1)
965  MEMCMP(VG_Z_LIBC_SONAME, bcmp)
966  MEMCMP(VG_Z_LD_SO_1,     bcmp)
967 
968 #elif defined(VGO_darwin)
969  //MEMCMP(VG_Z_LIBC_SONAME, memcmp)
970  //MEMCMP(VG_Z_LIBC_SONAME, bcmp)
971  //MEMCMP(VG_Z_DYLD,        memcmp)
972  //MEMCMP(VG_Z_DYLD,        bcmp)
973 
974 #endif
975 
976 
977 /*---------------------- stpcpy ----------------------*/
978 
979 /* Copy SRC to DEST, returning the address of the terminating '\0' in
980    DEST. (minor variant of strcpy) */
981 #define STPCPY(soname, fnname) \
982    char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
983             ( char* dst, const char* src ); \
984    char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
985             ( char* dst, const char* src ) \
986    { \
987       const HChar* src_orig = src; \
988             HChar* dst_orig = dst; \
989       \
990       while (*src) *dst++ = *src++; \
991       *dst = 0; \
992       \
993       /* This checks for overlap after copying, unavoidable without */ \
994       /* pre-counting length... should be ok */ \
995       if (is_overlap(dst_orig,  \
996                      src_orig,  \
997                      (Addr)dst-(Addr)dst_orig+1,  \
998                      (Addr)src-(Addr)src_orig+1)) \
999          RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
1000       \
1001       return dst; \
1002    }
1003 
1004 #if defined(VGO_linux)
1005  STPCPY(VG_Z_LIBC_SONAME,          stpcpy)
1006  STPCPY(VG_Z_LIBC_SONAME,          __GI_stpcpy)
1007  STPCPY(VG_Z_LIBC_SONAME,          __stpcpy_sse2)
1008  STPCPY(VG_Z_LIBC_SONAME,          __stpcpy_sse2_unaligned)
1009  STPCPY(VG_Z_LD_LINUX_SO_2,        stpcpy)
1010  STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
1011 
1012 #elif defined(VGO_darwin)
1013  //STPCPY(VG_Z_LIBC_SONAME,          stpcpy)
1014  //STPCPY(VG_Z_DYLD,                 stpcpy)
1015 
1016 #endif
1017 
1018 
1019 /*---------------------- stpncpy ----------------------*/
1020 
1021 #define STPNCPY(soname, fnname) \
1022    char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1023             ( char* dst, const char* src, SizeT n ); \
1024    char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1025             ( char* dst, const char* src, SizeT n ) \
1026    { \
1027       const HChar* src_orig = src; \
1028             HChar* dst_str  = dst; \
1029       SizeT m = 0; \
1030       \
1031       while (m   < n && *src) { m++; *dst++ = *src++; } \
1032       /* Check for overlap after copying; all n bytes of dst are relevant, */ \
1033       /* but only m+1 bytes of src if terminator was found */ \
1034       if (is_overlap(dst_str, src_orig, n, (m < n) ? m+1 : n)) \
1035          RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \
1036       dst_str = dst; \
1037       while (m++ < n) *dst++ = 0;         /* must pad remainder with nulls */ \
1038       \
1039       return dst_str; \
1040    }
1041 
1042 #if defined(VGO_linux)
1043  STPNCPY(VG_Z_LIBC_SONAME, stpncpy)
1044 #endif
1045 
1046 
1047 /*---------------------- memset ----------------------*/
1048 
1049 /* Why are we bothering to intercept this?  It seems entirely
1050    pointless. */
1051 
1052 #define MEMSET(soname, fnname) \
1053    void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1054             (void *s, Int c, SizeT n); \
1055    void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1056             (void *s, Int c, SizeT n) \
1057    { \
1058       if (sizeof(void*) == 8) { \
1059          Addr  a  = (Addr)s;   \
1060          ULong c8 = (c & 0xFF); \
1061          c8 = (c8 << 8) | c8; \
1062          c8 = (c8 << 16) | c8; \
1063          c8 = (c8 << 32) | c8; \
1064          while ((a & 7) != 0 && n >= 1) \
1065             { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1066          while (n >= 8) \
1067             { *(ULong*)a = c8; a += 8; n -= 8; } \
1068          while (n >= 1) \
1069             { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1070          return s; \
1071       } else { \
1072          Addr a  = (Addr)s;   \
1073          UInt c4 = (c & 0xFF); \
1074          c4 = (c4 << 8) | c4; \
1075          c4 = (c4 << 16) | c4; \
1076          while ((a & 3) != 0 && n >= 1) \
1077             { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1078          while (n >= 4) \
1079             { *(UInt*)a = c4; a += 4; n -= 4; } \
1080          while (n >= 1) \
1081             { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1082          return s; \
1083       } \
1084    }
1085 
1086 #if defined(VGO_linux)
1087  MEMSET(VG_Z_LIBC_SONAME, memset)
1088 
1089 #elif defined(VGO_darwin)
1090  //MEMSET(VG_Z_LIBC_SONAME, memset)
1091  //MEMSET(VG_Z_DYLD,        memset)
1092  MEMSET(VG_Z_LIBC_SONAME, memset)
1093 
1094 #endif
1095 
1096 
1097 /*---------------------- memmove ----------------------*/
1098 
1099 /* memmove -- use the MEMMOVE defn above. */
1100 
1101 #if defined(VGO_linux)
1102  MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1103  MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove)
1104 
1105 #elif defined(VGO_darwin)
1106 # if DARWIN_VERS <= DARWIN_10_6
1107   MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1108 # endif
1109  MEMMOVE(VG_Z_LIBC_SONAME,  memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
1110  MEMMOVE(VG_Z_LIBC_SONAME,  memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
1111 
1112 #endif
1113 
1114 
1115 /*---------------------- bcopy ----------------------*/
1116 
1117 #define BCOPY(soname, fnname) \
1118    void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1119             (const void *srcV, void *dstV, SizeT n); \
1120    void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1121             (const void *srcV, void *dstV, SizeT n) \
1122    { \
1123       SizeT i; \
1124       HChar* dst = dstV; \
1125       const HChar* src = srcV; \
1126       if (dst < src) { \
1127          for (i = 0; i < n; i++) \
1128             dst[i] = src[i]; \
1129       } \
1130       else  \
1131       if (dst > src) { \
1132          for (i = 0; i < n; i++) \
1133             dst[n-i-1] = src[n-i-1]; \
1134       } \
1135    }
1136 
1137 #if defined(VGO_linux)
1138  BCOPY(VG_Z_LIBC_SONAME, bcopy)
1139 
1140 #elif defined(VGO_darwin)
1141  //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1142  //BCOPY(VG_Z_DYLD,        bcopy)
1143 
1144 #endif
1145 
1146 
1147 /*-------------------- memmove_chk --------------------*/
1148 
1149 /* glibc 2.5 variant of memmove which checks the dest is big enough.
1150    There is no specific part of glibc that this is copied from. */
1151 #define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1152    void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1153             (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1154    void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1155             (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1156    { \
1157       SizeT i; \
1158       HChar* dst = dstV;        \
1159       const HChar* src = srcV; \
1160       if (destlen < n) \
1161          goto badness; \
1162       if (dst < src) { \
1163          for (i = 0; i < n; i++) \
1164             dst[i] = src[i]; \
1165       } \
1166       else  \
1167       if (dst > src) { \
1168          for (i = 0; i < n; i++) \
1169             dst[n-i-1] = src[n-i-1]; \
1170       } \
1171       return dst; \
1172      badness: \
1173       VALGRIND_PRINTF_BACKTRACE( \
1174          "*** memmove_chk: buffer overflow detected ***: " \
1175          "program terminated\n"); \
1176      my_exit(127); \
1177      /*NOTREACHED*/ \
1178      return NULL; \
1179    }
1180 
1181 #if defined(VGO_linux)
1182  GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
1183 
1184 #elif defined(VGO_darwin)
1185 
1186 #endif
1187 
1188 
1189 /*-------------------- strchrnul --------------------*/
1190 
1191 /* Find the first occurrence of C in S or the final NUL byte.  */
1192 #define GLIBC232_STRCHRNUL(soname, fnname) \
1193    char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1194             (const char* s, int c_in); \
1195    char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1196             (const char* s, int c_in) \
1197    { \
1198       UChar  c        = (UChar) c_in; \
1199       UChar* char_ptr = (UChar *)s; \
1200       while (1) { \
1201          if (*char_ptr == 0) return (HChar *)char_ptr;   \
1202          if (*char_ptr == c) return (HChar *)char_ptr;   \
1203          char_ptr++; \
1204       } \
1205    }
1206 
1207 #if defined(VGO_linux)
1208  GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1209 
1210 #elif defined(VGO_darwin)
1211 
1212 #endif
1213 
1214 
1215 /*---------------------- rawmemchr ----------------------*/
1216 
1217 /* Find the first occurrence of C in S.  */
1218 #define GLIBC232_RAWMEMCHR(soname, fnname) \
1219    char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1220             (const char* s, int c_in); \
1221    char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1222             (const char* s, int c_in) \
1223    { \
1224       UChar  c        = (UChar) c_in; \
1225       UChar* char_ptr = (UChar *)s; \
1226       while (1) { \
1227         if (*char_ptr == c) return (HChar *)char_ptr;   \
1228          char_ptr++; \
1229       } \
1230    }
1231 
1232 #if defined (VGO_linux)
1233  GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1234  GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1235 
1236 #elif defined(VGO_darwin)
1237 
1238 #endif
1239 
1240 
1241 /*---------------------- strcpy_chk ----------------------*/
1242 
1243 /* glibc variant of strcpy that checks the dest is big enough.
1244    Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1245 #define GLIBC25___STRCPY_CHK(soname,fnname) \
1246    char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1247             (char* dst, const char* src, SizeT len); \
1248    char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1249             (char* dst, const char* src, SizeT len) \
1250    { \
1251       HChar* ret = dst; \
1252       if (! len) \
1253          goto badness; \
1254       while ((*dst++ = *src++) != '\0') \
1255          if (--len == 0) \
1256             goto badness; \
1257       return ret; \
1258      badness: \
1259       VALGRIND_PRINTF_BACKTRACE( \
1260          "*** strcpy_chk: buffer overflow detected ***: " \
1261          "program terminated\n"); \
1262      my_exit(127); \
1263      /*NOTREACHED*/ \
1264      return NULL; \
1265    }
1266 
1267 #if defined(VGO_linux)
1268  GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1269 
1270 #elif defined(VGO_darwin)
1271 
1272 #endif
1273 
1274 
1275 /*---------------------- stpcpy_chk ----------------------*/
1276 
1277 /* glibc variant of stpcpy that checks the dest is big enough.
1278    Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1279 #define GLIBC25___STPCPY_CHK(soname,fnname) \
1280    char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1281             (char* dst, const char* src, SizeT len); \
1282    char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1283             (char* dst, const char* src, SizeT len) \
1284    { \
1285       if (! len) \
1286          goto badness; \
1287       while ((*dst++ = *src++) != '\0') \
1288          if (--len == 0) \
1289             goto badness; \
1290       return dst - 1; \
1291      badness: \
1292       VALGRIND_PRINTF_BACKTRACE( \
1293          "*** stpcpy_chk: buffer overflow detected ***: " \
1294          "program terminated\n"); \
1295      my_exit(127); \
1296      /*NOTREACHED*/ \
1297      return NULL; \
1298    }
1299 
1300 #if defined(VGO_linux)
1301  GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1302 
1303 #elif defined(VGO_darwin)
1304 
1305 #endif
1306 
1307 
1308 /*---------------------- mempcpy ----------------------*/
1309 
1310 /* mempcpy */
1311 #define GLIBC25_MEMPCPY(soname, fnname) \
1312    void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1313             ( void *dst, const void *src, SizeT len ); \
1314    void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1315             ( void *dst, const void *src, SizeT len ) \
1316    { \
1317       register HChar *d; \
1318       register HChar *s; \
1319       SizeT len_saved = len; \
1320       \
1321       if (len == 0) \
1322          return dst; \
1323       \
1324       if (is_overlap(dst, src, len, len)) \
1325          RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1326       \
1327       if ( dst > src ) { \
1328          d = (char *)dst + len - 1; \
1329          s = (char *)src + len - 1; \
1330          while ( len-- ) { \
1331             *d-- = *s--; \
1332          } \
1333       } else if ( dst < src ) { \
1334          d = (char *)dst; \
1335          s = (char *)src; \
1336          while ( len-- ) { \
1337             *d++ = *s++; \
1338          } \
1339       } \
1340       return (void*)( ((char*)dst) + len_saved ); \
1341    }
1342 
1343 #if defined(VGO_linux)
1344  GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1345  GLIBC25_MEMPCPY(VG_Z_LD_SO_1,     mempcpy) /* ld.so.1 */
1346  GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */
1347  GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */
1348 
1349 #elif defined(VGO_darwin)
1350  //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1351 
1352 #endif
1353 
1354 
1355 /*-------------------- memcpy_chk --------------------*/
1356 
1357 #define GLIBC26___MEMCPY_CHK(soname, fnname) \
1358    void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1359             (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1360    void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1361             (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1362    { \
1363       register HChar *d; \
1364       register const HChar *s; \
1365       \
1366       if (dstlen < len) goto badness; \
1367       \
1368       if (len == 0) \
1369          return dst; \
1370       \
1371       if (is_overlap(dst, src, len, len)) \
1372          RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1373       \
1374       if ( dst > src ) { \
1375          d = (HChar *)dst + len - 1; \
1376          s = (const HChar *)src + len - 1; \
1377          while ( len-- ) { \
1378             *d-- = *s--; \
1379          } \
1380       } else if ( dst < src ) { \
1381          d = (HChar *)dst; \
1382          s = (const HChar *)src; \
1383          while ( len-- ) { \
1384             *d++ = *s++; \
1385          } \
1386       } \
1387       return dst; \
1388      badness: \
1389       VALGRIND_PRINTF_BACKTRACE( \
1390          "*** memcpy_chk: buffer overflow detected ***: " \
1391          "program terminated\n"); \
1392      my_exit(127); \
1393      /*NOTREACHED*/ \
1394      return NULL; \
1395    }
1396 
1397 #if defined(VGO_linux)
1398  GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1399 
1400 #elif defined(VGO_darwin)
1401 
1402 #endif
1403 
1404 
1405 /*---------------------- strstr ----------------------*/
1406 
1407 #define STRSTR(soname, fnname) \
1408    char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1409          (const char* haystack, const char* needle); \
1410    char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1411          (const char* haystack, const char* needle) \
1412    { \
1413       const HChar* h = haystack; \
1414       const HChar* n = needle; \
1415       \
1416       /* find the length of n, not including terminating zero */ \
1417       UWord nlen = 0; \
1418       while (n[nlen]) nlen++; \
1419       \
1420       /* if n is the empty string, match immediately. */ \
1421       if (nlen == 0) return (HChar *)h;                  \
1422       \
1423       /* assert(nlen >= 1); */ \
1424       HChar n0 = n[0]; \
1425       \
1426       while (1) { \
1427          const HChar hh = *h; \
1428          if (hh == 0) return NULL; \
1429          if (hh != n0) { h++; continue; } \
1430          \
1431          UWord i; \
1432          for (i = 0; i < nlen; i++) { \
1433             if (n[i] != h[i]) \
1434                break; \
1435          } \
1436          /* assert(i >= 0 && i <= nlen); */ \
1437          if (i == nlen) \
1438            return (HChar *)h;                   \
1439          \
1440          h++; \
1441       } \
1442    }
1443 
1444 #if defined(VGO_linux)
1445  STRSTR(VG_Z_LIBC_SONAME,          strstr)
1446  STRSTR(VG_Z_LIBC_SONAME,          __strstr_sse2)
1447  STRSTR(VG_Z_LIBC_SONAME,          __strstr_sse42)
1448 
1449 #elif defined(VGO_darwin)
1450 
1451 #endif
1452 
1453 
1454 /*---------------------- strpbrk ----------------------*/
1455 
1456 #define STRPBRK(soname, fnname) \
1457    char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1458          (const char* sV, const char* acceptV); \
1459    char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1460          (const char* sV, const char* acceptV) \
1461    { \
1462       const HChar* s = sV; \
1463       const HChar* accept = acceptV; \
1464       \
1465       /*  find the length of 'accept', not including terminating zero */ \
1466       UWord nacc = 0; \
1467       while (accept[nacc]) nacc++; \
1468       \
1469       /* if n is the empty string, fail immediately. */ \
1470       if (nacc == 0) return NULL; \
1471       \
1472       /* assert(nacc >= 1); */ \
1473       while (1) { \
1474          UWord i; \
1475          HChar sc = *s; \
1476          if (sc == 0) \
1477             break; \
1478          for (i = 0; i < nacc; i++) { \
1479             if (sc == accept[i]) \
1480               return (HChar *)s; \
1481          } \
1482          s++; \
1483       } \
1484       \
1485       return NULL; \
1486    }
1487 
1488 #if defined(VGO_linux)
1489  STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
1490 
1491 #elif defined(VGO_darwin)
1492 
1493 #endif
1494 
1495 
1496 /*---------------------- strcspn ----------------------*/
1497 
1498 #define STRCSPN(soname, fnname) \
1499    SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1500          (const char* sV, const char* rejectV); \
1501    SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1502          (const char* sV, const char* rejectV) \
1503    { \
1504       const HChar* s = sV; \
1505       const HChar* reject = rejectV; \
1506       \
1507       /* find the length of 'reject', not including terminating zero */ \
1508       UWord nrej = 0; \
1509       while (reject[nrej]) nrej++; \
1510       \
1511       UWord len = 0; \
1512       while (1) { \
1513          UWord i; \
1514          HChar sc = *s; \
1515          if (sc == 0) \
1516             break; \
1517          for (i = 0; i < nrej; i++) { \
1518             if (sc == reject[i]) \
1519                break; \
1520          } \
1521          /* assert(i >= 0 && i <= nrej); */ \
1522          if (i < nrej) \
1523             break; \
1524          s++; \
1525          len++; \
1526       } \
1527       \
1528       return len; \
1529    }
1530 
1531 #if defined(VGO_linux)
1532  STRCSPN(VG_Z_LIBC_SONAME,          strcspn)
1533 
1534 #elif defined(VGO_darwin)
1535 
1536 #endif
1537 
1538 
1539 /*---------------------- strspn ----------------------*/
1540 
1541 #define STRSPN(soname, fnname) \
1542    SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1543          (const char* sV, const char* acceptV); \
1544    SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1545          (const char* sV, const char* acceptV) \
1546    { \
1547       const UChar* s = (const UChar *)sV;        \
1548       const UChar* accept = (const UChar *)acceptV;     \
1549       \
1550       /* find the length of 'accept', not including terminating zero */ \
1551       UWord nacc = 0; \
1552       while (accept[nacc]) nacc++; \
1553       if (nacc == 0) return 0; \
1554       \
1555       UWord len = 0; \
1556       while (1) { \
1557          UWord i; \
1558          HChar sc = *s; \
1559          if (sc == 0) \
1560             break; \
1561          for (i = 0; i < nacc; i++) { \
1562             if (sc == accept[i]) \
1563                break; \
1564          } \
1565          /* assert(i >= 0 && i <= nacc); */ \
1566          if (i == nacc) \
1567             break; \
1568          s++; \
1569          len++; \
1570       } \
1571       \
1572       return len; \
1573    }
1574 
1575 #if defined(VGO_linux)
1576  STRSPN(VG_Z_LIBC_SONAME,          strspn)
1577 
1578 #elif defined(VGO_darwin)
1579 
1580 #endif
1581 
1582 
1583 /*---------------------- strcasestr ----------------------*/
1584 
1585 #define STRCASESTR(soname, fnname) \
1586    char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1587          (const char* haystack, const char* needle); \
1588    char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1589          (const char* haystack, const char* needle) \
1590    { \
1591       extern int tolower(int); \
1592       const HChar* h = haystack; \
1593       const HChar* n = needle;   \
1594       \
1595       /* find the length of n, not including terminating zero */ \
1596       UWord nlen = 0; \
1597       while (n[nlen]) nlen++; \
1598       \
1599       /* if n is the empty string, match immediately. */ \
1600       if (nlen == 0) return (HChar *)h;                  \
1601       \
1602       /* assert(nlen >= 1); */ \
1603       UChar n0 = tolower(n[0]);                 \
1604       \
1605       while (1) { \
1606          UChar hh = tolower(*h);    \
1607          if (hh == 0) return NULL; \
1608          if (hh != n0) { h++; continue; } \
1609          \
1610          UWord i; \
1611          for (i = 0; i < nlen; i++) { \
1612             if (tolower(n[i]) != tolower(h[i]))  \
1613                break; \
1614          } \
1615          /* assert(i >= 0 && i <= nlen); */ \
1616          if (i == nlen) \
1617            return (HChar *)h;                   \
1618          \
1619          h++; \
1620       } \
1621    }
1622 
1623 #if defined(VGO_linux)
1624 # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
1625      && !defined(VGPV_mips32_linux_android)
1626   STRCASESTR(VG_Z_LIBC_SONAME,      strcasestr)
1627 # endif
1628 
1629 #elif defined(VGO_darwin)
1630 
1631 #endif
1632 
1633 
1634 /*---------------------- wcslen ----------------------*/
1635 
1636 // This is a wchar_t equivalent to strlen.  Unfortunately
1637 // we don't have wchar_t available here, but it looks like
1638 // a 32 bit int on Linux.  I don't know if that is also
1639 // valid on MacOSX.
1640 
1641 #define WCSLEN(soname, fnname) \
1642    SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1643       ( const UInt* str ); \
1644    SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1645       ( const UInt* str )  \
1646    { \
1647       SizeT i = 0; \
1648       while (str[i] != 0) i++; \
1649       return i; \
1650    }
1651 
1652 #if defined(VGO_linux)
1653  WCSLEN(VG_Z_LIBC_SONAME,          wcslen)
1654 
1655 #elif defined(VGO_darwin)
1656 
1657 #endif
1658 
1659 /*---------------------- wcscmp ----------------------*/
1660 
1661 // This is a wchar_t equivalent to strcmp.  We don't
1662 // have wchar_t available here, but in the GNU C Library
1663 // wchar_t is always 32 bits wide and wcscmp uses signed
1664 // comparison, not unsigned as in strcmp function.
1665 
1666 #define WCSCMP(soname, fnname) \
1667    int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1668           ( const Int* s1, const Int* s2 ); \
1669    int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1670           ( const Int* s1, const Int* s2 ) \
1671    { \
1672       register Int c1; \
1673       register Int c2; \
1674       while (True) { \
1675          c1 = *s1; \
1676          c2 = *s2; \
1677          if (c1 != c2) break; \
1678          if (c1 == 0) break; \
1679          s1++; s2++; \
1680       } \
1681       if (c1 < c2) return -1; \
1682       if (c1 > c2) return 1; \
1683       return 0; \
1684    }
1685 
1686 #if defined(VGO_linux)
1687  WCSCMP(VG_Z_LIBC_SONAME,          wcscmp)
1688 #endif
1689 
1690 /*---------------------- wcscpy ----------------------*/
1691 
1692 // This is a wchar_t equivalent to strcpy.  We don't
1693 // have wchar_t available here, but in the GNU C Library
1694 // wchar_t is always 32 bits wide.
1695 
1696 #define WCSCPY(soname, fnname) \
1697    Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1698       ( Int* dst, const Int* src ); \
1699    Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1700       ( Int* dst, const Int* src ) \
1701    { \
1702       const Int* src_orig = src; \
1703             Int* dst_orig = dst; \
1704       \
1705       while (*src) *dst++ = *src++; \
1706       *dst = 0; \
1707       \
1708       /* This checks for overlap after copying, unavoidable without */ \
1709       /* pre-counting length... should be ok */ \
1710       if (is_overlap(dst_orig,  \
1711                      src_orig,  \
1712                      (Addr)dst-(Addr)dst_orig+1, \
1713                      (Addr)src-(Addr)src_orig+1)) \
1714          RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
1715       \
1716       return dst_orig; \
1717    }
1718 
1719 #if defined(VGO_linux)
1720  WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
1721 #endif
1722 
1723 
1724 /*---------------------- wcschr ----------------------*/
1725 
1726 // This is a wchar_t equivalent to strchr.  We don't
1727 // have wchar_t available here, but in the GNU C Library
1728 // wchar_t is always 32 bits wide.
1729 
1730 #define WCSCHR(soname, fnname) \
1731    Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
1732    Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
1733    { \
1734       Int* p  = (Int*)s; \
1735       while (True) { \
1736          if (*p == c) return p; \
1737          if (*p == 0) return NULL; \
1738          p++; \
1739       } \
1740    }
1741 
1742 #if defined(VGO_linux)
1743  WCSCHR(VG_Z_LIBC_SONAME,          wcschr)
1744 #endif
1745 /*---------------------- wcsrchr ----------------------*/
1746 
1747 // This is a wchar_t equivalent to strrchr.  We don't
1748 // have wchar_t available here, but in the GNU C Library
1749 // wchar_t is always 32 bits wide.
1750 
1751 #define WCSRCHR(soname, fnname) \
1752    Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
1753    Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
1754    { \
1755       Int* p    = (Int*) s; \
1756       Int* last = NULL; \
1757       while (True) { \
1758          if (*p == c) last = p; \
1759          if (*p == 0) return last; \
1760          p++; \
1761       } \
1762    }
1763 
1764 #if defined(VGO_linux)
1765  WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
1766 #endif
1767 
1768 /*------------------------------------------------------------*/
1769 /*--- Improve definedness checking of process environment  ---*/
1770 /*------------------------------------------------------------*/
1771 
1772 #if defined(VGO_linux)
1773 
1774 /* If these wind up getting generated via a macro, so that multiple
1775    versions of each function exist (as above), use the _EZU variants
1776    to assign equivalance class tags. */
1777 
1778 /*---------------------- putenv ----------------------*/
1779 
1780 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME,putenv)1781 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
1782 {
1783     OrigFn fn;
1784     Word result;
1785     const HChar* p = string;
1786     VALGRIND_GET_ORIG_FN(fn);
1787     /* Now by walking over the string we magically produce
1788        traces when hitting undefined memory. */
1789     if (p)
1790         while (*p++)
1791             __asm__ __volatile__("" ::: "memory");
1792     CALL_FN_W_W(result, fn, string);
1793     return result;
1794 }
1795 
1796 
1797 /*---------------------- unsetenv ----------------------*/
1798 
1799 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME,unsetenv)1800 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
1801 {
1802     OrigFn fn;
1803     Word result;
1804     const HChar* p = name;
1805     VALGRIND_GET_ORIG_FN(fn);
1806     /* Now by walking over the string we magically produce
1807        traces when hitting undefined memory. */
1808     if (p)
1809         while (*p++)
1810             __asm__ __volatile__("" ::: "memory");
1811     CALL_FN_W_W(result, fn, name);
1812     return result;
1813 }
1814 
1815 
1816 /*---------------------- setenv ----------------------*/
1817 
1818 /* setenv */
1819 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1820     (const char* name, const char* value, int overwrite);
VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME,setenv)1821 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1822     (const char* name, const char* value, int overwrite)
1823 {
1824     OrigFn fn;
1825     Word result;
1826     const HChar* p;
1827     VALGRIND_GET_ORIG_FN(fn);
1828     /* Now by walking over the string we magically produce
1829        traces when hitting undefined memory. */
1830     if (name)
1831         for (p = name; *p; p++)
1832             __asm__ __volatile__("" ::: "memory");
1833     if (value)
1834         for (p = value; *p; p++)
1835             __asm__ __volatile__("" ::: "memory");
1836     (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1837     CALL_FN_W_WWW(result, fn, name, value, overwrite);
1838     return result;
1839 }
1840 
1841 #endif /* defined(VGO_linux) */
1842 
1843 /*--------------------------------------------------------------------*/
1844 /*--- end                                                          ---*/
1845 /*--------------------------------------------------------------------*/
1846