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