blob: d500367f38aa4365f19ab326de76b7bcfb1606a1 [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 { \
njn16eeb4e2005-06-16 03:56:58 +0000458 if (is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000459 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000460 \
sewardj7b4e00b2010-08-24 09:05:52 +0000461 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
462 const Addr WM = WS - 1; /* 7 or 3 */ \
463 \
464 if (dst < src) { \
465 \
466 /* Copying backwards. */ \
467 SizeT n = len; \
468 Addr d = (Addr)dst; \
469 Addr s = (Addr)src; \
470 \
471 if (((s^d) & WM) == 0) { \
472 /* s and d have same UWord alignment. */ \
473 /* Pull up to a UWord boundary. */ \
474 while ((s & WM) != 0 && n >= 1) \
475 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
476 /* Copy UWords. */ \
477 while (n >= WS) \
478 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
479 if (n == 0) \
480 return dst; \
njn16eeb4e2005-06-16 03:56:58 +0000481 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000482 if (((s|d) & 1) == 0) { \
483 /* Both are 16-aligned; copy what we can thusly. */ \
484 while (n >= 2) \
485 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
njn16eeb4e2005-06-16 03:56:58 +0000486 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000487 /* Copy leftovers, or everything if misaligned. */ \
488 while (n >= 1) \
489 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
490 \
491 } else if (dst > src) { \
492 \
493 SizeT n = len; \
494 Addr d = ((Addr)dst) + n; \
495 Addr s = ((Addr)src) + n; \
496 \
497 /* Copying forwards. */ \
498 if (((s^d) & WM) == 0) { \
499 /* s and d have same UWord alignment. */ \
500 /* Back down to a UWord boundary. */ \
501 while ((s & WM) != 0 && n >= 1) \
502 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
503 /* Copy UWords. */ \
504 while (n >= WS) \
505 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
506 if (n == 0) \
507 return dst; \
njn16eeb4e2005-06-16 03:56:58 +0000508 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000509 if (((s|d) & 1) == 0) { \
510 /* Both are 16-aligned; copy what we can thusly. */ \
511 while (n >= 2) \
512 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
njn16eeb4e2005-06-16 03:56:58 +0000513 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000514 /* Copy leftovers, or everything if misaligned. */ \
515 while (n >= 1) \
516 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
517 \
njn16eeb4e2005-06-16 03:56:58 +0000518 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000519 \
njn16eeb4e2005-06-16 03:56:58 +0000520 return dst; \
521 }
522
njne6154662009-02-10 04:23:41 +0000523MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000524#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000525MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
526MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnf76d27a2009-05-28 01:53:07 +0000527#elif defined(VGO_darwin)
528MEMCPY(VG_Z_DYLD, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000529#endif
sewardjf0b34322007-01-16 21:42:28 +0000530/* icc9 blats these around all over the place. Not only in the main
531 executable but various .so's. They are highly tuned and read
532 memory beyond the source boundary (although work correctly and
533 never go across page boundaries), so give errors when run natively,
534 at least for misaligned source arg. Just intercepting in the exe
535 only until we understand more about the problem. See
536 http://bugs.kde.org/show_bug.cgi?id=139776
537 */
538MEMCPY(NONE, _intel_fast_memcpy)
sewardj31b9ce12006-10-17 01:27:13 +0000539
njn16eeb4e2005-06-16 03:56:58 +0000540
541#define MEMCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000542 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
543 ( const void *s1V, const void *s2V, SizeT n ); \
544 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
545 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000546 { \
547 int res; \
548 unsigned char a0; \
549 unsigned char b0; \
550 unsigned char* s1 = (unsigned char*)s1V; \
551 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000552 \
njn16eeb4e2005-06-16 03:56:58 +0000553 while (n != 0) { \
554 a0 = s1[0]; \
555 b0 = s2[0]; \
556 s1 += 1; \
557 s2 += 1; \
558 res = ((int)a0) - ((int)b0); \
559 if (res != 0) \
560 return res; \
561 n -= 1; \
562 } \
563 return 0; \
564 }
565
njne6154662009-02-10 04:23:41 +0000566MEMCMP(VG_Z_LIBC_SONAME, memcmp)
567MEMCMP(VG_Z_LIBC_SONAME, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000568#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000569MEMCMP(VG_Z_LD_SO_1, bcmp)
njnf76d27a2009-05-28 01:53:07 +0000570#elif defined(VGO_darwin)
571MEMCMP(VG_Z_DYLD, memcmp)
572MEMCMP(VG_Z_DYLD, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000573#endif
njn3e884182003-04-15 13:03:23 +0000574
jseward0845ef82003-12-22 22:31:27 +0000575
576/* Copy SRC to DEST, returning the address of the terminating '\0' in
577 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000578#define STPCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000579 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
580 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000581 { \
582 const Char* src_orig = src; \
583 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000584 \
njn16eeb4e2005-06-16 03:56:58 +0000585 while (*src) *dst++ = *src++; \
586 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000587 \
njn16eeb4e2005-06-16 03:56:58 +0000588 /* This checks for overlap after copying, unavoidable without */ \
589 /* pre-counting length... should be ok */ \
590 if (is_overlap(dst_orig, \
591 src_orig, \
592 (Addr)dst-(Addr)dst_orig+1, \
593 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000594 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000595 \
njn16eeb4e2005-06-16 03:56:58 +0000596 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000597 }
njn16eeb4e2005-06-16 03:56:58 +0000598
njne6154662009-02-10 04:23:41 +0000599STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000600#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000601STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
njne6154662009-02-10 04:23:41 +0000602STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
603STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnf76d27a2009-05-28 01:53:07 +0000604#elif defined(VGO_darwin)
605STPCPY(VG_Z_DYLD, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000606#endif
607
njn16eeb4e2005-06-16 03:56:58 +0000608
609#define MEMSET(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000610 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \
611 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000612 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000613 Addr a = (Addr)s; \
614 UInt c4 = (c & 0xFF); \
615 c4 = (c4 << 8) | c4; \
616 c4 = (c4 << 16) | c4; \
617 while ((a & 3) != 0 && n >= 1) \
618 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
619 while (n >= 4) \
620 { *(UInt*)a = c4; a += 4; n -= 4; } \
621 while (n >= 1) \
622 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000623 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000624 }
njn16eeb4e2005-06-16 03:56:58 +0000625
njne6154662009-02-10 04:23:41 +0000626MEMSET(VG_Z_LIBC_SONAME, memset)
njnf76d27a2009-05-28 01:53:07 +0000627#if defined(VGO_darwin)
628MEMSET(VG_Z_DYLD, memset)
629#endif
njn16eeb4e2005-06-16 03:56:58 +0000630
631
632#define MEMMOVE(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000633 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
634 (void *dstV, const void *srcV, SizeT n); \
635 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
636 (void *dstV, const void *srcV, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000637 { \
638 SizeT i; \
639 Char* dst = (Char*)dstV; \
640 Char* src = (Char*)srcV; \
641 if (dst < src) { \
642 for (i = 0; i < n; i++) \
643 dst[i] = src[i]; \
644 } \
645 else \
646 if (dst > src) { \
647 for (i = 0; i < n; i++) \
648 dst[n-i-1] = src[n-i-1]; \
649 } \
650 return dst; \
651 }
652
njne6154662009-02-10 04:23:41 +0000653MEMMOVE(VG_Z_LIBC_SONAME, memmove)
njnf76d27a2009-05-28 01:53:07 +0000654#if defined(VGO_darwin)
655MEMMOVE(VG_Z_DYLD, memmove)
656#endif
657
658
659#define BCOPY(soname, fnname) \
660 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
661 (const void *srcV, void *dstV, SizeT n); \
662 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
663 (const void *srcV, void *dstV, SizeT n) \
664 { \
665 SizeT i; \
666 Char* dst = (Char*)dstV; \
667 Char* src = (Char*)srcV; \
668 if (dst < src) { \
669 for (i = 0; i < n; i++) \
670 dst[i] = src[i]; \
671 } \
672 else \
673 if (dst > src) { \
674 for (i = 0; i < n; i++) \
675 dst[n-i-1] = src[n-i-1]; \
676 } \
677 }
678
679#if defined(VGO_darwin)
680BCOPY(VG_Z_LIBC_SONAME, bcopy)
681BCOPY(VG_Z_DYLD, bcopy)
682#endif
sewardj44e495f2005-05-12 17:58:28 +0000683
jseward0845ef82003-12-22 22:31:27 +0000684
sewardj24cb2172007-02-23 09:03:26 +0000685/* glibc 2.5 variant of memmove which checks the dest is big enough.
686 There is no specific part of glibc that this is copied from. */
687#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
688 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
689 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
690 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
691 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
692 { \
693 extern void _exit(int status); \
694 SizeT i; \
695 Char* dst = (Char*)dstV; \
696 Char* src = (Char*)srcV; \
697 if (destlen < n) \
698 goto badness; \
699 if (dst < src) { \
700 for (i = 0; i < n; i++) \
701 dst[i] = src[i]; \
702 } \
703 else \
704 if (dst > src) { \
705 for (i = 0; i < n; i++) \
706 dst[n-i-1] = src[n-i-1]; \
707 } \
708 return dst; \
709 badness: \
710 VALGRIND_PRINTF_BACKTRACE( \
711 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000712 "program terminated\n"); \
sewardj24cb2172007-02-23 09:03:26 +0000713 _exit(127); \
sewardjc271ec82007-02-27 22:36:14 +0000714 /*NOTREACHED*/ \
715 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +0000716 }
717
njne6154662009-02-10 04:23:41 +0000718GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj24cb2172007-02-23 09:03:26 +0000719
720
sewardj4e9a4b62004-11-23 00:20:17 +0000721/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000722#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000723 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
724 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000725 { \
726 unsigned char c = (unsigned char) c_in; \
727 unsigned char* char_ptr = (unsigned char *)s; \
728 while (1) { \
729 if (*char_ptr == 0) return char_ptr; \
730 if (*char_ptr == c) return char_ptr; \
731 char_ptr++; \
732 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000733 }
njn16eeb4e2005-06-16 03:56:58 +0000734
njne6154662009-02-10 04:23:41 +0000735GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000736
737
738/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000739#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000740 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
741 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000742 { \
743 unsigned char c = (unsigned char) c_in; \
744 unsigned char* char_ptr = (unsigned char *)s; \
745 while (1) { \
746 if (*char_ptr == c) return char_ptr; \
747 char_ptr++; \
748 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000749 }
njn16eeb4e2005-06-16 03:56:58 +0000750
njne6154662009-02-10 04:23:41 +0000751GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
tomd2645142009-10-29 09:27:11 +0000752#if defined (VGO_linux)
753GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
754#endif
sewardj4e9a4b62004-11-23 00:20:17 +0000755
sewardjdc5d8322007-01-28 06:32:01 +0000756/* glibc variant of strcpy that checks the dest is big enough.
757 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +0000758#define GLIBC25___STRCPY_CHK(soname,fnname) \
759 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
760 (char* dst, const char* src, SizeT len); \
761 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
762 (char* dst, const char* src, SizeT len) \
763 { \
764 extern void _exit(int status); \
765 char* ret = dst; \
766 if (! len) \
767 goto badness; \
768 while ((*dst++ = *src++) != '\0') \
769 if (--len == 0) \
770 goto badness; \
771 return ret; \
772 badness: \
773 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000774 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000775 "program terminated\n"); \
sewardj620e5262006-12-31 00:22:30 +0000776 _exit(127); \
777 /*NOTREACHED*/ \
778 return NULL; \
779 }
780
njne6154662009-02-10 04:23:41 +0000781GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj620e5262006-12-31 00:22:30 +0000782
783
sewardjdc5d8322007-01-28 06:32:01 +0000784/* glibc variant of stpcpy that checks the dest is big enough.
785 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +0000786#define GLIBC25___STPCPY_CHK(soname,fnname) \
787 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
788 (char* dst, const char* src, SizeT len); \
789 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
790 (char* dst, const char* src, SizeT len) \
791 { \
792 extern void _exit(int status); \
sewardjdc5d8322007-01-28 06:32:01 +0000793 if (! len) \
794 goto badness; \
795 while ((*dst++ = *src++) != '\0') \
796 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +0000797 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +0000798 return dst - 1; \
799 badness: \
800 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000801 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000802 "program terminated\n"); \
sewardjb8d03852007-01-27 00:49:44 +0000803 _exit(127); \
804 /*NOTREACHED*/ \
805 return NULL; \
806 }
807
njne6154662009-02-10 04:23:41 +0000808GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardjb8d03852007-01-27 00:49:44 +0000809
810
sewardj841b72d2006-12-31 18:55:56 +0000811/* mempcpy */
812#define GLIBC25_MEMPCPY(soname, fnname) \
813 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
814 ( void *dst, const void *src, SizeT len ); \
815 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
816 ( void *dst, const void *src, SizeT len ) \
817 { \
818 register char *d; \
819 register char *s; \
820 SizeT len_saved = len; \
821 \
822 if (len == 0) \
823 return dst; \
824 \
825 if (is_overlap(dst, src, len, len)) \
826 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
827 \
828 if ( dst > src ) { \
829 d = (char *)dst + len - 1; \
830 s = (char *)src + len - 1; \
831 while ( len-- ) { \
832 *d-- = *s--; \
833 } \
834 } else if ( dst < src ) { \
835 d = (char *)dst; \
836 s = (char *)src; \
837 while ( len-- ) { \
838 *d++ = *s++; \
839 } \
840 } \
841 return (void*)( ((char*)dst) + len_saved ); \
842 }
843
njne6154662009-02-10 04:23:41 +0000844GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
njnb4cfbc42009-05-04 04:20:02 +0000845#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000846GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
njnb4cfbc42009-05-04 04:20:02 +0000847#endif
sewardj841b72d2006-12-31 18:55:56 +0000848
849
sewardjb6c04032007-11-13 20:52:29 +0000850#define GLIBC26___MEMCPY_CHK(soname, fnname) \
851 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
852 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
853 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
854 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
855 { \
856 extern void _exit(int status); \
857 register char *d; \
858 register char *s; \
859 \
860 if (dstlen < len) goto badness; \
861 \
862 if (len == 0) \
863 return dst; \
864 \
865 if (is_overlap(dst, src, len, len)) \
866 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
867 \
868 if ( dst > src ) { \
869 d = (char *)dst + len - 1; \
870 s = (char *)src + len - 1; \
871 while ( len-- ) { \
872 *d-- = *s--; \
873 } \
874 } else if ( dst < src ) { \
875 d = (char *)dst; \
876 s = (char *)src; \
877 while ( len-- ) { \
878 *d++ = *s++; \
879 } \
880 } \
881 return dst; \
882 badness: \
883 VALGRIND_PRINTF_BACKTRACE( \
884 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000885 "program terminated\n"); \
sewardjb6c04032007-11-13 20:52:29 +0000886 _exit(127); \
887 /*NOTREACHED*/ \
888 return NULL; \
889 }
890
njne6154662009-02-10 04:23:41 +0000891GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardjb6c04032007-11-13 20:52:29 +0000892
893
sewardja77687c2010-08-19 13:22:34 +0000894#define STRSTR(soname, fnname) \
895 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
896 (void* haystack, void* needle); \
897 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
898 (void* haystack, void* needle) \
899 { \
900 UChar* h = (UChar*)haystack; \
901 UChar* n = (UChar*)needle; \
902 \
903 /* find the length of n, not including terminating zero */ \
904 UWord nlen = 0; \
905 while (n[nlen]) nlen++; \
906 \
907 /* if n is the empty string, match immediately. */ \
908 if (nlen == 0) return h; \
909 \
910 /* assert(nlen >= 1); */ \
911 UChar n0 = n[0]; \
912 \
913 while (1) { \
914 UChar hh = *h; \
915 if (hh == 0) return NULL; \
916 if (hh != n0) { h++; continue; } \
917 \
918 UWord i; \
919 for (i = 0; i < nlen; i++) { \
920 if (n[i] != h[i]) \
921 break; \
922 } \
923 /* assert(i >= 0 && i <= nlen); */ \
924 if (i == nlen) \
925 return h; \
926 \
927 h++; \
928 } \
929 }
930
931#if defined(VGO_linux)
932STRSTR(VG_Z_LIBC_SONAME, strstr)
933#endif
934
935
936#define STRPBRK(soname, fnname) \
937 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
938 (void* sV, void* acceptV); \
939 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
940 (void* sV, void* acceptV) \
941 { \
942 UChar* s = (UChar*)sV; \
943 UChar* accept = (UChar*)acceptV; \
944 \
945 /* find the length of 'accept', not including terminating zero */ \
946 UWord nacc = 0; \
947 while (accept[nacc]) nacc++; \
948 \
949 /* if n is the empty string, fail immediately. */ \
950 if (nacc == 0) return NULL; \
951 \
952 /* assert(nacc >= 1); */ \
953 while (1) { \
954 UWord i; \
955 UChar sc = *s; \
956 if (sc == 0) \
957 break; \
958 for (i = 0; i < nacc; i++) { \
959 if (sc == accept[i]) \
960 return s; \
961 } \
962 s++; \
963 } \
964 \
965 return NULL; \
966 }
967
968#if defined(VGO_linux)
969STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
970#endif
971
972
973#define STRCSPN(soname, fnname) \
974 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
975 (void* sV, void* rejectV); \
976 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
977 (void* sV, void* rejectV) \
978 { \
979 UChar* s = (UChar*)sV; \
980 UChar* reject = (UChar*)rejectV; \
981 \
982 /* find the length of 'reject', not including terminating zero */ \
983 UWord nrej = 0; \
984 while (reject[nrej]) nrej++; \
985 \
986 UWord len = 0; \
987 while (1) { \
988 UWord i; \
989 UChar sc = *s; \
990 if (sc == 0) \
991 break; \
992 for (i = 0; i < nrej; i++) { \
993 if (sc == reject[i]) \
994 break; \
995 } \
996 /* assert(i >= 0 && i <= nrej); */ \
997 if (i < nrej) \
998 break; \
999 s++; \
1000 len++; \
1001 } \
1002 \
1003 return len; \
1004 }
1005
1006#if defined(VGO_linux)
1007STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1008#endif
1009
1010
sewardjba189352010-08-20 18:24:16 +00001011// And here's a validated strspn replacement, should it
1012// become necessary.
1013//UWord mystrspn( UChar* s, UChar* accept )
1014//{
1015// /* find the length of 'accept', not including terminating zero */
1016// UWord nacc = 0;
1017// while (accept[nacc]) nacc++;
1018// if (nacc == 0) return 0;
1019//
1020// UWord len = 0;
1021// while (1) {
1022// UWord i;
1023// UChar sc = *s;
1024// if (sc == 0)
1025// break;
1026// for (i = 0; i < nacc; i++) {
1027// if (sc == accept[i])
1028// break;
1029// }
1030// assert(i >= 0 && i <= nacc);
1031// if (i == nacc)
1032// break;
1033// s++;
1034// len++;
1035// }
1036//
1037// return len;
1038//}
1039
1040
sewardj31b9ce12006-10-17 01:27:13 +00001041/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001042/*--- Improve definedness checking of process environment ---*/
1043/*------------------------------------------------------------*/
1044
sewardjddc00dd2007-11-27 11:42:47 +00001045#if defined(VGO_linux)
1046
dirk09beb9e2007-04-19 09:47:32 +00001047/* putenv */
njne6154662009-02-10 04:23:41 +00001048int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1049int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001050{
1051 OrigFn fn;
1052 Word result;
1053 const char* p = string;
1054 VALGRIND_GET_ORIG_FN(fn);
1055 /* Now by walking over the string we magically produce
1056 traces when hitting undefined memory. */
1057 if (p)
1058 while (*p++)
1059 ;
1060 CALL_FN_W_W(result, fn, string);
1061 return result;
1062}
1063
1064/* unsetenv */
njne6154662009-02-10 04:23:41 +00001065int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1066int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001067{
1068 OrigFn fn;
1069 Word result;
1070 const char* p = name;
1071 VALGRIND_GET_ORIG_FN(fn);
1072 /* Now by walking over the string we magically produce
1073 traces when hitting undefined memory. */
1074 if (p)
1075 while (*p++)
1076 ;
1077 CALL_FN_W_W(result, fn, name);
1078 return result;
1079}
1080
1081/* setenv */
njne6154662009-02-10 04:23:41 +00001082int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001083 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001084int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001085 (const char* name, const char* value, int overwrite)
1086{
1087 OrigFn fn;
1088 Word result;
1089 const char* p;
1090 VALGRIND_GET_ORIG_FN(fn);
1091 /* Now by walking over the string we magically produce
1092 traces when hitting undefined memory. */
1093 if (name)
1094 for (p = name; *p; p++)
1095 ;
1096 if (value)
1097 for (p = value; *p; p++)
1098 ;
1099 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1100 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1101 return result;
1102}
1103
sewardjddc00dd2007-11-27 11:42:47 +00001104#endif /* defined(VGO_linux) */
1105
1106
dirk09beb9e2007-04-19 09:47:32 +00001107/*------------------------------------------------------------*/
sewardj31b9ce12006-10-17 01:27:13 +00001108/*--- AIX stuff only after this point ---*/
1109/*------------------------------------------------------------*/
1110
sewardjddc00dd2007-11-27 11:42:47 +00001111/* Generate replacements for strcat, strncat, strcpy, strncpy, strcmp
sewardj31b9ce12006-10-17 01:27:13 +00001112 in the given soname. */
sewardjddc00dd2007-11-27 11:42:47 +00001113#define Str5FNs(_soname) \
sewardj31b9ce12006-10-17 01:27:13 +00001114 STRCAT(_soname, strcat) \
1115 STRNCAT(_soname, strncat) \
1116 STRCPY(_soname, strcpy) \
sewardjddc00dd2007-11-27 11:42:47 +00001117 STRNCPY(_soname, strncpy) \
1118 STRCMP(_soname, strcmp)
sewardj31b9ce12006-10-17 01:27:13 +00001119
1120#if defined(VGP_ppc32_aix5)
sewardjddc00dd2007-11-27 11:42:47 +00001121Str5FNs(NONE) /* in main exe */
1122Str5FNs(libCZdaZLshrcoreZdoZR) /* libC.a(shrcore.o) */
1123Str5FNs(libX11ZdaZLshr4ZdoZR) /* libX11.a(shr4.o) */
1124Str5FNs(libXmZdaZLshrZaZdoZR) /* libXm.a(shr*.o) */
1125Str5FNs(libXtZdaZLshr4ZdoZR) /* libXt.a(shr4.o) */
1126Str5FNs(libppeZurZdaZLdynamicZdoZR) /* libppe_r.a(dynamic.o) */
1127Str5FNs(libodmZdaZLshrZdoZR) /* libodm.a(shr.o) */
1128Str5FNs(libmpiZurZdaZLmpicoreZurZdoZR) /* libmpi_r.a(mpicore_r.o) */
1129Str5FNs(libmpiZurZdaZLmpipoeZurZdoZR) /* libmpi_r.a(mpipoe_r.o) */
1130Str5FNs(libmpiZurZdaZLmpciZurZdoZR) /* libmpi_r.a(mpci_r.o) */
1131Str5FNs(libslurmZdso) /* libslurm.so */
1132Str5FNs(libglibZdso) /* libglib.so */
1133Str5FNs(libIMZdaZLshrZdoZR) /* libIM.a(shr.o) */
1134Str5FNs(libiconvZdaZLshr4ZdoZR) /* libiconv.a(shr4.o) */
1135Str5FNs(libGLZdaZLshrZdoZR) /* libGL.a(shr.o) */
1136Str5FNs(libgdkZdso) /* libgdk.so */
1137Str5FNs(libcursesZdaZLshr42ZdoZR) /* libcurses.a(shr42.o) */
1138Str5FNs(libqtZda) /* libqt.a */
sewardjfd4b6f42007-11-29 03:08:32 +00001139Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
1140Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
1141Str5FNs(libQtZaa) /* libQt*.a */
sewardj31b9ce12006-10-17 01:27:13 +00001142#endif
1143#if defined(VGP_ppc64_aix5)
sewardjddc00dd2007-11-27 11:42:47 +00001144Str5FNs(NONE) /* in main exe */
1145Str5FNs(libX11ZdaZLshrZu64ZdoZR) /* libX11.a(shr_64.o) */
1146Str5FNs(libiconvZdaZLshr4Zu64ZdoZR) /* libiconv.a(shr4_64.o) */
1147Str5FNs(libGLZdaZLshrZu64ZdoZR) /* libGL.a(shr_64.o) */
1148Str5FNs(libppeZurZdaZLdynamic64ZdoZR) /* libppe_r.a(dynamic64.o) */
1149Str5FNs(libodmZdaZLshrZu64ZdoZR) /* libodm.a(shr_64.o) */
1150Str5FNs(libmpiZurZdaZLmpicore64ZurZdoZR) /* libmpi_r.a(mpicore64_r.o) */
1151Str5FNs(libmpiZurZdaZLmpipoe64ZurZdoZR) /* libmpi_r.a(mpipoe64_r.o) */
1152Str5FNs(libCZdaZLshrcoreZu64ZdoZR) /* libC.a(shrcore_64.o) */
1153Str5FNs(libmpiZurZdaZLmpci64ZurZdoZR) /* libmpi_r.a(mpci64_r.o) */
1154Str5FNs(libqtZda) /* libqt.a */
sewardjfd4b6f42007-11-29 03:08:32 +00001155Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
1156Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
1157Str5FNs(libQtZaa) /* libQt*.a */
sewardj31b9ce12006-10-17 01:27:13 +00001158#endif
1159
1160
1161/* AIX's libm contains a sqrt implementation which does a nasty thing:
1162 it loads the initial estimate of the root into a FP register, but
1163 only the upper half of the number is initialised data. Hence the
1164 least significant 32 mantissa bits are undefined, and it then uses
1165 Newton-Raphson iteration to compute the final, defined result.
1166 This fools memcheck completely; the only solution I can think of is
1167 provide our own substitute. The _FAST variant is almost right
1168 except the result is not correctly rounded. The _EXACT variant,
1169 which is selected by default, is always right; but it's also pretty
1170 darn slow. */
1171
1172#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
1173#define SQRT_FAST(soname, fnname) \
1174 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1175 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1176 { \
1177 static UInt T1[32] = \
1178 { 0, 1024, 3062, 5746, 9193, 13348, \
1179 18162, 23592, 29598, 36145, 43202, 50740, \
1180 58733, 67158, 75992, 85215, 83599, 71378, \
1181 60428, 50647, 41945, 34246, 27478, 21581, \
1182 16499, 12183, 8588, 5674, 3403, 1742, \
1183 661, 130 }; \
1184 UInt x0, x1, sign, expo, mant0, bIGENDIAN = 1; \
1185 union { UInt w[2]; double d; } u; \
1186 u.d = x; \
1187 x0 = u.w[1 - bIGENDIAN]; /* high half */ \
1188 x1 = u.w[bIGENDIAN]; /* low half */ \
1189 sign = x0 >> 31; \
1190 expo = (x0 >> 20) & 0x7FF; \
1191 mant0 = x0 & 0xFFFFF; \
1192 if ( (sign == 0 && expo >= 1 && expo <= 0x7FE) /* +normal */ \
1193 || (sign == 0 && expo == 0 \
1194 && (mant0 | x1) > 0) /* +denorm */) { \
1195 /* common case; do Newton-Raphson */ \
1196 /* technically k should be signed int32, but since we're \
1197 always entering here with x > 0, doesn't matter that it's \
1198 unsigned. */ \
1199 double y; \
1200 UInt k = (x0>>1) + 0x1ff80000; \
1201 u.w[1 - bIGENDIAN] = k - T1[31&(k>>15)]; \
1202 u.w[bIGENDIAN] = 0; \
1203 y = u.d; \
1204 y = (y+x/y)/2.0 ; \
1205 y = (y+x/y)/2.0 ; \
1206 y = y-(y-x/y)/2.0 ; \
1207 return y; \
1208 } \
1209 if ( (sign == 1 && expo >= 1 && expo <= 0x7FE) /* -normal */ \
1210 || (sign == 1 && expo == 0 \
1211 && (mant0 | x1) > 0) /* -denorm */) { \
1212 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1213 u.w[bIGENDIAN] = 0x1; \
1214 return u.d; /* -Inf -> NaN */ \
1215 } \
1216 if ((expo | mant0 | x1) == 0) \
1217 return x; /* +/-zero -> self */ \
1218 if (expo == 0x7FF && (mant0 | x1) == 0) { \
1219 if (sign == 0) \
1220 return x; /* +Inf -> self */ \
1221 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1222 u.w[bIGENDIAN] = 0x1; \
1223 return u.d; /* -Inf -> NaN */ \
1224 } \
1225 /* must be +/- NaN */ \
1226 return x; /* +/-NaN -> self */ \
1227 }
1228
1229#define SQRT_EXACT(soname, fnname) \
1230 /* \
1231 * ==================================================== \
1232 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. \
1233 * \
1234 * Developed at SunPro, a Sun Microsystems, Inc. business. \
1235 * Permission to use, copy, modify, and distribute this \
1236 * software is freely granted, provided that this notice \
1237 * is preserved. \
1238 * ==================================================== \
1239 */ \
1240 /* \
1241 * Return correctly rounded sqrt. \
1242 * ------------------------------------------ \
1243 * | Use the hardware sqrt if you have one | \
1244 * ------------------------------------------ \
1245 * Method: \
1246 * Bit by bit method using integer arithmetic. (Slow, but portable) \
1247 * 1. Normalization \
1248 * Scale x to y in [1,4) with even powers of 2: \
1249 * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then \
1250 * sqrt(x) = 2^k * sqrt(y) \
1251 * 2. Bit by bit computation \
1252 * Let q = sqrt(y) truncated to i bit after binary point (q = 1), \
1253 * i 0 \
1254 * i+1 2 \
1255 * s = 2*q , and y = 2 * ( y - q ). (1) \
1256 * i i i i \
1257 * \
1258 * To compute q from q , one checks whether \
1259 * i+1 i \
1260 * \
1261 * -(i+1) 2 \
1262 * (q + 2 ) <= y. (2) \
1263 * i \
1264 * -(i+1) \
1265 * If (2) is false, then q = q ; otherwise q = q + 2 . \
1266 * i+1 i i+1 i \
1267 * \
1268 * With some algebric manipulation, it is not difficult to see \
1269 * that (2) is equivalent to \
1270 * -(i+1) \
1271 * s + 2 <= y (3) \
1272 * i i \
1273 * \
1274 * The advantage of (3) is that s and y can be computed by \
1275 * i i \
1276 * the following recurrence formula: \
1277 * if (3) is false \
1278 * \
1279 * s = s , y = y ; (4) \
1280 * i+1 i i+1 i \
1281 * \
1282 * otherwise, \
1283 * -i -(i+1) \
1284 * s = s + 2 , y = y - s - 2 (5) \
1285 * i+1 i i+1 i i \
1286 * \
1287 * \
1288 * One may easily use induction to prove (4) and (5). \
1289 * Note. Since the left hand side of (3) contain only i+2 bits, \
1290 * it does not necessary to do a full (53-bit) comparison \
1291 * in (3). \
1292 * 3. Final rounding \
1293 * After generating the 53 bits result, we compute one more bit. \
1294 * Together with the remainder, we can decide whether the \
1295 * result is exact, bigger than 1/2ulp, or less than 1/2ulp \
1296 * (it will never equal to 1/2ulp). \
1297 * The rounding mode can be detected by checking whether \
1298 * huge + tiny is equal to huge, and whether huge - tiny is \
1299 * equal to huge for some floating point number "huge" and "tiny". \
1300 * \
1301 * Special cases: \
1302 * sqrt(+-0) = +-0 ... exact \
1303 * sqrt(inf) = inf \
1304 * sqrt(-ve) = NaN ... with invalid signal \
1305 * sqrt(NaN) = NaN ... with invalid signal for signaling NaN \
1306 * \
1307 */ \
1308 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1309 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1310 { \
1311 const Int bIGENDIAN = 1; \
1312 const double one = 1.0, tiny=1.0e-300; \
1313 double z; \
1314 Int sign = (Int)0x80000000; \
1315 Int ix0,s0,q,m,t,i; \
1316 UInt r,t1,s1,ix1,q1; \
1317 union { UInt w[2]; double d; } u; \
1318 u.d = x; \
1319 ix0 = u.w[1-bIGENDIAN]; \
1320 ix1 = u.w[bIGENDIAN]; \
1321 \
1322 /* take care of Inf and NaN */ \
1323 if((ix0&0x7ff00000)==0x7ff00000) { \
1324 return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf \
1325 sqrt(-inf)=sNaN */ \
1326 } \
1327 /* take care of zero */ \
1328 if(ix0<=0) { \
1329 if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ \
1330 else if(ix0<0) \
1331 return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ \
1332 } \
1333 /* normalize x */ \
1334 m = (ix0>>20); \
1335 if(m==0) { /* subnormal x */ \
1336 while(ix0==0) { \
1337 m -= 21; \
1338 ix0 |= (ix1>>11); ix1 <<= 21; \
1339 } \
1340 for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; \
1341 m -= i-1; \
1342 ix0 |= (ix1>>(32-i)); \
1343 ix1 <<= i; \
1344 } \
1345 m -= 1023; /* unbias exponent */ \
1346 ix0 = (ix0&0x000fffff)|0x00100000; \
1347 if(m&1){ /* odd m, double x to make it even */ \
1348 ix0 += ix0 + ((ix1&sign)>>31); \
1349 ix1 += ix1; \
1350 } \
1351 m >>= 1; /* m = [m/2] */ \
1352 /* generate sqrt(x) bit by bit */ \
1353 ix0 += ix0 + ((ix1&sign)>>31); \
1354 ix1 += ix1; \
1355 q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ \
1356 r = 0x00200000; /* r = moving bit from right to left */ \
1357 while(r!=0) { \
1358 t = s0+r; \
1359 if(t<=ix0) { \
1360 s0 = t+r; \
1361 ix0 -= t; \
1362 q += r; \
1363 } \
1364 ix0 += ix0 + ((ix1&sign)>>31); \
1365 ix1 += ix1; \
1366 r>>=1; \
1367 } \
1368 r = sign; \
1369 while(r!=0) { \
1370 t1 = s1+r; \
1371 t = s0; \
1372 if((t<ix0)||((t==ix0)&&(t1<=ix1))) { \
1373 s1 = t1+r; \
1374 if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; \
1375 ix0 -= t; \
1376 if (ix1 < t1) ix0 -= 1; \
1377 ix1 -= t1; \
1378 q1 += r; \
1379 } \
1380 ix0 += ix0 + ((ix1&sign)>>31); \
1381 ix1 += ix1; \
1382 r>>=1; \
1383 } \
1384 /* use floating add to find out rounding direction */ \
1385 if((ix0|ix1)!=0) { \
1386 z = one-tiny; /* trigger inexact flag */ \
1387 if (z>=one) { \
1388 z = one+tiny; \
1389 if (q1==(UInt)0xffffffff) { q1=0; q += 1;} \
1390 else if (z>one) { \
1391 if (q1==(UInt)0xfffffffe) q+=1; \
1392 q1+=2; \
1393 } else \
1394 q1 += (q1&1); \
1395 } \
1396 } \
1397 ix0 = (q>>1)+0x3fe00000; \
1398 ix1 = q1>>1; \
1399 if ((q&1)==1) ix1 |= sign; \
1400 ix0 += (m <<20); \
1401 ix0 = u.w[1-bIGENDIAN] = ix0; \
1402 ix1 = u.w[bIGENDIAN] = ix1; \
1403 z = u.d; \
1404 return z; \
1405 }
1406
1407#if 0
1408SQRT_FAST(NONE, sqrt) /* xlC generates these */
1409SQRT_FAST(NONE, _sqrt) /* xlf generates these */
1410#else
1411SQRT_EXACT(NONE, sqrt) /* xlC generates these */
1412SQRT_EXACT(NONE, _sqrt) /* xlf generates these */
1413#endif
1414
1415#endif /* defined(VGP_ppc32_aix5) */
1416
njn3e884182003-04-15 13:03:23 +00001417/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001418/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001419/*--------------------------------------------------------------------*/