blob: ddaf5121e8c48753c65a196e42ab8ea72a170bb1 [file] [log] [blame]
njn3e884182003-04-15 13:03:23 +00001
2/*--------------------------------------------------------------------*/
3/*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/
4/*--- simulated CPU. ---*/
njn1d0825f2006-03-27 11:37:07 +00005/*--- mc_replace_strmem.c ---*/
njn3e884182003-04-15 13:03:23 +00006/*--------------------------------------------------------------------*/
7
8/*
nethercote137bc552003-11-14 17:47:54 +00009 This file is part of MemCheck, a heavyweight Valgrind tool for
njn0e1b5142003-04-15 14:58:06 +000010 detecting memory errors.
njn3e884182003-04-15 13:03:23 +000011
sewardj9eecbbb2010-05-03 21:37:12 +000012 Copyright (C) 2000-2010 Julian Seward
njn3e884182003-04-15 13:03:23 +000013 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
njnc7561b92005-06-19 01:24:32 +000033#include "pub_tool_basics.h"
njnc7561b92005-06-19 01:24:32 +000034#include "pub_tool_hashtable.h"
njnc7561b92005-06-19 01:24:32 +000035#include "pub_tool_redir.h"
36#include "pub_tool_tooliface.h"
37#include "valgrind.h"
38
njn34419c12003-05-02 17:24:29 +000039#include "mc_include.h"
fitzhardinge98abfc72003-12-16 02:05:15 +000040#include "memcheck.h"
njn3e884182003-04-15 13:03:23 +000041
njn3e884182003-04-15 13:03:23 +000042/* ---------------------------------------------------------------------
njn1f8b3e72005-03-22 04:27:14 +000043 We have our own versions of these functions for two reasons:
44 (a) it allows us to do overlap checking
45 (b) some of the normal versions are hyper-optimised, which fools
46 Memcheck and cause spurious value warnings. Our versions are
47 simpler.
48
njn16eeb4e2005-06-16 03:56:58 +000049 Note that overenthusiastic use of PLT bypassing by the glibc people also
50 means that we need to patch multiple versions of some of the functions to
51 our own implementations.
52
njn1f8b3e72005-03-22 04:27:14 +000053 THEY RUN ON THE SIMD CPU!
njn3e884182003-04-15 13:03:23 +000054 ------------------------------------------------------------------ */
55
sewardj96044842011-08-18 13:09:55 +000056/* Assignment of behavioural equivalence class tags: 2NNNP is intended
sewardjbd2cff22011-08-16 21:45:28 +000057 to be reserved for Memcheck. Current usage:
58
sewardj96044842011-08-18 13:09:55 +000059 20010 STRRCHR
60 20020 STRCHR
61 20030 STRCAT
62 20040 STRNCAT
63 20050 STRLCAT
64 20060 STRNLEN
65 20070 STRLEN
66 20080 STRCPY
67 20090 STRNCPY
68 20100 STRLCPY
69 20110 STRNCMP
70 20120 STRCASECMP
71 20130 STRNCASECMP
72 20140 STRCASECMP_L
73 20150 STRNCASECMP_L
74 20160 STRCMP
75 20170 MEMCHR
76
77 20180 MEMCPY if there's a conflict between memcpy and
78 20181 MEMMOVE memmove, prefer memmove
79
80 20190 MEMCMP
81 20200 STPCPY
82 20210 MEMSET
83 2022P unused (was previously MEMMOVE)
84 20230 BCOPY
85 20240 GLIBC25___MEMMOVE_CHK
86 20250 GLIBC232_STRCHRNUL
87 20260 GLIBC232_RAWMEMCHR
88 20270 GLIBC25___STRCPY_CHK
89 20280 GLIBC25___STPCPY_CHK
90 20290 GLIBC25_MEMPCPY
91 20300 GLIBC26___MEMCPY_CHK
92 20310 STRSTR
93 20320 STRPBRK
94 20330 STRCSPN
95 20340 STRSPN
sewardjbd2cff22011-08-16 21:45:28 +000096*/
97
sewardj126e82d2011-07-12 13:33:00 +000098
sewardjdda830a2003-07-20 22:28:42 +000099/* Figure out if [dst .. dst+dstlen-1] overlaps with
100 [src .. src+srclen-1].
101 We assume that the address ranges do not wrap around
102 (which is safe since on Linux addresses >= 0xC0000000
103 are not accessible and the program will segfault in this
104 circumstance, presumably).
105*/
sewardj126e82d2011-07-12 13:33:00 +0000106static inline
njnc6168192004-11-29 13:54:10 +0000107Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
njn3e884182003-04-15 13:03:23 +0000108{
sewardjdda830a2003-07-20 22:28:42 +0000109 Addr loS, hiS, loD, hiD;
110
111 if (dstlen == 0 || srclen == 0)
112 return False;
113
114 loS = (Addr)src;
115 loD = (Addr)dst;
116 hiS = loS + srclen - 1;
117 hiD = loD + dstlen - 1;
118
119 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
120 if (loS < loD) {
121 return !(hiS < loD);
122 }
123 else if (loD < loS) {
124 return !(hiD < loS);
125 }
126 else {
127 /* They start at same place. Since we know neither of them has
128 zero length, they must overlap. */
129 return True;
130 }
njn3e884182003-04-15 13:03:23 +0000131}
132
sewardj126e82d2011-07-12 13:33:00 +0000133
134/* Call here to exit if we can't continue. On Android we can't call
135 _exit for some reason, so we have to blunt-instrument it. */
136__attribute__ ((__noreturn__))
137static inline void my_exit ( int x )
138{
139# if defined(VGPV_arm_linux_android)
140 __asm__ __volatile__(".word 0xFFFFFFFF");
141 while (1) {}
142# else
143 extern void _exit(int status);
sewardj49665422011-07-12 13:50:59 +0000144 _exit(x);
sewardj126e82d2011-07-12 13:33:00 +0000145# endif
146}
147
148
njn1f8b3e72005-03-22 04:27:14 +0000149// This is a macro rather than a function because we don't want to have an
150// extra function in the stack trace.
bart575ce8e2011-05-15 07:04:03 +0000151#define RECORD_OVERLAP_ERROR(s, src, dst, len) \
152 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
153 _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \
154 s, src, dst, len, 0)
njn3e884182003-04-15 13:03:23 +0000155
njn16eeb4e2005-06-16 03:56:58 +0000156
sewardj3c944452011-09-05 20:39:57 +0000157/*---------------------- strrchr ----------------------*/
158
njn16eeb4e2005-06-16 03:56:58 +0000159#define STRRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000160 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
161 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000162 { \
163 UChar ch = (UChar)((UInt)c); \
164 UChar* p = (UChar*)s; \
165 UChar* last = NULL; \
166 while (True) { \
167 if (*p == ch) last = p; \
168 if (*p == 0) return last; \
169 p++; \
170 } \
njn3e884182003-04-15 13:03:23 +0000171 }
njn3e884182003-04-15 13:03:23 +0000172
njn16eeb4e2005-06-16 03:56:58 +0000173// Apparently rindex() is the same thing as strrchr()
njnb4cfbc42009-05-04 04:20:02 +0000174#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000175 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
176 STRRCHR(VG_Z_LIBC_SONAME, rindex)
177 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
178 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
sewardj4157d4f2011-09-05 22:18:13 +0000179
njnf76d27a2009-05-28 01:53:07 +0000180#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000181 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
182 STRRCHR(VG_Z_LIBC_SONAME, rindex)
183 STRRCHR(VG_Z_DYLD, strrchr)
184 STRRCHR(VG_Z_DYLD, rindex)
sewardj4157d4f2011-09-05 22:18:13 +0000185
njnb4cfbc42009-05-04 04:20:02 +0000186#endif
njn16eeb4e2005-06-16 03:56:58 +0000187
188
sewardj3c944452011-09-05 20:39:57 +0000189/*---------------------- strchr ----------------------*/
190
njn16eeb4e2005-06-16 03:56:58 +0000191#define STRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000192 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
193 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000194 { \
195 UChar ch = (UChar)((UInt)c); \
196 UChar* p = (UChar*)s; \
197 while (True) { \
198 if (*p == ch) return p; \
199 if (*p == 0) return NULL; \
200 p++; \
201 } \
njn3e884182003-04-15 13:03:23 +0000202 }
njn3e884182003-04-15 13:03:23 +0000203
njn16eeb4e2005-06-16 03:56:58 +0000204// Apparently index() is the same thing as strchr()
njnb4cfbc42009-05-04 04:20:02 +0000205#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000206 STRCHR(VG_Z_LIBC_SONAME, strchr)
207 STRCHR(VG_Z_LIBC_SONAME, index)
208 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
209# if !defined(VGP_x86_linux)
210 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
211 STRCHR(VG_Z_LD_LINUX_SO_2, index)
212 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
213 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
214# endif
sewardj4157d4f2011-09-05 22:18:13 +0000215
njnf76d27a2009-05-28 01:53:07 +0000216#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000217 STRCHR(VG_Z_LIBC_SONAME, strchr)
218 STRCHR(VG_Z_LIBC_SONAME, index)
219 STRCHR(VG_Z_DYLD, strchr)
220 STRCHR(VG_Z_DYLD, index)
sewardj4157d4f2011-09-05 22:18:13 +0000221
njnb4cfbc42009-05-04 04:20:02 +0000222#endif
njn3e884182003-04-15 13:03:23 +0000223
njn3e884182003-04-15 13:03:23 +0000224
sewardj3c944452011-09-05 20:39:57 +0000225/*---------------------- strcat ----------------------*/
226
njn16eeb4e2005-06-16 03:56:58 +0000227#define STRCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000228 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000229 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000230 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000231 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000232 { \
233 const Char* src_orig = src; \
234 Char* dst_orig = dst; \
235 while (*dst) dst++; \
236 while (*src) *dst++ = *src++; \
237 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000238 \
njn16eeb4e2005-06-16 03:56:58 +0000239 /* This is a bit redundant, I think; any overlap and the strcat will */ \
240 /* go forever... or until a seg fault occurs. */ \
241 if (is_overlap(dst_orig, \
242 src_orig, \
243 (Addr)dst-(Addr)dst_orig+1, \
244 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000245 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000246 \
njn16eeb4e2005-06-16 03:56:58 +0000247 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000248 }
njn3e884182003-04-15 13:03:23 +0000249
tomd2645142009-10-29 09:27:11 +0000250#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000251 STRCAT(VG_Z_LIBC_SONAME, strcat)
252 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
sewardj4157d4f2011-09-05 22:18:13 +0000253
sewardj3c944452011-09-05 20:39:57 +0000254#elif defined(VGO_darwin)
255 STRCAT(VG_Z_LIBC_SONAME, strcat)
sewardj4157d4f2011-09-05 22:18:13 +0000256
tomd2645142009-10-29 09:27:11 +0000257#endif
njn16eeb4e2005-06-16 03:56:58 +0000258
sewardj3c944452011-09-05 20:39:57 +0000259
260/*---------------------- strncat ----------------------*/
261
njn16eeb4e2005-06-16 03:56:58 +0000262#define STRNCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000263 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000264 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000265 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000266 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000267 { \
268 const Char* src_orig = src; \
269 Char* dst_orig = dst; \
270 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000271 \
njn16eeb4e2005-06-16 03:56:58 +0000272 while (*dst) dst++; \
273 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
274 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000275 \
njn16eeb4e2005-06-16 03:56:58 +0000276 /* This checks for overlap after copying, unavoidable without */ \
277 /* pre-counting lengths... should be ok */ \
278 if (is_overlap(dst_orig, \
279 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000280 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000281 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000282 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000283 \
njn16eeb4e2005-06-16 03:56:58 +0000284 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000285 }
njn3e884182003-04-15 13:03:23 +0000286
sewardj3c944452011-09-05 20:39:57 +0000287#if defined(VGO_linux)
288 STRNCAT(VG_Z_LIBC_SONAME, strncat)
sewardj4157d4f2011-09-05 22:18:13 +0000289
sewardj3c944452011-09-05 20:39:57 +0000290#elif defined(VGO_darwin)
291 STRNCAT(VG_Z_LIBC_SONAME, strncat)
292 STRNCAT(VG_Z_DYLD, strncat)
sewardj4157d4f2011-09-05 22:18:13 +0000293
njnf76d27a2009-05-28 01:53:07 +0000294#endif
295
296
sewardj3c944452011-09-05 20:39:57 +0000297/*---------------------- strlcat ----------------------*/
298
njnf76d27a2009-05-28 01:53:07 +0000299/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
300 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
301 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
302 Truncation occurred if retval >= n.
303*/
304#define STRLCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000305 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000306 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000307 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000308 ( char* dst, const char* src, SizeT n ) \
309 { \
310 const Char* src_orig = src; \
311 Char* dst_orig = dst; \
312 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000313 \
njnf76d27a2009-05-28 01:53:07 +0000314 while (m < n && *dst) { m++; dst++; } \
315 if (m < n) { \
316 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
317 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
318 *dst = 0; \
319 } else { \
320 /* No space to copy anything to dst. m == n */ \
321 } \
322 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
323 while (*src) { m++; src++; } \
324 /* This checks for overlap after copying, unavoidable without */ \
325 /* pre-counting lengths... should be ok */ \
326 if (is_overlap(dst_orig, \
327 src_orig, \
328 (Addr)dst-(Addr)dst_orig+1, \
329 (Addr)src-(Addr)src_orig+1)) \
330 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
sewardjbd2cff22011-08-16 21:45:28 +0000331 \
njnf76d27a2009-05-28 01:53:07 +0000332 return m; \
333 }
334
sewardj3c944452011-09-05 20:39:57 +0000335#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000336
sewardj3c944452011-09-05 20:39:57 +0000337#elif defined(VGO_darwin)
338 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
339 STRLCAT(VG_Z_DYLD, strlcat)
sewardj4157d4f2011-09-05 22:18:13 +0000340
njnf76d27a2009-05-28 01:53:07 +0000341#endif
sewardj31b9ce12006-10-17 01:27:13 +0000342
njn3e884182003-04-15 13:03:23 +0000343
sewardj3c944452011-09-05 20:39:57 +0000344/*---------------------- strnlen ----------------------*/
345
njn16eeb4e2005-06-16 03:56:58 +0000346#define STRNLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000347 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000348 ( const char* str, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000349 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000350 ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000351 { \
352 SizeT i = 0; \
353 while (i < n && str[i] != 0) i++; \
354 return i; \
njn3e884182003-04-15 13:03:23 +0000355 }
njn3e884182003-04-15 13:03:23 +0000356
tomd2645142009-10-29 09:27:11 +0000357#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000358 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
359 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
sewardj4157d4f2011-09-05 22:18:13 +0000360
sewardj3c944452011-09-05 20:39:57 +0000361#elif defined(VGO_darwin)
362 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
sewardj4157d4f2011-09-05 22:18:13 +0000363
tomd2645142009-10-29 09:27:11 +0000364#endif
njn16eeb4e2005-06-16 03:56:58 +0000365
sewardj3ceec242003-07-30 21:24:25 +0000366
sewardj3c944452011-09-05 20:39:57 +0000367/*---------------------- strlen ----------------------*/
368
njn5ec15ed2005-08-24 19:55:51 +0000369// Note that this replacement often doesn't get used because gcc inlines
370// calls to strlen() with its own built-in version. This can be very
sewardj3c944452011-09-05 20:39:57 +0000371// confusing if you aren't expecting it. Other small functions in
372// this file may also be inline by gcc.
373
njn16eeb4e2005-06-16 03:56:58 +0000374#define STRLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000375 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000376 ( const char* str ); \
sewardj96044842011-08-18 13:09:55 +0000377 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000378 ( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000379 { \
380 SizeT i = 0; \
381 while (str[i] != 0) i++; \
382 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000383 }
njn16eeb4e2005-06-16 03:56:58 +0000384
njnb4cfbc42009-05-04 04:20:02 +0000385#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000386 STRLEN(VG_Z_LIBC_SONAME, strlen)
387 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
sewardj4157d4f2011-09-05 22:18:13 +0000388
sewardj3c944452011-09-05 20:39:57 +0000389#elif defined(VGO_darwin)
390 STRLEN(VG_Z_LIBC_SONAME, strlen)
sewardj4157d4f2011-09-05 22:18:13 +0000391
njnb4cfbc42009-05-04 04:20:02 +0000392#endif
sewardj31b9ce12006-10-17 01:27:13 +0000393
njn16eeb4e2005-06-16 03:56:58 +0000394
sewardj3c944452011-09-05 20:39:57 +0000395/*---------------------- strcpy ----------------------*/
396
njn16eeb4e2005-06-16 03:56:58 +0000397#define STRCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000398 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000399 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000400 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000401 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000402 { \
403 const Char* src_orig = src; \
404 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000405 \
njn16eeb4e2005-06-16 03:56:58 +0000406 while (*src) *dst++ = *src++; \
407 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000408 \
njn16eeb4e2005-06-16 03:56:58 +0000409 /* This checks for overlap after copying, unavoidable without */ \
410 /* pre-counting length... should be ok */ \
411 if (is_overlap(dst_orig, \
412 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000413 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000414 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000415 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000416 \
njn16eeb4e2005-06-16 03:56:58 +0000417 return dst_orig; \
418 }
419
tomd2645142009-10-29 09:27:11 +0000420#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000421 STRCPY(VG_Z_LIBC_SONAME, strcpy)
422 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000423
tomd2645142009-10-29 09:27:11 +0000424#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000425 STRCPY(VG_Z_LIBC_SONAME, strcpy)
426 STRCPY(VG_Z_DYLD, strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000427
njnf76d27a2009-05-28 01:53:07 +0000428#endif
njn16eeb4e2005-06-16 03:56:58 +0000429
430
sewardj3c944452011-09-05 20:39:57 +0000431/*---------------------- strncpy ----------------------*/
432
njn16eeb4e2005-06-16 03:56:58 +0000433#define STRNCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000434 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000435 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000436 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000437 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000438 { \
439 const Char* src_orig = src; \
440 Char* dst_orig = dst; \
441 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000442 \
njn16eeb4e2005-06-16 03:56:58 +0000443 while (m < n && *src) { m++; *dst++ = *src++; } \
444 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
445 /* but only m+1 bytes of src if terminator was found */ \
446 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000447 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000448 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
sewardj3c944452011-09-05 20:39:57 +0000449 \
njn16eeb4e2005-06-16 03:56:58 +0000450 return dst_orig; \
451 }
452
tomd2645142009-10-29 09:27:11 +0000453#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000454 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
455 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000456
tomd2645142009-10-29 09:27:11 +0000457#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000458 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
459 STRNCPY(VG_Z_DYLD, strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000460
njnf76d27a2009-05-28 01:53:07 +0000461#endif
462
463
sewardj3c944452011-09-05 20:39:57 +0000464/*---------------------- strlcpy ----------------------*/
465
njnf76d27a2009-05-28 01:53:07 +0000466/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
467 Returns strlen(src). Does not zero-fill the remainder of dst. */
468#define STRLCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000469 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000470 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000471 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000472 ( char* dst, const char* src, SizeT n ) \
473 { \
474 const char* src_orig = src; \
475 char* dst_orig = dst; \
476 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000477 \
njnf76d27a2009-05-28 01:53:07 +0000478 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
479 /* m non-nul bytes have now been copied, and m <= n-1. */ \
480 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
481 /* but only m+1 bytes of src if terminator was found */ \
482 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
483 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
484 /* Nul-terminate dst. */ \
485 if (n > 0) *dst = 0; \
486 /* Finish counting strlen(src). */ \
487 while (*src) src++; \
488 return src - src_orig; \
489 }
490
sewardj3c944452011-09-05 20:39:57 +0000491#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000492
sewardj3c944452011-09-05 20:39:57 +0000493#elif defined(VGO_darwin)
494 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
495 STRLCPY(VG_Z_DYLD, strlcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000496
njnf76d27a2009-05-28 01:53:07 +0000497#endif
njn16eeb4e2005-06-16 03:56:58 +0000498
499
sewardj3c944452011-09-05 20:39:57 +0000500/*---------------------- strncmp ----------------------*/
501
njn16eeb4e2005-06-16 03:56:58 +0000502#define STRNCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000503 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000504 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000505 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000506 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000507 { \
508 SizeT n = 0; \
509 while (True) { \
510 if (n >= nmax) return 0; \
511 if (*s1 == 0 && *s2 == 0) return 0; \
512 if (*s1 == 0) return -1; \
513 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000514 \
njn16eeb4e2005-06-16 03:56:58 +0000515 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
516 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000517 \
njn16eeb4e2005-06-16 03:56:58 +0000518 s1++; s2++; n++; \
519 } \
520 }
521
tomd2645142009-10-29 09:27:11 +0000522#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000523 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
524 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000525
tomd2645142009-10-29 09:27:11 +0000526#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000527 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
528 STRNCMP(VG_Z_DYLD, strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000529
njnf76d27a2009-05-28 01:53:07 +0000530#endif
njn16eeb4e2005-06-16 03:56:58 +0000531
532
sewardj3c944452011-09-05 20:39:57 +0000533/*---------------------- strcasecmp ----------------------*/
534
tomce6d0ac2010-11-12 10:03:13 +0000535#define STRCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000536 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000537 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000538 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000539 ( const char* s1, const char* s2 ) \
540 { \
tome03c8c42010-11-12 10:40:20 +0000541 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000542 register unsigned char c1; \
543 register unsigned char c2; \
544 while (True) { \
545 c1 = tolower(*(unsigned char *)s1); \
546 c2 = tolower(*(unsigned char *)s2); \
547 if (c1 != c2) break; \
548 if (c1 == 0) break; \
549 s1++; s2++; \
550 } \
551 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
552 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
553 return 0; \
554 }
555
sewardj3c944452011-09-05 20:39:57 +0000556#if defined(VGO_linux)
557# if !defined(VGPV_arm_linux_android)
558 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
559 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
560# endif
sewardj4157d4f2011-09-05 22:18:13 +0000561
sewardj3c944452011-09-05 20:39:57 +0000562#elif defined(VGO_darwin)
563 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000564
tomce6d0ac2010-11-12 10:03:13 +0000565#endif
566
567
sewardj3c944452011-09-05 20:39:57 +0000568/*---------------------- strncasecmp ----------------------*/
569
tomce6d0ac2010-11-12 10:03:13 +0000570#define STRNCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000571 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000572 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000573 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000574 ( const char* s1, const char* s2, SizeT nmax ) \
575 { \
tome03c8c42010-11-12 10:40:20 +0000576 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000577 SizeT n = 0; \
578 while (True) { \
579 if (n >= nmax) return 0; \
580 if (*s1 == 0 && *s2 == 0) return 0; \
581 if (*s1 == 0) return -1; \
582 if (*s2 == 0) return 1; \
583 \
sewardjbd2cff22011-08-16 21:45:28 +0000584 if (tolower(*(unsigned char*)s1) \
585 < tolower(*(unsigned char*)s2)) return -1; \
586 if (tolower(*(unsigned char*)s1) \
587 > tolower(*(unsigned char*)s2)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000588 \
589 s1++; s2++; n++; \
590 } \
591 }
592
sewardj3c944452011-09-05 20:39:57 +0000593#if defined(VGO_linux)
594# if !defined(VGPV_arm_linux_android)
595 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
596 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
597# endif
sewardj4157d4f2011-09-05 22:18:13 +0000598
tomce6d0ac2010-11-12 10:03:13 +0000599#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000600 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
601 STRNCASECMP(VG_Z_DYLD, strncasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000602
tomce6d0ac2010-11-12 10:03:13 +0000603#endif
604
605
sewardj3c944452011-09-05 20:39:57 +0000606/*---------------------- strcasecmp_l ----------------------*/
607
tomce6d0ac2010-11-12 10:03:13 +0000608#define STRCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000609 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000610 ( const char* s1, const char* s2, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000611 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000612 ( const char* s1, const char* s2, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000613 { \
sewardj3c944452011-09-05 20:39:57 +0000614 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000615 register unsigned char c1; \
616 register unsigned char c2; \
617 while (True) { \
618 c1 = tolower_l(*(unsigned char *)s1, locale); \
619 c2 = tolower_l(*(unsigned char *)s2, locale); \
620 if (c1 != c2) break; \
621 if (c1 == 0) break; \
622 s1++; s2++; \
623 } \
624 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
625 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
626 return 0; \
627 }
628
tomce6d0ac2010-11-12 10:03:13 +0000629#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000630 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
631 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
632 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000633
sewardj3c944452011-09-05 20:39:57 +0000634#elif defined(VGO_darwin)
635 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000636
tomce6d0ac2010-11-12 10:03:13 +0000637#endif
638
639
sewardj3c944452011-09-05 20:39:57 +0000640/*---------------------- strncasecmp_l ----------------------*/
641
tomce6d0ac2010-11-12 10:03:13 +0000642#define STRNCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000643 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000644 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000645 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000646 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000647 { \
tome03c8c42010-11-12 10:40:20 +0000648 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000649 SizeT n = 0; \
650 while (True) { \
651 if (n >= nmax) return 0; \
652 if (*s1 == 0 && *s2 == 0) return 0; \
653 if (*s1 == 0) return -1; \
654 if (*s2 == 0) return 1; \
655 \
sewardjbd2cff22011-08-16 21:45:28 +0000656 if (tolower_l(*(unsigned char*)s1, locale) \
657 < tolower_l(*(unsigned char*)s2, locale)) return -1; \
658 if (tolower_l(*(unsigned char*)s1, locale) \
659 > tolower_l(*(unsigned char*)s2, locale)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000660 \
661 s1++; s2++; n++; \
662 } \
663 }
664
tomce6d0ac2010-11-12 10:03:13 +0000665#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000666 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
667 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000668
tomce6d0ac2010-11-12 10:03:13 +0000669#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000670 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
671 STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000672
tomce6d0ac2010-11-12 10:03:13 +0000673#endif
674
675
sewardj3c944452011-09-05 20:39:57 +0000676/*---------------------- strcmp ----------------------*/
677
njn16eeb4e2005-06-16 03:56:58 +0000678#define STRCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000679 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000680 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000681 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000682 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000683 { \
684 register unsigned char c1; \
685 register unsigned char c2; \
686 while (True) { \
687 c1 = *(unsigned char *)s1; \
688 c2 = *(unsigned char *)s2; \
689 if (c1 != c2) break; \
690 if (c1 == 0) break; \
691 s1++; s2++; \
692 } \
693 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
694 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
695 return 0; \
696 }
697
njnb4cfbc42009-05-04 04:20:02 +0000698#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000699 STRCMP(VG_Z_LIBC_SONAME, strcmp)
700 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
701 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
702 STRCMP(VG_Z_LD64_SO_1, strcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000703
sewardj3c944452011-09-05 20:39:57 +0000704#elif defined(VGO_darwin)
705 STRCMP(VG_Z_LIBC_SONAME, strcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000706
njnb4cfbc42009-05-04 04:20:02 +0000707#endif
njn16eeb4e2005-06-16 03:56:58 +0000708
709
sewardj3c944452011-09-05 20:39:57 +0000710/*---------------------- memchr ----------------------*/
711
njn16eeb4e2005-06-16 03:56:58 +0000712#define MEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000713 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000714 (const void *s, int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000715 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000716 (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000717 { \
718 SizeT i; \
719 UChar c0 = (UChar)c; \
720 UChar* p = (UChar*)s; \
721 for (i = 0; i < n; i++) \
722 if (p[i] == c0) return (void*)(&p[i]); \
723 return NULL; \
724 }
725
sewardj3c944452011-09-05 20:39:57 +0000726#if defined(VGO_linux)
727 MEMCHR(VG_Z_LIBC_SONAME, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000728
sewardj3c944452011-09-05 20:39:57 +0000729#elif defined(VGO_darwin)
730 MEMCHR(VG_Z_LIBC_SONAME, memchr)
731 MEMCHR(VG_Z_DYLD, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000732
njnf76d27a2009-05-28 01:53:07 +0000733#endif
njn16eeb4e2005-06-16 03:56:58 +0000734
735
sewardj3c944452011-09-05 20:39:57 +0000736/*---------------------- memcpy ----------------------*/
737
sewardjbd2cff22011-08-16 21:45:28 +0000738#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
sewardjd88797f2011-08-17 21:25:50 +0000739 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000740 ( void *dst, const void *src, SizeT len ); \
sewardjd88797f2011-08-17 21:25:50 +0000741 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000742 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000743 { \
sewardjbd2cff22011-08-16 21:45:28 +0000744 if (do_ol_check && is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000745 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000746 \
sewardj7b4e00b2010-08-24 09:05:52 +0000747 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
748 const Addr WM = WS - 1; /* 7 or 3 */ \
749 \
tom863ab7c2011-08-18 08:10:20 +0000750 if (len > 0) { \
751 if (dst < src) { \
sewardj7b4e00b2010-08-24 09:05:52 +0000752 \
tom863ab7c2011-08-18 08:10:20 +0000753 /* Copying backwards. */ \
754 SizeT n = len; \
755 Addr d = (Addr)dst; \
756 Addr s = (Addr)src; \
757 \
758 if (((s^d) & WM) == 0) { \
759 /* s and d have same UWord alignment. */ \
760 /* Pull up to a UWord boundary. */ \
761 while ((s & WM) != 0 && n >= 1) \
762 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
763 /* Copy UWords. */ \
764 while (n >= WS) \
765 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
766 if (n == 0) \
767 return dst; \
768 } \
769 if (((s|d) & 1) == 0) { \
770 /* Both are 16-aligned; copy what we can thusly. */ \
771 while (n >= 2) \
772 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
773 } \
774 /* Copy leftovers, or everything if misaligned. */ \
775 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000776 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
sewardj7b4e00b2010-08-24 09:05:52 +0000777 \
tom863ab7c2011-08-18 08:10:20 +0000778 } else if (dst > src) { \
779 \
780 SizeT n = len; \
781 Addr d = ((Addr)dst) + n; \
782 Addr s = ((Addr)src) + n; \
783 \
784 /* Copying forwards. */ \
785 if (((s^d) & WM) == 0) { \
786 /* s and d have same UWord alignment. */ \
787 /* Back down to a UWord boundary. */ \
788 while ((s & WM) != 0 && n >= 1) \
789 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
790 /* Copy UWords. */ \
791 while (n >= WS) \
792 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
793 if (n == 0) \
794 return dst; \
795 } \
796 if (((s|d) & 1) == 0) { \
797 /* Both are 16-aligned; copy what we can thusly. */ \
798 while (n >= 2) \
799 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
800 } \
801 /* Copy leftovers, or everything if misaligned. */ \
802 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000803 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
tom863ab7c2011-08-18 08:10:20 +0000804 \
njn16eeb4e2005-06-16 03:56:58 +0000805 } \
njn16eeb4e2005-06-16 03:56:58 +0000806 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000807 \
njn16eeb4e2005-06-16 03:56:58 +0000808 return dst; \
809 }
810
sewardjbd2cff22011-08-16 21:45:28 +0000811#define MEMMOVE(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000812 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
sewardjbd2cff22011-08-16 21:45:28 +0000813
814#define MEMCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000815 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
sewardjbd2cff22011-08-16 21:45:28 +0000816
njnb4cfbc42009-05-04 04:20:02 +0000817#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000818 /* For older memcpy we have to use memmove-like semantics and skip
819 the overlap check; sigh; see #275284. */
820 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
821 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
822 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
823 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
824 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
sewardj3c944452011-09-05 20:39:57 +0000825 /* icc9 blats these around all over the place. Not only in the main
826 executable but various .so's. They are highly tuned and read
827 memory beyond the source boundary (although work correctly and
828 never go across page boundaries), so give errors when run
829 natively, at least for misaligned source arg. Just intercepting
830 in the exe only until we understand more about the problem. See
831 http://bugs.kde.org/show_bug.cgi?id=139776
sewardjf0b34322007-01-16 21:42:28 +0000832 */
sewardj3c944452011-09-05 20:39:57 +0000833 MEMCPY(NONE, ZuintelZufastZumemcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000834
835#elif defined(VGO_darwin)
836 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
837 MEMCPY(VG_Z_DYLD, memcpy)
838
sewardj3c944452011-09-05 20:39:57 +0000839#endif
sewardj31b9ce12006-10-17 01:27:13 +0000840
njn16eeb4e2005-06-16 03:56:58 +0000841
sewardj3c944452011-09-05 20:39:57 +0000842/*---------------------- memcmp ----------------------*/
843
njn16eeb4e2005-06-16 03:56:58 +0000844#define MEMCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000845 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000846 ( const void *s1V, const void *s2V, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000847 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000848 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000849 { \
850 int res; \
851 unsigned char a0; \
852 unsigned char b0; \
853 unsigned char* s1 = (unsigned char*)s1V; \
854 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000855 \
njn16eeb4e2005-06-16 03:56:58 +0000856 while (n != 0) { \
857 a0 = s1[0]; \
858 b0 = s2[0]; \
859 s1 += 1; \
860 s2 += 1; \
861 res = ((int)a0) - ((int)b0); \
862 if (res != 0) \
863 return res; \
864 n -= 1; \
865 } \
866 return 0; \
867 }
868
njnb4cfbc42009-05-04 04:20:02 +0000869#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000870 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
871 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
872 MEMCMP(VG_Z_LD_SO_1, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000873
njnf76d27a2009-05-28 01:53:07 +0000874#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000875 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
876 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
877 MEMCMP(VG_Z_DYLD, memcmp)
878 MEMCMP(VG_Z_DYLD, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000879
njnb4cfbc42009-05-04 04:20:02 +0000880#endif
njn3e884182003-04-15 13:03:23 +0000881
jseward0845ef82003-12-22 22:31:27 +0000882
sewardj3c944452011-09-05 20:39:57 +0000883/*---------------------- stpcpy ----------------------*/
884
jseward0845ef82003-12-22 22:31:27 +0000885/* Copy SRC to DEST, returning the address of the terminating '\0' in
886 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000887#define STPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000888 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000889 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000890 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000891 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000892 { \
893 const Char* src_orig = src; \
894 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000895 \
njn16eeb4e2005-06-16 03:56:58 +0000896 while (*src) *dst++ = *src++; \
897 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000898 \
njn16eeb4e2005-06-16 03:56:58 +0000899 /* This checks for overlap after copying, unavoidable without */ \
900 /* pre-counting length... should be ok */ \
901 if (is_overlap(dst_orig, \
902 src_orig, \
903 (Addr)dst-(Addr)dst_orig+1, \
904 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000905 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000906 \
njn16eeb4e2005-06-16 03:56:58 +0000907 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000908 }
njn16eeb4e2005-06-16 03:56:58 +0000909
njnb4cfbc42009-05-04 04:20:02 +0000910#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000911 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
912 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
913 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
914 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000915
njnf76d27a2009-05-28 01:53:07 +0000916#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000917 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
918 STPCPY(VG_Z_DYLD, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000919
njnb4cfbc42009-05-04 04:20:02 +0000920#endif
921
njn16eeb4e2005-06-16 03:56:58 +0000922
sewardj3c944452011-09-05 20:39:57 +0000923/*---------------------- memset ----------------------*/
924
925/* Why are we bothering to intercept this? It seems entirely
926 pointless. */
njn16eeb4e2005-06-16 03:56:58 +0000927#define MEMSET(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000928 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000929 (void *s, Int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000930 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000931 (void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000932 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000933 Addr a = (Addr)s; \
934 UInt c4 = (c & 0xFF); \
935 c4 = (c4 << 8) | c4; \
936 c4 = (c4 << 16) | c4; \
937 while ((a & 3) != 0 && n >= 1) \
938 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
939 while (n >= 4) \
940 { *(UInt*)a = c4; a += 4; n -= 4; } \
941 while (n >= 1) \
942 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000943 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000944 }
njn16eeb4e2005-06-16 03:56:58 +0000945
sewardj3c944452011-09-05 20:39:57 +0000946#if defined(VGO_linux)
947 MEMSET(VG_Z_LIBC_SONAME, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000948
sewardj3c944452011-09-05 20:39:57 +0000949#elif defined(VGO_darwin)
950 MEMSET(VG_Z_LIBC_SONAME, memset)
951 MEMSET(VG_Z_DYLD, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000952
njnf76d27a2009-05-28 01:53:07 +0000953#endif
njn16eeb4e2005-06-16 03:56:58 +0000954
955
sewardj3c944452011-09-05 20:39:57 +0000956/*---------------------- memmove ----------------------*/
957
sewardj96044842011-08-18 13:09:55 +0000958/* memmove -- use the MEMMOVE defn above. */
sewardj3c944452011-09-05 20:39:57 +0000959#if defined(VGO_linux)
960 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
sewardj4157d4f2011-09-05 22:18:13 +0000961
sewardj3c944452011-09-05 20:39:57 +0000962#elif defined(VGO_darwin)
963 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
964 MEMMOVE(VG_Z_DYLD, memmove)
sewardj4157d4f2011-09-05 22:18:13 +0000965
njnf76d27a2009-05-28 01:53:07 +0000966#endif
967
968
sewardj3c944452011-09-05 20:39:57 +0000969/*---------------------- bcopy ----------------------*/
970
njnf76d27a2009-05-28 01:53:07 +0000971#define BCOPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000972 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000973 (const void *srcV, void *dstV, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000974 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000975 (const void *srcV, void *dstV, SizeT n) \
976 { \
977 SizeT i; \
978 Char* dst = (Char*)dstV; \
979 Char* src = (Char*)srcV; \
980 if (dst < src) { \
981 for (i = 0; i < n; i++) \
982 dst[i] = src[i]; \
983 } \
984 else \
985 if (dst > src) { \
986 for (i = 0; i < n; i++) \
987 dst[n-i-1] = src[n-i-1]; \
988 } \
989 }
990
sewardj3c944452011-09-05 20:39:57 +0000991#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000992
sewardj3c944452011-09-05 20:39:57 +0000993#elif defined(VGO_darwin)
994 BCOPY(VG_Z_LIBC_SONAME, bcopy)
995 BCOPY(VG_Z_DYLD, bcopy)
sewardj4157d4f2011-09-05 22:18:13 +0000996
njnf76d27a2009-05-28 01:53:07 +0000997#endif
sewardj44e495f2005-05-12 17:58:28 +0000998
jseward0845ef82003-12-22 22:31:27 +0000999
sewardj3c944452011-09-05 20:39:57 +00001000/*-------------------- memmove_chk --------------------*/
1001
sewardj24cb2172007-02-23 09:03:26 +00001002/* glibc 2.5 variant of memmove which checks the dest is big enough.
1003 There is no specific part of glibc that this is copied from. */
1004#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001005 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001006 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
sewardj96044842011-08-18 13:09:55 +00001007 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001008 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1009 { \
sewardj24cb2172007-02-23 09:03:26 +00001010 SizeT i; \
1011 Char* dst = (Char*)dstV; \
1012 Char* src = (Char*)srcV; \
1013 if (destlen < n) \
1014 goto badness; \
1015 if (dst < src) { \
1016 for (i = 0; i < n; i++) \
1017 dst[i] = src[i]; \
1018 } \
1019 else \
1020 if (dst > src) { \
1021 for (i = 0; i < n; i++) \
1022 dst[n-i-1] = src[n-i-1]; \
1023 } \
1024 return dst; \
1025 badness: \
1026 VALGRIND_PRINTF_BACKTRACE( \
1027 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001028 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001029 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +00001030 /*NOTREACHED*/ \
1031 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +00001032 }
1033
sewardj3c944452011-09-05 20:39:57 +00001034#if defined(VGO_linux)
1035 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001036
sewardj3c944452011-09-05 20:39:57 +00001037#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001038
sewardj3c944452011-09-05 20:39:57 +00001039#endif
sewardj24cb2172007-02-23 09:03:26 +00001040
1041
sewardj3c944452011-09-05 20:39:57 +00001042/*-------------------- strchrnul --------------------*/
1043
sewardj4e9a4b62004-11-23 00:20:17 +00001044/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +00001045#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001046 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001047 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001048 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001049 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001050 { \
1051 unsigned char c = (unsigned char) c_in; \
1052 unsigned char* char_ptr = (unsigned char *)s; \
1053 while (1) { \
1054 if (*char_ptr == 0) return char_ptr; \
1055 if (*char_ptr == c) return char_ptr; \
1056 char_ptr++; \
1057 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001058 }
njn16eeb4e2005-06-16 03:56:58 +00001059
sewardj3c944452011-09-05 20:39:57 +00001060#if defined(VGO_linux)
1061 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4157d4f2011-09-05 22:18:13 +00001062
sewardj3c944452011-09-05 20:39:57 +00001063#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001064
sewardj3c944452011-09-05 20:39:57 +00001065#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001066
1067
sewardj3c944452011-09-05 20:39:57 +00001068/*---------------------- rawmemchr ----------------------*/
1069
sewardj4e9a4b62004-11-23 00:20:17 +00001070/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +00001071#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001072 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001073 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001074 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001075 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001076 { \
1077 unsigned char c = (unsigned char) c_in; \
1078 unsigned char* char_ptr = (unsigned char *)s; \
1079 while (1) { \
1080 if (*char_ptr == c) return char_ptr; \
1081 char_ptr++; \
1082 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001083 }
njn16eeb4e2005-06-16 03:56:58 +00001084
tomd2645142009-10-29 09:27:11 +00001085#if defined (VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001086 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1087 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
sewardj4157d4f2011-09-05 22:18:13 +00001088
sewardj3c944452011-09-05 20:39:57 +00001089#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001090
tomd2645142009-10-29 09:27:11 +00001091#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001092
sewardj3c944452011-09-05 20:39:57 +00001093
1094/*---------------------- strcpy_chk ----------------------*/
1095
sewardjdc5d8322007-01-28 06:32:01 +00001096/* glibc variant of strcpy that checks the dest is big enough.
1097 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +00001098#define GLIBC25___STRCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001099 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001100 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001101 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001102 (char* dst, const char* src, SizeT len) \
sewardj620e5262006-12-31 00:22:30 +00001103 { \
sewardj620e5262006-12-31 00:22:30 +00001104 char* ret = dst; \
1105 if (! len) \
1106 goto badness; \
1107 while ((*dst++ = *src++) != '\0') \
1108 if (--len == 0) \
1109 goto badness; \
1110 return ret; \
1111 badness: \
1112 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001113 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001114 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001115 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +00001116 /*NOTREACHED*/ \
1117 return NULL; \
1118 }
1119
sewardj3c944452011-09-05 20:39:57 +00001120#if defined(VGO_linux)
1121 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001122
sewardj3c944452011-09-05 20:39:57 +00001123#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001124
sewardj3c944452011-09-05 20:39:57 +00001125#endif
sewardj620e5262006-12-31 00:22:30 +00001126
1127
sewardj3c944452011-09-05 20:39:57 +00001128/*---------------------- stpcpy_chk ----------------------*/
1129
sewardjdc5d8322007-01-28 06:32:01 +00001130/* glibc variant of stpcpy that checks the dest is big enough.
1131 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +00001132#define GLIBC25___STPCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001133 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001134 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001135 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001136 (char* dst, const char* src, SizeT len) \
sewardjb8d03852007-01-27 00:49:44 +00001137 { \
sewardjdc5d8322007-01-28 06:32:01 +00001138 if (! len) \
1139 goto badness; \
1140 while ((*dst++ = *src++) != '\0') \
1141 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +00001142 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +00001143 return dst - 1; \
1144 badness: \
1145 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001146 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001147 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001148 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +00001149 /*NOTREACHED*/ \
1150 return NULL; \
1151 }
1152
sewardj3c944452011-09-05 20:39:57 +00001153#if defined(VGO_linux)
1154 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001155
sewardj3c944452011-09-05 20:39:57 +00001156#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001157
sewardj3c944452011-09-05 20:39:57 +00001158#endif
sewardjb8d03852007-01-27 00:49:44 +00001159
1160
sewardj3c944452011-09-05 20:39:57 +00001161/*---------------------- mempcpy ----------------------*/
1162
sewardj841b72d2006-12-31 18:55:56 +00001163/* mempcpy */
1164#define GLIBC25_MEMPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001165 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001166 ( void *dst, const void *src, SizeT len ); \
sewardj96044842011-08-18 13:09:55 +00001167 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001168 ( void *dst, const void *src, SizeT len ) \
1169 { \
1170 register char *d; \
1171 register char *s; \
1172 SizeT len_saved = len; \
1173 \
1174 if (len == 0) \
1175 return dst; \
1176 \
1177 if (is_overlap(dst, src, len, len)) \
1178 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1179 \
1180 if ( dst > src ) { \
1181 d = (char *)dst + len - 1; \
1182 s = (char *)src + len - 1; \
1183 while ( len-- ) { \
1184 *d-- = *s--; \
1185 } \
1186 } else if ( dst < src ) { \
1187 d = (char *)dst; \
1188 s = (char *)src; \
1189 while ( len-- ) { \
1190 *d++ = *s++; \
1191 } \
1192 } \
1193 return (void*)( ((char*)dst) + len_saved ); \
1194 }
1195
njnb4cfbc42009-05-04 04:20:02 +00001196#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001197 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1198 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
sewardj4157d4f2011-09-05 22:18:13 +00001199
sewardj3c944452011-09-05 20:39:57 +00001200#elif defined(VGO_darwin)
1201 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
sewardj4157d4f2011-09-05 22:18:13 +00001202
njnb4cfbc42009-05-04 04:20:02 +00001203#endif
sewardj841b72d2006-12-31 18:55:56 +00001204
1205
sewardj3c944452011-09-05 20:39:57 +00001206/*-------------------- memcpy_chk --------------------*/
1207
sewardjb6c04032007-11-13 20:52:29 +00001208#define GLIBC26___MEMCPY_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001209 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001210 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
sewardj96044842011-08-18 13:09:55 +00001211 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001212 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1213 { \
sewardjb6c04032007-11-13 20:52:29 +00001214 register char *d; \
1215 register char *s; \
1216 \
1217 if (dstlen < len) goto badness; \
1218 \
1219 if (len == 0) \
1220 return dst; \
1221 \
1222 if (is_overlap(dst, src, len, len)) \
1223 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1224 \
1225 if ( dst > src ) { \
1226 d = (char *)dst + len - 1; \
1227 s = (char *)src + len - 1; \
1228 while ( len-- ) { \
1229 *d-- = *s--; \
1230 } \
1231 } else if ( dst < src ) { \
1232 d = (char *)dst; \
1233 s = (char *)src; \
1234 while ( len-- ) { \
1235 *d++ = *s++; \
1236 } \
1237 } \
1238 return dst; \
1239 badness: \
1240 VALGRIND_PRINTF_BACKTRACE( \
1241 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001242 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001243 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001244 /*NOTREACHED*/ \
1245 return NULL; \
1246 }
1247
sewardj3c944452011-09-05 20:39:57 +00001248#if defined(VGO_linux)
1249 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001250
sewardj3c944452011-09-05 20:39:57 +00001251#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001252
sewardj3c944452011-09-05 20:39:57 +00001253#endif
sewardjb6c04032007-11-13 20:52:29 +00001254
1255
sewardj3c944452011-09-05 20:39:57 +00001256/*---------------------- strstr ----------------------*/
1257
sewardja77687c2010-08-19 13:22:34 +00001258#define STRSTR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001259 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001260 (void* haystack, void* needle); \
sewardj96044842011-08-18 13:09:55 +00001261 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001262 (void* haystack, void* needle) \
1263 { \
1264 UChar* h = (UChar*)haystack; \
1265 UChar* n = (UChar*)needle; \
1266 \
1267 /* find the length of n, not including terminating zero */ \
1268 UWord nlen = 0; \
1269 while (n[nlen]) nlen++; \
1270 \
1271 /* if n is the empty string, match immediately. */ \
1272 if (nlen == 0) return h; \
1273 \
1274 /* assert(nlen >= 1); */ \
1275 UChar n0 = n[0]; \
1276 \
1277 while (1) { \
1278 UChar hh = *h; \
1279 if (hh == 0) return NULL; \
1280 if (hh != n0) { h++; continue; } \
1281 \
1282 UWord i; \
1283 for (i = 0; i < nlen; i++) { \
1284 if (n[i] != h[i]) \
1285 break; \
1286 } \
1287 /* assert(i >= 0 && i <= nlen); */ \
1288 if (i == nlen) \
1289 return h; \
1290 \
1291 h++; \
1292 } \
1293 }
1294
1295#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001296 STRSTR(VG_Z_LIBC_SONAME, strstr)
sewardj4157d4f2011-09-05 22:18:13 +00001297
sewardj3c944452011-09-05 20:39:57 +00001298#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001299
sewardja77687c2010-08-19 13:22:34 +00001300#endif
1301
1302
sewardj3c944452011-09-05 20:39:57 +00001303/*---------------------- strpbrk ----------------------*/
1304
sewardja77687c2010-08-19 13:22:34 +00001305#define STRPBRK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001306 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001307 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001308 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001309 (void* sV, void* acceptV) \
1310 { \
1311 UChar* s = (UChar*)sV; \
1312 UChar* accept = (UChar*)acceptV; \
1313 \
1314 /* find the length of 'accept', not including terminating zero */ \
1315 UWord nacc = 0; \
1316 while (accept[nacc]) nacc++; \
1317 \
1318 /* if n is the empty string, fail immediately. */ \
1319 if (nacc == 0) return NULL; \
1320 \
1321 /* assert(nacc >= 1); */ \
1322 while (1) { \
1323 UWord i; \
1324 UChar sc = *s; \
1325 if (sc == 0) \
1326 break; \
1327 for (i = 0; i < nacc; i++) { \
1328 if (sc == accept[i]) \
1329 return s; \
1330 } \
1331 s++; \
1332 } \
1333 \
1334 return NULL; \
1335 }
1336
1337#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001338 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
sewardj4157d4f2011-09-05 22:18:13 +00001339
sewardj3c944452011-09-05 20:39:57 +00001340#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001341
sewardja77687c2010-08-19 13:22:34 +00001342#endif
1343
1344
sewardj3c944452011-09-05 20:39:57 +00001345/*---------------------- strcspn ----------------------*/
1346
sewardja77687c2010-08-19 13:22:34 +00001347#define STRCSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001348 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001349 (void* sV, void* rejectV); \
sewardj96044842011-08-18 13:09:55 +00001350 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001351 (void* sV, void* rejectV) \
1352 { \
1353 UChar* s = (UChar*)sV; \
1354 UChar* reject = (UChar*)rejectV; \
1355 \
1356 /* find the length of 'reject', not including terminating zero */ \
1357 UWord nrej = 0; \
1358 while (reject[nrej]) nrej++; \
1359 \
1360 UWord len = 0; \
1361 while (1) { \
1362 UWord i; \
1363 UChar sc = *s; \
1364 if (sc == 0) \
1365 break; \
1366 for (i = 0; i < nrej; i++) { \
1367 if (sc == reject[i]) \
1368 break; \
1369 } \
1370 /* assert(i >= 0 && i <= nrej); */ \
1371 if (i < nrej) \
1372 break; \
1373 s++; \
1374 len++; \
1375 } \
1376 \
1377 return len; \
1378 }
1379
1380#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001381 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
sewardj4157d4f2011-09-05 22:18:13 +00001382
sewardj3c944452011-09-05 20:39:57 +00001383#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001384
sewardja77687c2010-08-19 13:22:34 +00001385#endif
1386
1387
sewardj3c944452011-09-05 20:39:57 +00001388/*---------------------- strspn ----------------------*/
1389
sewardjbd2cff22011-08-16 21:45:28 +00001390#define STRSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001391 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001392 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001393 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001394 (void* sV, void* acceptV) \
1395 { \
1396 UChar* s = (UChar*)sV; \
1397 UChar* accept = (UChar*)acceptV; \
1398 \
1399 /* find the length of 'accept', not including terminating zero */ \
1400 UWord nacc = 0; \
1401 while (accept[nacc]) nacc++; \
1402 if (nacc == 0) return 0; \
1403 \
1404 UWord len = 0; \
1405 while (1) { \
1406 UWord i; \
1407 UChar sc = *s; \
1408 if (sc == 0) \
1409 break; \
1410 for (i = 0; i < nacc; i++) { \
1411 if (sc == accept[i]) \
1412 break; \
1413 } \
1414 /* assert(i >= 0 && i <= nacc); */ \
1415 if (i == nacc) \
1416 break; \
1417 s++; \
1418 len++; \
1419 } \
1420 \
1421 return len; \
1422 }
1423
1424#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001425 STRSPN(VG_Z_LIBC_SONAME, strspn)
sewardj4157d4f2011-09-05 22:18:13 +00001426
sewardj3c944452011-09-05 20:39:57 +00001427#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001428
sewardjbd2cff22011-08-16 21:45:28 +00001429#endif
sewardjba189352010-08-20 18:24:16 +00001430
1431
sewardj31b9ce12006-10-17 01:27:13 +00001432/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001433/*--- Improve definedness checking of process environment ---*/
1434/*------------------------------------------------------------*/
1435
sewardjddc00dd2007-11-27 11:42:47 +00001436#if defined(VGO_linux)
1437
sewardjbd2cff22011-08-16 21:45:28 +00001438/* If these wind up getting generated via a macro, so that multiple
1439 versions of each function exist (as above), use the _EZU variants
1440 to assign equivalance class tags. */
1441
sewardj3c944452011-09-05 20:39:57 +00001442/*---------------------- putenv ----------------------*/
1443
njne6154662009-02-10 04:23:41 +00001444int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1445int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001446{
1447 OrigFn fn;
1448 Word result;
1449 const char* p = string;
1450 VALGRIND_GET_ORIG_FN(fn);
1451 /* Now by walking over the string we magically produce
1452 traces when hitting undefined memory. */
1453 if (p)
1454 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001455 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001456 CALL_FN_W_W(result, fn, string);
1457 return result;
1458}
1459
sewardj3c944452011-09-05 20:39:57 +00001460
1461/*---------------------- unsetenv ----------------------*/
1462
njne6154662009-02-10 04:23:41 +00001463int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1464int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001465{
1466 OrigFn fn;
1467 Word result;
1468 const char* p = name;
1469 VALGRIND_GET_ORIG_FN(fn);
1470 /* Now by walking over the string we magically produce
1471 traces when hitting undefined memory. */
1472 if (p)
1473 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001474 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001475 CALL_FN_W_W(result, fn, name);
1476 return result;
1477}
1478
sewardj3c944452011-09-05 20:39:57 +00001479
1480/*---------------------- setenv ----------------------*/
1481
dirk09beb9e2007-04-19 09:47:32 +00001482/* setenv */
njne6154662009-02-10 04:23:41 +00001483int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001484 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001485int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001486 (const char* name, const char* value, int overwrite)
1487{
1488 OrigFn fn;
1489 Word result;
1490 const char* p;
1491 VALGRIND_GET_ORIG_FN(fn);
1492 /* Now by walking over the string we magically produce
1493 traces when hitting undefined memory. */
1494 if (name)
1495 for (p = name; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001496 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001497 if (value)
1498 for (p = value; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001499 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001500 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1501 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1502 return result;
1503}
1504
sewardjddc00dd2007-11-27 11:42:47 +00001505#endif /* defined(VGO_linux) */
1506
njn3e884182003-04-15 13:03:23 +00001507/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001508/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001509/*--------------------------------------------------------------------*/