blob: f928769dfba477e7c83f4a1ba34c6a1f4df703f7 [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
sewardjdda830a2003-07-20 22:28:42 +000056/* Figure out if [dst .. dst+dstlen-1] overlaps with
57 [src .. src+srclen-1].
58 We assume that the address ranges do not wrap around
59 (which is safe since on Linux addresses >= 0xC0000000
60 are not accessible and the program will segfault in this
61 circumstance, presumably).
62*/
njn3e884182003-04-15 13:03:23 +000063static __inline__
njnc6168192004-11-29 13:54:10 +000064Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
njn3e884182003-04-15 13:03:23 +000065{
sewardjdda830a2003-07-20 22:28:42 +000066 Addr loS, hiS, loD, hiD;
67
68 if (dstlen == 0 || srclen == 0)
69 return False;
70
71 loS = (Addr)src;
72 loD = (Addr)dst;
73 hiS = loS + srclen - 1;
74 hiD = loD + dstlen - 1;
75
76 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
77 if (loS < loD) {
78 return !(hiS < loD);
79 }
80 else if (loD < loS) {
81 return !(hiD < loS);
82 }
83 else {
84 /* They start at same place. Since we know neither of them has
85 zero length, they must overlap. */
86 return True;
87 }
njn3e884182003-04-15 13:03:23 +000088}
89
njn1f8b3e72005-03-22 04:27:14 +000090// This is a macro rather than a function because we don't want to have an
91// extra function in the stack trace.
njn718d3b12006-12-16 00:54:12 +000092#define RECORD_OVERLAP_ERROR(s, src, dst, len) \
njn1f8b3e72005-03-22 04:27:14 +000093{ \
94 Word unused_res; \
sewardj0ec07f32006-01-12 12:32:32 +000095 VALGRIND_DO_CLIENT_REQUEST(unused_res, 0, \
96 _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \
njn718d3b12006-12-16 00:54:12 +000097 s, src, dst, len, 0); \
njn3e884182003-04-15 13:03:23 +000098}
99
njn16eeb4e2005-06-16 03:56:58 +0000100
101#define STRRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000102 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
103 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000104 { \
105 UChar ch = (UChar)((UInt)c); \
106 UChar* p = (UChar*)s; \
107 UChar* last = NULL; \
108 while (True) { \
109 if (*p == ch) last = p; \
110 if (*p == 0) return last; \
111 p++; \
112 } \
njn3e884182003-04-15 13:03:23 +0000113 }
njn3e884182003-04-15 13:03:23 +0000114
njn16eeb4e2005-06-16 03:56:58 +0000115// Apparently rindex() is the same thing as strrchr()
njne6154662009-02-10 04:23:41 +0000116STRRCHR(VG_Z_LIBC_SONAME, strrchr)
117STRRCHR(VG_Z_LIBC_SONAME, rindex)
njnb4cfbc42009-05-04 04:20:02 +0000118#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000119STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
njne6154662009-02-10 04:23:41 +0000120STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
njnf76d27a2009-05-28 01:53:07 +0000121#elif defined(VGO_darwin)
122STRRCHR(VG_Z_DYLD, strrchr)
123STRRCHR(VG_Z_DYLD, rindex)
njnb4cfbc42009-05-04 04:20:02 +0000124#endif
njn16eeb4e2005-06-16 03:56:58 +0000125
126
127#define STRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000128 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
129 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000130 { \
131 UChar ch = (UChar)((UInt)c); \
132 UChar* p = (UChar*)s; \
133 while (True) { \
134 if (*p == ch) return p; \
135 if (*p == 0) return NULL; \
136 p++; \
137 } \
njn3e884182003-04-15 13:03:23 +0000138 }
njn3e884182003-04-15 13:03:23 +0000139
njn16eeb4e2005-06-16 03:56:58 +0000140// Apparently index() is the same thing as strchr()
njne6154662009-02-10 04:23:41 +0000141STRCHR(VG_Z_LIBC_SONAME, strchr)
njne6154662009-02-10 04:23:41 +0000142STRCHR(VG_Z_LIBC_SONAME, index)
njnb4cfbc42009-05-04 04:20:02 +0000143#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000144STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
njnb4cfbc42009-05-04 04:20:02 +0000145STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
njne6154662009-02-10 04:23:41 +0000146STRCHR(VG_Z_LD_LINUX_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +0000147STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
njne6154662009-02-10 04:23:41 +0000148STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
njnf76d27a2009-05-28 01:53:07 +0000149#elif defined(VGO_darwin)
150STRCHR(VG_Z_DYLD, strchr)
151STRCHR(VG_Z_DYLD, index)
njnb4cfbc42009-05-04 04:20:02 +0000152#endif
njn3e884182003-04-15 13:03:23 +0000153
njn3e884182003-04-15 13:03:23 +0000154
njn16eeb4e2005-06-16 03:56:58 +0000155#define STRCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000156 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
157 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000158 { \
159 const Char* src_orig = src; \
160 Char* dst_orig = dst; \
161 while (*dst) dst++; \
162 while (*src) *dst++ = *src++; \
163 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000164 \
njn16eeb4e2005-06-16 03:56:58 +0000165 /* This is a bit redundant, I think; any overlap and the strcat will */ \
166 /* go forever... or until a seg fault occurs. */ \
167 if (is_overlap(dst_orig, \
168 src_orig, \
169 (Addr)dst-(Addr)dst_orig+1, \
170 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000171 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000172 \
njn16eeb4e2005-06-16 03:56:58 +0000173 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000174 }
njn3e884182003-04-15 13:03:23 +0000175
njne6154662009-02-10 04:23:41 +0000176STRCAT(VG_Z_LIBC_SONAME, strcat)
tomd2645142009-10-29 09:27:11 +0000177#if defined(VGO_linux)
178STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
179#endif
njn16eeb4e2005-06-16 03:56:58 +0000180
181#define STRNCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000182 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
183 ( char* dst, const char* src, SizeT n ); \
184 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
185 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000186 { \
187 const Char* src_orig = src; \
188 Char* dst_orig = dst; \
189 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000190 \
njn16eeb4e2005-06-16 03:56:58 +0000191 while (*dst) dst++; \
192 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
193 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000194 \
njn16eeb4e2005-06-16 03:56:58 +0000195 /* This checks for overlap after copying, unavoidable without */ \
196 /* pre-counting lengths... should be ok */ \
197 if (is_overlap(dst_orig, \
198 src_orig, \
199 (Addr)dst-(Addr)dst_orig+1, \
200 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000201 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000202 \
njn16eeb4e2005-06-16 03:56:58 +0000203 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000204 }
njn3e884182003-04-15 13:03:23 +0000205
njne6154662009-02-10 04:23:41 +0000206STRNCAT(VG_Z_LIBC_SONAME, strncat)
njnf76d27a2009-05-28 01:53:07 +0000207#if defined(VGO_darwin)
208STRNCAT(VG_Z_DYLD, strncat)
209#endif
210
211
212/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
213 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
214 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
215 Truncation occurred if retval >= n.
216*/
217#define STRLCAT(soname, fnname) \
218 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
219 ( char* dst, const char* src, SizeT n ); \
220 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
221 ( char* dst, const char* src, SizeT n ) \
222 { \
223 const Char* src_orig = src; \
224 Char* dst_orig = dst; \
225 SizeT m = 0; \
226\
227 while (m < n && *dst) { m++; dst++; } \
228 if (m < n) { \
229 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
230 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
231 *dst = 0; \
232 } else { \
233 /* No space to copy anything to dst. m == n */ \
234 } \
235 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
236 while (*src) { m++; src++; } \
237 /* This checks for overlap after copying, unavoidable without */ \
238 /* pre-counting lengths... should be ok */ \
239 if (is_overlap(dst_orig, \
240 src_orig, \
241 (Addr)dst-(Addr)dst_orig+1, \
242 (Addr)src-(Addr)src_orig+1)) \
243 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
244\
245 return m; \
246 }
247
248#if defined(VGO_darwin)
249STRLCAT(VG_Z_LIBC_SONAME, strlcat)
250STRLCAT(VG_Z_DYLD, strlcat)
251#endif
sewardj31b9ce12006-10-17 01:27:13 +0000252
njn3e884182003-04-15 13:03:23 +0000253
njn16eeb4e2005-06-16 03:56:58 +0000254#define STRNLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000255 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
256 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000257 { \
258 SizeT i = 0; \
259 while (i < n && str[i] != 0) i++; \
260 return i; \
njn3e884182003-04-15 13:03:23 +0000261 }
njn3e884182003-04-15 13:03:23 +0000262
njne6154662009-02-10 04:23:41 +0000263STRNLEN(VG_Z_LIBC_SONAME, strnlen)
tomd2645142009-10-29 09:27:11 +0000264#if defined(VGO_linux)
265STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
266#endif
njn16eeb4e2005-06-16 03:56:58 +0000267
sewardj3ceec242003-07-30 21:24:25 +0000268
njn5ec15ed2005-08-24 19:55:51 +0000269// Note that this replacement often doesn't get used because gcc inlines
270// calls to strlen() with its own built-in version. This can be very
271// confusing if you aren't expecting it. Other small functions in this file
272// may also be inline by gcc.
njn16eeb4e2005-06-16 03:56:58 +0000273#define STRLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000274 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
275 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000276 { \
277 SizeT i = 0; \
278 while (str[i] != 0) i++; \
279 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000280 }
njn16eeb4e2005-06-16 03:56:58 +0000281
njnb4cfbc42009-05-04 04:20:02 +0000282STRLEN(VG_Z_LIBC_SONAME, strlen)
283#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000284STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
njne6154662009-02-10 04:23:41 +0000285STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
286STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000287#endif
sewardj31b9ce12006-10-17 01:27:13 +0000288
njn16eeb4e2005-06-16 03:56:58 +0000289
290#define STRCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000291 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
292 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000293 { \
294 const Char* src_orig = src; \
295 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000296 \
njn16eeb4e2005-06-16 03:56:58 +0000297 while (*src) *dst++ = *src++; \
298 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000299 \
njn16eeb4e2005-06-16 03:56:58 +0000300 /* This checks for overlap after copying, unavoidable without */ \
301 /* pre-counting length... should be ok */ \
302 if (is_overlap(dst_orig, \
303 src_orig, \
304 (Addr)dst-(Addr)dst_orig+1, \
305 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000306 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000307 \
njn16eeb4e2005-06-16 03:56:58 +0000308 return dst_orig; \
309 }
310
njne6154662009-02-10 04:23:41 +0000311STRCPY(VG_Z_LIBC_SONAME, strcpy)
tomd2645142009-10-29 09:27:11 +0000312#if defined(VGO_linux)
313STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
314#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000315STRCPY(VG_Z_DYLD, strcpy)
316#endif
njn16eeb4e2005-06-16 03:56:58 +0000317
318
319#define STRNCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000320 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
321 ( char* dst, const char* src, SizeT n ); \
322 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
323 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000324 { \
325 const Char* src_orig = src; \
326 Char* dst_orig = dst; \
327 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000328 \
njn16eeb4e2005-06-16 03:56:58 +0000329 while (m < n && *src) { m++; *dst++ = *src++; } \
330 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
331 /* but only m+1 bytes of src if terminator was found */ \
332 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000333 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000334 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
335 \
336 return dst_orig; \
337 }
338
njne6154662009-02-10 04:23:41 +0000339STRNCPY(VG_Z_LIBC_SONAME, strncpy)
tomd2645142009-10-29 09:27:11 +0000340#if defined(VGO_linux)
341STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
342#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000343STRNCPY(VG_Z_DYLD, strncpy)
344#endif
345
346
347/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
348 Returns strlen(src). Does not zero-fill the remainder of dst. */
349#define STRLCPY(soname, fnname) \
350 SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \
351 ( char* dst, const char* src, SizeT n ); \
352 SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \
353 ( char* dst, const char* src, SizeT n ) \
354 { \
355 const char* src_orig = src; \
356 char* dst_orig = dst; \
357 SizeT m = 0; \
358\
359 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
360 /* m non-nul bytes have now been copied, and m <= n-1. */ \
361 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
362 /* but only m+1 bytes of src if terminator was found */ \
363 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
364 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
365 /* Nul-terminate dst. */ \
366 if (n > 0) *dst = 0; \
367 /* Finish counting strlen(src). */ \
368 while (*src) src++; \
369 return src - src_orig; \
370 }
371
372#if defined(VGO_darwin)
373STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
374STRLCPY(VG_Z_DYLD, strlcpy)
375#endif
njn16eeb4e2005-06-16 03:56:58 +0000376
377
378#define STRNCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000379 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
380 ( const char* s1, const char* s2, SizeT nmax ); \
381 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
382 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000383 { \
384 SizeT n = 0; \
385 while (True) { \
386 if (n >= nmax) return 0; \
387 if (*s1 == 0 && *s2 == 0) return 0; \
388 if (*s1 == 0) return -1; \
389 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000390 \
njn16eeb4e2005-06-16 03:56:58 +0000391 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
392 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000393 \
njn16eeb4e2005-06-16 03:56:58 +0000394 s1++; s2++; n++; \
395 } \
396 }
397
njne6154662009-02-10 04:23:41 +0000398STRNCMP(VG_Z_LIBC_SONAME, strncmp)
tomd2645142009-10-29 09:27:11 +0000399#if defined(VGO_linux)
400STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
401#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000402STRNCMP(VG_Z_DYLD, strncmp)
403#endif
njn16eeb4e2005-06-16 03:56:58 +0000404
405
406#define STRCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000407 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
408 ( const char* s1, const char* s2 ); \
409 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
410 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000411 { \
412 register unsigned char c1; \
413 register unsigned char c2; \
414 while (True) { \
415 c1 = *(unsigned char *)s1; \
416 c2 = *(unsigned char *)s2; \
417 if (c1 != c2) break; \
418 if (c1 == 0) break; \
419 s1++; s2++; \
420 } \
421 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
422 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
423 return 0; \
424 }
425
njne6154662009-02-10 04:23:41 +0000426STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000427#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000428STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
njne6154662009-02-10 04:23:41 +0000429STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
430STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000431#endif
njn16eeb4e2005-06-16 03:56:58 +0000432
433
434#define MEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000435 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
436 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000437 { \
438 SizeT i; \
439 UChar c0 = (UChar)c; \
440 UChar* p = (UChar*)s; \
441 for (i = 0; i < n; i++) \
442 if (p[i] == c0) return (void*)(&p[i]); \
443 return NULL; \
444 }
445
njne6154662009-02-10 04:23:41 +0000446MEMCHR(VG_Z_LIBC_SONAME, memchr)
njnf76d27a2009-05-28 01:53:07 +0000447#if defined(VGO_darwin)
448MEMCHR(VG_Z_DYLD, memchr)
449#endif
njn16eeb4e2005-06-16 03:56:58 +0000450
451
452#define MEMCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000453 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
454 ( void *dst, const void *src, SizeT len ); \
455 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
456 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000457 { \
458 register char *d; \
459 register char *s; \
sewardjb6c04032007-11-13 20:52:29 +0000460 \
njn16eeb4e2005-06-16 03:56:58 +0000461 if (len == 0) \
462 return dst; \
sewardjb6c04032007-11-13 20:52:29 +0000463 \
njn16eeb4e2005-06-16 03:56:58 +0000464 if (is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000465 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000466 \
njn16eeb4e2005-06-16 03:56:58 +0000467 if ( dst > src ) { \
468 d = (char *)dst + len - 1; \
469 s = (char *)src + len - 1; \
470 while ( len >= 4 ) { \
471 *d-- = *s--; \
472 *d-- = *s--; \
473 *d-- = *s--; \
474 *d-- = *s--; \
475 len -= 4; \
476 } \
477 while ( len-- ) { \
478 *d-- = *s--; \
479 } \
480 } else if ( dst < src ) { \
481 d = (char *)dst; \
482 s = (char *)src; \
483 while ( len >= 4 ) { \
484 *d++ = *s++; \
485 *d++ = *s++; \
486 *d++ = *s++; \
487 *d++ = *s++; \
488 len -= 4; \
489 } \
490 while ( len-- ) { \
491 *d++ = *s++; \
492 } \
493 } \
494 return dst; \
495 }
496
njne6154662009-02-10 04:23:41 +0000497MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000498#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000499MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
500MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnf76d27a2009-05-28 01:53:07 +0000501#elif defined(VGO_darwin)
502MEMCPY(VG_Z_DYLD, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000503#endif
sewardjf0b34322007-01-16 21:42:28 +0000504/* icc9 blats these around all over the place. Not only in the main
505 executable but various .so's. They are highly tuned and read
506 memory beyond the source boundary (although work correctly and
507 never go across page boundaries), so give errors when run natively,
508 at least for misaligned source arg. Just intercepting in the exe
509 only until we understand more about the problem. See
510 http://bugs.kde.org/show_bug.cgi?id=139776
511 */
512MEMCPY(NONE, _intel_fast_memcpy)
sewardj31b9ce12006-10-17 01:27:13 +0000513
njn16eeb4e2005-06-16 03:56:58 +0000514
515#define MEMCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000516 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
517 ( const void *s1V, const void *s2V, SizeT n ); \
518 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
519 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000520 { \
521 int res; \
522 unsigned char a0; \
523 unsigned char b0; \
524 unsigned char* s1 = (unsigned char*)s1V; \
525 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000526 \
njn16eeb4e2005-06-16 03:56:58 +0000527 while (n != 0) { \
528 a0 = s1[0]; \
529 b0 = s2[0]; \
530 s1 += 1; \
531 s2 += 1; \
532 res = ((int)a0) - ((int)b0); \
533 if (res != 0) \
534 return res; \
535 n -= 1; \
536 } \
537 return 0; \
538 }
539
njne6154662009-02-10 04:23:41 +0000540MEMCMP(VG_Z_LIBC_SONAME, memcmp)
541MEMCMP(VG_Z_LIBC_SONAME, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000542#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000543MEMCMP(VG_Z_LD_SO_1, bcmp)
njnf76d27a2009-05-28 01:53:07 +0000544#elif defined(VGO_darwin)
545MEMCMP(VG_Z_DYLD, memcmp)
546MEMCMP(VG_Z_DYLD, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000547#endif
njn3e884182003-04-15 13:03:23 +0000548
jseward0845ef82003-12-22 22:31:27 +0000549
550/* Copy SRC to DEST, returning the address of the terminating '\0' in
551 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000552#define STPCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000553 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
554 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000555 { \
556 const Char* src_orig = src; \
557 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000558 \
njn16eeb4e2005-06-16 03:56:58 +0000559 while (*src) *dst++ = *src++; \
560 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000561 \
njn16eeb4e2005-06-16 03:56:58 +0000562 /* This checks for overlap after copying, unavoidable without */ \
563 /* pre-counting length... should be ok */ \
564 if (is_overlap(dst_orig, \
565 src_orig, \
566 (Addr)dst-(Addr)dst_orig+1, \
567 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000568 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000569 \
njn16eeb4e2005-06-16 03:56:58 +0000570 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000571 }
njn16eeb4e2005-06-16 03:56:58 +0000572
njne6154662009-02-10 04:23:41 +0000573STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000574#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000575STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
njne6154662009-02-10 04:23:41 +0000576STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
577STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnf76d27a2009-05-28 01:53:07 +0000578#elif defined(VGO_darwin)
579STPCPY(VG_Z_DYLD, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000580#endif
581
njn16eeb4e2005-06-16 03:56:58 +0000582
583#define MEMSET(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000584 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \
585 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000586 { \
587 unsigned char *cp = s; \
sewardj487cadb2007-08-25 23:25:00 +0000588 while (n >= 4) { \
589 cp[0] = c; \
590 cp[1] = c; \
591 cp[2] = c; \
592 cp[3] = c; \
593 cp += 4; \
594 n -= 4; \
595 } \
596 while (n--) { \
njn16eeb4e2005-06-16 03:56:58 +0000597 *cp++ = c; \
sewardj487cadb2007-08-25 23:25:00 +0000598 } \
njn16eeb4e2005-06-16 03:56:58 +0000599 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000600 }
njn16eeb4e2005-06-16 03:56:58 +0000601
njne6154662009-02-10 04:23:41 +0000602MEMSET(VG_Z_LIBC_SONAME, memset)
njnf76d27a2009-05-28 01:53:07 +0000603#if defined(VGO_darwin)
604MEMSET(VG_Z_DYLD, memset)
605#endif
njn16eeb4e2005-06-16 03:56:58 +0000606
607
608#define MEMMOVE(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000609 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
610 (void *dstV, const void *srcV, SizeT n); \
611 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
612 (void *dstV, const void *srcV, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000613 { \
614 SizeT i; \
615 Char* dst = (Char*)dstV; \
616 Char* src = (Char*)srcV; \
617 if (dst < src) { \
618 for (i = 0; i < n; i++) \
619 dst[i] = src[i]; \
620 } \
621 else \
622 if (dst > src) { \
623 for (i = 0; i < n; i++) \
624 dst[n-i-1] = src[n-i-1]; \
625 } \
626 return dst; \
627 }
628
njne6154662009-02-10 04:23:41 +0000629MEMMOVE(VG_Z_LIBC_SONAME, memmove)
njnf76d27a2009-05-28 01:53:07 +0000630#if defined(VGO_darwin)
631MEMMOVE(VG_Z_DYLD, memmove)
632#endif
633
634
635#define BCOPY(soname, fnname) \
636 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
637 (const void *srcV, void *dstV, SizeT n); \
638 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
639 (const void *srcV, void *dstV, SizeT n) \
640 { \
641 SizeT i; \
642 Char* dst = (Char*)dstV; \
643 Char* src = (Char*)srcV; \
644 if (dst < src) { \
645 for (i = 0; i < n; i++) \
646 dst[i] = src[i]; \
647 } \
648 else \
649 if (dst > src) { \
650 for (i = 0; i < n; i++) \
651 dst[n-i-1] = src[n-i-1]; \
652 } \
653 }
654
655#if defined(VGO_darwin)
656BCOPY(VG_Z_LIBC_SONAME, bcopy)
657BCOPY(VG_Z_DYLD, bcopy)
658#endif
sewardj44e495f2005-05-12 17:58:28 +0000659
jseward0845ef82003-12-22 22:31:27 +0000660
sewardj24cb2172007-02-23 09:03:26 +0000661/* glibc 2.5 variant of memmove which checks the dest is big enough.
662 There is no specific part of glibc that this is copied from. */
663#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
664 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
665 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
666 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
667 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
668 { \
669 extern void _exit(int status); \
670 SizeT i; \
671 Char* dst = (Char*)dstV; \
672 Char* src = (Char*)srcV; \
673 if (destlen < n) \
674 goto badness; \
675 if (dst < src) { \
676 for (i = 0; i < n; i++) \
677 dst[i] = src[i]; \
678 } \
679 else \
680 if (dst > src) { \
681 for (i = 0; i < n; i++) \
682 dst[n-i-1] = src[n-i-1]; \
683 } \
684 return dst; \
685 badness: \
686 VALGRIND_PRINTF_BACKTRACE( \
687 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000688 "program terminated\n"); \
sewardj24cb2172007-02-23 09:03:26 +0000689 _exit(127); \
sewardjc271ec82007-02-27 22:36:14 +0000690 /*NOTREACHED*/ \
691 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +0000692 }
693
njne6154662009-02-10 04:23:41 +0000694GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj24cb2172007-02-23 09:03:26 +0000695
696
sewardj4e9a4b62004-11-23 00:20:17 +0000697/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000698#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000699 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
700 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000701 { \
702 unsigned char c = (unsigned char) c_in; \
703 unsigned char* char_ptr = (unsigned char *)s; \
704 while (1) { \
705 if (*char_ptr == 0) return char_ptr; \
706 if (*char_ptr == c) return char_ptr; \
707 char_ptr++; \
708 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000709 }
njn16eeb4e2005-06-16 03:56:58 +0000710
njne6154662009-02-10 04:23:41 +0000711GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000712
713
714/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000715#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000716 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
717 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000718 { \
719 unsigned char c = (unsigned char) c_in; \
720 unsigned char* char_ptr = (unsigned char *)s; \
721 while (1) { \
722 if (*char_ptr == c) return char_ptr; \
723 char_ptr++; \
724 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000725 }
njn16eeb4e2005-06-16 03:56:58 +0000726
njne6154662009-02-10 04:23:41 +0000727GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
tomd2645142009-10-29 09:27:11 +0000728#if defined (VGO_linux)
729GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
730#endif
sewardj4e9a4b62004-11-23 00:20:17 +0000731
sewardjdc5d8322007-01-28 06:32:01 +0000732/* glibc variant of strcpy that checks the dest is big enough.
733 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +0000734#define GLIBC25___STRCPY_CHK(soname,fnname) \
735 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
736 (char* dst, const char* src, SizeT len); \
737 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
738 (char* dst, const char* src, SizeT len) \
739 { \
740 extern void _exit(int status); \
741 char* ret = dst; \
742 if (! len) \
743 goto badness; \
744 while ((*dst++ = *src++) != '\0') \
745 if (--len == 0) \
746 goto badness; \
747 return ret; \
748 badness: \
749 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000750 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000751 "program terminated\n"); \
sewardj620e5262006-12-31 00:22:30 +0000752 _exit(127); \
753 /*NOTREACHED*/ \
754 return NULL; \
755 }
756
njne6154662009-02-10 04:23:41 +0000757GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj620e5262006-12-31 00:22:30 +0000758
759
sewardjdc5d8322007-01-28 06:32:01 +0000760/* glibc variant of stpcpy that checks the dest is big enough.
761 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +0000762#define GLIBC25___STPCPY_CHK(soname,fnname) \
763 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
764 (char* dst, const char* src, SizeT len); \
765 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
766 (char* dst, const char* src, SizeT len) \
767 { \
768 extern void _exit(int status); \
sewardjdc5d8322007-01-28 06:32:01 +0000769 if (! len) \
770 goto badness; \
771 while ((*dst++ = *src++) != '\0') \
772 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +0000773 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +0000774 return dst - 1; \
775 badness: \
776 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000777 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000778 "program terminated\n"); \
sewardjb8d03852007-01-27 00:49:44 +0000779 _exit(127); \
780 /*NOTREACHED*/ \
781 return NULL; \
782 }
783
njne6154662009-02-10 04:23:41 +0000784GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardjb8d03852007-01-27 00:49:44 +0000785
786
sewardj841b72d2006-12-31 18:55:56 +0000787/* mempcpy */
788#define GLIBC25_MEMPCPY(soname, fnname) \
789 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
790 ( void *dst, const void *src, SizeT len ); \
791 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
792 ( void *dst, const void *src, SizeT len ) \
793 { \
794 register char *d; \
795 register char *s; \
796 SizeT len_saved = len; \
797 \
798 if (len == 0) \
799 return dst; \
800 \
801 if (is_overlap(dst, src, len, len)) \
802 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
803 \
804 if ( dst > src ) { \
805 d = (char *)dst + len - 1; \
806 s = (char *)src + len - 1; \
807 while ( len-- ) { \
808 *d-- = *s--; \
809 } \
810 } else if ( dst < src ) { \
811 d = (char *)dst; \
812 s = (char *)src; \
813 while ( len-- ) { \
814 *d++ = *s++; \
815 } \
816 } \
817 return (void*)( ((char*)dst) + len_saved ); \
818 }
819
njne6154662009-02-10 04:23:41 +0000820GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
njnb4cfbc42009-05-04 04:20:02 +0000821#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000822GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
njnb4cfbc42009-05-04 04:20:02 +0000823#endif
sewardj841b72d2006-12-31 18:55:56 +0000824
825
sewardjb6c04032007-11-13 20:52:29 +0000826#define GLIBC26___MEMCPY_CHK(soname, fnname) \
827 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
828 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
829 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
830 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
831 { \
832 extern void _exit(int status); \
833 register char *d; \
834 register char *s; \
835 \
836 if (dstlen < len) goto badness; \
837 \
838 if (len == 0) \
839 return dst; \
840 \
841 if (is_overlap(dst, src, len, len)) \
842 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
843 \
844 if ( dst > src ) { \
845 d = (char *)dst + len - 1; \
846 s = (char *)src + len - 1; \
847 while ( len-- ) { \
848 *d-- = *s--; \
849 } \
850 } else if ( dst < src ) { \
851 d = (char *)dst; \
852 s = (char *)src; \
853 while ( len-- ) { \
854 *d++ = *s++; \
855 } \
856 } \
857 return dst; \
858 badness: \
859 VALGRIND_PRINTF_BACKTRACE( \
860 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000861 "program terminated\n"); \
sewardjb6c04032007-11-13 20:52:29 +0000862 _exit(127); \
863 /*NOTREACHED*/ \
864 return NULL; \
865 }
866
njne6154662009-02-10 04:23:41 +0000867GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardjb6c04032007-11-13 20:52:29 +0000868
869
sewardja77687c2010-08-19 13:22:34 +0000870#define STRSTR(soname, fnname) \
871 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
872 (void* haystack, void* needle); \
873 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
874 (void* haystack, void* needle) \
875 { \
876 UChar* h = (UChar*)haystack; \
877 UChar* n = (UChar*)needle; \
878 \
879 /* find the length of n, not including terminating zero */ \
880 UWord nlen = 0; \
881 while (n[nlen]) nlen++; \
882 \
883 /* if n is the empty string, match immediately. */ \
884 if (nlen == 0) return h; \
885 \
886 /* assert(nlen >= 1); */ \
887 UChar n0 = n[0]; \
888 \
889 while (1) { \
890 UChar hh = *h; \
891 if (hh == 0) return NULL; \
892 if (hh != n0) { h++; continue; } \
893 \
894 UWord i; \
895 for (i = 0; i < nlen; i++) { \
896 if (n[i] != h[i]) \
897 break; \
898 } \
899 /* assert(i >= 0 && i <= nlen); */ \
900 if (i == nlen) \
901 return h; \
902 \
903 h++; \
904 } \
905 }
906
907#if defined(VGO_linux)
908STRSTR(VG_Z_LIBC_SONAME, strstr)
909#endif
910
911
912#define STRPBRK(soname, fnname) \
913 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
914 (void* sV, void* acceptV); \
915 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
916 (void* sV, void* acceptV) \
917 { \
918 UChar* s = (UChar*)sV; \
919 UChar* accept = (UChar*)acceptV; \
920 \
921 /* find the length of 'accept', not including terminating zero */ \
922 UWord nacc = 0; \
923 while (accept[nacc]) nacc++; \
924 \
925 /* if n is the empty string, fail immediately. */ \
926 if (nacc == 0) return NULL; \
927 \
928 /* assert(nacc >= 1); */ \
929 while (1) { \
930 UWord i; \
931 UChar sc = *s; \
932 if (sc == 0) \
933 break; \
934 for (i = 0; i < nacc; i++) { \
935 if (sc == accept[i]) \
936 return s; \
937 } \
938 s++; \
939 } \
940 \
941 return NULL; \
942 }
943
944#if defined(VGO_linux)
945STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
946#endif
947
948
949#define STRCSPN(soname, fnname) \
950 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
951 (void* sV, void* rejectV); \
952 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
953 (void* sV, void* rejectV) \
954 { \
955 UChar* s = (UChar*)sV; \
956 UChar* reject = (UChar*)rejectV; \
957 \
958 /* find the length of 'reject', not including terminating zero */ \
959 UWord nrej = 0; \
960 while (reject[nrej]) nrej++; \
961 \
962 UWord len = 0; \
963 while (1) { \
964 UWord i; \
965 UChar sc = *s; \
966 if (sc == 0) \
967 break; \
968 for (i = 0; i < nrej; i++) { \
969 if (sc == reject[i]) \
970 break; \
971 } \
972 /* assert(i >= 0 && i <= nrej); */ \
973 if (i < nrej) \
974 break; \
975 s++; \
976 len++; \
977 } \
978 \
979 return len; \
980 }
981
982#if defined(VGO_linux)
983STRCSPN(VG_Z_LIBC_SONAME, strcspn)
984#endif
985
986
sewardj31b9ce12006-10-17 01:27:13 +0000987/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +0000988/*--- Improve definedness checking of process environment ---*/
989/*------------------------------------------------------------*/
990
sewardjddc00dd2007-11-27 11:42:47 +0000991#if defined(VGO_linux)
992
dirk09beb9e2007-04-19 09:47:32 +0000993/* putenv */
njne6154662009-02-10 04:23:41 +0000994int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
995int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +0000996{
997 OrigFn fn;
998 Word result;
999 const char* p = string;
1000 VALGRIND_GET_ORIG_FN(fn);
1001 /* Now by walking over the string we magically produce
1002 traces when hitting undefined memory. */
1003 if (p)
1004 while (*p++)
1005 ;
1006 CALL_FN_W_W(result, fn, string);
1007 return result;
1008}
1009
1010/* unsetenv */
njne6154662009-02-10 04:23:41 +00001011int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1012int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001013{
1014 OrigFn fn;
1015 Word result;
1016 const char* p = name;
1017 VALGRIND_GET_ORIG_FN(fn);
1018 /* Now by walking over the string we magically produce
1019 traces when hitting undefined memory. */
1020 if (p)
1021 while (*p++)
1022 ;
1023 CALL_FN_W_W(result, fn, name);
1024 return result;
1025}
1026
1027/* setenv */
njne6154662009-02-10 04:23:41 +00001028int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001029 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001030int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001031 (const char* name, const char* value, int overwrite)
1032{
1033 OrigFn fn;
1034 Word result;
1035 const char* p;
1036 VALGRIND_GET_ORIG_FN(fn);
1037 /* Now by walking over the string we magically produce
1038 traces when hitting undefined memory. */
1039 if (name)
1040 for (p = name; *p; p++)
1041 ;
1042 if (value)
1043 for (p = value; *p; p++)
1044 ;
1045 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1046 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1047 return result;
1048}
1049
sewardjddc00dd2007-11-27 11:42:47 +00001050#endif /* defined(VGO_linux) */
1051
1052
dirk09beb9e2007-04-19 09:47:32 +00001053/*------------------------------------------------------------*/
sewardj31b9ce12006-10-17 01:27:13 +00001054/*--- AIX stuff only after this point ---*/
1055/*------------------------------------------------------------*/
1056
sewardjddc00dd2007-11-27 11:42:47 +00001057/* Generate replacements for strcat, strncat, strcpy, strncpy, strcmp
sewardj31b9ce12006-10-17 01:27:13 +00001058 in the given soname. */
sewardjddc00dd2007-11-27 11:42:47 +00001059#define Str5FNs(_soname) \
sewardj31b9ce12006-10-17 01:27:13 +00001060 STRCAT(_soname, strcat) \
1061 STRNCAT(_soname, strncat) \
1062 STRCPY(_soname, strcpy) \
sewardjddc00dd2007-11-27 11:42:47 +00001063 STRNCPY(_soname, strncpy) \
1064 STRCMP(_soname, strcmp)
sewardj31b9ce12006-10-17 01:27:13 +00001065
1066#if defined(VGP_ppc32_aix5)
sewardjddc00dd2007-11-27 11:42:47 +00001067Str5FNs(NONE) /* in main exe */
1068Str5FNs(libCZdaZLshrcoreZdoZR) /* libC.a(shrcore.o) */
1069Str5FNs(libX11ZdaZLshr4ZdoZR) /* libX11.a(shr4.o) */
1070Str5FNs(libXmZdaZLshrZaZdoZR) /* libXm.a(shr*.o) */
1071Str5FNs(libXtZdaZLshr4ZdoZR) /* libXt.a(shr4.o) */
1072Str5FNs(libppeZurZdaZLdynamicZdoZR) /* libppe_r.a(dynamic.o) */
1073Str5FNs(libodmZdaZLshrZdoZR) /* libodm.a(shr.o) */
1074Str5FNs(libmpiZurZdaZLmpicoreZurZdoZR) /* libmpi_r.a(mpicore_r.o) */
1075Str5FNs(libmpiZurZdaZLmpipoeZurZdoZR) /* libmpi_r.a(mpipoe_r.o) */
1076Str5FNs(libmpiZurZdaZLmpciZurZdoZR) /* libmpi_r.a(mpci_r.o) */
1077Str5FNs(libslurmZdso) /* libslurm.so */
1078Str5FNs(libglibZdso) /* libglib.so */
1079Str5FNs(libIMZdaZLshrZdoZR) /* libIM.a(shr.o) */
1080Str5FNs(libiconvZdaZLshr4ZdoZR) /* libiconv.a(shr4.o) */
1081Str5FNs(libGLZdaZLshrZdoZR) /* libGL.a(shr.o) */
1082Str5FNs(libgdkZdso) /* libgdk.so */
1083Str5FNs(libcursesZdaZLshr42ZdoZR) /* libcurses.a(shr42.o) */
1084Str5FNs(libqtZda) /* libqt.a */
sewardjfd4b6f42007-11-29 03:08:32 +00001085Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
1086Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
1087Str5FNs(libQtZaa) /* libQt*.a */
sewardj31b9ce12006-10-17 01:27:13 +00001088#endif
1089#if defined(VGP_ppc64_aix5)
sewardjddc00dd2007-11-27 11:42:47 +00001090Str5FNs(NONE) /* in main exe */
1091Str5FNs(libX11ZdaZLshrZu64ZdoZR) /* libX11.a(shr_64.o) */
1092Str5FNs(libiconvZdaZLshr4Zu64ZdoZR) /* libiconv.a(shr4_64.o) */
1093Str5FNs(libGLZdaZLshrZu64ZdoZR) /* libGL.a(shr_64.o) */
1094Str5FNs(libppeZurZdaZLdynamic64ZdoZR) /* libppe_r.a(dynamic64.o) */
1095Str5FNs(libodmZdaZLshrZu64ZdoZR) /* libodm.a(shr_64.o) */
1096Str5FNs(libmpiZurZdaZLmpicore64ZurZdoZR) /* libmpi_r.a(mpicore64_r.o) */
1097Str5FNs(libmpiZurZdaZLmpipoe64ZurZdoZR) /* libmpi_r.a(mpipoe64_r.o) */
1098Str5FNs(libCZdaZLshrcoreZu64ZdoZR) /* libC.a(shrcore_64.o) */
1099Str5FNs(libmpiZurZdaZLmpci64ZurZdoZR) /* libmpi_r.a(mpci64_r.o) */
1100Str5FNs(libqtZda) /* libqt.a */
sewardjfd4b6f42007-11-29 03:08:32 +00001101Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
1102Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
1103Str5FNs(libQtZaa) /* libQt*.a */
sewardj31b9ce12006-10-17 01:27:13 +00001104#endif
1105
1106
1107/* AIX's libm contains a sqrt implementation which does a nasty thing:
1108 it loads the initial estimate of the root into a FP register, but
1109 only the upper half of the number is initialised data. Hence the
1110 least significant 32 mantissa bits are undefined, and it then uses
1111 Newton-Raphson iteration to compute the final, defined result.
1112 This fools memcheck completely; the only solution I can think of is
1113 provide our own substitute. The _FAST variant is almost right
1114 except the result is not correctly rounded. The _EXACT variant,
1115 which is selected by default, is always right; but it's also pretty
1116 darn slow. */
1117
1118#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
1119#define SQRT_FAST(soname, fnname) \
1120 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1121 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1122 { \
1123 static UInt T1[32] = \
1124 { 0, 1024, 3062, 5746, 9193, 13348, \
1125 18162, 23592, 29598, 36145, 43202, 50740, \
1126 58733, 67158, 75992, 85215, 83599, 71378, \
1127 60428, 50647, 41945, 34246, 27478, 21581, \
1128 16499, 12183, 8588, 5674, 3403, 1742, \
1129 661, 130 }; \
1130 UInt x0, x1, sign, expo, mant0, bIGENDIAN = 1; \
1131 union { UInt w[2]; double d; } u; \
1132 u.d = x; \
1133 x0 = u.w[1 - bIGENDIAN]; /* high half */ \
1134 x1 = u.w[bIGENDIAN]; /* low half */ \
1135 sign = x0 >> 31; \
1136 expo = (x0 >> 20) & 0x7FF; \
1137 mant0 = x0 & 0xFFFFF; \
1138 if ( (sign == 0 && expo >= 1 && expo <= 0x7FE) /* +normal */ \
1139 || (sign == 0 && expo == 0 \
1140 && (mant0 | x1) > 0) /* +denorm */) { \
1141 /* common case; do Newton-Raphson */ \
1142 /* technically k should be signed int32, but since we're \
1143 always entering here with x > 0, doesn't matter that it's \
1144 unsigned. */ \
1145 double y; \
1146 UInt k = (x0>>1) + 0x1ff80000; \
1147 u.w[1 - bIGENDIAN] = k - T1[31&(k>>15)]; \
1148 u.w[bIGENDIAN] = 0; \
1149 y = u.d; \
1150 y = (y+x/y)/2.0 ; \
1151 y = (y+x/y)/2.0 ; \
1152 y = y-(y-x/y)/2.0 ; \
1153 return y; \
1154 } \
1155 if ( (sign == 1 && expo >= 1 && expo <= 0x7FE) /* -normal */ \
1156 || (sign == 1 && expo == 0 \
1157 && (mant0 | x1) > 0) /* -denorm */) { \
1158 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1159 u.w[bIGENDIAN] = 0x1; \
1160 return u.d; /* -Inf -> NaN */ \
1161 } \
1162 if ((expo | mant0 | x1) == 0) \
1163 return x; /* +/-zero -> self */ \
1164 if (expo == 0x7FF && (mant0 | x1) == 0) { \
1165 if (sign == 0) \
1166 return x; /* +Inf -> self */ \
1167 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1168 u.w[bIGENDIAN] = 0x1; \
1169 return u.d; /* -Inf -> NaN */ \
1170 } \
1171 /* must be +/- NaN */ \
1172 return x; /* +/-NaN -> self */ \
1173 }
1174
1175#define SQRT_EXACT(soname, fnname) \
1176 /* \
1177 * ==================================================== \
1178 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. \
1179 * \
1180 * Developed at SunPro, a Sun Microsystems, Inc. business. \
1181 * Permission to use, copy, modify, and distribute this \
1182 * software is freely granted, provided that this notice \
1183 * is preserved. \
1184 * ==================================================== \
1185 */ \
1186 /* \
1187 * Return correctly rounded sqrt. \
1188 * ------------------------------------------ \
1189 * | Use the hardware sqrt if you have one | \
1190 * ------------------------------------------ \
1191 * Method: \
1192 * Bit by bit method using integer arithmetic. (Slow, but portable) \
1193 * 1. Normalization \
1194 * Scale x to y in [1,4) with even powers of 2: \
1195 * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then \
1196 * sqrt(x) = 2^k * sqrt(y) \
1197 * 2. Bit by bit computation \
1198 * Let q = sqrt(y) truncated to i bit after binary point (q = 1), \
1199 * i 0 \
1200 * i+1 2 \
1201 * s = 2*q , and y = 2 * ( y - q ). (1) \
1202 * i i i i \
1203 * \
1204 * To compute q from q , one checks whether \
1205 * i+1 i \
1206 * \
1207 * -(i+1) 2 \
1208 * (q + 2 ) <= y. (2) \
1209 * i \
1210 * -(i+1) \
1211 * If (2) is false, then q = q ; otherwise q = q + 2 . \
1212 * i+1 i i+1 i \
1213 * \
1214 * With some algebric manipulation, it is not difficult to see \
1215 * that (2) is equivalent to \
1216 * -(i+1) \
1217 * s + 2 <= y (3) \
1218 * i i \
1219 * \
1220 * The advantage of (3) is that s and y can be computed by \
1221 * i i \
1222 * the following recurrence formula: \
1223 * if (3) is false \
1224 * \
1225 * s = s , y = y ; (4) \
1226 * i+1 i i+1 i \
1227 * \
1228 * otherwise, \
1229 * -i -(i+1) \
1230 * s = s + 2 , y = y - s - 2 (5) \
1231 * i+1 i i+1 i i \
1232 * \
1233 * \
1234 * One may easily use induction to prove (4) and (5). \
1235 * Note. Since the left hand side of (3) contain only i+2 bits, \
1236 * it does not necessary to do a full (53-bit) comparison \
1237 * in (3). \
1238 * 3. Final rounding \
1239 * After generating the 53 bits result, we compute one more bit. \
1240 * Together with the remainder, we can decide whether the \
1241 * result is exact, bigger than 1/2ulp, or less than 1/2ulp \
1242 * (it will never equal to 1/2ulp). \
1243 * The rounding mode can be detected by checking whether \
1244 * huge + tiny is equal to huge, and whether huge - tiny is \
1245 * equal to huge for some floating point number "huge" and "tiny". \
1246 * \
1247 * Special cases: \
1248 * sqrt(+-0) = +-0 ... exact \
1249 * sqrt(inf) = inf \
1250 * sqrt(-ve) = NaN ... with invalid signal \
1251 * sqrt(NaN) = NaN ... with invalid signal for signaling NaN \
1252 * \
1253 */ \
1254 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1255 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1256 { \
1257 const Int bIGENDIAN = 1; \
1258 const double one = 1.0, tiny=1.0e-300; \
1259 double z; \
1260 Int sign = (Int)0x80000000; \
1261 Int ix0,s0,q,m,t,i; \
1262 UInt r,t1,s1,ix1,q1; \
1263 union { UInt w[2]; double d; } u; \
1264 u.d = x; \
1265 ix0 = u.w[1-bIGENDIAN]; \
1266 ix1 = u.w[bIGENDIAN]; \
1267 \
1268 /* take care of Inf and NaN */ \
1269 if((ix0&0x7ff00000)==0x7ff00000) { \
1270 return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf \
1271 sqrt(-inf)=sNaN */ \
1272 } \
1273 /* take care of zero */ \
1274 if(ix0<=0) { \
1275 if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ \
1276 else if(ix0<0) \
1277 return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ \
1278 } \
1279 /* normalize x */ \
1280 m = (ix0>>20); \
1281 if(m==0) { /* subnormal x */ \
1282 while(ix0==0) { \
1283 m -= 21; \
1284 ix0 |= (ix1>>11); ix1 <<= 21; \
1285 } \
1286 for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; \
1287 m -= i-1; \
1288 ix0 |= (ix1>>(32-i)); \
1289 ix1 <<= i; \
1290 } \
1291 m -= 1023; /* unbias exponent */ \
1292 ix0 = (ix0&0x000fffff)|0x00100000; \
1293 if(m&1){ /* odd m, double x to make it even */ \
1294 ix0 += ix0 + ((ix1&sign)>>31); \
1295 ix1 += ix1; \
1296 } \
1297 m >>= 1; /* m = [m/2] */ \
1298 /* generate sqrt(x) bit by bit */ \
1299 ix0 += ix0 + ((ix1&sign)>>31); \
1300 ix1 += ix1; \
1301 q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ \
1302 r = 0x00200000; /* r = moving bit from right to left */ \
1303 while(r!=0) { \
1304 t = s0+r; \
1305 if(t<=ix0) { \
1306 s0 = t+r; \
1307 ix0 -= t; \
1308 q += r; \
1309 } \
1310 ix0 += ix0 + ((ix1&sign)>>31); \
1311 ix1 += ix1; \
1312 r>>=1; \
1313 } \
1314 r = sign; \
1315 while(r!=0) { \
1316 t1 = s1+r; \
1317 t = s0; \
1318 if((t<ix0)||((t==ix0)&&(t1<=ix1))) { \
1319 s1 = t1+r; \
1320 if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; \
1321 ix0 -= t; \
1322 if (ix1 < t1) ix0 -= 1; \
1323 ix1 -= t1; \
1324 q1 += r; \
1325 } \
1326 ix0 += ix0 + ((ix1&sign)>>31); \
1327 ix1 += ix1; \
1328 r>>=1; \
1329 } \
1330 /* use floating add to find out rounding direction */ \
1331 if((ix0|ix1)!=0) { \
1332 z = one-tiny; /* trigger inexact flag */ \
1333 if (z>=one) { \
1334 z = one+tiny; \
1335 if (q1==(UInt)0xffffffff) { q1=0; q += 1;} \
1336 else if (z>one) { \
1337 if (q1==(UInt)0xfffffffe) q+=1; \
1338 q1+=2; \
1339 } else \
1340 q1 += (q1&1); \
1341 } \
1342 } \
1343 ix0 = (q>>1)+0x3fe00000; \
1344 ix1 = q1>>1; \
1345 if ((q&1)==1) ix1 |= sign; \
1346 ix0 += (m <<20); \
1347 ix0 = u.w[1-bIGENDIAN] = ix0; \
1348 ix1 = u.w[bIGENDIAN] = ix1; \
1349 z = u.d; \
1350 return z; \
1351 }
1352
1353#if 0
1354SQRT_FAST(NONE, sqrt) /* xlC generates these */
1355SQRT_FAST(NONE, _sqrt) /* xlf generates these */
1356#else
1357SQRT_EXACT(NONE, sqrt) /* xlC generates these */
1358SQRT_EXACT(NONE, _sqrt) /* xlf generates these */
1359#endif
1360
1361#endif /* defined(VGP_ppc32_aix5) */
1362
njn3e884182003-04-15 13:03:23 +00001363/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001364/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001365/*--------------------------------------------------------------------*/