blob: e7cae0494e2f36ec960337371f378fa86a09a1c7 [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
sewardj31b9ce12006-10-17 01:27:13 +0000870/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +0000871/*--- Improve definedness checking of process environment ---*/
872/*------------------------------------------------------------*/
873
sewardjddc00dd2007-11-27 11:42:47 +0000874#if defined(VGO_linux)
875
dirk09beb9e2007-04-19 09:47:32 +0000876/* putenv */
njne6154662009-02-10 04:23:41 +0000877int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
878int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +0000879{
880 OrigFn fn;
881 Word result;
882 const char* p = string;
883 VALGRIND_GET_ORIG_FN(fn);
884 /* Now by walking over the string we magically produce
885 traces when hitting undefined memory. */
886 if (p)
887 while (*p++)
888 ;
889 CALL_FN_W_W(result, fn, string);
890 return result;
891}
892
893/* unsetenv */
njne6154662009-02-10 04:23:41 +0000894int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
895int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +0000896{
897 OrigFn fn;
898 Word result;
899 const char* p = name;
900 VALGRIND_GET_ORIG_FN(fn);
901 /* Now by walking over the string we magically produce
902 traces when hitting undefined memory. */
903 if (p)
904 while (*p++)
905 ;
906 CALL_FN_W_W(result, fn, name);
907 return result;
908}
909
910/* setenv */
njne6154662009-02-10 04:23:41 +0000911int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +0000912 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +0000913int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +0000914 (const char* name, const char* value, int overwrite)
915{
916 OrigFn fn;
917 Word result;
918 const char* p;
919 VALGRIND_GET_ORIG_FN(fn);
920 /* Now by walking over the string we magically produce
921 traces when hitting undefined memory. */
922 if (name)
923 for (p = name; *p; p++)
924 ;
925 if (value)
926 for (p = value; *p; p++)
927 ;
928 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
929 CALL_FN_W_WWW(result, fn, name, value, overwrite);
930 return result;
931}
932
sewardjddc00dd2007-11-27 11:42:47 +0000933#endif /* defined(VGO_linux) */
934
935
dirk09beb9e2007-04-19 09:47:32 +0000936/*------------------------------------------------------------*/
sewardj31b9ce12006-10-17 01:27:13 +0000937/*--- AIX stuff only after this point ---*/
938/*------------------------------------------------------------*/
939
sewardjddc00dd2007-11-27 11:42:47 +0000940/* Generate replacements for strcat, strncat, strcpy, strncpy, strcmp
sewardj31b9ce12006-10-17 01:27:13 +0000941 in the given soname. */
sewardjddc00dd2007-11-27 11:42:47 +0000942#define Str5FNs(_soname) \
sewardj31b9ce12006-10-17 01:27:13 +0000943 STRCAT(_soname, strcat) \
944 STRNCAT(_soname, strncat) \
945 STRCPY(_soname, strcpy) \
sewardjddc00dd2007-11-27 11:42:47 +0000946 STRNCPY(_soname, strncpy) \
947 STRCMP(_soname, strcmp)
sewardj31b9ce12006-10-17 01:27:13 +0000948
949#if defined(VGP_ppc32_aix5)
sewardjddc00dd2007-11-27 11:42:47 +0000950Str5FNs(NONE) /* in main exe */
951Str5FNs(libCZdaZLshrcoreZdoZR) /* libC.a(shrcore.o) */
952Str5FNs(libX11ZdaZLshr4ZdoZR) /* libX11.a(shr4.o) */
953Str5FNs(libXmZdaZLshrZaZdoZR) /* libXm.a(shr*.o) */
954Str5FNs(libXtZdaZLshr4ZdoZR) /* libXt.a(shr4.o) */
955Str5FNs(libppeZurZdaZLdynamicZdoZR) /* libppe_r.a(dynamic.o) */
956Str5FNs(libodmZdaZLshrZdoZR) /* libodm.a(shr.o) */
957Str5FNs(libmpiZurZdaZLmpicoreZurZdoZR) /* libmpi_r.a(mpicore_r.o) */
958Str5FNs(libmpiZurZdaZLmpipoeZurZdoZR) /* libmpi_r.a(mpipoe_r.o) */
959Str5FNs(libmpiZurZdaZLmpciZurZdoZR) /* libmpi_r.a(mpci_r.o) */
960Str5FNs(libslurmZdso) /* libslurm.so */
961Str5FNs(libglibZdso) /* libglib.so */
962Str5FNs(libIMZdaZLshrZdoZR) /* libIM.a(shr.o) */
963Str5FNs(libiconvZdaZLshr4ZdoZR) /* libiconv.a(shr4.o) */
964Str5FNs(libGLZdaZLshrZdoZR) /* libGL.a(shr.o) */
965Str5FNs(libgdkZdso) /* libgdk.so */
966Str5FNs(libcursesZdaZLshr42ZdoZR) /* libcurses.a(shr42.o) */
967Str5FNs(libqtZda) /* libqt.a */
sewardjfd4b6f42007-11-29 03:08:32 +0000968Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
969Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
970Str5FNs(libQtZaa) /* libQt*.a */
sewardj31b9ce12006-10-17 01:27:13 +0000971#endif
972#if defined(VGP_ppc64_aix5)
sewardjddc00dd2007-11-27 11:42:47 +0000973Str5FNs(NONE) /* in main exe */
974Str5FNs(libX11ZdaZLshrZu64ZdoZR) /* libX11.a(shr_64.o) */
975Str5FNs(libiconvZdaZLshr4Zu64ZdoZR) /* libiconv.a(shr4_64.o) */
976Str5FNs(libGLZdaZLshrZu64ZdoZR) /* libGL.a(shr_64.o) */
977Str5FNs(libppeZurZdaZLdynamic64ZdoZR) /* libppe_r.a(dynamic64.o) */
978Str5FNs(libodmZdaZLshrZu64ZdoZR) /* libodm.a(shr_64.o) */
979Str5FNs(libmpiZurZdaZLmpicore64ZurZdoZR) /* libmpi_r.a(mpicore64_r.o) */
980Str5FNs(libmpiZurZdaZLmpipoe64ZurZdoZR) /* libmpi_r.a(mpipoe64_r.o) */
981Str5FNs(libCZdaZLshrcoreZu64ZdoZR) /* libC.a(shrcore_64.o) */
982Str5FNs(libmpiZurZdaZLmpci64ZurZdoZR) /* libmpi_r.a(mpci64_r.o) */
983Str5FNs(libqtZda) /* libqt.a */
sewardjfd4b6f42007-11-29 03:08:32 +0000984Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
985Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
986Str5FNs(libQtZaa) /* libQt*.a */
sewardj31b9ce12006-10-17 01:27:13 +0000987#endif
988
989
990/* AIX's libm contains a sqrt implementation which does a nasty thing:
991 it loads the initial estimate of the root into a FP register, but
992 only the upper half of the number is initialised data. Hence the
993 least significant 32 mantissa bits are undefined, and it then uses
994 Newton-Raphson iteration to compute the final, defined result.
995 This fools memcheck completely; the only solution I can think of is
996 provide our own substitute. The _FAST variant is almost right
997 except the result is not correctly rounded. The _EXACT variant,
998 which is selected by default, is always right; but it's also pretty
999 darn slow. */
1000
1001#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
1002#define SQRT_FAST(soname, fnname) \
1003 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1004 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1005 { \
1006 static UInt T1[32] = \
1007 { 0, 1024, 3062, 5746, 9193, 13348, \
1008 18162, 23592, 29598, 36145, 43202, 50740, \
1009 58733, 67158, 75992, 85215, 83599, 71378, \
1010 60428, 50647, 41945, 34246, 27478, 21581, \
1011 16499, 12183, 8588, 5674, 3403, 1742, \
1012 661, 130 }; \
1013 UInt x0, x1, sign, expo, mant0, bIGENDIAN = 1; \
1014 union { UInt w[2]; double d; } u; \
1015 u.d = x; \
1016 x0 = u.w[1 - bIGENDIAN]; /* high half */ \
1017 x1 = u.w[bIGENDIAN]; /* low half */ \
1018 sign = x0 >> 31; \
1019 expo = (x0 >> 20) & 0x7FF; \
1020 mant0 = x0 & 0xFFFFF; \
1021 if ( (sign == 0 && expo >= 1 && expo <= 0x7FE) /* +normal */ \
1022 || (sign == 0 && expo == 0 \
1023 && (mant0 | x1) > 0) /* +denorm */) { \
1024 /* common case; do Newton-Raphson */ \
1025 /* technically k should be signed int32, but since we're \
1026 always entering here with x > 0, doesn't matter that it's \
1027 unsigned. */ \
1028 double y; \
1029 UInt k = (x0>>1) + 0x1ff80000; \
1030 u.w[1 - bIGENDIAN] = k - T1[31&(k>>15)]; \
1031 u.w[bIGENDIAN] = 0; \
1032 y = u.d; \
1033 y = (y+x/y)/2.0 ; \
1034 y = (y+x/y)/2.0 ; \
1035 y = y-(y-x/y)/2.0 ; \
1036 return y; \
1037 } \
1038 if ( (sign == 1 && expo >= 1 && expo <= 0x7FE) /* -normal */ \
1039 || (sign == 1 && expo == 0 \
1040 && (mant0 | x1) > 0) /* -denorm */) { \
1041 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1042 u.w[bIGENDIAN] = 0x1; \
1043 return u.d; /* -Inf -> NaN */ \
1044 } \
1045 if ((expo | mant0 | x1) == 0) \
1046 return x; /* +/-zero -> self */ \
1047 if (expo == 0x7FF && (mant0 | x1) == 0) { \
1048 if (sign == 0) \
1049 return x; /* +Inf -> self */ \
1050 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1051 u.w[bIGENDIAN] = 0x1; \
1052 return u.d; /* -Inf -> NaN */ \
1053 } \
1054 /* must be +/- NaN */ \
1055 return x; /* +/-NaN -> self */ \
1056 }
1057
1058#define SQRT_EXACT(soname, fnname) \
1059 /* \
1060 * ==================================================== \
1061 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. \
1062 * \
1063 * Developed at SunPro, a Sun Microsystems, Inc. business. \
1064 * Permission to use, copy, modify, and distribute this \
1065 * software is freely granted, provided that this notice \
1066 * is preserved. \
1067 * ==================================================== \
1068 */ \
1069 /* \
1070 * Return correctly rounded sqrt. \
1071 * ------------------------------------------ \
1072 * | Use the hardware sqrt if you have one | \
1073 * ------------------------------------------ \
1074 * Method: \
1075 * Bit by bit method using integer arithmetic. (Slow, but portable) \
1076 * 1. Normalization \
1077 * Scale x to y in [1,4) with even powers of 2: \
1078 * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then \
1079 * sqrt(x) = 2^k * sqrt(y) \
1080 * 2. Bit by bit computation \
1081 * Let q = sqrt(y) truncated to i bit after binary point (q = 1), \
1082 * i 0 \
1083 * i+1 2 \
1084 * s = 2*q , and y = 2 * ( y - q ). (1) \
1085 * i i i i \
1086 * \
1087 * To compute q from q , one checks whether \
1088 * i+1 i \
1089 * \
1090 * -(i+1) 2 \
1091 * (q + 2 ) <= y. (2) \
1092 * i \
1093 * -(i+1) \
1094 * If (2) is false, then q = q ; otherwise q = q + 2 . \
1095 * i+1 i i+1 i \
1096 * \
1097 * With some algebric manipulation, it is not difficult to see \
1098 * that (2) is equivalent to \
1099 * -(i+1) \
1100 * s + 2 <= y (3) \
1101 * i i \
1102 * \
1103 * The advantage of (3) is that s and y can be computed by \
1104 * i i \
1105 * the following recurrence formula: \
1106 * if (3) is false \
1107 * \
1108 * s = s , y = y ; (4) \
1109 * i+1 i i+1 i \
1110 * \
1111 * otherwise, \
1112 * -i -(i+1) \
1113 * s = s + 2 , y = y - s - 2 (5) \
1114 * i+1 i i+1 i i \
1115 * \
1116 * \
1117 * One may easily use induction to prove (4) and (5). \
1118 * Note. Since the left hand side of (3) contain only i+2 bits, \
1119 * it does not necessary to do a full (53-bit) comparison \
1120 * in (3). \
1121 * 3. Final rounding \
1122 * After generating the 53 bits result, we compute one more bit. \
1123 * Together with the remainder, we can decide whether the \
1124 * result is exact, bigger than 1/2ulp, or less than 1/2ulp \
1125 * (it will never equal to 1/2ulp). \
1126 * The rounding mode can be detected by checking whether \
1127 * huge + tiny is equal to huge, and whether huge - tiny is \
1128 * equal to huge for some floating point number "huge" and "tiny". \
1129 * \
1130 * Special cases: \
1131 * sqrt(+-0) = +-0 ... exact \
1132 * sqrt(inf) = inf \
1133 * sqrt(-ve) = NaN ... with invalid signal \
1134 * sqrt(NaN) = NaN ... with invalid signal for signaling NaN \
1135 * \
1136 */ \
1137 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1138 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1139 { \
1140 const Int bIGENDIAN = 1; \
1141 const double one = 1.0, tiny=1.0e-300; \
1142 double z; \
1143 Int sign = (Int)0x80000000; \
1144 Int ix0,s0,q,m,t,i; \
1145 UInt r,t1,s1,ix1,q1; \
1146 union { UInt w[2]; double d; } u; \
1147 u.d = x; \
1148 ix0 = u.w[1-bIGENDIAN]; \
1149 ix1 = u.w[bIGENDIAN]; \
1150 \
1151 /* take care of Inf and NaN */ \
1152 if((ix0&0x7ff00000)==0x7ff00000) { \
1153 return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf \
1154 sqrt(-inf)=sNaN */ \
1155 } \
1156 /* take care of zero */ \
1157 if(ix0<=0) { \
1158 if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ \
1159 else if(ix0<0) \
1160 return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ \
1161 } \
1162 /* normalize x */ \
1163 m = (ix0>>20); \
1164 if(m==0) { /* subnormal x */ \
1165 while(ix0==0) { \
1166 m -= 21; \
1167 ix0 |= (ix1>>11); ix1 <<= 21; \
1168 } \
1169 for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; \
1170 m -= i-1; \
1171 ix0 |= (ix1>>(32-i)); \
1172 ix1 <<= i; \
1173 } \
1174 m -= 1023; /* unbias exponent */ \
1175 ix0 = (ix0&0x000fffff)|0x00100000; \
1176 if(m&1){ /* odd m, double x to make it even */ \
1177 ix0 += ix0 + ((ix1&sign)>>31); \
1178 ix1 += ix1; \
1179 } \
1180 m >>= 1; /* m = [m/2] */ \
1181 /* generate sqrt(x) bit by bit */ \
1182 ix0 += ix0 + ((ix1&sign)>>31); \
1183 ix1 += ix1; \
1184 q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ \
1185 r = 0x00200000; /* r = moving bit from right to left */ \
1186 while(r!=0) { \
1187 t = s0+r; \
1188 if(t<=ix0) { \
1189 s0 = t+r; \
1190 ix0 -= t; \
1191 q += r; \
1192 } \
1193 ix0 += ix0 + ((ix1&sign)>>31); \
1194 ix1 += ix1; \
1195 r>>=1; \
1196 } \
1197 r = sign; \
1198 while(r!=0) { \
1199 t1 = s1+r; \
1200 t = s0; \
1201 if((t<ix0)||((t==ix0)&&(t1<=ix1))) { \
1202 s1 = t1+r; \
1203 if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; \
1204 ix0 -= t; \
1205 if (ix1 < t1) ix0 -= 1; \
1206 ix1 -= t1; \
1207 q1 += r; \
1208 } \
1209 ix0 += ix0 + ((ix1&sign)>>31); \
1210 ix1 += ix1; \
1211 r>>=1; \
1212 } \
1213 /* use floating add to find out rounding direction */ \
1214 if((ix0|ix1)!=0) { \
1215 z = one-tiny; /* trigger inexact flag */ \
1216 if (z>=one) { \
1217 z = one+tiny; \
1218 if (q1==(UInt)0xffffffff) { q1=0; q += 1;} \
1219 else if (z>one) { \
1220 if (q1==(UInt)0xfffffffe) q+=1; \
1221 q1+=2; \
1222 } else \
1223 q1 += (q1&1); \
1224 } \
1225 } \
1226 ix0 = (q>>1)+0x3fe00000; \
1227 ix1 = q1>>1; \
1228 if ((q&1)==1) ix1 |= sign; \
1229 ix0 += (m <<20); \
1230 ix0 = u.w[1-bIGENDIAN] = ix0; \
1231 ix1 = u.w[bIGENDIAN] = ix1; \
1232 z = u.d; \
1233 return z; \
1234 }
1235
1236#if 0
1237SQRT_FAST(NONE, sqrt) /* xlC generates these */
1238SQRT_FAST(NONE, _sqrt) /* xlf generates these */
1239#else
1240SQRT_EXACT(NONE, sqrt) /* xlC generates these */
1241SQRT_EXACT(NONE, _sqrt) /* xlf generates these */
1242#endif
1243
1244#endif /* defined(VGP_ppc32_aix5) */
1245
njn3e884182003-04-15 13:03:23 +00001246/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001247/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001248/*--------------------------------------------------------------------*/