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