1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Replacements for strcpy(), memcpy() et al, which run on the  ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- simulated CPU.                                               ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                          mc_replace_strmem.c ---*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of MemCheck, a heavyweight Valgrind tool for
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   detecting memory errors.
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2000-2012 Julian Seward
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jseward@acm.org
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h"
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_tool_poolalloc.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_hashtable.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_redir.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "valgrind.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "mc_include.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "memcheck.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We have our own versions of these functions for two reasons:
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (a) it allows us to do overlap checking
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (b) some of the normal versions are hyper-optimised, which fools
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       Memcheck and cause spurious value warnings.  Our versions are
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       simpler.
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that overenthusiastic use of PLT bypassing by the glibc people also
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   means that we need to patch multiple versions of some of the functions to
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   our own implementations.
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   THEY RUN ON THE SIMD CPU!
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Assignment of behavioural equivalence class tags: 2NNNP is intended
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to be reserved for Memcheck.  Current usage:
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20010 STRRCHR
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20020 STRCHR
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20030 STRCAT
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20040 STRNCAT
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20050 STRLCAT
65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20060 STRNLEN
66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20070 STRLEN
67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20080 STRCPY
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20090 STRNCPY
69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20100 STRLCPY
70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20110 STRNCMP
71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20120 STRCASECMP
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20130 STRNCASECMP
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20140 STRCASECMP_L
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20150 STRNCASECMP_L
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20160 STRCMP
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20170 MEMCHR
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20180 MEMCPY    if there's a conflict between memcpy and
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20181 MEMMOVE   memmove, prefer memmove
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20190 MEMCMP
82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20200 STPCPY
83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20210 MEMSET
84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   2022P unused (was previously MEMMOVE)
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20230 BCOPY
86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20240 GLIBC25___MEMMOVE_CHK
87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20250 GLIBC232_STRCHRNUL
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20260 GLIBC232_RAWMEMCHR
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20270 GLIBC25___STRCPY_CHK
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20280 GLIBC25___STPCPY_CHK
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20290 GLIBC25_MEMPCPY
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20300 GLIBC26___MEMCPY_CHK
93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20310 STRSTR
94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20320 STRPBRK
95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20330 STRCSPN
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20340 STRSPN
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   20350 STRCASESTR
98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   20360 MEMRCHR
99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   20370 WCSLEN
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if [dst .. dst+dstlen-1] overlaps with
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 [src .. src+srclen-1].
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We assume that the address ranges do not wrap around
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (which is safe since on Linux addresses >= 0xC0000000
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are not accessible and the program will segfault in this
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   circumstance, presumably).
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr loS, hiS, loD, hiD;
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dstlen == 0 || srclen == 0)
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loS = (Addr)src;
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loD = (Addr)dst;
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hiS = loS + srclen - 1;
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hiD = loD + dstlen - 1;
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (loS < loD) {
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return !(hiS < loD);
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (loD < loS) {
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return !(hiD < loS);
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* They start at same place.  Since we know neither of them has
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zero length, they must overlap. */
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Call here to exit if we can't continue.  On Android we can't call
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   _exit for some reason, so we have to blunt-instrument it. */
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__ ((__noreturn__))
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline void my_exit ( int x )
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  if defined(VGPV_arm_linux_android)
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   __asm__ __volatile__(".word 0xFFFFFFFF");
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while (1) {}
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  elif defined(VGPV_x86_linux_android)
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   __asm__ __volatile__("ud2");
148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   while (1) {}
149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  else
150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   extern __attribute__ ((__noreturn__)) void _exit(int status);
151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   _exit(x);
152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  endif
153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is a macro rather than a function because we don't want to have an
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// extra function in the stack trace.
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define RECORD_OVERLAP_ERROR(s, src, dst, len)                  \
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  VALGRIND_DO_CLIENT_REQUEST_STMT(                              \
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR,   \
161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  s, src, dst, len, 0)
162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strrchr ----------------------*/
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRRCHR(soname, fnname) \
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar  ch   = (UChar)((UInt)c); \
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* p    = (UChar*)s; \
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* last = NULL; \
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) { \
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*p == ch) last = p; \
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*p == 0) return last; \
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p++; \
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Apparently rindex() is the same thing as strrchr()
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME,   strrchr)
183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME,   rindex)
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME,   __GI_strrchr)
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */
188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRRCHR(VG_Z_LIBC_SONAME,   strrchr)
192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRRCHR(VG_Z_LIBC_SONAME,   rindex)
193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRRCHR(VG_Z_DYLD,          strrchr)
194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRRCHR(VG_Z_DYLD,          rindex)
195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME, strrchr)
196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strchr ----------------------*/
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCHR(soname, fnname) \
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar  ch = (UChar)((UInt)c); \
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* p  = (UChar*)s; \
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) { \
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*p == ch) return p; \
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*p == 0) return NULL; \
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p++; \
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Apparently index() is the same thing as strchr()
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME,          strchr)
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME,          index)
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME,          __GI_strchr)
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_linux)
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRCHR(VG_Z_LD_LINUX_SO_2,        strchr)
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRCHR(VG_Z_LD_LINUX_SO_2,        index)
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRCHR(VG_Z_LIBC_SONAME,          strchr)
229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRCHR(VG_Z_LIBC_SONAME,          index)
230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRCHR(VG_Z_DYLD,                 strchr)
231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRCHR(VG_Z_DYLD,                 index)
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME, strchr)
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcat ----------------------*/
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCAT(soname, fnname) \
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ( char* dst, const char* src ); \
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ( char* dst, const char* src ) \
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Char* src_orig = src; \
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Char* dst_orig = dst; \
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*dst) dst++; \
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*src) *dst++ = *src++; \
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = 0; \
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is a bit redundant, I think;  any overlap and the strcat will */ \
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* go forever... or until a seg fault occurs. */ \
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst_orig,  \
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     src_orig,  \
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)dst-(Addr)dst_orig+1,  \
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)src-(Addr)src_orig+1)) \
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst_orig; \
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCAT(VG_Z_LIBC_SONAME, strcat)
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRCAT(VG_Z_LIBC_SONAME, strcat)
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncat ----------------------*/
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNCAT(soname, fnname) \
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( char* dst, const char* src, SizeT n ); \
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( char* dst, const char* src, SizeT n ) \
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Char* src_orig = src; \
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Char* dst_orig = dst; \
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT m = 0; \
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*dst) dst++; \
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = 0;                                       /* always add null   */ \
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This checks for overlap after copying, unavoidable without */ \
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* pre-counting lengths... should be ok */ \
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst_orig,  \
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     src_orig,  \
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     (Addr)dst-(Addr)dst_orig+1, \
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)src-(Addr)src_orig+1)) \
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst_orig; \
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCAT(VG_Z_LIBC_SONAME, strncat)
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCAT(VG_Z_LIBC_SONAME, strncat)
304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCAT(VG_Z_DYLD,        strncat)
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strlcat ----------------------*/
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to be nul-terminated after the copy, unless n <= strlen(dst_orig).
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Returns min(n, strlen(dst_orig)) + strlen(src_orig).
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Truncation occurred if retval >= n.
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRLCAT(soname, fnname) \
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ( char* dst, const char* src, SizeT n ); \
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ( char* dst, const char* src, SizeT n ) \
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Char* src_orig = src; \
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* dst_orig = dst; \
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT m = 0; \
325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (m < n && *dst) { m++; dst++; } \
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (m < n) { \
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (m < n-1 && *src) { m++; *dst++ = *src++; } \
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *dst = 0; \
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else { \
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No space to copy anything to dst. m == n */ \
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*src) { m++; src++; } \
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This checks for overlap after copying, unavoidable without */ \
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* pre-counting lengths... should be ok */ \
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst_orig,  \
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     src_orig,  \
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)dst-(Addr)dst_orig+1,  \
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)src-(Addr)src_orig+1)) \
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return m; \
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRLCAT(VG_Z_DYLD,        strlcat)
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLCAT(VG_Z_LIBC_SONAME, strlcat)
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strnlen ----------------------*/
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNLEN(soname, fnname) \
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ( const char* str, SizeT n ); \
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ( const char* str, SizeT n ) \
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT i = 0; \
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (i < n && str[i] != 0) i++; \
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i; \
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNLEN(VG_Z_LIBC_SONAME, strnlen)
372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNLEN(VG_Z_LIBC_SONAME, strnlen)
376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strlen ----------------------*/
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note that this replacement often doesn't get used because gcc inlines
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// calls to strlen() with its own built-in version.  This can be very
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// confusing if you aren't expecting it.  Other small functions in
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// this file may also be inline by gcc.
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRLEN(soname, fnname) \
388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ( const char* str ); \
390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ( const char* str )  \
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT i = 0; \
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (str[i] != 0) i++; \
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i; \
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME,          strlen)
400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME,          __GI_strlen)
401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif
404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRLEN(VG_Z_LIBC_SONAME,          strlen)
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME, strlen)
408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcpy ----------------------*/
413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCPY(soname, fnname) \
415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ( char* dst, const char* src ); \
417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ( char* dst, const char* src ) \
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Char* src_orig = src; \
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Char* dst_orig = dst; \
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*src) *dst++ = *src++; \
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = 0; \
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This checks for overlap after copying, unavoidable without */ \
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* pre-counting length... should be ok */ \
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst_orig,  \
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     src_orig,  \
430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     (Addr)dst-(Addr)dst_orig+1, \
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)src-(Addr)src_orig+1)) \
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst_orig; \
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, strcpy)
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRCPY(VG_Z_LIBC_SONAME, strcpy)
443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRCPY(VG_Z_DYLD,        strcpy)
444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, strcpy)
445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncpy ----------------------*/
450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNCPY(soname, fnname) \
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( char* dst, const char* src, SizeT n ); \
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( char* dst, const char* src, SizeT n ) \
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Char* src_orig = src; \
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Char* dst_orig = dst; \
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT m = 0; \
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (m   < n && *src) { m++; *dst++ = *src++; } \
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Check for overlap after copying; all n bytes of dst are relevant, */ \
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* but only m+1 bytes of src if terminator was found */ \
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (m++ < n) *dst++ = 0;         /* must pad remainder with nulls */ \
467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst_orig; \
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCPY(VG_Z_LIBC_SONAME, strncpy)
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRNCPY(VG_Z_LIBC_SONAME, strncpy)
477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCPY(VG_Z_DYLD,        strncpy)
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCPY(VG_Z_LIBC_SONAME, strncpy)
479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strlcpy ----------------------*/
484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Returns strlen(src). Does not zero-fill the remainder of dst. */
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRLCPY(soname, fnname) \
488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ( char* dst, const char* src, SizeT n ); \
490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ( char* dst, const char* src, SizeT n ) \
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const char* src_orig = src; \
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      char* dst_orig = dst; \
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT m = 0; \
496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (m < n-1 && *src) { m++; *dst++ = *src++; } \
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* m non-nul bytes have now been copied, and m <= n-1. */ \
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Check for overlap after copying; all n bytes of dst are relevant, */ \
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* but only m+1 bytes of src if terminator was found */ \
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Nul-terminate dst. */ \
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (n > 0) *dst = 0; \
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Finish counting strlen(src). */ \
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*src) src++; \
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return src - src_orig; \
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng STRLCPY(VG_Z_LIBC_SONAME, strlcpy);
514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRLCPY(VG_Z_DYLD,        strlcpy)
519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncmp ----------------------*/
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNCMP(soname, fnname) \
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( const char* s1, const char* s2, SizeT nmax ); \
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( const char* s1, const char* s2, SizeT nmax ) \
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT n = 0; \
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) { \
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n >= nmax) return 0; \
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*s1 == 0 && *s2 == 0) return 0; \
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*s1 == 0) return -1; \
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*s2 == 0) return 1; \
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         \
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         \
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s1++; s2++; n++; \
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCMP(VG_Z_LIBC_SONAME, strncmp)
548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRNCMP(VG_Z_LIBC_SONAME, strncmp)
552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCMP(VG_Z_DYLD,        strncmp)
553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCMP(VG_Z_LIBC_SONAME,        strncmp)
554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcasecmp ----------------------*/
559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
560f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRCASECMP(soname, fnname) \
561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
562f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2 ); \
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
564f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2 ) \
565f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   { \
566f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      extern int tolower(int); \
567f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      register unsigned char c1; \
568f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      register unsigned char c2; \
569f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      while (True) { \
570f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         c1 = tolower(*(unsigned char *)s1); \
571f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         c2 = tolower(*(unsigned char *)s2); \
572f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (c1 != c2) break; \
573f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (c1 == 0) break; \
574f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         s1++; s2++; \
575f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      } \
576f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if ((unsigned char)c1 < (unsigned char)c2) return -1; \
577f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if ((unsigned char)c1 > (unsigned char)c2) return 1; \
578f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      return 0; \
579f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
580f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
581f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux)
582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android)
583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif
586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
590f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif
591f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
592f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncasecmp ----------------------*/
594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
595f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRNCASECMP(soname, fnname) \
596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
597f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2, SizeT nmax ); \
598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
599f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2, SizeT nmax ) \
600f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   { \
601f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      extern int tolower(int); \
602f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      SizeT n = 0; \
603f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      while (True) { \
604f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (n >= nmax) return 0; \
605f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (*s1 == 0 && *s2 == 0) return 0; \
606f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (*s1 == 0) return -1; \
607f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (*s2 == 0) return 1; \
608f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         \
609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (tolower(*(unsigned char*)s1) \
610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             < tolower(*(unsigned char*)s2)) return -1; \
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (tolower(*(unsigned char*)s1) \
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             > tolower(*(unsigned char*)s2)) return 1; \
613f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         \
614f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         s1++; s2++; n++; \
615f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      } \
616f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
617f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
618f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux)
619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android)
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
624f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#elif defined(VGO_darwin)
625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCASECMP(VG_Z_DYLD,        strncasecmp)
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
628f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif
629f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
630f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcasecmp_l ----------------------*/
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
633f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRCASECMP_L(soname, fnname) \
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
635f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2, void* locale ); \
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
637f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2, void* locale ) \
638f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   { \
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      extern int tolower_l(int, void*) __attribute__((weak)); \
640f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      register unsigned char c1; \
641f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      register unsigned char c2; \
642f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      while (True) { \
643f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         c1 = tolower_l(*(unsigned char *)s1, locale); \
644f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         c2 = tolower_l(*(unsigned char *)s2, locale); \
645f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (c1 != c2) break; \
646f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (c1 == 0) break; \
647f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         s1++; s2++; \
648f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      } \
649f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if ((unsigned char)c1 < (unsigned char)c2) return -1; \
650f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if ((unsigned char)c1 > (unsigned char)c2) return 1; \
651f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      return 0; \
652f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
653f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
654f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux)
655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
662f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif
663f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
664f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncasecmp_l ----------------------*/
666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
667f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRNCASECMP_L(soname, fnname) \
668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
669f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
671f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root          ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
672f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   { \
673f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      extern int tolower_l(int, void*) __attribute__((weak));    \
674f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      SizeT n = 0; \
675f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      while (True) { \
676f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (n >= nmax) return 0; \
677f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (*s1 == 0 && *s2 == 0) return 0; \
678f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (*s1 == 0) return -1; \
679f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (*s2 == 0) return 1; \
680f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         \
681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (tolower_l(*(unsigned char*)s1, locale) \
682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             < tolower_l(*(unsigned char*)s2, locale)) return -1; \
683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (tolower_l(*(unsigned char*)s1, locale) \
684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             > tolower_l(*(unsigned char*)s2, locale)) return 1; \
685f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         \
686f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         s1++; s2++; n++; \
687f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      } \
688f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
689f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
690f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux)
691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l)
694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
695f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#elif defined(VGO_darwin)
696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STRNCASECMP_L(VG_Z_DYLD,        strncasecmp_l)
698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
699f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif
700f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
701f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcmp ----------------------*/
703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCMP(soname, fnname) \
705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( const char* s1, const char* s2 ); \
707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( const char* s1, const char* s2 ) \
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register unsigned char c1; \
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register unsigned char c2; \
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) { \
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         c1 = *(unsigned char *)s1; \
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         c2 = *(unsigned char *)s2; \
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c1 != c2) break; \
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c1 == 0) break; \
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s1++; s2++; \
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((unsigned char)c1 < (unsigned char)c2) return -1; \
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((unsigned char)c1 > (unsigned char)c2) return 1; \
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0; \
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME,          strcmp)
726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME,          __GI_strcmp)
727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LD64_SO_1,            strcmp)
729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif
732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRCMP(VG_Z_LIBC_SONAME,          strcmp)
735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME, strcmp)
736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memchr ----------------------*/
741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMCHR(soname, fnname) \
743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (const void *s, int c, SizeT n); \
745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (const void *s, int c, SizeT n) \
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT i; \
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar c0 = (UChar)c; \
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* p = (UChar*)s; \
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n; i++) \
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (p[i] == c0) return (void*)(&p[i]); \
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL; \
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCHR(VG_Z_LIBC_SONAME, memchr)
758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMCHR(VG_Z_LIBC_SONAME, memchr)
761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMCHR(VG_Z_DYLD,        memchr)
762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------- memrchr ----------------------*/
767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define MEMRCHR(soname, fnname) \
769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (const void *s, int c, SizeT n); \
771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (const void *s, int c, SizeT n) \
773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   { \
774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      SizeT i; \
775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar c0 = (UChar)c; \
776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar* p = (UChar*)s; \
777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < n; i++) \
778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (p[n-1-i] == c0) return (void*)(&p[n-1-i]); \
779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return NULL; \
780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGO_linux)
783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGO_darwin)
786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMRCHR(VG_Z_DYLD,        memrchr)
788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memcpy ----------------------*/
793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check)  \
795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( void *dst, const void *src, SizeT len ); \
797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( void *dst, const void *src, SizeT len ) \
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (do_ol_check && is_overlap(dst, src, len, len)) \
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Addr WS = sizeof(UWord); /* 8 or 4 */ \
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Addr WM = WS - 1;        /* 7 or 3 */ \
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (len > 0) { \
807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dst < src) { \
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         \
809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Copying backwards. */ \
810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            SizeT n = len; \
811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            Addr  d = (Addr)dst; \
812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            Addr  s = (Addr)src; \
813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            \
814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (((s^d) & WM) == 0) { \
815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* s and d have same UWord alignment. */ \
816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Pull up to a UWord boundary. */ \
817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               while ((s & WM) != 0 && n >= 1) \
818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Copy UWords. */ \
820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               while (n >= WS) \
821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (n == 0) \
823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  return dst; \
824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } \
825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (((s|d) & 1) == 0) { \
826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Both are 16-aligned; copy what we can thusly. */ \
827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               while (n >= 2) \
828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } \
830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Copy leftovers, or everything if misaligned. */ \
831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            while (n >= 1) \
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         \
834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else if (dst > src) { \
835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         \
836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            SizeT n = len; \
837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            Addr  d = ((Addr)dst) + n; \
838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            Addr  s = ((Addr)src) + n; \
839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            \
840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Copying forwards. */ \
841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (((s^d) & WM) == 0) { \
842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* s and d have same UWord alignment. */ \
843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Back down to a UWord boundary. */ \
844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               while ((s & WM) != 0 && n >= 1) \
845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Copy UWords. */ \
847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               while (n >= WS) \
848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (n == 0) \
850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  return dst; \
851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } \
852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (((s|d) & 1) == 0) { \
853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Both are 16-aligned; copy what we can thusly. */ \
854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               while (n >= 2) \
855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } \
857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Copy leftovers, or everything if misaligned. */ \
858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            while (n >= 1) \
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            \
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst; \
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MEMMOVE(soname, fnname)  \
868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MEMCPY(soname, fnname) \
871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* For older memcpy we have to use memmove-like semantics and skip
875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    the overlap check; sigh; see #275284. */
876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME,  memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME,  memcpy) /* fallback case */
879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LD_SO_1,      memcpy) /* ld.so.1 */
880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LD64_SO_1,    memcpy) /* ld64.so.1 */
881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* icc9 blats these around all over the place.  Not only in the main
882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    executable but various .so's.  They are highly tuned and read
883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    memory beyond the source boundary (although work correctly and
884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    never go across page boundaries), so give errors when run
885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    natively, at least for misaligned source arg.  Just intercepting
886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    in the exe only until we understand more about the problem.  See
887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    http://bugs.kde.org/show_bug.cgi?id=139776
888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(NONE, ZuintelZufastZumemcpy)
890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if DARWIN_VERS <= DARWIN_10_6
893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  MEMCPY(VG_Z_LIBC_SONAME,  memcpy)
894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif
895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME,  memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME,  memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memcmp ----------------------*/
902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMCMP(soname, fnname) \
904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname)       \
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( const void *s1V, const void *s2V, SizeT n ); \
906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname)       \
907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          ( const void *s1V, const void *s2V, SizeT n )  \
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int res; \
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char a0; \
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char b0; \
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char* s1 = (unsigned char*)s1V; \
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char* s2 = (unsigned char*)s2V; \
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (n != 0) { \
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         a0 = s1[0]; \
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b0 = s2[0]; \
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s1 += 1; \
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s2 += 1; \
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = ((int)a0) - ((int)b0); \
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (res != 0) \
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return res; \
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n -= 1; \
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0; \
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LIBC_SONAME, memcmp)
930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LIBC_SONAME, bcmp)
931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LD_SO_1,     bcmp)
932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMCMP(VG_Z_LIBC_SONAME, memcmp)
935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMCMP(VG_Z_LIBC_SONAME, bcmp)
936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMCMP(VG_Z_DYLD,        memcmp)
937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMCMP(VG_Z_DYLD,        bcmp)
938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- stpcpy ----------------------*/
943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy SRC to DEST, returning the address of the terminating '\0' in
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DEST. (minor variant of strcpy) */
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STPCPY(soname, fnname) \
947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ( char* dst, const char* src ); \
949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ( char* dst, const char* src ) \
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Char* src_orig = src; \
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Char* dst_orig = dst; \
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*src) *dst++ = *src++; \
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = 0; \
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This checks for overlap after copying, unavoidable without */ \
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* pre-counting length... should be ok */ \
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst_orig,  \
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     src_orig,  \
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)dst-(Addr)dst_orig+1,  \
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)src-(Addr)src_orig+1)) \
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst; \
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LIBC_SONAME,          stpcpy)
971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LIBC_SONAME,          __GI_stpcpy)
972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LD_LINUX_SO_2,        stpcpy)
973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STPCPY(VG_Z_LIBC_SONAME,          stpcpy)
977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //STPCPY(VG_Z_DYLD,                 stpcpy)
978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memset ----------------------*/
983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Why are we bothering to intercept this?  It seems entirely
985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pointless. */
986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMSET(soname, fnname) \
988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (void *s, Int c, SizeT n); \
990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (void *s, Int c, SizeT n) \
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr a  = (Addr)s;   \
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt c4 = (c & 0xFF); \
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c4 = (c4 << 8) | c4; \
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c4 = (c4 << 16) | c4; \
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while ((a & 3) != 0 && n >= 1) \
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (n >= 4) \
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { *(UInt*)a = c4; a += 4; n -= 4; } \
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (n >= 1) \
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return s; \
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMSET(VG_Z_LIBC_SONAME, memset)
1008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //MEMSET(VG_Z_LIBC_SONAME, memset)
1011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //MEMSET(VG_Z_DYLD,        memset)
1012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMSET(VG_Z_LIBC_SONAME, memset)
1013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memmove ----------------------*/
1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* memmove -- use the MEMMOVE defn above. */
1020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove)
1024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if DARWIN_VERS <= DARWIN_10_6
1027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif
1029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME,  memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
1030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME,  memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- bcopy ----------------------*/
1036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BCOPY(soname, fnname) \
1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (const void *srcV, void *dstV, SizeT n); \
1040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (const void *srcV, void *dstV, SizeT n) \
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT i; \
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* dst = (Char*)dstV; \
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* src = (Char*)srcV; \
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dst < src) { \
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < n; i++) \
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst[i] = src[i]; \
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else  \
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dst > src) { \
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < n; i++) \
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst[n-i-1] = src[n-i-1]; \
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //BCOPY(VG_Z_DYLD,        bcopy)
1062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*-------------------- memmove_chk --------------------*/
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* glibc 2.5 variant of memmove which checks the dest is big enough.
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   There is no specific part of glibc that this is copied from. */
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT i; \
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* dst = (Char*)dstV; \
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* src = (Char*)srcV; \
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (destlen < n) \
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto badness; \
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dst < src) { \
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < n; i++) \
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst[i] = src[i]; \
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else  \
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dst > src) { \
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < n; i++) \
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst[n-i-1] = src[n-i-1]; \
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst; \
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     badness: \
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_PRINTF_BACKTRACE( \
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "*** memmove_chk: buffer overflow detected ***: " \
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "program terminated\n"); \
1095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     my_exit(127); \
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /*NOTREACHED*/ \
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return NULL; \
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
1102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*-------------------- strchrnul --------------------*/
1109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the first occurrence of C in S or the final NUL byte.  */
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC232_STRCHRNUL(soname, fnname) \
1112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (const char* s, int c_in); \
1114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (const char* s, int c_in) \
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char  c        = (unsigned char) c_in; \
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char* char_ptr = (unsigned char *)s; \
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (1) { \
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*char_ptr == 0) return char_ptr; \
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*char_ptr == c) return char_ptr; \
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         char_ptr++; \
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- rawmemchr ----------------------*/
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the first occurrence of C in S.  */
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC232_RAWMEMCHR(soname, fnname) \
1138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (const char* s, int c_in); \
1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (const char* s, int c_in) \
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char  c        = (unsigned char) c_in; \
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned char* char_ptr = (unsigned char *)s; \
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (1) { \
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*char_ptr == c) return char_ptr; \
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         char_ptr++; \
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined (VGO_linux)
1152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcpy_chk ----------------------*/
1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* glibc variant of strcpy that checks the dest is big enough.
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25___STRCPY_CHK(soname,fnname) \
1165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (char* dst, const char* src, SizeT len); \
1167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (char* dst, const char* src, SizeT len) \
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      char* ret = dst; \
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (! len) \
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto badness; \
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while ((*dst++ = *src++) != '\0') \
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (--len == 0) \
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto badness; \
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ret; \
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     badness: \
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_PRINTF_BACKTRACE( \
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "*** strcpy_chk: buffer overflow detected ***: " \
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "program terminated\n"); \
1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     my_exit(127); \
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /*NOTREACHED*/ \
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return NULL; \
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- stpcpy_chk ----------------------*/
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* glibc variant of stpcpy that checks the dest is big enough.
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25___STPCPY_CHK(soname,fnname) \
1199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (char* dst, const char* src, SizeT len); \
1201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (char* dst, const char* src, SizeT len) \
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (! len) \
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto badness; \
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while ((*dst++ = *src++) != '\0') \
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (--len == 0) \
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto badness; \
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst - 1; \
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     badness: \
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_PRINTF_BACKTRACE( \
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "*** stpcpy_chk: buffer overflow detected ***: " \
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "program terminated\n"); \
1214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     my_exit(127); \
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /*NOTREACHED*/ \
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return NULL; \
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- mempcpy ----------------------*/
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* mempcpy */
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25_MEMPCPY(soname, fnname) \
1231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( void *dst, const void *src, SizeT len ); \
1233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( void *dst, const void *src, SizeT len ) \
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register char *d; \
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register char *s; \
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT len_saved = len; \
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (len == 0) \
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst; \
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst, src, len, len)) \
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( dst > src ) { \
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = (char *)dst + len - 1; \
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s = (char *)src + len - 1; \
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len-- ) { \
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d-- = *s--; \
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else if ( dst < src ) { \
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = (char *)dst; \
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s = (char *)src; \
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len-- ) { \
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d++ = *s++; \
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (void*)( ((char*)dst) + len_saved ); \
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25_MEMPCPY(VG_Z_LD_SO_1,     mempcpy) /* ld.so.1 */
1265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*-------------------- memcpy_chk --------------------*/
1273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC26___MEMCPY_CHK(soname, fnname) \
1275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register char *d; \
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register char *s; \
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dstlen < len) goto badness; \
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (len == 0) \
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst; \
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_overlap(dst, src, len, len)) \
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( dst > src ) { \
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = (char *)dst + len - 1; \
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s = (char *)src + len - 1; \
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len-- ) { \
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d-- = *s--; \
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else if ( dst < src ) { \
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = (char *)dst; \
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s = (char *)src; \
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len-- ) { \
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d++ = *s++; \
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst; \
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     badness: \
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_PRINTF_BACKTRACE( \
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "*** memcpy_chk: buffer overflow detected ***: " \
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "program terminated\n"); \
1309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     my_exit(127); \
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /*NOTREACHED*/ \
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return NULL; \
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strstr ----------------------*/
1323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRSTR(soname, fnname) \
1325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void* haystack, void* needle); \
1327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void* haystack, void* needle) \
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* h = (UChar*)haystack; \
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* n = (UChar*)needle; \
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* find the length of n, not including terminating zero */ \
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord nlen = 0; \
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (n[nlen]) nlen++; \
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if n is the empty string, match immediately. */ \
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (nlen == 0) return h; \
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* assert(nlen >= 1); */ \
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar n0 = n[0]; \
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (1) { \
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar hh = *h; \
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (hh == 0) return NULL; \
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (hh != n0) { h++; continue; } \
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         \
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord i; \
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < nlen; i++) { \
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n[i] != h[i]) \
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break; \
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* assert(i >= 0 && i <= nlen); */ \
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i == nlen) \
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return h; \
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         \
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         h++; \
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRSTR(VG_Z_LIBC_SONAME,          strstr)
1363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strpbrk ----------------------*/
1370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRPBRK(soname, fnname) \
1372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void* sV, void* acceptV); \
1374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void* sV, void* acceptV) \
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* s = (UChar*)sV; \
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* accept = (UChar*)acceptV; \
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*  find the length of 'accept', not including terminating zero */ \
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord nacc = 0; \
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (accept[nacc]) nacc++; \
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if n is the empty string, fail immediately. */ \
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (nacc == 0) return NULL; \
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* assert(nacc >= 1); */ \
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (1) { \
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord i; \
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar sc = *s; \
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sc == 0) \
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break; \
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < nacc; i++) { \
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sc == accept[i]) \
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return s; \
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s++; \
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL; \
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
1405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcspn ----------------------*/
1412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCSPN(soname, fnname) \
1414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void* sV, void* rejectV); \
1416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void* sV, void* rejectV) \
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* s = (UChar*)sV; \
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* reject = (UChar*)rejectV; \
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* find the length of 'reject', not including terminating zero */ \
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord nrej = 0; \
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (reject[nrej]) nrej++; \
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord len = 0; \
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (1) { \
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord i; \
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar sc = *s; \
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sc == 0) \
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break; \
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < nrej; i++) { \
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sc == reject[i]) \
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break; \
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* assert(i >= 0 && i <= nrej); */ \
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i < nrej) \
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break; \
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s++; \
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len++; \
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len; \
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCSPN(VG_Z_LIBC_SONAME,          strcspn)
1448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strspn ----------------------*/
1455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define STRSPN(soname, fnname) \
1457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (void* sV, void* acceptV); \
1459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (void* sV, void* acceptV) \
1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   { \
1462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UChar* s = (UChar*)sV; \
1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UChar* accept = (UChar*)acceptV; \
1464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
1465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* find the length of 'accept', not including terminating zero */ \
1466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UWord nacc = 0; \
1467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (accept[nacc]) nacc++; \
1468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (nacc == 0) return 0; \
1469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
1470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UWord len = 0; \
1471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (1) { \
1472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UWord i; \
1473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar sc = *s; \
1474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (sc == 0) \
1475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break; \
1476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         for (i = 0; i < nacc; i++) { \
1477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (sc == accept[i]) \
1478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break; \
1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } \
1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* assert(i >= 0 && i <= nacc); */ \
1481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (i == nacc) \
1482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break; \
1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         s++; \
1484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         len++; \
1485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } \
1486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
1487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return len; \
1488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRSPN(VG_Z_LIBC_SONAME,          strspn)
1492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcasestr ----------------------*/
1499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define STRCASESTR(soname, fnname) \
1501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (void* haystack, void* needle); \
1503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (void* haystack, void* needle) \
1505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   { \
1506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      extern int tolower(int); \
1507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UChar* h = (UChar*)haystack; \
1508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UChar* n = (UChar*)needle; \
1509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
1510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* find the length of n, not including terminating zero */ \
1511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UWord nlen = 0; \
1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (n[nlen]) nlen++; \
1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* if n is the empty string, match immediately. */ \
1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (nlen == 0) return h; \
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* assert(nlen >= 1); */ \
1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UChar n0 = tolower(n[0]);                 \
1519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      \
1520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (1) { \
1521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar hh = tolower(*h);    \
1522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (hh == 0) return NULL; \
1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (hh != n0) { h++; continue; } \
1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         \
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UWord i; \
1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         for (i = 0; i < nlen; i++) { \
1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (tolower(n[i]) != tolower(h[i]))  \
1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break; \
1529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } \
1530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* assert(i >= 0 && i <= nlen); */ \
1531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (i == nlen) \
1532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return h; \
1533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         \
1534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         h++; \
1535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } \
1536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
1539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android)
1540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  STRCASESTR(VG_Z_LIBC_SONAME,      strcasestr)
1541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif
1542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGO_darwin)
1544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
1546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------- wcslen ----------------------*/
1549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// This is a wchar_t equivalent to strlen.  Unfortunately
1551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// we don't have wchar_t available here, but it looks like
1552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// a 32 bit int on Linux.  I don't know if that is also
1553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// valid on MacOSX.
1554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define WCSLEN(soname, fnname) \
1556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( const UInt* str ); \
1558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( const UInt* str )  \
1560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   { \
1561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      SizeT i = 0; \
1562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      while (str[i] != 0) i++; \
1563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return i; \
1564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGO_linux)
1567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng WCSLEN(VG_Z_LIBC_SONAME,          wcslen)
1568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
1570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Improve definedness checking of process environment  ---*/
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* If these wind up getting generated via a macro, so that multiple
1581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   versions of each function exist (as above), use the _EZU variants
1582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to assign equivalance class tags. */
1583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- putenv ----------------------*/
1585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    OrigFn fn;
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Word result;
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char* p = string;
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VALGRIND_GET_ORIG_FN(fn);
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Now by walking over the string we magically produce
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       traces when hitting undefined memory. */
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p)
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (*p++)
1597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            __asm__ __volatile__("" ::: "memory");
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CALL_FN_W_W(result, fn, string);
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return result;
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- unsetenv ----------------------*/
1604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    OrigFn fn;
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Word result;
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char* p = name;
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VALGRIND_GET_ORIG_FN(fn);
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Now by walking over the string we magically produce
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       traces when hitting undefined memory. */
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p)
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (*p++)
1616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            __asm__ __volatile__("" ::: "memory");
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CALL_FN_W_W(result, fn, name);
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return result;
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- setenv ----------------------*/
1623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* setenv */
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    (const char* name, const char* value, int overwrite);
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    (const char* name, const char* value, int overwrite)
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    OrigFn fn;
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Word result;
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char* p;
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VALGRIND_GET_ORIG_FN(fn);
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Now by walking over the string we magically produce
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       traces when hitting undefined memory. */
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (name)
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for (p = name; *p; p++)
1638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            __asm__ __volatile__("" ::: "memory");
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (value)
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for (p = value; *p; p++)
1641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            __asm__ __volatile__("" ::: "memory");
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CALL_FN_W_WWW(result, fn, name, value, overwrite);
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return result;
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* defined(VGO_linux) */
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1652