blob: 1fdb7ebb39254f6cbaa758ef6a6d32006f393018 [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)
sewardj731f9cf2011-09-21 08:43:08 +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)
185 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
sewardj4157d4f2011-09-05 22:18:13 +0000186
njnb4cfbc42009-05-04 04:20:02 +0000187#endif
njn16eeb4e2005-06-16 03:56:58 +0000188
189
sewardj3c944452011-09-05 20:39:57 +0000190/*---------------------- strchr ----------------------*/
191
njn16eeb4e2005-06-16 03:56:58 +0000192#define STRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000193 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
194 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000195 { \
196 UChar ch = (UChar)((UInt)c); \
197 UChar* p = (UChar*)s; \
198 while (True) { \
199 if (*p == ch) return p; \
200 if (*p == 0) return NULL; \
201 p++; \
202 } \
njn3e884182003-04-15 13:03:23 +0000203 }
njn3e884182003-04-15 13:03:23 +0000204
njn16eeb4e2005-06-16 03:56:58 +0000205// Apparently index() is the same thing as strchr()
njnb4cfbc42009-05-04 04:20:02 +0000206#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000207 STRCHR(VG_Z_LIBC_SONAME, strchr)
208 STRCHR(VG_Z_LIBC_SONAME, index)
209 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
210# if !defined(VGP_x86_linux)
211 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
212 STRCHR(VG_Z_LD_LINUX_SO_2, index)
213 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
214 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
215# endif
sewardj4157d4f2011-09-05 22:18:13 +0000216
njnf76d27a2009-05-28 01:53:07 +0000217#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000218 //STRCHR(VG_Z_LIBC_SONAME, strchr)
219 //STRCHR(VG_Z_LIBC_SONAME, index)
220 //STRCHR(VG_Z_DYLD, strchr)
221 //STRCHR(VG_Z_DYLD, index)
222 STRCHR(VG_Z_LIBC_SONAME, strchr)
sewardj4157d4f2011-09-05 22:18:13 +0000223
njnb4cfbc42009-05-04 04:20:02 +0000224#endif
njn3e884182003-04-15 13:03:23 +0000225
njn3e884182003-04-15 13:03:23 +0000226
sewardj3c944452011-09-05 20:39:57 +0000227/*---------------------- strcat ----------------------*/
228
njn16eeb4e2005-06-16 03:56:58 +0000229#define STRCAT(soname, fnname) \
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 ); \
sewardj96044842011-08-18 13:09:55 +0000232 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000233 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000234 { \
235 const Char* src_orig = src; \
236 Char* dst_orig = dst; \
237 while (*dst) dst++; \
238 while (*src) *dst++ = *src++; \
239 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000240 \
njn16eeb4e2005-06-16 03:56:58 +0000241 /* This is a bit redundant, I think; any overlap and the strcat will */ \
242 /* go forever... or until a seg fault occurs. */ \
243 if (is_overlap(dst_orig, \
244 src_orig, \
245 (Addr)dst-(Addr)dst_orig+1, \
246 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000247 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000248 \
njn16eeb4e2005-06-16 03:56:58 +0000249 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000250 }
njn3e884182003-04-15 13:03:23 +0000251
tomd2645142009-10-29 09:27:11 +0000252#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000253 STRCAT(VG_Z_LIBC_SONAME, strcat)
254 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
sewardj4157d4f2011-09-05 22:18:13 +0000255
sewardj3c944452011-09-05 20:39:57 +0000256#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000257 //STRCAT(VG_Z_LIBC_SONAME, strcat)
sewardj4157d4f2011-09-05 22:18:13 +0000258
tomd2645142009-10-29 09:27:11 +0000259#endif
njn16eeb4e2005-06-16 03:56:58 +0000260
sewardj3c944452011-09-05 20:39:57 +0000261
262/*---------------------- strncat ----------------------*/
263
njn16eeb4e2005-06-16 03:56:58 +0000264#define STRNCAT(soname, fnname) \
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 ); \
sewardj96044842011-08-18 13:09:55 +0000267 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000268 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000269 { \
270 const Char* src_orig = src; \
271 Char* dst_orig = dst; \
272 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000273 \
njn16eeb4e2005-06-16 03:56:58 +0000274 while (*dst) dst++; \
275 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
276 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000277 \
njn16eeb4e2005-06-16 03:56:58 +0000278 /* This checks for overlap after copying, unavoidable without */ \
279 /* pre-counting lengths... should be ok */ \
280 if (is_overlap(dst_orig, \
281 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000282 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000283 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000284 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000285 \
njn16eeb4e2005-06-16 03:56:58 +0000286 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000287 }
njn3e884182003-04-15 13:03:23 +0000288
sewardj3c944452011-09-05 20:39:57 +0000289#if defined(VGO_linux)
290 STRNCAT(VG_Z_LIBC_SONAME, strncat)
sewardj4157d4f2011-09-05 22:18:13 +0000291
sewardj3c944452011-09-05 20:39:57 +0000292#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000293 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
294 //STRNCAT(VG_Z_DYLD, strncat)
sewardj4157d4f2011-09-05 22:18:13 +0000295
njnf76d27a2009-05-28 01:53:07 +0000296#endif
297
298
sewardj3c944452011-09-05 20:39:57 +0000299/*---------------------- strlcat ----------------------*/
300
njnf76d27a2009-05-28 01:53:07 +0000301/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
302 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
303 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
304 Truncation occurred if retval >= n.
305*/
306#define STRLCAT(soname, fnname) \
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 ); \
sewardj96044842011-08-18 13:09:55 +0000309 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000310 ( char* dst, const char* src, SizeT n ) \
311 { \
312 const Char* src_orig = src; \
313 Char* dst_orig = dst; \
314 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000315 \
njnf76d27a2009-05-28 01:53:07 +0000316 while (m < n && *dst) { m++; dst++; } \
317 if (m < n) { \
318 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
319 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
320 *dst = 0; \
321 } else { \
322 /* No space to copy anything to dst. m == n */ \
323 } \
324 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
325 while (*src) { m++; src++; } \
326 /* This checks for overlap after copying, unavoidable without */ \
327 /* pre-counting lengths... should be ok */ \
328 if (is_overlap(dst_orig, \
329 src_orig, \
330 (Addr)dst-(Addr)dst_orig+1, \
331 (Addr)src-(Addr)src_orig+1)) \
332 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
sewardjbd2cff22011-08-16 21:45:28 +0000333 \
njnf76d27a2009-05-28 01:53:07 +0000334 return m; \
335 }
336
sewardj3c944452011-09-05 20:39:57 +0000337#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000338
sewardj3c944452011-09-05 20:39:57 +0000339#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000340 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
341 //STRLCAT(VG_Z_DYLD, strlcat)
sewardj3c944452011-09-05 20:39:57 +0000342 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
sewardj4157d4f2011-09-05 22:18:13 +0000343
njnf76d27a2009-05-28 01:53:07 +0000344#endif
sewardj31b9ce12006-10-17 01:27:13 +0000345
njn3e884182003-04-15 13:03:23 +0000346
sewardj3c944452011-09-05 20:39:57 +0000347/*---------------------- strnlen ----------------------*/
348
njn16eeb4e2005-06-16 03:56:58 +0000349#define STRNLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000350 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000351 ( const char* str, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000352 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000353 ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000354 { \
355 SizeT i = 0; \
356 while (i < n && str[i] != 0) i++; \
357 return i; \
njn3e884182003-04-15 13:03:23 +0000358 }
njn3e884182003-04-15 13:03:23 +0000359
tomd2645142009-10-29 09:27:11 +0000360#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000361 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
362 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
sewardj4157d4f2011-09-05 22:18:13 +0000363
sewardj3c944452011-09-05 20:39:57 +0000364#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000365 //STRNLEN(VG_Z_LIBC_SONAME, strnlen)
sewardj4157d4f2011-09-05 22:18:13 +0000366
tomd2645142009-10-29 09:27:11 +0000367#endif
njn16eeb4e2005-06-16 03:56:58 +0000368
sewardj3ceec242003-07-30 21:24:25 +0000369
sewardj3c944452011-09-05 20:39:57 +0000370/*---------------------- strlen ----------------------*/
371
njn5ec15ed2005-08-24 19:55:51 +0000372// Note that this replacement often doesn't get used because gcc inlines
373// calls to strlen() with its own built-in version. This can be very
sewardj3c944452011-09-05 20:39:57 +0000374// confusing if you aren't expecting it. Other small functions in
375// this file may also be inline by gcc.
376
njn16eeb4e2005-06-16 03:56:58 +0000377#define STRLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000378 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000379 ( const char* str ); \
sewardj96044842011-08-18 13:09:55 +0000380 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000381 ( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000382 { \
383 SizeT i = 0; \
384 while (str[i] != 0) i++; \
385 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000386 }
njn16eeb4e2005-06-16 03:56:58 +0000387
njnb4cfbc42009-05-04 04:20:02 +0000388#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000389 STRLEN(VG_Z_LIBC_SONAME, strlen)
390 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
sewardj4157d4f2011-09-05 22:18:13 +0000391
sewardj3c944452011-09-05 20:39:57 +0000392#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000393 //STRLEN(VG_Z_LIBC_SONAME, strlen)
394 STRLEN(VG_Z_LIBC_SONAME, strlen)
sewardj4157d4f2011-09-05 22:18:13 +0000395
njnb4cfbc42009-05-04 04:20:02 +0000396#endif
sewardj31b9ce12006-10-17 01:27:13 +0000397
njn16eeb4e2005-06-16 03:56:58 +0000398
sewardj3c944452011-09-05 20:39:57 +0000399/*---------------------- strcpy ----------------------*/
400
njn16eeb4e2005-06-16 03:56:58 +0000401#define STRCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000402 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000403 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000404 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000405 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000406 { \
407 const Char* src_orig = src; \
408 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000409 \
njn16eeb4e2005-06-16 03:56:58 +0000410 while (*src) *dst++ = *src++; \
411 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000412 \
njn16eeb4e2005-06-16 03:56:58 +0000413 /* This checks for overlap after copying, unavoidable without */ \
414 /* pre-counting length... should be ok */ \
415 if (is_overlap(dst_orig, \
416 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000417 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000418 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000419 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000420 \
njn16eeb4e2005-06-16 03:56:58 +0000421 return dst_orig; \
422 }
423
tomd2645142009-10-29 09:27:11 +0000424#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000425 STRCPY(VG_Z_LIBC_SONAME, strcpy)
426 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000427
tomd2645142009-10-29 09:27:11 +0000428#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000429 //STRCPY(VG_Z_LIBC_SONAME, strcpy)
430 //STRCPY(VG_Z_DYLD, strcpy)
sewardj3c944452011-09-05 20:39:57 +0000431 STRCPY(VG_Z_LIBC_SONAME, strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000432
njnf76d27a2009-05-28 01:53:07 +0000433#endif
njn16eeb4e2005-06-16 03:56:58 +0000434
435
sewardj3c944452011-09-05 20:39:57 +0000436/*---------------------- strncpy ----------------------*/
437
njn16eeb4e2005-06-16 03:56:58 +0000438#define STRNCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000439 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000440 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000441 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000442 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000443 { \
444 const Char* src_orig = src; \
445 Char* dst_orig = dst; \
446 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000447 \
njn16eeb4e2005-06-16 03:56:58 +0000448 while (m < n && *src) { m++; *dst++ = *src++; } \
449 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
450 /* but only m+1 bytes of src if terminator was found */ \
451 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000452 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000453 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
sewardj3c944452011-09-05 20:39:57 +0000454 \
njn16eeb4e2005-06-16 03:56:58 +0000455 return dst_orig; \
456 }
457
tomd2645142009-10-29 09:27:11 +0000458#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000459 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
460 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000461
tomd2645142009-10-29 09:27:11 +0000462#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000463 //STRNCPY(VG_Z_LIBC_SONAME, strncpy)
464 //STRNCPY(VG_Z_DYLD, strncpy)
sewardj3c944452011-09-05 20:39:57 +0000465 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000466
njnf76d27a2009-05-28 01:53:07 +0000467#endif
468
469
sewardj3c944452011-09-05 20:39:57 +0000470/*---------------------- strlcpy ----------------------*/
471
njnf76d27a2009-05-28 01:53:07 +0000472/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
473 Returns strlen(src). Does not zero-fill the remainder of dst. */
474#define STRLCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000475 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000476 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000477 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000478 ( char* dst, const char* src, SizeT n ) \
479 { \
480 const char* src_orig = src; \
481 char* dst_orig = dst; \
482 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000483 \
njnf76d27a2009-05-28 01:53:07 +0000484 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
485 /* m non-nul bytes have now been copied, and m <= n-1. */ \
486 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
487 /* but only m+1 bytes of src if terminator was found */ \
488 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
489 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
490 /* Nul-terminate dst. */ \
491 if (n > 0) *dst = 0; \
492 /* Finish counting strlen(src). */ \
493 while (*src) src++; \
494 return src - src_orig; \
495 }
496
sewardj3c944452011-09-05 20:39:57 +0000497#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000498
sewardj3c944452011-09-05 20:39:57 +0000499#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000500 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
501 //STRLCPY(VG_Z_DYLD, strlcpy)
sewardj3c944452011-09-05 20:39:57 +0000502 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000503
njnf76d27a2009-05-28 01:53:07 +0000504#endif
njn16eeb4e2005-06-16 03:56:58 +0000505
506
sewardj3c944452011-09-05 20:39:57 +0000507/*---------------------- strncmp ----------------------*/
508
njn16eeb4e2005-06-16 03:56:58 +0000509#define STRNCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000510 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000511 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000512 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000513 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000514 { \
515 SizeT n = 0; \
516 while (True) { \
517 if (n >= nmax) return 0; \
518 if (*s1 == 0 && *s2 == 0) return 0; \
519 if (*s1 == 0) return -1; \
520 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000521 \
njn16eeb4e2005-06-16 03:56:58 +0000522 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
523 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000524 \
njn16eeb4e2005-06-16 03:56:58 +0000525 s1++; s2++; n++; \
526 } \
527 }
528
tomd2645142009-10-29 09:27:11 +0000529#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000530 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
531 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000532
tomd2645142009-10-29 09:27:11 +0000533#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000534 //STRNCMP(VG_Z_LIBC_SONAME, strncmp)
535 //STRNCMP(VG_Z_DYLD, strncmp)
536 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000537
njnf76d27a2009-05-28 01:53:07 +0000538#endif
njn16eeb4e2005-06-16 03:56:58 +0000539
540
sewardj3c944452011-09-05 20:39:57 +0000541/*---------------------- strcasecmp ----------------------*/
542
tomce6d0ac2010-11-12 10:03:13 +0000543#define STRCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000544 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000545 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000546 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000547 ( const char* s1, const char* s2 ) \
548 { \
tome03c8c42010-11-12 10:40:20 +0000549 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000550 register unsigned char c1; \
551 register unsigned char c2; \
552 while (True) { \
553 c1 = tolower(*(unsigned char *)s1); \
554 c2 = tolower(*(unsigned char *)s2); \
555 if (c1 != c2) break; \
556 if (c1 == 0) break; \
557 s1++; s2++; \
558 } \
559 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
560 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
561 return 0; \
562 }
563
sewardj3c944452011-09-05 20:39:57 +0000564#if defined(VGO_linux)
565# if !defined(VGPV_arm_linux_android)
566 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
567 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
568# endif
sewardj4157d4f2011-09-05 22:18:13 +0000569
sewardj3c944452011-09-05 20:39:57 +0000570#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000571 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000572
tomce6d0ac2010-11-12 10:03:13 +0000573#endif
574
575
sewardj3c944452011-09-05 20:39:57 +0000576/*---------------------- strncasecmp ----------------------*/
577
tomce6d0ac2010-11-12 10:03:13 +0000578#define STRNCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000579 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000580 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000581 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000582 ( const char* s1, const char* s2, SizeT nmax ) \
583 { \
tome03c8c42010-11-12 10:40:20 +0000584 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000585 SizeT n = 0; \
586 while (True) { \
587 if (n >= nmax) return 0; \
588 if (*s1 == 0 && *s2 == 0) return 0; \
589 if (*s1 == 0) return -1; \
590 if (*s2 == 0) return 1; \
591 \
sewardjbd2cff22011-08-16 21:45:28 +0000592 if (tolower(*(unsigned char*)s1) \
593 < tolower(*(unsigned char*)s2)) return -1; \
594 if (tolower(*(unsigned char*)s1) \
595 > tolower(*(unsigned char*)s2)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000596 \
597 s1++; s2++; n++; \
598 } \
599 }
600
sewardj3c944452011-09-05 20:39:57 +0000601#if defined(VGO_linux)
602# if !defined(VGPV_arm_linux_android)
603 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
604 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
605# endif
sewardj4157d4f2011-09-05 22:18:13 +0000606
tomce6d0ac2010-11-12 10:03:13 +0000607#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000608 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
609 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000610
tomce6d0ac2010-11-12 10:03:13 +0000611#endif
612
613
sewardj3c944452011-09-05 20:39:57 +0000614/*---------------------- strcasecmp_l ----------------------*/
615
tomce6d0ac2010-11-12 10:03:13 +0000616#define STRCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000617 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000618 ( const char* s1, const char* s2, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000619 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000620 ( const char* s1, const char* s2, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000621 { \
sewardj3c944452011-09-05 20:39:57 +0000622 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000623 register unsigned char c1; \
624 register unsigned char c2; \
625 while (True) { \
626 c1 = tolower_l(*(unsigned char *)s1, locale); \
627 c2 = tolower_l(*(unsigned char *)s2, locale); \
628 if (c1 != c2) break; \
629 if (c1 == 0) break; \
630 s1++; s2++; \
631 } \
632 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
633 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
634 return 0; \
635 }
636
tomce6d0ac2010-11-12 10:03:13 +0000637#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000638 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
639 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
640 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000641
sewardj3c944452011-09-05 20:39:57 +0000642#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000643 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000644
tomce6d0ac2010-11-12 10:03:13 +0000645#endif
646
647
sewardj3c944452011-09-05 20:39:57 +0000648/*---------------------- strncasecmp_l ----------------------*/
649
tomce6d0ac2010-11-12 10:03:13 +0000650#define STRNCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000651 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000652 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000653 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000654 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000655 { \
tome03c8c42010-11-12 10:40:20 +0000656 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000657 SizeT n = 0; \
658 while (True) { \
659 if (n >= nmax) return 0; \
660 if (*s1 == 0 && *s2 == 0) return 0; \
661 if (*s1 == 0) return -1; \
662 if (*s2 == 0) return 1; \
663 \
sewardjbd2cff22011-08-16 21:45:28 +0000664 if (tolower_l(*(unsigned char*)s1, locale) \
665 < tolower_l(*(unsigned char*)s2, locale)) return -1; \
666 if (tolower_l(*(unsigned char*)s1, locale) \
667 > tolower_l(*(unsigned char*)s2, locale)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000668 \
669 s1++; s2++; n++; \
670 } \
671 }
672
tomce6d0ac2010-11-12 10:03:13 +0000673#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000674 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
675 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000676
tomce6d0ac2010-11-12 10:03:13 +0000677#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000678 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
679 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000680
tomce6d0ac2010-11-12 10:03:13 +0000681#endif
682
683
sewardj3c944452011-09-05 20:39:57 +0000684/*---------------------- strcmp ----------------------*/
685
njn16eeb4e2005-06-16 03:56:58 +0000686#define STRCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000687 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000688 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000689 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000690 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000691 { \
692 register unsigned char c1; \
693 register unsigned char c2; \
694 while (True) { \
695 c1 = *(unsigned char *)s1; \
696 c2 = *(unsigned char *)s2; \
697 if (c1 != c2) break; \
698 if (c1 == 0) break; \
699 s1++; s2++; \
700 } \
701 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
702 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
703 return 0; \
704 }
705
njnb4cfbc42009-05-04 04:20:02 +0000706#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000707 STRCMP(VG_Z_LIBC_SONAME, strcmp)
708 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
709 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
710 STRCMP(VG_Z_LD64_SO_1, strcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000711
sewardj3c944452011-09-05 20:39:57 +0000712#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000713 //STRCMP(VG_Z_LIBC_SONAME, strcmp)
714 STRCMP(VG_Z_LIBC_SONAME, strcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000715
njnb4cfbc42009-05-04 04:20:02 +0000716#endif
njn16eeb4e2005-06-16 03:56:58 +0000717
718
sewardj3c944452011-09-05 20:39:57 +0000719/*---------------------- memchr ----------------------*/
720
njn16eeb4e2005-06-16 03:56:58 +0000721#define MEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000722 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000723 (const void *s, int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000724 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000725 (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000726 { \
727 SizeT i; \
728 UChar c0 = (UChar)c; \
729 UChar* p = (UChar*)s; \
730 for (i = 0; i < n; i++) \
731 if (p[i] == c0) return (void*)(&p[i]); \
732 return NULL; \
733 }
734
sewardj3c944452011-09-05 20:39:57 +0000735#if defined(VGO_linux)
736 MEMCHR(VG_Z_LIBC_SONAME, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000737
sewardj3c944452011-09-05 20:39:57 +0000738#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000739 //MEMCHR(VG_Z_LIBC_SONAME, memchr)
740 //MEMCHR(VG_Z_DYLD, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000741
njnf76d27a2009-05-28 01:53:07 +0000742#endif
njn16eeb4e2005-06-16 03:56:58 +0000743
744
sewardj3c944452011-09-05 20:39:57 +0000745/*---------------------- memcpy ----------------------*/
746
sewardjbd2cff22011-08-16 21:45:28 +0000747#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
sewardjd88797f2011-08-17 21:25:50 +0000748 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000749 ( void *dst, const void *src, SizeT len ); \
sewardjd88797f2011-08-17 21:25:50 +0000750 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000751 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000752 { \
sewardjbd2cff22011-08-16 21:45:28 +0000753 if (do_ol_check && is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000754 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000755 \
sewardj7b4e00b2010-08-24 09:05:52 +0000756 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
757 const Addr WM = WS - 1; /* 7 or 3 */ \
758 \
tom863ab7c2011-08-18 08:10:20 +0000759 if (len > 0) { \
760 if (dst < src) { \
sewardj7b4e00b2010-08-24 09:05:52 +0000761 \
tom863ab7c2011-08-18 08:10:20 +0000762 /* Copying backwards. */ \
763 SizeT n = len; \
764 Addr d = (Addr)dst; \
765 Addr s = (Addr)src; \
766 \
767 if (((s^d) & WM) == 0) { \
768 /* s and d have same UWord alignment. */ \
769 /* Pull up to a UWord boundary. */ \
770 while ((s & WM) != 0 && n >= 1) \
771 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
772 /* Copy UWords. */ \
773 while (n >= WS) \
774 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
775 if (n == 0) \
776 return dst; \
777 } \
778 if (((s|d) & 1) == 0) { \
779 /* Both are 16-aligned; copy what we can thusly. */ \
780 while (n >= 2) \
781 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
782 } \
783 /* Copy leftovers, or everything if misaligned. */ \
784 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000785 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
sewardj7b4e00b2010-08-24 09:05:52 +0000786 \
tom863ab7c2011-08-18 08:10:20 +0000787 } else if (dst > src) { \
788 \
789 SizeT n = len; \
790 Addr d = ((Addr)dst) + n; \
791 Addr s = ((Addr)src) + n; \
792 \
793 /* Copying forwards. */ \
794 if (((s^d) & WM) == 0) { \
795 /* s and d have same UWord alignment. */ \
796 /* Back down to a UWord boundary. */ \
797 while ((s & WM) != 0 && n >= 1) \
798 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
799 /* Copy UWords. */ \
800 while (n >= WS) \
801 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
802 if (n == 0) \
803 return dst; \
804 } \
805 if (((s|d) & 1) == 0) { \
806 /* Both are 16-aligned; copy what we can thusly. */ \
807 while (n >= 2) \
808 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
809 } \
810 /* Copy leftovers, or everything if misaligned. */ \
811 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000812 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
tom863ab7c2011-08-18 08:10:20 +0000813 \
njn16eeb4e2005-06-16 03:56:58 +0000814 } \
njn16eeb4e2005-06-16 03:56:58 +0000815 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000816 \
njn16eeb4e2005-06-16 03:56:58 +0000817 return dst; \
818 }
819
sewardjbd2cff22011-08-16 21:45:28 +0000820#define MEMMOVE(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000821 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
sewardjbd2cff22011-08-16 21:45:28 +0000822
823#define MEMCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000824 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
sewardjbd2cff22011-08-16 21:45:28 +0000825
njnb4cfbc42009-05-04 04:20:02 +0000826#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000827 /* For older memcpy we have to use memmove-like semantics and skip
828 the overlap check; sigh; see #275284. */
829 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
830 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
831 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
832 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
833 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
sewardj3c944452011-09-05 20:39:57 +0000834 /* icc9 blats these around all over the place. Not only in the main
835 executable but various .so's. They are highly tuned and read
836 memory beyond the source boundary (although work correctly and
837 never go across page boundaries), so give errors when run
838 natively, at least for misaligned source arg. Just intercepting
839 in the exe only until we understand more about the problem. See
840 http://bugs.kde.org/show_bug.cgi?id=139776
sewardjf0b34322007-01-16 21:42:28 +0000841 */
sewardj3c944452011-09-05 20:39:57 +0000842 MEMCPY(NONE, ZuintelZufastZumemcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000843
844#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000845 //MEMCPY(VG_Z_LIBC_SONAME, memcpy)
846 //MEMCPY(VG_Z_DYLD, memcpy)
847 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
848 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
sewardj4157d4f2011-09-05 22:18:13 +0000849
sewardj3c944452011-09-05 20:39:57 +0000850#endif
sewardj31b9ce12006-10-17 01:27:13 +0000851
njn16eeb4e2005-06-16 03:56:58 +0000852
sewardj3c944452011-09-05 20:39:57 +0000853/*---------------------- memcmp ----------------------*/
854
njn16eeb4e2005-06-16 03:56:58 +0000855#define MEMCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000856 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000857 ( const void *s1V, const void *s2V, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000858 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000859 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000860 { \
861 int res; \
862 unsigned char a0; \
863 unsigned char b0; \
864 unsigned char* s1 = (unsigned char*)s1V; \
865 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000866 \
njn16eeb4e2005-06-16 03:56:58 +0000867 while (n != 0) { \
868 a0 = s1[0]; \
869 b0 = s2[0]; \
870 s1 += 1; \
871 s2 += 1; \
872 res = ((int)a0) - ((int)b0); \
873 if (res != 0) \
874 return res; \
875 n -= 1; \
876 } \
877 return 0; \
878 }
879
njnb4cfbc42009-05-04 04:20:02 +0000880#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000881 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
882 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
883 MEMCMP(VG_Z_LD_SO_1, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000884
njnf76d27a2009-05-28 01:53:07 +0000885#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000886 //MEMCMP(VG_Z_LIBC_SONAME, memcmp)
887 //MEMCMP(VG_Z_LIBC_SONAME, bcmp)
888 //MEMCMP(VG_Z_DYLD, memcmp)
889 //MEMCMP(VG_Z_DYLD, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000890
njnb4cfbc42009-05-04 04:20:02 +0000891#endif
njn3e884182003-04-15 13:03:23 +0000892
jseward0845ef82003-12-22 22:31:27 +0000893
sewardj3c944452011-09-05 20:39:57 +0000894/*---------------------- stpcpy ----------------------*/
895
jseward0845ef82003-12-22 22:31:27 +0000896/* Copy SRC to DEST, returning the address of the terminating '\0' in
897 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000898#define STPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000899 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000900 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000901 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000902 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000903 { \
904 const Char* src_orig = src; \
905 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000906 \
njn16eeb4e2005-06-16 03:56:58 +0000907 while (*src) *dst++ = *src++; \
908 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000909 \
njn16eeb4e2005-06-16 03:56:58 +0000910 /* This checks for overlap after copying, unavoidable without */ \
911 /* pre-counting length... should be ok */ \
912 if (is_overlap(dst_orig, \
913 src_orig, \
914 (Addr)dst-(Addr)dst_orig+1, \
915 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000916 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000917 \
njn16eeb4e2005-06-16 03:56:58 +0000918 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000919 }
njn16eeb4e2005-06-16 03:56:58 +0000920
njnb4cfbc42009-05-04 04:20:02 +0000921#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000922 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
923 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
924 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
925 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000926
njnf76d27a2009-05-28 01:53:07 +0000927#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000928 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
929 //STPCPY(VG_Z_DYLD, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000930
njnb4cfbc42009-05-04 04:20:02 +0000931#endif
932
njn16eeb4e2005-06-16 03:56:58 +0000933
sewardj3c944452011-09-05 20:39:57 +0000934/*---------------------- memset ----------------------*/
935
936/* Why are we bothering to intercept this? It seems entirely
937 pointless. */
sewardj731f9cf2011-09-21 08:43:08 +0000938
njn16eeb4e2005-06-16 03:56:58 +0000939#define MEMSET(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000940 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000941 (void *s, Int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000942 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000943 (void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000944 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000945 Addr a = (Addr)s; \
946 UInt c4 = (c & 0xFF); \
947 c4 = (c4 << 8) | c4; \
948 c4 = (c4 << 16) | c4; \
949 while ((a & 3) != 0 && n >= 1) \
950 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
951 while (n >= 4) \
952 { *(UInt*)a = c4; a += 4; n -= 4; } \
953 while (n >= 1) \
954 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000955 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000956 }
njn16eeb4e2005-06-16 03:56:58 +0000957
sewardj3c944452011-09-05 20:39:57 +0000958#if defined(VGO_linux)
959 MEMSET(VG_Z_LIBC_SONAME, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000960
sewardj3c944452011-09-05 20:39:57 +0000961#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000962 //MEMSET(VG_Z_LIBC_SONAME, memset)
963 //MEMSET(VG_Z_DYLD, memset)
sewardj3c944452011-09-05 20:39:57 +0000964 MEMSET(VG_Z_LIBC_SONAME, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000965
njnf76d27a2009-05-28 01:53:07 +0000966#endif
njn16eeb4e2005-06-16 03:56:58 +0000967
968
sewardj3c944452011-09-05 20:39:57 +0000969/*---------------------- memmove ----------------------*/
970
sewardj96044842011-08-18 13:09:55 +0000971/* memmove -- use the MEMMOVE defn above. */
sewardj731f9cf2011-09-21 08:43:08 +0000972
sewardj3c944452011-09-05 20:39:57 +0000973#if defined(VGO_linux)
974 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
sewardj4157d4f2011-09-05 22:18:13 +0000975
sewardj3c944452011-09-05 20:39:57 +0000976#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000977 //MEMMOVE(VG_Z_LIBC_SONAME, memmove)
978 //MEMMOVE(VG_Z_DYLD, memmove)#
979 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
980 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
sewardj4157d4f2011-09-05 22:18:13 +0000981
njnf76d27a2009-05-28 01:53:07 +0000982#endif
983
984
sewardj3c944452011-09-05 20:39:57 +0000985/*---------------------- bcopy ----------------------*/
986
njnf76d27a2009-05-28 01:53:07 +0000987#define BCOPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000988 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000989 (const void *srcV, void *dstV, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000990 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000991 (const void *srcV, void *dstV, SizeT n) \
992 { \
993 SizeT i; \
994 Char* dst = (Char*)dstV; \
995 Char* src = (Char*)srcV; \
996 if (dst < src) { \
997 for (i = 0; i < n; i++) \
998 dst[i] = src[i]; \
999 } \
1000 else \
1001 if (dst > src) { \
1002 for (i = 0; i < n; i++) \
1003 dst[n-i-1] = src[n-i-1]; \
1004 } \
1005 }
1006
sewardj3c944452011-09-05 20:39:57 +00001007#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +00001008
sewardj3c944452011-09-05 20:39:57 +00001009#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +00001010 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1011 //BCOPY(VG_Z_DYLD, bcopy)
sewardj4157d4f2011-09-05 22:18:13 +00001012
njnf76d27a2009-05-28 01:53:07 +00001013#endif
sewardj44e495f2005-05-12 17:58:28 +00001014
jseward0845ef82003-12-22 22:31:27 +00001015
sewardj3c944452011-09-05 20:39:57 +00001016/*-------------------- memmove_chk --------------------*/
1017
sewardj24cb2172007-02-23 09:03:26 +00001018/* glibc 2.5 variant of memmove which checks the dest is big enough.
1019 There is no specific part of glibc that this is copied from. */
1020#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001021 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001022 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
sewardj96044842011-08-18 13:09:55 +00001023 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001024 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1025 { \
sewardj24cb2172007-02-23 09:03:26 +00001026 SizeT i; \
1027 Char* dst = (Char*)dstV; \
1028 Char* src = (Char*)srcV; \
1029 if (destlen < n) \
1030 goto badness; \
1031 if (dst < src) { \
1032 for (i = 0; i < n; i++) \
1033 dst[i] = src[i]; \
1034 } \
1035 else \
1036 if (dst > src) { \
1037 for (i = 0; i < n; i++) \
1038 dst[n-i-1] = src[n-i-1]; \
1039 } \
1040 return dst; \
1041 badness: \
1042 VALGRIND_PRINTF_BACKTRACE( \
1043 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001044 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001045 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +00001046 /*NOTREACHED*/ \
1047 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +00001048 }
1049
sewardj3c944452011-09-05 20:39:57 +00001050#if defined(VGO_linux)
1051 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001052
sewardj3c944452011-09-05 20:39:57 +00001053#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001054
sewardj3c944452011-09-05 20:39:57 +00001055#endif
sewardj24cb2172007-02-23 09:03:26 +00001056
1057
sewardj3c944452011-09-05 20:39:57 +00001058/*-------------------- strchrnul --------------------*/
1059
sewardj4e9a4b62004-11-23 00:20:17 +00001060/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +00001061#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001062 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001063 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001064 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001065 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001066 { \
1067 unsigned char c = (unsigned char) c_in; \
1068 unsigned char* char_ptr = (unsigned char *)s; \
1069 while (1) { \
1070 if (*char_ptr == 0) return char_ptr; \
1071 if (*char_ptr == c) return char_ptr; \
1072 char_ptr++; \
1073 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001074 }
njn16eeb4e2005-06-16 03:56:58 +00001075
sewardj3c944452011-09-05 20:39:57 +00001076#if defined(VGO_linux)
1077 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4157d4f2011-09-05 22:18:13 +00001078
sewardj3c944452011-09-05 20:39:57 +00001079#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001080
sewardj3c944452011-09-05 20:39:57 +00001081#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001082
1083
sewardj3c944452011-09-05 20:39:57 +00001084/*---------------------- rawmemchr ----------------------*/
1085
sewardj4e9a4b62004-11-23 00:20:17 +00001086/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +00001087#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001088 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001089 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001090 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001091 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001092 { \
1093 unsigned char c = (unsigned char) c_in; \
1094 unsigned char* char_ptr = (unsigned char *)s; \
1095 while (1) { \
1096 if (*char_ptr == c) return char_ptr; \
1097 char_ptr++; \
1098 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001099 }
njn16eeb4e2005-06-16 03:56:58 +00001100
tomd2645142009-10-29 09:27:11 +00001101#if defined (VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001102 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1103 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
sewardj4157d4f2011-09-05 22:18:13 +00001104
sewardj3c944452011-09-05 20:39:57 +00001105#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001106
tomd2645142009-10-29 09:27:11 +00001107#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001108
sewardj3c944452011-09-05 20:39:57 +00001109
1110/*---------------------- strcpy_chk ----------------------*/
1111
sewardjdc5d8322007-01-28 06:32:01 +00001112/* glibc variant of strcpy that checks the dest is big enough.
1113 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +00001114#define GLIBC25___STRCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001115 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001116 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001117 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001118 (char* dst, const char* src, SizeT len) \
sewardj620e5262006-12-31 00:22:30 +00001119 { \
sewardj620e5262006-12-31 00:22:30 +00001120 char* ret = dst; \
1121 if (! len) \
1122 goto badness; \
1123 while ((*dst++ = *src++) != '\0') \
1124 if (--len == 0) \
1125 goto badness; \
1126 return ret; \
1127 badness: \
1128 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001129 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001130 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001131 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +00001132 /*NOTREACHED*/ \
1133 return NULL; \
1134 }
1135
sewardj3c944452011-09-05 20:39:57 +00001136#if defined(VGO_linux)
1137 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001138
sewardj3c944452011-09-05 20:39:57 +00001139#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001140
sewardj3c944452011-09-05 20:39:57 +00001141#endif
sewardj620e5262006-12-31 00:22:30 +00001142
1143
sewardj3c944452011-09-05 20:39:57 +00001144/*---------------------- stpcpy_chk ----------------------*/
1145
sewardjdc5d8322007-01-28 06:32:01 +00001146/* glibc variant of stpcpy that checks the dest is big enough.
1147 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +00001148#define GLIBC25___STPCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001149 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001150 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001151 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001152 (char* dst, const char* src, SizeT len) \
sewardjb8d03852007-01-27 00:49:44 +00001153 { \
sewardjdc5d8322007-01-28 06:32:01 +00001154 if (! len) \
1155 goto badness; \
1156 while ((*dst++ = *src++) != '\0') \
1157 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +00001158 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +00001159 return dst - 1; \
1160 badness: \
1161 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001162 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001163 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001164 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +00001165 /*NOTREACHED*/ \
1166 return NULL; \
1167 }
1168
sewardj3c944452011-09-05 20:39:57 +00001169#if defined(VGO_linux)
1170 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001171
sewardj3c944452011-09-05 20:39:57 +00001172#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001173
sewardj3c944452011-09-05 20:39:57 +00001174#endif
sewardjb8d03852007-01-27 00:49:44 +00001175
1176
sewardj3c944452011-09-05 20:39:57 +00001177/*---------------------- mempcpy ----------------------*/
1178
sewardj841b72d2006-12-31 18:55:56 +00001179/* mempcpy */
1180#define GLIBC25_MEMPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001181 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001182 ( void *dst, const void *src, SizeT len ); \
sewardj96044842011-08-18 13:09:55 +00001183 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001184 ( void *dst, const void *src, SizeT len ) \
1185 { \
1186 register char *d; \
1187 register char *s; \
1188 SizeT len_saved = len; \
1189 \
1190 if (len == 0) \
1191 return dst; \
1192 \
1193 if (is_overlap(dst, src, len, len)) \
1194 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1195 \
1196 if ( dst > src ) { \
1197 d = (char *)dst + len - 1; \
1198 s = (char *)src + len - 1; \
1199 while ( len-- ) { \
1200 *d-- = *s--; \
1201 } \
1202 } else if ( dst < src ) { \
1203 d = (char *)dst; \
1204 s = (char *)src; \
1205 while ( len-- ) { \
1206 *d++ = *s++; \
1207 } \
1208 } \
1209 return (void*)( ((char*)dst) + len_saved ); \
1210 }
1211
njnb4cfbc42009-05-04 04:20:02 +00001212#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001213 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1214 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
sewardj4157d4f2011-09-05 22:18:13 +00001215
sewardj3c944452011-09-05 20:39:57 +00001216#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +00001217 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
sewardj4157d4f2011-09-05 22:18:13 +00001218
njnb4cfbc42009-05-04 04:20:02 +00001219#endif
sewardj841b72d2006-12-31 18:55:56 +00001220
1221
sewardj3c944452011-09-05 20:39:57 +00001222/*-------------------- memcpy_chk --------------------*/
1223
sewardjb6c04032007-11-13 20:52:29 +00001224#define GLIBC26___MEMCPY_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001225 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001226 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
sewardj96044842011-08-18 13:09:55 +00001227 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001228 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1229 { \
sewardjb6c04032007-11-13 20:52:29 +00001230 register char *d; \
1231 register char *s; \
1232 \
1233 if (dstlen < len) goto badness; \
1234 \
1235 if (len == 0) \
1236 return dst; \
1237 \
1238 if (is_overlap(dst, src, len, len)) \
1239 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1240 \
1241 if ( dst > src ) { \
1242 d = (char *)dst + len - 1; \
1243 s = (char *)src + len - 1; \
1244 while ( len-- ) { \
1245 *d-- = *s--; \
1246 } \
1247 } else if ( dst < src ) { \
1248 d = (char *)dst; \
1249 s = (char *)src; \
1250 while ( len-- ) { \
1251 *d++ = *s++; \
1252 } \
1253 } \
1254 return dst; \
1255 badness: \
1256 VALGRIND_PRINTF_BACKTRACE( \
1257 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001258 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001259 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001260 /*NOTREACHED*/ \
1261 return NULL; \
1262 }
1263
sewardj3c944452011-09-05 20:39:57 +00001264#if defined(VGO_linux)
1265 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001266
sewardj3c944452011-09-05 20:39:57 +00001267#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001268
sewardj3c944452011-09-05 20:39:57 +00001269#endif
sewardjb6c04032007-11-13 20:52:29 +00001270
1271
sewardj3c944452011-09-05 20:39:57 +00001272/*---------------------- strstr ----------------------*/
1273
sewardja77687c2010-08-19 13:22:34 +00001274#define STRSTR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001275 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001276 (void* haystack, void* needle); \
sewardj96044842011-08-18 13:09:55 +00001277 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001278 (void* haystack, void* needle) \
1279 { \
1280 UChar* h = (UChar*)haystack; \
1281 UChar* n = (UChar*)needle; \
1282 \
1283 /* find the length of n, not including terminating zero */ \
1284 UWord nlen = 0; \
1285 while (n[nlen]) nlen++; \
1286 \
1287 /* if n is the empty string, match immediately. */ \
1288 if (nlen == 0) return h; \
1289 \
1290 /* assert(nlen >= 1); */ \
1291 UChar n0 = n[0]; \
1292 \
1293 while (1) { \
1294 UChar hh = *h; \
1295 if (hh == 0) return NULL; \
1296 if (hh != n0) { h++; continue; } \
1297 \
1298 UWord i; \
1299 for (i = 0; i < nlen; i++) { \
1300 if (n[i] != h[i]) \
1301 break; \
1302 } \
1303 /* assert(i >= 0 && i <= nlen); */ \
1304 if (i == nlen) \
1305 return h; \
1306 \
1307 h++; \
1308 } \
1309 }
1310
1311#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001312 STRSTR(VG_Z_LIBC_SONAME, strstr)
sewardj4157d4f2011-09-05 22:18:13 +00001313
sewardj3c944452011-09-05 20:39:57 +00001314#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001315
sewardja77687c2010-08-19 13:22:34 +00001316#endif
1317
1318
sewardj3c944452011-09-05 20:39:57 +00001319/*---------------------- strpbrk ----------------------*/
1320
sewardja77687c2010-08-19 13:22:34 +00001321#define STRPBRK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001322 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001323 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001324 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001325 (void* sV, void* acceptV) \
1326 { \
1327 UChar* s = (UChar*)sV; \
1328 UChar* accept = (UChar*)acceptV; \
1329 \
1330 /* find the length of 'accept', not including terminating zero */ \
1331 UWord nacc = 0; \
1332 while (accept[nacc]) nacc++; \
1333 \
1334 /* if n is the empty string, fail immediately. */ \
1335 if (nacc == 0) return NULL; \
1336 \
1337 /* assert(nacc >= 1); */ \
1338 while (1) { \
1339 UWord i; \
1340 UChar sc = *s; \
1341 if (sc == 0) \
1342 break; \
1343 for (i = 0; i < nacc; i++) { \
1344 if (sc == accept[i]) \
1345 return s; \
1346 } \
1347 s++; \
1348 } \
1349 \
1350 return NULL; \
1351 }
1352
1353#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001354 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
sewardj4157d4f2011-09-05 22:18:13 +00001355
sewardj3c944452011-09-05 20:39:57 +00001356#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001357
sewardja77687c2010-08-19 13:22:34 +00001358#endif
1359
1360
sewardj3c944452011-09-05 20:39:57 +00001361/*---------------------- strcspn ----------------------*/
1362
sewardja77687c2010-08-19 13:22:34 +00001363#define STRCSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001364 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001365 (void* sV, void* rejectV); \
sewardj96044842011-08-18 13:09:55 +00001366 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001367 (void* sV, void* rejectV) \
1368 { \
1369 UChar* s = (UChar*)sV; \
1370 UChar* reject = (UChar*)rejectV; \
1371 \
1372 /* find the length of 'reject', not including terminating zero */ \
1373 UWord nrej = 0; \
1374 while (reject[nrej]) nrej++; \
1375 \
1376 UWord len = 0; \
1377 while (1) { \
1378 UWord i; \
1379 UChar sc = *s; \
1380 if (sc == 0) \
1381 break; \
1382 for (i = 0; i < nrej; i++) { \
1383 if (sc == reject[i]) \
1384 break; \
1385 } \
1386 /* assert(i >= 0 && i <= nrej); */ \
1387 if (i < nrej) \
1388 break; \
1389 s++; \
1390 len++; \
1391 } \
1392 \
1393 return len; \
1394 }
1395
1396#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001397 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
sewardj4157d4f2011-09-05 22:18:13 +00001398
sewardj3c944452011-09-05 20:39:57 +00001399#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001400
sewardja77687c2010-08-19 13:22:34 +00001401#endif
1402
1403
sewardj3c944452011-09-05 20:39:57 +00001404/*---------------------- strspn ----------------------*/
1405
sewardjbd2cff22011-08-16 21:45:28 +00001406#define STRSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001407 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001408 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001409 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001410 (void* sV, void* acceptV) \
1411 { \
1412 UChar* s = (UChar*)sV; \
1413 UChar* accept = (UChar*)acceptV; \
1414 \
1415 /* find the length of 'accept', not including terminating zero */ \
1416 UWord nacc = 0; \
1417 while (accept[nacc]) nacc++; \
1418 if (nacc == 0) return 0; \
1419 \
1420 UWord len = 0; \
1421 while (1) { \
1422 UWord i; \
1423 UChar sc = *s; \
1424 if (sc == 0) \
1425 break; \
1426 for (i = 0; i < nacc; i++) { \
1427 if (sc == accept[i]) \
1428 break; \
1429 } \
1430 /* assert(i >= 0 && i <= nacc); */ \
1431 if (i == nacc) \
1432 break; \
1433 s++; \
1434 len++; \
1435 } \
1436 \
1437 return len; \
1438 }
1439
1440#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001441 STRSPN(VG_Z_LIBC_SONAME, strspn)
sewardj4157d4f2011-09-05 22:18:13 +00001442
sewardj3c944452011-09-05 20:39:57 +00001443#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001444
sewardjbd2cff22011-08-16 21:45:28 +00001445#endif
sewardjba189352010-08-20 18:24:16 +00001446
1447
sewardj31b9ce12006-10-17 01:27:13 +00001448/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001449/*--- Improve definedness checking of process environment ---*/
1450/*------------------------------------------------------------*/
1451
sewardjddc00dd2007-11-27 11:42:47 +00001452#if defined(VGO_linux)
1453
sewardjbd2cff22011-08-16 21:45:28 +00001454/* If these wind up getting generated via a macro, so that multiple
1455 versions of each function exist (as above), use the _EZU variants
1456 to assign equivalance class tags. */
1457
sewardj3c944452011-09-05 20:39:57 +00001458/*---------------------- putenv ----------------------*/
1459
njne6154662009-02-10 04:23:41 +00001460int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1461int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001462{
1463 OrigFn fn;
1464 Word result;
1465 const char* p = string;
1466 VALGRIND_GET_ORIG_FN(fn);
1467 /* Now by walking over the string we magically produce
1468 traces when hitting undefined memory. */
1469 if (p)
1470 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001471 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001472 CALL_FN_W_W(result, fn, string);
1473 return result;
1474}
1475
sewardj3c944452011-09-05 20:39:57 +00001476
1477/*---------------------- unsetenv ----------------------*/
1478
njne6154662009-02-10 04:23:41 +00001479int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1480int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001481{
1482 OrigFn fn;
1483 Word result;
1484 const char* p = name;
1485 VALGRIND_GET_ORIG_FN(fn);
1486 /* Now by walking over the string we magically produce
1487 traces when hitting undefined memory. */
1488 if (p)
1489 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001490 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001491 CALL_FN_W_W(result, fn, name);
1492 return result;
1493}
1494
sewardj3c944452011-09-05 20:39:57 +00001495
1496/*---------------------- setenv ----------------------*/
1497
dirk09beb9e2007-04-19 09:47:32 +00001498/* setenv */
njne6154662009-02-10 04:23:41 +00001499int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001500 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001501int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001502 (const char* name, const char* value, int overwrite)
1503{
1504 OrigFn fn;
1505 Word result;
1506 const char* p;
1507 VALGRIND_GET_ORIG_FN(fn);
1508 /* Now by walking over the string we magically produce
1509 traces when hitting undefined memory. */
1510 if (name)
1511 for (p = name; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001512 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001513 if (value)
1514 for (p = value; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001515 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001516 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1517 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1518 return result;
1519}
1520
sewardjddc00dd2007-11-27 11:42:47 +00001521#endif /* defined(VGO_linux) */
1522
njn3e884182003-04-15 13:03:23 +00001523/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001524/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001525/*--------------------------------------------------------------------*/