blob: b4ac8898dc9cb7d3e68095fcaa90455a8410059f [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)
sewardj70f291d2011-09-26 20:20:19 +0000391# if defined(VGPV_arm_linux_android)
392 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
393# endif
sewardj4157d4f2011-09-05 22:18:13 +0000394
sewardj3c944452011-09-05 20:39:57 +0000395#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000396 //STRLEN(VG_Z_LIBC_SONAME, strlen)
397 STRLEN(VG_Z_LIBC_SONAME, strlen)
sewardj4157d4f2011-09-05 22:18:13 +0000398
njnb4cfbc42009-05-04 04:20:02 +0000399#endif
sewardj31b9ce12006-10-17 01:27:13 +0000400
njn16eeb4e2005-06-16 03:56:58 +0000401
sewardj3c944452011-09-05 20:39:57 +0000402/*---------------------- strcpy ----------------------*/
403
njn16eeb4e2005-06-16 03:56:58 +0000404#define STRCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000405 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000406 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000407 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000408 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000409 { \
410 const Char* src_orig = src; \
411 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000412 \
njn16eeb4e2005-06-16 03:56:58 +0000413 while (*src) *dst++ = *src++; \
414 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000415 \
njn16eeb4e2005-06-16 03:56:58 +0000416 /* This checks for overlap after copying, unavoidable without */ \
417 /* pre-counting length... should be ok */ \
418 if (is_overlap(dst_orig, \
419 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000420 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000421 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000422 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000423 \
njn16eeb4e2005-06-16 03:56:58 +0000424 return dst_orig; \
425 }
426
tomd2645142009-10-29 09:27:11 +0000427#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000428 STRCPY(VG_Z_LIBC_SONAME, strcpy)
429 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000430
tomd2645142009-10-29 09:27:11 +0000431#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000432 //STRCPY(VG_Z_LIBC_SONAME, strcpy)
433 //STRCPY(VG_Z_DYLD, strcpy)
sewardj3c944452011-09-05 20:39:57 +0000434 STRCPY(VG_Z_LIBC_SONAME, strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000435
njnf76d27a2009-05-28 01:53:07 +0000436#endif
njn16eeb4e2005-06-16 03:56:58 +0000437
438
sewardj3c944452011-09-05 20:39:57 +0000439/*---------------------- strncpy ----------------------*/
440
njn16eeb4e2005-06-16 03:56:58 +0000441#define STRNCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000442 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000443 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000444 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000445 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000446 { \
447 const Char* src_orig = src; \
448 Char* dst_orig = dst; \
449 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000450 \
njn16eeb4e2005-06-16 03:56:58 +0000451 while (m < n && *src) { m++; *dst++ = *src++; } \
452 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
453 /* but only m+1 bytes of src if terminator was found */ \
454 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000455 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000456 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
sewardj3c944452011-09-05 20:39:57 +0000457 \
njn16eeb4e2005-06-16 03:56:58 +0000458 return dst_orig; \
459 }
460
tomd2645142009-10-29 09:27:11 +0000461#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000462 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
463 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000464
tomd2645142009-10-29 09:27:11 +0000465#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000466 //STRNCPY(VG_Z_LIBC_SONAME, strncpy)
467 //STRNCPY(VG_Z_DYLD, strncpy)
sewardj3c944452011-09-05 20:39:57 +0000468 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000469
njnf76d27a2009-05-28 01:53:07 +0000470#endif
471
472
sewardj3c944452011-09-05 20:39:57 +0000473/*---------------------- strlcpy ----------------------*/
474
njnf76d27a2009-05-28 01:53:07 +0000475/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
476 Returns strlen(src). Does not zero-fill the remainder of dst. */
477#define STRLCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000478 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000479 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000480 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000481 ( char* dst, const char* src, SizeT n ) \
482 { \
483 const char* src_orig = src; \
484 char* dst_orig = dst; \
485 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000486 \
njnf76d27a2009-05-28 01:53:07 +0000487 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
488 /* m non-nul bytes have now been copied, and m <= n-1. */ \
489 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
490 /* but only m+1 bytes of src if terminator was found */ \
491 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
492 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
493 /* Nul-terminate dst. */ \
494 if (n > 0) *dst = 0; \
495 /* Finish counting strlen(src). */ \
496 while (*src) src++; \
497 return src - src_orig; \
498 }
499
sewardj3c944452011-09-05 20:39:57 +0000500#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000501
sewardj3c944452011-09-05 20:39:57 +0000502#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000503 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
504 //STRLCPY(VG_Z_DYLD, strlcpy)
sewardj3c944452011-09-05 20:39:57 +0000505 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000506
njnf76d27a2009-05-28 01:53:07 +0000507#endif
njn16eeb4e2005-06-16 03:56:58 +0000508
509
sewardj3c944452011-09-05 20:39:57 +0000510/*---------------------- strncmp ----------------------*/
511
njn16eeb4e2005-06-16 03:56:58 +0000512#define STRNCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000513 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000514 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000515 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000516 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000517 { \
518 SizeT n = 0; \
519 while (True) { \
520 if (n >= nmax) return 0; \
521 if (*s1 == 0 && *s2 == 0) return 0; \
522 if (*s1 == 0) return -1; \
523 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000524 \
njn16eeb4e2005-06-16 03:56:58 +0000525 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
526 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000527 \
njn16eeb4e2005-06-16 03:56:58 +0000528 s1++; s2++; n++; \
529 } \
530 }
531
tomd2645142009-10-29 09:27:11 +0000532#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000533 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
534 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000535
tomd2645142009-10-29 09:27:11 +0000536#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000537 //STRNCMP(VG_Z_LIBC_SONAME, strncmp)
538 //STRNCMP(VG_Z_DYLD, strncmp)
539 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000540
njnf76d27a2009-05-28 01:53:07 +0000541#endif
njn16eeb4e2005-06-16 03:56:58 +0000542
543
sewardj3c944452011-09-05 20:39:57 +0000544/*---------------------- strcasecmp ----------------------*/
545
tomce6d0ac2010-11-12 10:03:13 +0000546#define STRCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000547 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000548 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000549 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000550 ( const char* s1, const char* s2 ) \
551 { \
tome03c8c42010-11-12 10:40:20 +0000552 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000553 register unsigned char c1; \
554 register unsigned char c2; \
555 while (True) { \
556 c1 = tolower(*(unsigned char *)s1); \
557 c2 = tolower(*(unsigned char *)s2); \
558 if (c1 != c2) break; \
559 if (c1 == 0) break; \
560 s1++; s2++; \
561 } \
562 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
563 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
564 return 0; \
565 }
566
sewardj3c944452011-09-05 20:39:57 +0000567#if defined(VGO_linux)
568# if !defined(VGPV_arm_linux_android)
569 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
570 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
571# endif
sewardj4157d4f2011-09-05 22:18:13 +0000572
sewardj3c944452011-09-05 20:39:57 +0000573#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000574 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000575
tomce6d0ac2010-11-12 10:03:13 +0000576#endif
577
578
sewardj3c944452011-09-05 20:39:57 +0000579/*---------------------- strncasecmp ----------------------*/
580
tomce6d0ac2010-11-12 10:03:13 +0000581#define STRNCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000582 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000583 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000584 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000585 ( const char* s1, const char* s2, SizeT nmax ) \
586 { \
tome03c8c42010-11-12 10:40:20 +0000587 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000588 SizeT n = 0; \
589 while (True) { \
590 if (n >= nmax) return 0; \
591 if (*s1 == 0 && *s2 == 0) return 0; \
592 if (*s1 == 0) return -1; \
593 if (*s2 == 0) return 1; \
594 \
sewardjbd2cff22011-08-16 21:45:28 +0000595 if (tolower(*(unsigned char*)s1) \
596 < tolower(*(unsigned char*)s2)) return -1; \
597 if (tolower(*(unsigned char*)s1) \
598 > tolower(*(unsigned char*)s2)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000599 \
600 s1++; s2++; n++; \
601 } \
602 }
603
sewardj3c944452011-09-05 20:39:57 +0000604#if defined(VGO_linux)
605# if !defined(VGPV_arm_linux_android)
606 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
607 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
608# endif
sewardj4157d4f2011-09-05 22:18:13 +0000609
tomce6d0ac2010-11-12 10:03:13 +0000610#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000611 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
612 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000613
tomce6d0ac2010-11-12 10:03:13 +0000614#endif
615
616
sewardj3c944452011-09-05 20:39:57 +0000617/*---------------------- strcasecmp_l ----------------------*/
618
tomce6d0ac2010-11-12 10:03:13 +0000619#define STRCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000620 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000621 ( const char* s1, const char* s2, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000622 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000623 ( const char* s1, const char* s2, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000624 { \
sewardj3c944452011-09-05 20:39:57 +0000625 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000626 register unsigned char c1; \
627 register unsigned char c2; \
628 while (True) { \
629 c1 = tolower_l(*(unsigned char *)s1, locale); \
630 c2 = tolower_l(*(unsigned char *)s2, locale); \
631 if (c1 != c2) break; \
632 if (c1 == 0) break; \
633 s1++; s2++; \
634 } \
635 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
636 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
637 return 0; \
638 }
639
tomce6d0ac2010-11-12 10:03:13 +0000640#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000641 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
642 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
643 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000644
sewardj3c944452011-09-05 20:39:57 +0000645#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000646 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000647
tomce6d0ac2010-11-12 10:03:13 +0000648#endif
649
650
sewardj3c944452011-09-05 20:39:57 +0000651/*---------------------- strncasecmp_l ----------------------*/
652
tomce6d0ac2010-11-12 10:03:13 +0000653#define STRNCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000654 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000655 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000656 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000657 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000658 { \
tome03c8c42010-11-12 10:40:20 +0000659 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000660 SizeT n = 0; \
661 while (True) { \
662 if (n >= nmax) return 0; \
663 if (*s1 == 0 && *s2 == 0) return 0; \
664 if (*s1 == 0) return -1; \
665 if (*s2 == 0) return 1; \
666 \
sewardjbd2cff22011-08-16 21:45:28 +0000667 if (tolower_l(*(unsigned char*)s1, locale) \
668 < tolower_l(*(unsigned char*)s2, locale)) return -1; \
669 if (tolower_l(*(unsigned char*)s1, locale) \
670 > tolower_l(*(unsigned char*)s2, locale)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000671 \
672 s1++; s2++; n++; \
673 } \
674 }
675
tomce6d0ac2010-11-12 10:03:13 +0000676#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000677 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
678 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000679
tomce6d0ac2010-11-12 10:03:13 +0000680#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000681 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
682 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000683
tomce6d0ac2010-11-12 10:03:13 +0000684#endif
685
686
sewardj3c944452011-09-05 20:39:57 +0000687/*---------------------- strcmp ----------------------*/
688
njn16eeb4e2005-06-16 03:56:58 +0000689#define STRCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000690 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000691 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000692 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000693 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000694 { \
695 register unsigned char c1; \
696 register unsigned char c2; \
697 while (True) { \
698 c1 = *(unsigned char *)s1; \
699 c2 = *(unsigned char *)s2; \
700 if (c1 != c2) break; \
701 if (c1 == 0) break; \
702 s1++; s2++; \
703 } \
704 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
705 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
706 return 0; \
707 }
708
njnb4cfbc42009-05-04 04:20:02 +0000709#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000710 STRCMP(VG_Z_LIBC_SONAME, strcmp)
711 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
712 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
713 STRCMP(VG_Z_LD64_SO_1, strcmp)
sewardj70f291d2011-09-26 20:20:19 +0000714# if defined(VGPV_arm_linux_android)
715 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
716# endif
sewardj4157d4f2011-09-05 22:18:13 +0000717
sewardj3c944452011-09-05 20:39:57 +0000718#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000719 //STRCMP(VG_Z_LIBC_SONAME, strcmp)
720 STRCMP(VG_Z_LIBC_SONAME, strcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000721
njnb4cfbc42009-05-04 04:20:02 +0000722#endif
njn16eeb4e2005-06-16 03:56:58 +0000723
724
sewardj3c944452011-09-05 20:39:57 +0000725/*---------------------- memchr ----------------------*/
726
njn16eeb4e2005-06-16 03:56:58 +0000727#define MEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000728 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000729 (const void *s, int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000730 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000731 (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000732 { \
733 SizeT i; \
734 UChar c0 = (UChar)c; \
735 UChar* p = (UChar*)s; \
736 for (i = 0; i < n; i++) \
737 if (p[i] == c0) return (void*)(&p[i]); \
738 return NULL; \
739 }
740
sewardj3c944452011-09-05 20:39:57 +0000741#if defined(VGO_linux)
742 MEMCHR(VG_Z_LIBC_SONAME, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000743
sewardj3c944452011-09-05 20:39:57 +0000744#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000745 //MEMCHR(VG_Z_LIBC_SONAME, memchr)
746 //MEMCHR(VG_Z_DYLD, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000747
njnf76d27a2009-05-28 01:53:07 +0000748#endif
njn16eeb4e2005-06-16 03:56:58 +0000749
750
sewardj3c944452011-09-05 20:39:57 +0000751/*---------------------- memcpy ----------------------*/
752
sewardjbd2cff22011-08-16 21:45:28 +0000753#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
sewardjd88797f2011-08-17 21:25:50 +0000754 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000755 ( void *dst, const void *src, SizeT len ); \
sewardjd88797f2011-08-17 21:25:50 +0000756 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000757 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000758 { \
sewardjbd2cff22011-08-16 21:45:28 +0000759 if (do_ol_check && is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000760 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000761 \
sewardj7b4e00b2010-08-24 09:05:52 +0000762 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
763 const Addr WM = WS - 1; /* 7 or 3 */ \
764 \
tom863ab7c2011-08-18 08:10:20 +0000765 if (len > 0) { \
766 if (dst < src) { \
sewardj7b4e00b2010-08-24 09:05:52 +0000767 \
tom863ab7c2011-08-18 08:10:20 +0000768 /* Copying backwards. */ \
769 SizeT n = len; \
770 Addr d = (Addr)dst; \
771 Addr s = (Addr)src; \
772 \
773 if (((s^d) & WM) == 0) { \
774 /* s and d have same UWord alignment. */ \
775 /* Pull up to a UWord boundary. */ \
776 while ((s & WM) != 0 && n >= 1) \
777 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
778 /* Copy UWords. */ \
779 while (n >= WS) \
780 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
781 if (n == 0) \
782 return dst; \
783 } \
784 if (((s|d) & 1) == 0) { \
785 /* Both are 16-aligned; copy what we can thusly. */ \
786 while (n >= 2) \
787 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
788 } \
789 /* Copy leftovers, or everything if misaligned. */ \
790 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000791 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
sewardj7b4e00b2010-08-24 09:05:52 +0000792 \
tom863ab7c2011-08-18 08:10:20 +0000793 } else if (dst > src) { \
794 \
795 SizeT n = len; \
796 Addr d = ((Addr)dst) + n; \
797 Addr s = ((Addr)src) + n; \
798 \
799 /* Copying forwards. */ \
800 if (((s^d) & WM) == 0) { \
801 /* s and d have same UWord alignment. */ \
802 /* Back down to a UWord boundary. */ \
803 while ((s & WM) != 0 && n >= 1) \
804 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
805 /* Copy UWords. */ \
806 while (n >= WS) \
807 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
808 if (n == 0) \
809 return dst; \
810 } \
811 if (((s|d) & 1) == 0) { \
812 /* Both are 16-aligned; copy what we can thusly. */ \
813 while (n >= 2) \
814 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
815 } \
816 /* Copy leftovers, or everything if misaligned. */ \
817 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000818 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
tom863ab7c2011-08-18 08:10:20 +0000819 \
njn16eeb4e2005-06-16 03:56:58 +0000820 } \
njn16eeb4e2005-06-16 03:56:58 +0000821 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000822 \
njn16eeb4e2005-06-16 03:56:58 +0000823 return dst; \
824 }
825
sewardjbd2cff22011-08-16 21:45:28 +0000826#define MEMMOVE(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000827 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
sewardjbd2cff22011-08-16 21:45:28 +0000828
829#define MEMCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000830 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
sewardjbd2cff22011-08-16 21:45:28 +0000831
njnb4cfbc42009-05-04 04:20:02 +0000832#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000833 /* For older memcpy we have to use memmove-like semantics and skip
834 the overlap check; sigh; see #275284. */
835 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
836 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
837 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
838 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
839 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
sewardj3c944452011-09-05 20:39:57 +0000840 /* icc9 blats these around all over the place. Not only in the main
841 executable but various .so's. They are highly tuned and read
842 memory beyond the source boundary (although work correctly and
843 never go across page boundaries), so give errors when run
844 natively, at least for misaligned source arg. Just intercepting
845 in the exe only until we understand more about the problem. See
846 http://bugs.kde.org/show_bug.cgi?id=139776
sewardjf0b34322007-01-16 21:42:28 +0000847 */
sewardj3c944452011-09-05 20:39:57 +0000848 MEMCPY(NONE, ZuintelZufastZumemcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000849
850#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000851 //MEMCPY(VG_Z_LIBC_SONAME, memcpy)
852 //MEMCPY(VG_Z_DYLD, memcpy)
853 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
854 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
sewardj4157d4f2011-09-05 22:18:13 +0000855
sewardj3c944452011-09-05 20:39:57 +0000856#endif
sewardj31b9ce12006-10-17 01:27:13 +0000857
njn16eeb4e2005-06-16 03:56:58 +0000858
sewardj3c944452011-09-05 20:39:57 +0000859/*---------------------- memcmp ----------------------*/
860
njn16eeb4e2005-06-16 03:56:58 +0000861#define MEMCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000862 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000863 ( const void *s1V, const void *s2V, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000864 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000865 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000866 { \
867 int res; \
868 unsigned char a0; \
869 unsigned char b0; \
870 unsigned char* s1 = (unsigned char*)s1V; \
871 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000872 \
njn16eeb4e2005-06-16 03:56:58 +0000873 while (n != 0) { \
874 a0 = s1[0]; \
875 b0 = s2[0]; \
876 s1 += 1; \
877 s2 += 1; \
878 res = ((int)a0) - ((int)b0); \
879 if (res != 0) \
880 return res; \
881 n -= 1; \
882 } \
883 return 0; \
884 }
885
njnb4cfbc42009-05-04 04:20:02 +0000886#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000887 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
888 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
889 MEMCMP(VG_Z_LD_SO_1, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000890
njnf76d27a2009-05-28 01:53:07 +0000891#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000892 //MEMCMP(VG_Z_LIBC_SONAME, memcmp)
893 //MEMCMP(VG_Z_LIBC_SONAME, bcmp)
894 //MEMCMP(VG_Z_DYLD, memcmp)
895 //MEMCMP(VG_Z_DYLD, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000896
njnb4cfbc42009-05-04 04:20:02 +0000897#endif
njn3e884182003-04-15 13:03:23 +0000898
jseward0845ef82003-12-22 22:31:27 +0000899
sewardj3c944452011-09-05 20:39:57 +0000900/*---------------------- stpcpy ----------------------*/
901
jseward0845ef82003-12-22 22:31:27 +0000902/* Copy SRC to DEST, returning the address of the terminating '\0' in
903 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000904#define STPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000905 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000906 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000907 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000908 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000909 { \
910 const Char* src_orig = src; \
911 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000912 \
njn16eeb4e2005-06-16 03:56:58 +0000913 while (*src) *dst++ = *src++; \
914 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000915 \
njn16eeb4e2005-06-16 03:56:58 +0000916 /* This checks for overlap after copying, unavoidable without */ \
917 /* pre-counting length... should be ok */ \
918 if (is_overlap(dst_orig, \
919 src_orig, \
920 (Addr)dst-(Addr)dst_orig+1, \
921 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000922 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000923 \
njn16eeb4e2005-06-16 03:56:58 +0000924 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000925 }
njn16eeb4e2005-06-16 03:56:58 +0000926
njnb4cfbc42009-05-04 04:20:02 +0000927#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000928 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
929 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
930 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
931 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000932
njnf76d27a2009-05-28 01:53:07 +0000933#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000934 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
935 //STPCPY(VG_Z_DYLD, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000936
njnb4cfbc42009-05-04 04:20:02 +0000937#endif
938
njn16eeb4e2005-06-16 03:56:58 +0000939
sewardj3c944452011-09-05 20:39:57 +0000940/*---------------------- memset ----------------------*/
941
942/* Why are we bothering to intercept this? It seems entirely
943 pointless. */
sewardj731f9cf2011-09-21 08:43:08 +0000944
njn16eeb4e2005-06-16 03:56:58 +0000945#define MEMSET(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000946 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000947 (void *s, Int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000948 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000949 (void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000950 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000951 Addr a = (Addr)s; \
952 UInt c4 = (c & 0xFF); \
953 c4 = (c4 << 8) | c4; \
954 c4 = (c4 << 16) | c4; \
955 while ((a & 3) != 0 && n >= 1) \
956 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
957 while (n >= 4) \
958 { *(UInt*)a = c4; a += 4; n -= 4; } \
959 while (n >= 1) \
960 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000961 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000962 }
njn16eeb4e2005-06-16 03:56:58 +0000963
sewardj3c944452011-09-05 20:39:57 +0000964#if defined(VGO_linux)
965 MEMSET(VG_Z_LIBC_SONAME, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000966
sewardj3c944452011-09-05 20:39:57 +0000967#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000968 //MEMSET(VG_Z_LIBC_SONAME, memset)
969 //MEMSET(VG_Z_DYLD, memset)
sewardj3c944452011-09-05 20:39:57 +0000970 MEMSET(VG_Z_LIBC_SONAME, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000971
njnf76d27a2009-05-28 01:53:07 +0000972#endif
njn16eeb4e2005-06-16 03:56:58 +0000973
974
sewardj3c944452011-09-05 20:39:57 +0000975/*---------------------- memmove ----------------------*/
976
sewardj96044842011-08-18 13:09:55 +0000977/* memmove -- use the MEMMOVE defn above. */
sewardj731f9cf2011-09-21 08:43:08 +0000978
sewardj3c944452011-09-05 20:39:57 +0000979#if defined(VGO_linux)
980 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
sewardj4157d4f2011-09-05 22:18:13 +0000981
sewardj3c944452011-09-05 20:39:57 +0000982#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000983 //MEMMOVE(VG_Z_LIBC_SONAME, memmove)
984 //MEMMOVE(VG_Z_DYLD, memmove)#
985 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
986 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
sewardj4157d4f2011-09-05 22:18:13 +0000987
njnf76d27a2009-05-28 01:53:07 +0000988#endif
989
990
sewardj3c944452011-09-05 20:39:57 +0000991/*---------------------- bcopy ----------------------*/
992
njnf76d27a2009-05-28 01:53:07 +0000993#define BCOPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000994 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000995 (const void *srcV, void *dstV, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000996 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000997 (const void *srcV, void *dstV, SizeT n) \
998 { \
999 SizeT i; \
1000 Char* dst = (Char*)dstV; \
1001 Char* src = (Char*)srcV; \
1002 if (dst < src) { \
1003 for (i = 0; i < n; i++) \
1004 dst[i] = src[i]; \
1005 } \
1006 else \
1007 if (dst > src) { \
1008 for (i = 0; i < n; i++) \
1009 dst[n-i-1] = src[n-i-1]; \
1010 } \
1011 }
1012
sewardj3c944452011-09-05 20:39:57 +00001013#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +00001014
sewardj3c944452011-09-05 20:39:57 +00001015#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +00001016 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1017 //BCOPY(VG_Z_DYLD, bcopy)
sewardj4157d4f2011-09-05 22:18:13 +00001018
njnf76d27a2009-05-28 01:53:07 +00001019#endif
sewardj44e495f2005-05-12 17:58:28 +00001020
jseward0845ef82003-12-22 22:31:27 +00001021
sewardj3c944452011-09-05 20:39:57 +00001022/*-------------------- memmove_chk --------------------*/
1023
sewardj24cb2172007-02-23 09:03:26 +00001024/* glibc 2.5 variant of memmove which checks the dest is big enough.
1025 There is no specific part of glibc that this is copied from. */
1026#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001027 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001028 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
sewardj96044842011-08-18 13:09:55 +00001029 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001030 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1031 { \
sewardj24cb2172007-02-23 09:03:26 +00001032 SizeT i; \
1033 Char* dst = (Char*)dstV; \
1034 Char* src = (Char*)srcV; \
1035 if (destlen < n) \
1036 goto badness; \
1037 if (dst < src) { \
1038 for (i = 0; i < n; i++) \
1039 dst[i] = src[i]; \
1040 } \
1041 else \
1042 if (dst > src) { \
1043 for (i = 0; i < n; i++) \
1044 dst[n-i-1] = src[n-i-1]; \
1045 } \
1046 return dst; \
1047 badness: \
1048 VALGRIND_PRINTF_BACKTRACE( \
1049 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001050 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001051 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +00001052 /*NOTREACHED*/ \
1053 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +00001054 }
1055
sewardj3c944452011-09-05 20:39:57 +00001056#if defined(VGO_linux)
1057 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001058
sewardj3c944452011-09-05 20:39:57 +00001059#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001060
sewardj3c944452011-09-05 20:39:57 +00001061#endif
sewardj24cb2172007-02-23 09:03:26 +00001062
1063
sewardj3c944452011-09-05 20:39:57 +00001064/*-------------------- strchrnul --------------------*/
1065
sewardj4e9a4b62004-11-23 00:20:17 +00001066/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +00001067#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001068 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001069 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001070 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001071 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001072 { \
1073 unsigned char c = (unsigned char) c_in; \
1074 unsigned char* char_ptr = (unsigned char *)s; \
1075 while (1) { \
1076 if (*char_ptr == 0) return char_ptr; \
1077 if (*char_ptr == c) return char_ptr; \
1078 char_ptr++; \
1079 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001080 }
njn16eeb4e2005-06-16 03:56:58 +00001081
sewardj3c944452011-09-05 20:39:57 +00001082#if defined(VGO_linux)
1083 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4157d4f2011-09-05 22:18:13 +00001084
sewardj3c944452011-09-05 20:39:57 +00001085#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001086
sewardj3c944452011-09-05 20:39:57 +00001087#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001088
1089
sewardj3c944452011-09-05 20:39:57 +00001090/*---------------------- rawmemchr ----------------------*/
1091
sewardj4e9a4b62004-11-23 00:20:17 +00001092/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +00001093#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001094 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001095 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001096 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001097 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001098 { \
1099 unsigned char c = (unsigned char) c_in; \
1100 unsigned char* char_ptr = (unsigned char *)s; \
1101 while (1) { \
1102 if (*char_ptr == c) return char_ptr; \
1103 char_ptr++; \
1104 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001105 }
njn16eeb4e2005-06-16 03:56:58 +00001106
tomd2645142009-10-29 09:27:11 +00001107#if defined (VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001108 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1109 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
sewardj4157d4f2011-09-05 22:18:13 +00001110
sewardj3c944452011-09-05 20:39:57 +00001111#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001112
tomd2645142009-10-29 09:27:11 +00001113#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001114
sewardj3c944452011-09-05 20:39:57 +00001115
1116/*---------------------- strcpy_chk ----------------------*/
1117
sewardjdc5d8322007-01-28 06:32:01 +00001118/* glibc variant of strcpy that checks the dest is big enough.
1119 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +00001120#define GLIBC25___STRCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001121 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001122 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001123 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001124 (char* dst, const char* src, SizeT len) \
sewardj620e5262006-12-31 00:22:30 +00001125 { \
sewardj620e5262006-12-31 00:22:30 +00001126 char* ret = dst; \
1127 if (! len) \
1128 goto badness; \
1129 while ((*dst++ = *src++) != '\0') \
1130 if (--len == 0) \
1131 goto badness; \
1132 return ret; \
1133 badness: \
1134 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001135 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001136 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001137 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +00001138 /*NOTREACHED*/ \
1139 return NULL; \
1140 }
1141
sewardj3c944452011-09-05 20:39:57 +00001142#if defined(VGO_linux)
1143 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001144
sewardj3c944452011-09-05 20:39:57 +00001145#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001146
sewardj3c944452011-09-05 20:39:57 +00001147#endif
sewardj620e5262006-12-31 00:22:30 +00001148
1149
sewardj3c944452011-09-05 20:39:57 +00001150/*---------------------- stpcpy_chk ----------------------*/
1151
sewardjdc5d8322007-01-28 06:32:01 +00001152/* glibc variant of stpcpy that checks the dest is big enough.
1153 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +00001154#define GLIBC25___STPCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001155 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001156 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001157 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001158 (char* dst, const char* src, SizeT len) \
sewardjb8d03852007-01-27 00:49:44 +00001159 { \
sewardjdc5d8322007-01-28 06:32:01 +00001160 if (! len) \
1161 goto badness; \
1162 while ((*dst++ = *src++) != '\0') \
1163 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +00001164 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +00001165 return dst - 1; \
1166 badness: \
1167 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001168 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001169 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001170 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +00001171 /*NOTREACHED*/ \
1172 return NULL; \
1173 }
1174
sewardj3c944452011-09-05 20:39:57 +00001175#if defined(VGO_linux)
1176 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001177
sewardj3c944452011-09-05 20:39:57 +00001178#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001179
sewardj3c944452011-09-05 20:39:57 +00001180#endif
sewardjb8d03852007-01-27 00:49:44 +00001181
1182
sewardj3c944452011-09-05 20:39:57 +00001183/*---------------------- mempcpy ----------------------*/
1184
sewardj841b72d2006-12-31 18:55:56 +00001185/* mempcpy */
1186#define GLIBC25_MEMPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001187 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001188 ( void *dst, const void *src, SizeT len ); \
sewardj96044842011-08-18 13:09:55 +00001189 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001190 ( void *dst, const void *src, SizeT len ) \
1191 { \
1192 register char *d; \
1193 register char *s; \
1194 SizeT len_saved = len; \
1195 \
1196 if (len == 0) \
1197 return dst; \
1198 \
1199 if (is_overlap(dst, src, len, len)) \
1200 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1201 \
1202 if ( dst > src ) { \
1203 d = (char *)dst + len - 1; \
1204 s = (char *)src + len - 1; \
1205 while ( len-- ) { \
1206 *d-- = *s--; \
1207 } \
1208 } else if ( dst < src ) { \
1209 d = (char *)dst; \
1210 s = (char *)src; \
1211 while ( len-- ) { \
1212 *d++ = *s++; \
1213 } \
1214 } \
1215 return (void*)( ((char*)dst) + len_saved ); \
1216 }
1217
njnb4cfbc42009-05-04 04:20:02 +00001218#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001219 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1220 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
sewardj4157d4f2011-09-05 22:18:13 +00001221
sewardj3c944452011-09-05 20:39:57 +00001222#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +00001223 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
sewardj4157d4f2011-09-05 22:18:13 +00001224
njnb4cfbc42009-05-04 04:20:02 +00001225#endif
sewardj841b72d2006-12-31 18:55:56 +00001226
1227
sewardj3c944452011-09-05 20:39:57 +00001228/*-------------------- memcpy_chk --------------------*/
1229
sewardjb6c04032007-11-13 20:52:29 +00001230#define GLIBC26___MEMCPY_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001231 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001232 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
sewardj96044842011-08-18 13:09:55 +00001233 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001234 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1235 { \
sewardjb6c04032007-11-13 20:52:29 +00001236 register char *d; \
1237 register char *s; \
1238 \
1239 if (dstlen < len) goto badness; \
1240 \
1241 if (len == 0) \
1242 return dst; \
1243 \
1244 if (is_overlap(dst, src, len, len)) \
1245 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1246 \
1247 if ( dst > src ) { \
1248 d = (char *)dst + len - 1; \
1249 s = (char *)src + len - 1; \
1250 while ( len-- ) { \
1251 *d-- = *s--; \
1252 } \
1253 } else if ( dst < src ) { \
1254 d = (char *)dst; \
1255 s = (char *)src; \
1256 while ( len-- ) { \
1257 *d++ = *s++; \
1258 } \
1259 } \
1260 return dst; \
1261 badness: \
1262 VALGRIND_PRINTF_BACKTRACE( \
1263 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001264 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001265 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001266 /*NOTREACHED*/ \
1267 return NULL; \
1268 }
1269
sewardj3c944452011-09-05 20:39:57 +00001270#if defined(VGO_linux)
1271 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001272
sewardj3c944452011-09-05 20:39:57 +00001273#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001274
sewardj3c944452011-09-05 20:39:57 +00001275#endif
sewardjb6c04032007-11-13 20:52:29 +00001276
1277
sewardj3c944452011-09-05 20:39:57 +00001278/*---------------------- strstr ----------------------*/
1279
sewardja77687c2010-08-19 13:22:34 +00001280#define STRSTR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001281 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001282 (void* haystack, void* needle); \
sewardj96044842011-08-18 13:09:55 +00001283 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001284 (void* haystack, void* needle) \
1285 { \
1286 UChar* h = (UChar*)haystack; \
1287 UChar* n = (UChar*)needle; \
1288 \
1289 /* find the length of n, not including terminating zero */ \
1290 UWord nlen = 0; \
1291 while (n[nlen]) nlen++; \
1292 \
1293 /* if n is the empty string, match immediately. */ \
1294 if (nlen == 0) return h; \
1295 \
1296 /* assert(nlen >= 1); */ \
1297 UChar n0 = n[0]; \
1298 \
1299 while (1) { \
1300 UChar hh = *h; \
1301 if (hh == 0) return NULL; \
1302 if (hh != n0) { h++; continue; } \
1303 \
1304 UWord i; \
1305 for (i = 0; i < nlen; i++) { \
1306 if (n[i] != h[i]) \
1307 break; \
1308 } \
1309 /* assert(i >= 0 && i <= nlen); */ \
1310 if (i == nlen) \
1311 return h; \
1312 \
1313 h++; \
1314 } \
1315 }
1316
1317#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001318 STRSTR(VG_Z_LIBC_SONAME, strstr)
sewardj4157d4f2011-09-05 22:18:13 +00001319
sewardj3c944452011-09-05 20:39:57 +00001320#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001321
sewardja77687c2010-08-19 13:22:34 +00001322#endif
1323
1324
sewardj3c944452011-09-05 20:39:57 +00001325/*---------------------- strpbrk ----------------------*/
1326
sewardja77687c2010-08-19 13:22:34 +00001327#define STRPBRK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001328 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001329 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001330 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001331 (void* sV, void* acceptV) \
1332 { \
1333 UChar* s = (UChar*)sV; \
1334 UChar* accept = (UChar*)acceptV; \
1335 \
1336 /* find the length of 'accept', not including terminating zero */ \
1337 UWord nacc = 0; \
1338 while (accept[nacc]) nacc++; \
1339 \
1340 /* if n is the empty string, fail immediately. */ \
1341 if (nacc == 0) return NULL; \
1342 \
1343 /* assert(nacc >= 1); */ \
1344 while (1) { \
1345 UWord i; \
1346 UChar sc = *s; \
1347 if (sc == 0) \
1348 break; \
1349 for (i = 0; i < nacc; i++) { \
1350 if (sc == accept[i]) \
1351 return s; \
1352 } \
1353 s++; \
1354 } \
1355 \
1356 return NULL; \
1357 }
1358
1359#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001360 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
sewardj4157d4f2011-09-05 22:18:13 +00001361
sewardj3c944452011-09-05 20:39:57 +00001362#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001363
sewardja77687c2010-08-19 13:22:34 +00001364#endif
1365
1366
sewardj3c944452011-09-05 20:39:57 +00001367/*---------------------- strcspn ----------------------*/
1368
sewardja77687c2010-08-19 13:22:34 +00001369#define STRCSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001370 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001371 (void* sV, void* rejectV); \
sewardj96044842011-08-18 13:09:55 +00001372 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001373 (void* sV, void* rejectV) \
1374 { \
1375 UChar* s = (UChar*)sV; \
1376 UChar* reject = (UChar*)rejectV; \
1377 \
1378 /* find the length of 'reject', not including terminating zero */ \
1379 UWord nrej = 0; \
1380 while (reject[nrej]) nrej++; \
1381 \
1382 UWord len = 0; \
1383 while (1) { \
1384 UWord i; \
1385 UChar sc = *s; \
1386 if (sc == 0) \
1387 break; \
1388 for (i = 0; i < nrej; i++) { \
1389 if (sc == reject[i]) \
1390 break; \
1391 } \
1392 /* assert(i >= 0 && i <= nrej); */ \
1393 if (i < nrej) \
1394 break; \
1395 s++; \
1396 len++; \
1397 } \
1398 \
1399 return len; \
1400 }
1401
1402#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001403 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
sewardj4157d4f2011-09-05 22:18:13 +00001404
sewardj3c944452011-09-05 20:39:57 +00001405#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001406
sewardja77687c2010-08-19 13:22:34 +00001407#endif
1408
1409
sewardj3c944452011-09-05 20:39:57 +00001410/*---------------------- strspn ----------------------*/
1411
sewardjbd2cff22011-08-16 21:45:28 +00001412#define STRSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001413 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001414 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001415 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001416 (void* sV, void* acceptV) \
1417 { \
1418 UChar* s = (UChar*)sV; \
1419 UChar* accept = (UChar*)acceptV; \
1420 \
1421 /* find the length of 'accept', not including terminating zero */ \
1422 UWord nacc = 0; \
1423 while (accept[nacc]) nacc++; \
1424 if (nacc == 0) return 0; \
1425 \
1426 UWord len = 0; \
1427 while (1) { \
1428 UWord i; \
1429 UChar sc = *s; \
1430 if (sc == 0) \
1431 break; \
1432 for (i = 0; i < nacc; i++) { \
1433 if (sc == accept[i]) \
1434 break; \
1435 } \
1436 /* assert(i >= 0 && i <= nacc); */ \
1437 if (i == nacc) \
1438 break; \
1439 s++; \
1440 len++; \
1441 } \
1442 \
1443 return len; \
1444 }
1445
1446#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001447 STRSPN(VG_Z_LIBC_SONAME, strspn)
sewardj4157d4f2011-09-05 22:18:13 +00001448
sewardj3c944452011-09-05 20:39:57 +00001449#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001450
sewardjbd2cff22011-08-16 21:45:28 +00001451#endif
sewardjba189352010-08-20 18:24:16 +00001452
1453
sewardj31b9ce12006-10-17 01:27:13 +00001454/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001455/*--- Improve definedness checking of process environment ---*/
1456/*------------------------------------------------------------*/
1457
sewardjddc00dd2007-11-27 11:42:47 +00001458#if defined(VGO_linux)
1459
sewardjbd2cff22011-08-16 21:45:28 +00001460/* If these wind up getting generated via a macro, so that multiple
1461 versions of each function exist (as above), use the _EZU variants
1462 to assign equivalance class tags. */
1463
sewardj3c944452011-09-05 20:39:57 +00001464/*---------------------- putenv ----------------------*/
1465
njne6154662009-02-10 04:23:41 +00001466int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1467int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001468{
1469 OrigFn fn;
1470 Word result;
1471 const char* p = string;
1472 VALGRIND_GET_ORIG_FN(fn);
1473 /* Now by walking over the string we magically produce
1474 traces when hitting undefined memory. */
1475 if (p)
1476 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001477 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001478 CALL_FN_W_W(result, fn, string);
1479 return result;
1480}
1481
sewardj3c944452011-09-05 20:39:57 +00001482
1483/*---------------------- unsetenv ----------------------*/
1484
njne6154662009-02-10 04:23:41 +00001485int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1486int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001487{
1488 OrigFn fn;
1489 Word result;
1490 const char* p = name;
1491 VALGRIND_GET_ORIG_FN(fn);
1492 /* Now by walking over the string we magically produce
1493 traces when hitting undefined memory. */
1494 if (p)
1495 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001496 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001497 CALL_FN_W_W(result, fn, name);
1498 return result;
1499}
1500
sewardj3c944452011-09-05 20:39:57 +00001501
1502/*---------------------- setenv ----------------------*/
1503
dirk09beb9e2007-04-19 09:47:32 +00001504/* setenv */
njne6154662009-02-10 04:23:41 +00001505int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001506 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001507int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001508 (const char* name, const char* value, int overwrite)
1509{
1510 OrigFn fn;
1511 Word result;
1512 const char* p;
1513 VALGRIND_GET_ORIG_FN(fn);
1514 /* Now by walking over the string we magically produce
1515 traces when hitting undefined memory. */
1516 if (name)
1517 for (p = name; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001518 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001519 if (value)
1520 for (p = value; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001521 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001522 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1523 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1524 return result;
1525}
1526
sewardjddc00dd2007-11-27 11:42:47 +00001527#endif /* defined(VGO_linux) */
1528
njn3e884182003-04-15 13:03:23 +00001529/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001530/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001531/*--------------------------------------------------------------------*/