2 /*--------------------------------------------------------------------*/
3 /*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/
4 /*--- simulated CPU. ---*/
5 /*--- mc_replace_strmem.c ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of MemCheck, a heavyweight Valgrind tool for
10 detecting memory errors.
12 Copyright (C) 2000-2010 Julian Seward
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.
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.
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
30 The GNU General Public License is contained in the file COPYING.
33 #include "pub_tool_basics.h"
34 #include "pub_tool_hashtable.h"
35 #include "pub_tool_redir.h"
36 #include "pub_tool_tooliface.h"
39 #include "mc_include.h"
42 /* ---------------------------------------------------------------------
43 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
49 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.
53 THEY RUN ON THE SIMD CPU!
54 ------------------------------------------------------------------ */
56 /* 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).
64 Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
66 Addr loS, hiS, loD, hiD;
68 if (dstlen == 0 || srclen == 0)
73 hiS = loS + srclen - 1;
74 hiD = loD + dstlen - 1;
76 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
84 /* They start at same place. Since we know neither of them has
85 zero length, they must overlap. */
90 // This is a macro rather than a function because we don't want to have an
91 // extra function in the stack trace.
92 #define RECORD_OVERLAP_ERROR(s, src, dst, len) \
93 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
94 _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \
98 #define STRRCHR(soname, fnname) \
99 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
100 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
102 UChar ch = (UChar)((UInt)c); \
103 UChar* p = (UChar*)s; \
104 UChar* last = NULL; \
106 if (*p == ch) last = p; \
107 if (*p == 0) return last; \
112 // Apparently rindex() is the same thing as strrchr()
113 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
114 STRRCHR(VG_Z_LIBC_SONAME, rindex)
115 #if defined(VGO_linux)
116 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
117 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
118 #elif defined(VGO_darwin)
119 STRRCHR(VG_Z_DYLD, strrchr)
120 STRRCHR(VG_Z_DYLD, rindex)
124 #define STRCHR(soname, fnname) \
125 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
126 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
128 UChar ch = (UChar)((UInt)c); \
129 UChar* p = (UChar*)s; \
131 if (*p == ch) return p; \
132 if (*p == 0) return NULL; \
137 // Apparently index() is the same thing as strchr()
138 STRCHR(VG_Z_LIBC_SONAME, strchr)
139 STRCHR(VG_Z_LIBC_SONAME, index)
140 #if defined(VGO_linux)
141 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
142 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
143 STRCHR(VG_Z_LD_LINUX_SO_2, index)
144 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
145 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
146 #elif defined(VGO_darwin)
147 STRCHR(VG_Z_DYLD, strchr)
148 STRCHR(VG_Z_DYLD, index)
152 #define STRCAT(soname, fnname) \
153 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
154 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
156 const Char* src_orig = src; \
157 Char* dst_orig = dst; \
158 while (*dst) dst++; \
159 while (*src) *dst++ = *src++; \
162 /* This is a bit redundant, I think; any overlap and the strcat will */ \
163 /* go forever... or until a seg fault occurs. */ \
164 if (is_overlap(dst_orig, \
166 (Addr)dst-(Addr)dst_orig+1, \
167 (Addr)src-(Addr)src_orig+1)) \
168 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
173 STRCAT(VG_Z_LIBC_SONAME, strcat)
174 #if defined(VGO_linux)
175 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
178 #define STRNCAT(soname, fnname) \
179 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
180 ( char* dst, const char* src, SizeT n ); \
181 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
182 ( char* dst, const char* src, SizeT n ) \
184 const Char* src_orig = src; \
185 Char* dst_orig = dst; \
188 while (*dst) dst++; \
189 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
190 *dst = 0; /* always add null */ \
192 /* This checks for overlap after copying, unavoidable without */ \
193 /* pre-counting lengths... should be ok */ \
194 if (is_overlap(dst_orig, \
196 (Addr)dst-(Addr)dst_orig+1, \
197 (Addr)src-(Addr)src_orig+1)) \
198 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
203 STRNCAT(VG_Z_LIBC_SONAME, strncat)
204 #if defined(VGO_darwin)
205 STRNCAT(VG_Z_DYLD, strncat)
209 /* Append src to dst. n is the size of dst's buffer. dst is guaranteed
210 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
211 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
212 Truncation occurred if retval >= n.
214 #define STRLCAT(soname, fnname) \
215 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
216 ( char* dst, const char* src, SizeT n ); \
217 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
218 ( char* dst, const char* src, SizeT n ) \
220 const Char* src_orig = src; \
221 Char* dst_orig = dst; \
224 while (m < n && *dst) { m++; dst++; } \
226 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
227 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
230 /* No space to copy anything to dst. m == n */ \
232 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
233 while (*src) { m++; src++; } \
234 /* This checks for overlap after copying, unavoidable without */ \
235 /* pre-counting lengths... should be ok */ \
236 if (is_overlap(dst_orig, \
238 (Addr)dst-(Addr)dst_orig+1, \
239 (Addr)src-(Addr)src_orig+1)) \
240 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
245 #if defined(VGO_darwin)
246 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
247 STRLCAT(VG_Z_DYLD, strlcat)
251 #define STRNLEN(soname, fnname) \
252 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
253 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
256 while (i < n && str[i] != 0) i++; \
260 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
261 #if defined(VGO_linux)
262 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
266 // Note that this replacement often doesn't get used because gcc inlines
267 // calls to strlen() with its own built-in version. This can be very
268 // confusing if you aren't expecting it. Other small functions in this file
269 // may also be inline by gcc.
270 #define STRLEN(soname, fnname) \
271 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
272 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
275 while (str[i] != 0) i++; \
279 STRLEN(VG_Z_LIBC_SONAME, strlen)
280 #if defined(VGO_linux)
281 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
282 STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
283 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
287 #define STRCPY(soname, fnname) \
288 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
289 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
291 const Char* src_orig = src; \
292 Char* dst_orig = dst; \
294 while (*src) *dst++ = *src++; \
297 /* This checks for overlap after copying, unavoidable without */ \
298 /* pre-counting length... should be ok */ \
299 if (is_overlap(dst_orig, \
301 (Addr)dst-(Addr)dst_orig+1, \
302 (Addr)src-(Addr)src_orig+1)) \
303 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
308 STRCPY(VG_Z_LIBC_SONAME, strcpy)
309 #if defined(VGO_linux)
310 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
311 #elif defined(VGO_darwin)
312 STRCPY(VG_Z_DYLD, strcpy)
316 #define STRNCPY(soname, fnname) \
317 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
318 ( char* dst, const char* src, SizeT n ); \
319 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
320 ( char* dst, const char* src, SizeT n ) \
322 const Char* src_orig = src; \
323 Char* dst_orig = dst; \
326 while (m < n && *src) { m++; *dst++ = *src++; } \
327 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
328 /* but only m+1 bytes of src if terminator was found */ \
329 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
330 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
331 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
336 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
337 #if defined(VGO_linux)
338 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
339 #elif defined(VGO_darwin)
340 STRNCPY(VG_Z_DYLD, strncpy)
344 /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
345 Returns strlen(src). Does not zero-fill the remainder of dst. */
346 #define STRLCPY(soname, fnname) \
347 SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \
348 ( char* dst, const char* src, SizeT n ); \
349 SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \
350 ( char* dst, const char* src, SizeT n ) \
352 const char* src_orig = src; \
353 char* dst_orig = dst; \
356 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
357 /* m non-nul bytes have now been copied, and m <= n-1. */ \
358 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
359 /* but only m+1 bytes of src if terminator was found */ \
360 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
361 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
362 /* Nul-terminate dst. */ \
363 if (n > 0) *dst = 0; \
364 /* Finish counting strlen(src). */ \
365 while (*src) src++; \
366 return src - src_orig; \
369 #if defined(VGO_darwin)
370 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
371 STRLCPY(VG_Z_DYLD, strlcpy)
375 #define STRNCMP(soname, fnname) \
376 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
377 ( const char* s1, const char* s2, SizeT nmax ); \
378 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
379 ( const char* s1, const char* s2, SizeT nmax ) \
383 if (n >= nmax) return 0; \
384 if (*s1 == 0 && *s2 == 0) return 0; \
385 if (*s1 == 0) return -1; \
386 if (*s2 == 0) return 1; \
388 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
389 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
395 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
396 #if defined(VGO_linux)
397 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
398 #elif defined(VGO_darwin)
399 STRNCMP(VG_Z_DYLD, strncmp)
403 #define STRCASECMP(soname, fnname) \
404 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
405 ( const char* s1, const char* s2 ); \
406 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
407 ( const char* s1, const char* s2 ) \
409 extern int tolower(int); \
410 register unsigned char c1; \
411 register unsigned char c2; \
413 c1 = tolower(*(unsigned char *)s1); \
414 c2 = tolower(*(unsigned char *)s2); \
415 if (c1 != c2) break; \
416 if (c1 == 0) break; \
419 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
420 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
424 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
425 #if defined(VGO_linux)
426 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
430 #define STRNCASECMP(soname, fnname) \
431 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
432 ( const char* s1, const char* s2, SizeT nmax ); \
433 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
434 ( const char* s1, const char* s2, SizeT nmax ) \
436 extern int tolower(int); \
439 if (n >= nmax) return 0; \
440 if (*s1 == 0 && *s2 == 0) return 0; \
441 if (*s1 == 0) return -1; \
442 if (*s2 == 0) return 1; \
444 if (tolower(*(unsigned char*)s1) < tolower(*(unsigned char*)s2)) return -1; \
445 if (tolower(*(unsigned char*)s1) > tolower(*(unsigned char*)s2)) return 1; \
451 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
452 #if defined(VGO_linux)
453 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
454 #elif defined(VGO_darwin)
455 STRNCASECMP(VG_Z_DYLD, strncasecmp)
459 #define STRCASECMP_L(soname, fnname) \
460 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
461 ( const char* s1, const char* s2, void* locale ); \
462 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
463 ( const char* s1, const char* s2, void* locale ) \
465 extern int tolower_l(int, void*) __attribute__((weak)); \
466 register unsigned char c1; \
467 register unsigned char c2; \
469 c1 = tolower_l(*(unsigned char *)s1, locale); \
470 c2 = tolower_l(*(unsigned char *)s2, locale); \
471 if (c1 != c2) break; \
472 if (c1 == 0) break; \
475 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
476 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
480 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
481 #if defined(VGO_linux)
482 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
486 #define STRNCASECMP_L(soname, fnname) \
487 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
488 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
489 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
490 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
492 extern int tolower_l(int, void*) __attribute__((weak)); \
495 if (n >= nmax) return 0; \
496 if (*s1 == 0 && *s2 == 0) return 0; \
497 if (*s1 == 0) return -1; \
498 if (*s2 == 0) return 1; \
500 if (tolower_l(*(unsigned char*)s1, locale) < tolower_l(*(unsigned char*)s2, locale)) return -1; \
501 if (tolower_l(*(unsigned char*)s1, locale) > tolower_l(*(unsigned char*)s2, locale)) return 1; \
507 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
508 #if defined(VGO_linux)
509 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
510 #elif defined(VGO_darwin)
511 STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
515 #define STRCMP(soname, fnname) \
516 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
517 ( const char* s1, const char* s2 ); \
518 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
519 ( const char* s1, const char* s2 ) \
521 register unsigned char c1; \
522 register unsigned char c2; \
524 c1 = *(unsigned char *)s1; \
525 c2 = *(unsigned char *)s2; \
526 if (c1 != c2) break; \
527 if (c1 == 0) break; \
530 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
531 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
535 STRCMP(VG_Z_LIBC_SONAME, strcmp)
536 #if defined(VGO_linux)
537 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
538 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
539 STRCMP(VG_Z_LD64_SO_1, strcmp)
543 #define MEMCHR(soname, fnname) \
544 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
545 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
548 UChar c0 = (UChar)c; \
549 UChar* p = (UChar*)s; \
550 for (i = 0; i < n; i++) \
551 if (p[i] == c0) return (void*)(&p[i]); \
555 MEMCHR(VG_Z_LIBC_SONAME, memchr)
556 #if defined(VGO_darwin)
557 MEMCHR(VG_Z_DYLD, memchr)
561 #define MEMCPY(soname, fnname) \
562 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
563 ( void *dst, const void *src, SizeT len ); \
564 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
565 ( void *dst, const void *src, SizeT len ) \
567 if (is_overlap(dst, src, len, len)) \
568 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
570 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
571 const Addr WM = WS - 1; /* 7 or 3 */ \
575 /* Copying backwards. */ \
577 Addr d = (Addr)dst; \
578 Addr s = (Addr)src; \
580 if (((s^d) & WM) == 0) { \
581 /* s and d have same UWord alignment. */ \
582 /* Pull up to a UWord boundary. */ \
583 while ((s & WM) != 0 && n >= 1) \
584 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
587 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
591 if (((s|d) & 1) == 0) { \
592 /* Both are 16-aligned; copy what we can thusly. */ \
594 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
596 /* Copy leftovers, or everything if misaligned. */ \
598 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
600 } else if (dst > src) { \
603 Addr d = ((Addr)dst) + n; \
604 Addr s = ((Addr)src) + n; \
606 /* Copying forwards. */ \
607 if (((s^d) & WM) == 0) { \
608 /* s and d have same UWord alignment. */ \
609 /* Back down to a UWord boundary. */ \
610 while ((s & WM) != 0 && n >= 1) \
611 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
614 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
618 if (((s|d) & 1) == 0) { \
619 /* Both are 16-aligned; copy what we can thusly. */ \
621 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
623 /* Copy leftovers, or everything if misaligned. */ \
625 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
632 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
633 #if defined(VGO_linux)
634 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
635 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
636 #elif defined(VGO_darwin)
637 MEMCPY(VG_Z_DYLD, memcpy)
639 /* icc9 blats these around all over the place. Not only in the main
640 executable but various .so's. They are highly tuned and read
641 memory beyond the source boundary (although work correctly and
642 never go across page boundaries), so give errors when run natively,
643 at least for misaligned source arg. Just intercepting in the exe
644 only until we understand more about the problem. See
645 http://bugs.kde.org/show_bug.cgi?id=139776
647 MEMCPY(NONE, _intel_fast_memcpy)
650 #define MEMCMP(soname, fnname) \
651 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
652 ( const void *s1V, const void *s2V, SizeT n ); \
653 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
654 ( const void *s1V, const void *s2V, SizeT n ) \
659 unsigned char* s1 = (unsigned char*)s1V; \
660 unsigned char* s2 = (unsigned char*)s2V; \
667 res = ((int)a0) - ((int)b0); \
675 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
676 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
677 #if defined(VGO_linux)
678 MEMCMP(VG_Z_LD_SO_1, bcmp)
679 #elif defined(VGO_darwin)
680 MEMCMP(VG_Z_DYLD, memcmp)
681 MEMCMP(VG_Z_DYLD, bcmp)
685 /* Copy SRC to DEST, returning the address of the terminating '\0' in
686 DEST. (minor variant of strcpy) */
687 #define STPCPY(soname, fnname) \
688 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
689 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
691 const Char* src_orig = src; \
692 Char* dst_orig = dst; \
694 while (*src) *dst++ = *src++; \
697 /* This checks for overlap after copying, unavoidable without */ \
698 /* pre-counting length... should be ok */ \
699 if (is_overlap(dst_orig, \
701 (Addr)dst-(Addr)dst_orig+1, \
702 (Addr)src-(Addr)src_orig+1)) \
703 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
708 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
709 #if defined(VGO_linux)
710 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
711 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
712 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
713 #elif defined(VGO_darwin)
714 STPCPY(VG_Z_DYLD, stpcpy)
718 #define MEMSET(soname, fnname) \
719 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \
720 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
723 UInt c4 = (c & 0xFF); \
724 c4 = (c4 << 8) | c4; \
725 c4 = (c4 << 16) | c4; \
726 while ((a & 3) != 0 && n >= 1) \
727 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
729 { *(UInt*)a = c4; a += 4; n -= 4; } \
731 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
735 MEMSET(VG_Z_LIBC_SONAME, memset)
736 #if defined(VGO_darwin)
737 MEMSET(VG_Z_DYLD, memset)
741 #define MEMMOVE(soname, fnname) \
742 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
743 (void *dstV, const void *srcV, SizeT n); \
744 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
745 (void *dstV, const void *srcV, SizeT n) \
748 Char* dst = (Char*)dstV; \
749 Char* src = (Char*)srcV; \
751 for (i = 0; i < n; i++) \
756 for (i = 0; i < n; i++) \
757 dst[n-i-1] = src[n-i-1]; \
762 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
763 #if defined(VGO_darwin)
764 MEMMOVE(VG_Z_DYLD, memmove)
768 #define BCOPY(soname, fnname) \
769 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
770 (const void *srcV, void *dstV, SizeT n); \
771 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
772 (const void *srcV, void *dstV, SizeT n) \
775 Char* dst = (Char*)dstV; \
776 Char* src = (Char*)srcV; \
778 for (i = 0; i < n; i++) \
783 for (i = 0; i < n; i++) \
784 dst[n-i-1] = src[n-i-1]; \
788 #if defined(VGO_darwin)
789 BCOPY(VG_Z_LIBC_SONAME, bcopy)
790 BCOPY(VG_Z_DYLD, bcopy)
794 /* glibc 2.5 variant of memmove which checks the dest is big enough.
795 There is no specific part of glibc that this is copied from. */
796 #define GLIBC25___MEMMOVE_CHK(soname, fnname) \
797 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
798 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
799 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
800 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
802 extern void _exit(int status); \
804 Char* dst = (Char*)dstV; \
805 Char* src = (Char*)srcV; \
809 for (i = 0; i < n; i++) \
814 for (i = 0; i < n; i++) \
815 dst[n-i-1] = src[n-i-1]; \
819 VALGRIND_PRINTF_BACKTRACE( \
820 "*** memmove_chk: buffer overflow detected ***: " \
821 "program terminated\n"); \
827 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
830 /* Find the first occurrence of C in S or the final NUL byte. */
831 #define GLIBC232_STRCHRNUL(soname, fnname) \
832 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
833 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
835 unsigned char c = (unsigned char) c_in; \
836 unsigned char* char_ptr = (unsigned char *)s; \
838 if (*char_ptr == 0) return char_ptr; \
839 if (*char_ptr == c) return char_ptr; \
844 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
847 /* Find the first occurrence of C in S. */
848 #define GLIBC232_RAWMEMCHR(soname, fnname) \
849 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
850 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
852 unsigned char c = (unsigned char) c_in; \
853 unsigned char* char_ptr = (unsigned char *)s; \
855 if (*char_ptr == c) return char_ptr; \
860 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
861 #if defined (VGO_linux)
862 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
865 /* glibc variant of strcpy that checks the dest is big enough.
866 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
867 #define GLIBC25___STRCPY_CHK(soname,fnname) \
868 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
869 (char* dst, const char* src, SizeT len); \
870 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
871 (char* dst, const char* src, SizeT len) \
873 extern void _exit(int status); \
877 while ((*dst++ = *src++) != '\0') \
882 VALGRIND_PRINTF_BACKTRACE( \
883 "*** strcpy_chk: buffer overflow detected ***: " \
884 "program terminated\n"); \
890 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
893 /* glibc variant of stpcpy that checks the dest is big enough.
894 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
895 #define GLIBC25___STPCPY_CHK(soname,fnname) \
896 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
897 (char* dst, const char* src, SizeT len); \
898 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
899 (char* dst, const char* src, SizeT len) \
901 extern void _exit(int status); \
904 while ((*dst++ = *src++) != '\0') \
909 VALGRIND_PRINTF_BACKTRACE( \
910 "*** stpcpy_chk: buffer overflow detected ***: " \
911 "program terminated\n"); \
917 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
921 #define GLIBC25_MEMPCPY(soname, fnname) \
922 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
923 ( void *dst, const void *src, SizeT len ); \
924 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
925 ( void *dst, const void *src, SizeT len ) \
929 SizeT len_saved = len; \
934 if (is_overlap(dst, src, len, len)) \
935 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
938 d = (char *)dst + len - 1; \
939 s = (char *)src + len - 1; \
943 } else if ( dst < src ) { \
950 return (void*)( ((char*)dst) + len_saved ); \
953 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
954 #if defined(VGO_linux)
955 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
959 #define GLIBC26___MEMCPY_CHK(soname, fnname) \
960 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
961 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
962 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
963 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
965 extern void _exit(int status); \
969 if (dstlen < len) goto badness; \
974 if (is_overlap(dst, src, len, len)) \
975 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
978 d = (char *)dst + len - 1; \
979 s = (char *)src + len - 1; \
983 } else if ( dst < src ) { \
992 VALGRIND_PRINTF_BACKTRACE( \
993 "*** memcpy_chk: buffer overflow detected ***: " \
994 "program terminated\n"); \
1000 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1003 #define STRSTR(soname, fnname) \
1004 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1005 (void* haystack, void* needle); \
1006 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1007 (void* haystack, void* needle) \
1009 UChar* h = (UChar*)haystack; \
1010 UChar* n = (UChar*)needle; \
1012 /* find the length of n, not including terminating zero */ \
1014 while (n[nlen]) nlen++; \
1016 /* if n is the empty string, match immediately. */ \
1017 if (nlen == 0) return h; \
1019 /* assert(nlen >= 1); */ \
1024 if (hh == 0) return NULL; \
1025 if (hh != n0) { h++; continue; } \
1028 for (i = 0; i < nlen; i++) { \
1032 /* assert(i >= 0 && i <= nlen); */ \
1040 #if defined(VGO_linux)
1041 STRSTR(VG_Z_LIBC_SONAME, strstr)
1045 #define STRPBRK(soname, fnname) \
1046 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1047 (void* sV, void* acceptV); \
1048 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1049 (void* sV, void* acceptV) \
1051 UChar* s = (UChar*)sV; \
1052 UChar* accept = (UChar*)acceptV; \
1054 /* find the length of 'accept', not including terminating zero */ \
1056 while (accept[nacc]) nacc++; \
1058 /* if n is the empty string, fail immediately. */ \
1059 if (nacc == 0) return NULL; \
1061 /* assert(nacc >= 1); */ \
1067 for (i = 0; i < nacc; i++) { \
1068 if (sc == accept[i]) \
1077 #if defined(VGO_linux)
1078 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1082 #define STRCSPN(soname, fnname) \
1083 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1084 (void* sV, void* rejectV); \
1085 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1086 (void* sV, void* rejectV) \
1088 UChar* s = (UChar*)sV; \
1089 UChar* reject = (UChar*)rejectV; \
1091 /* find the length of 'reject', not including terminating zero */ \
1093 while (reject[nrej]) nrej++; \
1101 for (i = 0; i < nrej; i++) { \
1102 if (sc == reject[i]) \
1105 /* assert(i >= 0 && i <= nrej); */ \
1115 #if defined(VGO_linux)
1116 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1120 // And here's a validated strspn replacement, should it
1121 // become necessary.
1122 //UWord mystrspn( UChar* s, UChar* accept )
1124 // /* find the length of 'accept', not including terminating zero */
1126 // while (accept[nacc]) nacc++;
1127 // if (nacc == 0) return 0;
1135 // for (i = 0; i < nacc; i++) {
1136 // if (sc == accept[i])
1139 // assert(i >= 0 && i <= nacc);
1150 /*------------------------------------------------------------*/
1151 /*--- Improve definedness checking of process environment ---*/
1152 /*------------------------------------------------------------*/
1154 #if defined(VGO_linux)
1157 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1158 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
1162 const char* p = string;
1163 VALGRIND_GET_ORIG_FN(fn);
1164 /* Now by walking over the string we magically produce
1165 traces when hitting undefined memory. */
1169 CALL_FN_W_W(result, fn, string);
1174 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1175 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
1179 const char* p = name;
1180 VALGRIND_GET_ORIG_FN(fn);
1181 /* Now by walking over the string we magically produce
1182 traces when hitting undefined memory. */
1186 CALL_FN_W_W(result, fn, name);
1191 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1192 (const char* name, const char* value, int overwrite);
1193 int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1194 (const char* name, const char* value, int overwrite)
1199 VALGRIND_GET_ORIG_FN(fn);
1200 /* Now by walking over the string we magically produce
1201 traces when hitting undefined memory. */
1203 for (p = name; *p; p++)
1206 for (p = value; *p; p++)
1208 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1209 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1213 #endif /* defined(VGO_linux) */
1216 /*------------------------------------------------------------*/
1217 /*--- AIX stuff only after this point ---*/
1218 /*------------------------------------------------------------*/
1220 /* Generate replacements for strcat, strncat, strcpy, strncpy, strcmp
1221 in the given soname. */
1222 #define Str5FNs(_soname) \
1223 STRCAT(_soname, strcat) \
1224 STRNCAT(_soname, strncat) \
1225 STRCPY(_soname, strcpy) \
1226 STRNCPY(_soname, strncpy) \
1227 STRCMP(_soname, strcmp)
1229 #if defined(VGP_ppc32_aix5)
1230 Str5FNs(NONE) /* in main exe */
1231 Str5FNs(libCZdaZLshrcoreZdoZR) /* libC.a(shrcore.o) */
1232 Str5FNs(libX11ZdaZLshr4ZdoZR) /* libX11.a(shr4.o) */
1233 Str5FNs(libXmZdaZLshrZaZdoZR) /* libXm.a(shr*.o) */
1234 Str5FNs(libXtZdaZLshr4ZdoZR) /* libXt.a(shr4.o) */
1235 Str5FNs(libppeZurZdaZLdynamicZdoZR) /* libppe_r.a(dynamic.o) */
1236 Str5FNs(libodmZdaZLshrZdoZR) /* libodm.a(shr.o) */
1237 Str5FNs(libmpiZurZdaZLmpicoreZurZdoZR) /* libmpi_r.a(mpicore_r.o) */
1238 Str5FNs(libmpiZurZdaZLmpipoeZurZdoZR) /* libmpi_r.a(mpipoe_r.o) */
1239 Str5FNs(libmpiZurZdaZLmpciZurZdoZR) /* libmpi_r.a(mpci_r.o) */
1240 Str5FNs(libslurmZdso) /* libslurm.so */
1241 Str5FNs(libglibZdso) /* libglib.so */
1242 Str5FNs(libIMZdaZLshrZdoZR) /* libIM.a(shr.o) */
1243 Str5FNs(libiconvZdaZLshr4ZdoZR) /* libiconv.a(shr4.o) */
1244 Str5FNs(libGLZdaZLshrZdoZR) /* libGL.a(shr.o) */
1245 Str5FNs(libgdkZdso) /* libgdk.so */
1246 Str5FNs(libcursesZdaZLshr42ZdoZR) /* libcurses.a(shr42.o) */
1247 Str5FNs(libqtZda) /* libqt.a */
1248 Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
1249 Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
1250 Str5FNs(libQtZaa) /* libQt*.a */
1252 #if defined(VGP_ppc64_aix5)
1253 Str5FNs(NONE) /* in main exe */
1254 Str5FNs(libX11ZdaZLshrZu64ZdoZR) /* libX11.a(shr_64.o) */
1255 Str5FNs(libiconvZdaZLshr4Zu64ZdoZR) /* libiconv.a(shr4_64.o) */
1256 Str5FNs(libGLZdaZLshrZu64ZdoZR) /* libGL.a(shr_64.o) */
1257 Str5FNs(libppeZurZdaZLdynamic64ZdoZR) /* libppe_r.a(dynamic64.o) */
1258 Str5FNs(libodmZdaZLshrZu64ZdoZR) /* libodm.a(shr_64.o) */
1259 Str5FNs(libmpiZurZdaZLmpicore64ZurZdoZR) /* libmpi_r.a(mpicore64_r.o) */
1260 Str5FNs(libmpiZurZdaZLmpipoe64ZurZdoZR) /* libmpi_r.a(mpipoe64_r.o) */
1261 Str5FNs(libCZdaZLshrcoreZu64ZdoZR) /* libC.a(shrcore_64.o) */
1262 Str5FNs(libmpiZurZdaZLmpci64ZurZdoZR) /* libmpi_r.a(mpci64_r.o) */
1263 Str5FNs(libqtZda) /* libqt.a */
1264 Str5FNs(ZaZLlibglibZhZaZdsoZaZR) /* *(libglib-*.so*) */
1265 Str5FNs(ZaZLlibfontconfigZdsoZaZR) /* *(libfontconfig.so*) */
1266 Str5FNs(libQtZaa) /* libQt*.a */
1270 /* AIX's libm contains a sqrt implementation which does a nasty thing:
1271 it loads the initial estimate of the root into a FP register, but
1272 only the upper half of the number is initialised data. Hence the
1273 least significant 32 mantissa bits are undefined, and it then uses
1274 Newton-Raphson iteration to compute the final, defined result.
1275 This fools memcheck completely; the only solution I can think of is
1276 provide our own substitute. The _FAST variant is almost right
1277 except the result is not correctly rounded. The _EXACT variant,
1278 which is selected by default, is always right; but it's also pretty
1281 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
1282 #define SQRT_FAST(soname, fnname) \
1283 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1284 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1286 static UInt T1[32] = \
1287 { 0, 1024, 3062, 5746, 9193, 13348, \
1288 18162, 23592, 29598, 36145, 43202, 50740, \
1289 58733, 67158, 75992, 85215, 83599, 71378, \
1290 60428, 50647, 41945, 34246, 27478, 21581, \
1291 16499, 12183, 8588, 5674, 3403, 1742, \
1293 UInt x0, x1, sign, expo, mant0, bIGENDIAN = 1; \
1294 union { UInt w[2]; double d; } u; \
1296 x0 = u.w[1 - bIGENDIAN]; /* high half */ \
1297 x1 = u.w[bIGENDIAN]; /* low half */ \
1299 expo = (x0 >> 20) & 0x7FF; \
1300 mant0 = x0 & 0xFFFFF; \
1301 if ( (sign == 0 && expo >= 1 && expo <= 0x7FE) /* +normal */ \
1302 || (sign == 0 && expo == 0 \
1303 && (mant0 | x1) > 0) /* +denorm */) { \
1304 /* common case; do Newton-Raphson */ \
1305 /* technically k should be signed int32, but since we're \
1306 always entering here with x > 0, doesn't matter that it's \
1309 UInt k = (x0>>1) + 0x1ff80000; \
1310 u.w[1 - bIGENDIAN] = k - T1[31&(k>>15)]; \
1311 u.w[bIGENDIAN] = 0; \
1315 y = y-(y-x/y)/2.0 ; \
1318 if ( (sign == 1 && expo >= 1 && expo <= 0x7FE) /* -normal */ \
1319 || (sign == 1 && expo == 0 \
1320 && (mant0 | x1) > 0) /* -denorm */) { \
1321 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1322 u.w[bIGENDIAN] = 0x1; \
1323 return u.d; /* -Inf -> NaN */ \
1325 if ((expo | mant0 | x1) == 0) \
1326 return x; /* +/-zero -> self */ \
1327 if (expo == 0x7FF && (mant0 | x1) == 0) { \
1329 return x; /* +Inf -> self */ \
1330 u.w[1 - bIGENDIAN] = 0xFFF00000; \
1331 u.w[bIGENDIAN] = 0x1; \
1332 return u.d; /* -Inf -> NaN */ \
1334 /* must be +/- NaN */ \
1335 return x; /* +/-NaN -> self */ \
1338 #define SQRT_EXACT(soname, fnname) \
1340 * ==================================================== \
1341 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. \
1343 * Developed at SunPro, a Sun Microsystems, Inc. business. \
1344 * Permission to use, copy, modify, and distribute this \
1345 * software is freely granted, provided that this notice \
1347 * ==================================================== \
1350 * Return correctly rounded sqrt. \
1351 * ------------------------------------------ \
1352 * | Use the hardware sqrt if you have one | \
1353 * ------------------------------------------ \
1355 * Bit by bit method using integer arithmetic. (Slow, but portable) \
1356 * 1. Normalization \
1357 * Scale x to y in [1,4) with even powers of 2: \
1358 * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then \
1359 * sqrt(x) = 2^k * sqrt(y) \
1360 * 2. Bit by bit computation \
1361 * Let q = sqrt(y) truncated to i bit after binary point (q = 1), \
1364 * s = 2*q , and y = 2 * ( y - q ). (1) \
1367 * To compute q from q , one checks whether \
1371 * (q + 2 ) <= y. (2) \
1374 * If (2) is false, then q = q ; otherwise q = q + 2 . \
1377 * With some algebric manipulation, it is not difficult to see \
1378 * that (2) is equivalent to \
1383 * The advantage of (3) is that s and y can be computed by \
1385 * the following recurrence formula: \
1388 * s = s , y = y ; (4) \
1393 * s = s + 2 , y = y - s - 2 (5) \
1397 * One may easily use induction to prove (4) and (5). \
1398 * Note. Since the left hand side of (3) contain only i+2 bits, \
1399 * it does not necessary to do a full (53-bit) comparison \
1401 * 3. Final rounding \
1402 * After generating the 53 bits result, we compute one more bit. \
1403 * Together with the remainder, we can decide whether the \
1404 * result is exact, bigger than 1/2ulp, or less than 1/2ulp \
1405 * (it will never equal to 1/2ulp). \
1406 * The rounding mode can be detected by checking whether \
1407 * huge + tiny is equal to huge, and whether huge - tiny is \
1408 * equal to huge for some floating point number "huge" and "tiny". \
1411 * sqrt(+-0) = +-0 ... exact \
1413 * sqrt(-ve) = NaN ... with invalid signal \
1414 * sqrt(NaN) = NaN ... with invalid signal for signaling NaN \
1417 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
1418 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
1420 const Int bIGENDIAN = 1; \
1421 const double one = 1.0, tiny=1.0e-300; \
1423 Int sign = (Int)0x80000000; \
1424 Int ix0,s0,q,m,t,i; \
1425 UInt r,t1,s1,ix1,q1; \
1426 union { UInt w[2]; double d; } u; \
1428 ix0 = u.w[1-bIGENDIAN]; \
1429 ix1 = u.w[bIGENDIAN]; \
1431 /* take care of Inf and NaN */ \
1432 if((ix0&0x7ff00000)==0x7ff00000) { \
1433 return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf \
1434 sqrt(-inf)=sNaN */ \
1436 /* take care of zero */ \
1438 if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ \
1440 return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ \
1444 if(m==0) { /* subnormal x */ \
1447 ix0 |= (ix1>>11); ix1 <<= 21; \
1449 for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; \
1451 ix0 |= (ix1>>(32-i)); \
1454 m -= 1023; /* unbias exponent */ \
1455 ix0 = (ix0&0x000fffff)|0x00100000; \
1456 if(m&1){ /* odd m, double x to make it even */ \
1457 ix0 += ix0 + ((ix1&sign)>>31); \
1460 m >>= 1; /* m = [m/2] */ \
1461 /* generate sqrt(x) bit by bit */ \
1462 ix0 += ix0 + ((ix1&sign)>>31); \
1464 q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ \
1465 r = 0x00200000; /* r = moving bit from right to left */ \
1473 ix0 += ix0 + ((ix1&sign)>>31); \
1481 if((t<ix0)||((t==ix0)&&(t1<=ix1))) { \
1483 if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; \
1485 if (ix1 < t1) ix0 -= 1; \
1489 ix0 += ix0 + ((ix1&sign)>>31); \
1493 /* use floating add to find out rounding direction */ \
1494 if((ix0|ix1)!=0) { \
1495 z = one-tiny; /* trigger inexact flag */ \
1498 if (q1==(UInt)0xffffffff) { q1=0; q += 1;} \
1500 if (q1==(UInt)0xfffffffe) q+=1; \
1506 ix0 = (q>>1)+0x3fe00000; \
1508 if ((q&1)==1) ix1 |= sign; \
1510 ix0 = u.w[1-bIGENDIAN] = ix0; \
1511 ix1 = u.w[bIGENDIAN] = ix1; \
1517 SQRT_FAST(NONE, sqrt) /* xlC generates these */
1518 SQRT_FAST(NONE, _sqrt) /* xlf generates these */
1520 SQRT_EXACT(NONE, sqrt) /* xlC generates these */
1521 SQRT_EXACT(NONE, _sqrt) /* xlf generates these */
1524 #endif /* defined(VGP_ppc32_aix5) */
1526 /*--------------------------------------------------------------------*/
1528 /*--------------------------------------------------------------------*/