blob: bccae755a4b7f41e16ec52c57819ade9afa6c7c3 [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
sewardj9ebd6e02007-01-08 06:01:59 +000012 Copyright (C) 2000-2007 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
sewardj31b9ce12006-10-17 01:27:13 +0000100/* --------- Some handy Z-encoded names. --------- */
101
102/* --- Soname of the standard C library. --- */
103
104#if defined(VGO_linux)
105# define m_libc_soname libcZdsoZa // libc.so*
106#elif defined(VGP_ppc32_aix5)
107 /* AIX has both /usr/lib/libc.a and /usr/lib/libc_r.a. */
108# define m_libc_soname libcZaZdaZLshrZdoZR // libc*.a(shr.o)
109#elif defined(VGP_ppc64_aix5)
110# define m_libc_soname libcZaZdaZLshrZu64ZdoZR // libc*.a(shr_64.o)
111#else
112# error "Unknown platform"
113#endif
114
115/* --- Sonames for Linux ELF linkers. --- */
116
njn16eeb4e2005-06-16 03:56:58 +0000117#define m_ld_linux_so_2 ldZhlinuxZdsoZd2 // ld-linux.so.2
118#define m_ld_linux_x86_64_so_2 ldZhlinuxZhx86Zh64ZdsoZd2 // ld-linux-x86-64.so.2
sewardj776de2c2006-02-14 21:55:11 +0000119#define m_ld64_so_1 ld64ZdsoZd1 // ld64.so.1
sewardj79820562006-09-11 20:33:55 +0000120#define m_ld_so_1 ldZdsoZd1 // ld.so.1
njn46275862005-03-24 04:00:03 +0000121
njn16eeb4e2005-06-16 03:56:58 +0000122
123#define STRRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000124 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
125 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000126 { \
127 UChar ch = (UChar)((UInt)c); \
128 UChar* p = (UChar*)s; \
129 UChar* last = NULL; \
130 while (True) { \
131 if (*p == ch) last = p; \
132 if (*p == 0) return last; \
133 p++; \
134 } \
njn3e884182003-04-15 13:03:23 +0000135 }
njn3e884182003-04-15 13:03:23 +0000136
njn16eeb4e2005-06-16 03:56:58 +0000137// Apparently rindex() is the same thing as strrchr()
sewardj31b9ce12006-10-17 01:27:13 +0000138STRRCHR(m_libc_soname, strrchr)
139STRRCHR(m_libc_soname, rindex)
njn16eeb4e2005-06-16 03:56:58 +0000140STRRCHR(m_ld_linux_so_2, rindex)
141
142
143#define STRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000144 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
145 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000146 { \
147 UChar ch = (UChar)((UInt)c); \
148 UChar* p = (UChar*)s; \
149 while (True) { \
150 if (*p == ch) return p; \
151 if (*p == 0) return NULL; \
152 p++; \
153 } \
njn3e884182003-04-15 13:03:23 +0000154 }
njn3e884182003-04-15 13:03:23 +0000155
njn16eeb4e2005-06-16 03:56:58 +0000156// Apparently index() is the same thing as strchr()
sewardj31b9ce12006-10-17 01:27:13 +0000157STRCHR(m_libc_soname, strchr)
njn16eeb4e2005-06-16 03:56:58 +0000158STRCHR(m_ld_linux_so_2, strchr)
tom10e1beb2005-07-21 15:25:04 +0000159STRCHR(m_ld_linux_x86_64_so_2, strchr)
sewardj31b9ce12006-10-17 01:27:13 +0000160STRCHR(m_libc_soname, index)
njn16eeb4e2005-06-16 03:56:58 +0000161STRCHR(m_ld_linux_so_2, index)
162STRCHR(m_ld_linux_x86_64_so_2, index)
njn3e884182003-04-15 13:03:23 +0000163
njn3e884182003-04-15 13:03:23 +0000164
njn16eeb4e2005-06-16 03:56:58 +0000165#define STRCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000166 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
167 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000168 { \
169 const Char* src_orig = src; \
170 Char* dst_orig = dst; \
171 while (*dst) dst++; \
172 while (*src) *dst++ = *src++; \
173 *dst = 0; \
174 \
175 /* This is a bit redundant, I think; any overlap and the strcat will */ \
176 /* go forever... or until a seg fault occurs. */ \
177 if (is_overlap(dst_orig, \
178 src_orig, \
179 (Addr)dst-(Addr)dst_orig+1, \
180 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000181 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
njn16eeb4e2005-06-16 03:56:58 +0000182 \
183 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000184 }
njn3e884182003-04-15 13:03:23 +0000185
sewardj31b9ce12006-10-17 01:27:13 +0000186STRCAT(m_libc_soname, strcat)
njn16eeb4e2005-06-16 03:56:58 +0000187
188
189#define STRNCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000190 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
191 ( char* dst, const char* src, SizeT n ); \
192 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
193 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000194 { \
195 const Char* src_orig = src; \
196 Char* dst_orig = dst; \
197 SizeT m = 0; \
198 \
199 while (*dst) dst++; \
200 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
201 *dst = 0; /* always add null */ \
202 \
203 /* This checks for overlap after copying, unavoidable without */ \
204 /* pre-counting lengths... should be ok */ \
205 if (is_overlap(dst_orig, \
206 src_orig, \
207 (Addr)dst-(Addr)dst_orig+1, \
208 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000209 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
njn16eeb4e2005-06-16 03:56:58 +0000210 \
211 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000212 }
njn3e884182003-04-15 13:03:23 +0000213
sewardj31b9ce12006-10-17 01:27:13 +0000214STRNCAT(m_libc_soname, strncat)
215
njn3e884182003-04-15 13:03:23 +0000216
njn16eeb4e2005-06-16 03:56:58 +0000217#define STRNLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000218 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
219 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000220 { \
221 SizeT i = 0; \
222 while (i < n && str[i] != 0) i++; \
223 return i; \
njn3e884182003-04-15 13:03:23 +0000224 }
njn3e884182003-04-15 13:03:23 +0000225
sewardj31b9ce12006-10-17 01:27:13 +0000226STRNLEN(m_libc_soname, strnlen)
njn16eeb4e2005-06-16 03:56:58 +0000227
sewardj3ceec242003-07-30 21:24:25 +0000228
njn5ec15ed2005-08-24 19:55:51 +0000229// Note that this replacement often doesn't get used because gcc inlines
230// calls to strlen() with its own built-in version. This can be very
231// confusing if you aren't expecting it. Other small functions in this file
232// may also be inline by gcc.
njn16eeb4e2005-06-16 03:56:58 +0000233#define STRLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000234 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
235 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000236 { \
237 SizeT i = 0; \
238 while (str[i] != 0) i++; \
239 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000240 }
njn16eeb4e2005-06-16 03:56:58 +0000241
sewardj31b9ce12006-10-17 01:27:13 +0000242STRLEN(m_libc_soname, strlen)
njn16eeb4e2005-06-16 03:56:58 +0000243STRLEN(m_ld_linux_so_2, strlen)
244STRLEN(m_ld_linux_x86_64_so_2, strlen)
sewardj31b9ce12006-10-17 01:27:13 +0000245
njn16eeb4e2005-06-16 03:56:58 +0000246
247#define STRCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000248 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
249 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000250 { \
251 const Char* src_orig = src; \
252 Char* dst_orig = dst; \
253 \
254 while (*src) *dst++ = *src++; \
255 *dst = 0; \
256 \
257 /* This checks for overlap after copying, unavoidable without */ \
258 /* pre-counting length... should be ok */ \
259 if (is_overlap(dst_orig, \
260 src_orig, \
261 (Addr)dst-(Addr)dst_orig+1, \
262 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000263 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
njn16eeb4e2005-06-16 03:56:58 +0000264 \
265 return dst_orig; \
266 }
267
sewardj31b9ce12006-10-17 01:27:13 +0000268STRCPY(m_libc_soname, strcpy)
njn16eeb4e2005-06-16 03:56:58 +0000269
270
271#define STRNCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000272 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
273 ( char* dst, const char* src, SizeT n ); \
274 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
275 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000276 { \
277 const Char* src_orig = src; \
278 Char* dst_orig = dst; \
279 SizeT m = 0; \
280 \
281 while (m < n && *src) { m++; *dst++ = *src++; } \
282 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
283 /* but only m+1 bytes of src if terminator was found */ \
284 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000285 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000286 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
287 \
288 return dst_orig; \
289 }
290
sewardj31b9ce12006-10-17 01:27:13 +0000291STRNCPY(m_libc_soname, strncpy)
njn16eeb4e2005-06-16 03:56:58 +0000292
293
294#define STRNCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000295 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
296 ( const char* s1, const char* s2, SizeT nmax ); \
297 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
298 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000299 { \
300 SizeT n = 0; \
301 while (True) { \
302 if (n >= nmax) return 0; \
303 if (*s1 == 0 && *s2 == 0) return 0; \
304 if (*s1 == 0) return -1; \
305 if (*s2 == 0) return 1; \
306 \
307 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
308 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
309 \
310 s1++; s2++; n++; \
311 } \
312 }
313
sewardj31b9ce12006-10-17 01:27:13 +0000314STRNCMP(m_libc_soname, strncmp)
njn16eeb4e2005-06-16 03:56:58 +0000315
316
317#define STRCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000318 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
319 ( const char* s1, const char* s2 ); \
320 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
321 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000322 { \
323 register unsigned char c1; \
324 register unsigned char c2; \
325 while (True) { \
326 c1 = *(unsigned char *)s1; \
327 c2 = *(unsigned char *)s2; \
328 if (c1 != c2) break; \
329 if (c1 == 0) break; \
330 s1++; s2++; \
331 } \
332 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
333 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
334 return 0; \
335 }
336
sewardj31b9ce12006-10-17 01:27:13 +0000337STRCMP(m_libc_soname, strcmp)
njn16eeb4e2005-06-16 03:56:58 +0000338STRCMP(m_ld_linux_x86_64_so_2, strcmp)
sewardj776de2c2006-02-14 21:55:11 +0000339STRCMP(m_ld64_so_1, strcmp)
njn16eeb4e2005-06-16 03:56:58 +0000340
341
342#define MEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000343 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
344 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000345 { \
346 SizeT i; \
347 UChar c0 = (UChar)c; \
348 UChar* p = (UChar*)s; \
349 for (i = 0; i < n; i++) \
350 if (p[i] == c0) return (void*)(&p[i]); \
351 return NULL; \
352 }
353
sewardj31b9ce12006-10-17 01:27:13 +0000354MEMCHR(m_libc_soname, memchr)
njn16eeb4e2005-06-16 03:56:58 +0000355
356
357#define MEMCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000358 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
359 ( void *dst, const void *src, SizeT len ); \
360 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
361 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000362 { \
363 register char *d; \
364 register char *s; \
365 \
366 if (len == 0) \
367 return dst; \
368 \
369 if (is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000370 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
njn16eeb4e2005-06-16 03:56:58 +0000371 \
372 if ( dst > src ) { \
373 d = (char *)dst + len - 1; \
374 s = (char *)src + len - 1; \
375 while ( len >= 4 ) { \
376 *d-- = *s--; \
377 *d-- = *s--; \
378 *d-- = *s--; \
379 *d-- = *s--; \
380 len -= 4; \
381 } \
382 while ( len-- ) { \
383 *d-- = *s--; \
384 } \
385 } else if ( dst < src ) { \
386 d = (char *)dst; \
387 s = (char *)src; \
388 while ( len >= 4 ) { \
389 *d++ = *s++; \
390 *d++ = *s++; \
391 *d++ = *s++; \
392 *d++ = *s++; \
393 len -= 4; \
394 } \
395 while ( len-- ) { \
396 *d++ = *s++; \
397 } \
398 } \
399 return dst; \
400 }
401
sewardj31b9ce12006-10-17 01:27:13 +0000402MEMCPY(m_libc_soname, memcpy)
403MEMCPY(m_ld_so_1, memcpy) /* ld.so.1 */
404
njn16eeb4e2005-06-16 03:56:58 +0000405
406#define MEMCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000407 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
408 ( const void *s1V, const void *s2V, SizeT n ); \
409 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
410 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000411 { \
412 int res; \
413 unsigned char a0; \
414 unsigned char b0; \
415 unsigned char* s1 = (unsigned char*)s1V; \
416 unsigned char* s2 = (unsigned char*)s2V; \
417 \
418 while (n != 0) { \
419 a0 = s1[0]; \
420 b0 = s2[0]; \
421 s1 += 1; \
422 s2 += 1; \
423 res = ((int)a0) - ((int)b0); \
424 if (res != 0) \
425 return res; \
426 n -= 1; \
427 } \
428 return 0; \
429 }
430
sewardj31b9ce12006-10-17 01:27:13 +0000431MEMCMP(m_libc_soname, memcmp)
432MEMCMP(m_libc_soname, bcmp)
sewardj1eee0772007-01-06 06:30:48 +0000433MEMCMP(m_ld_so_1, bcmp)
njn3e884182003-04-15 13:03:23 +0000434
jseward0845ef82003-12-22 22:31:27 +0000435
436/* Copy SRC to DEST, returning the address of the terminating '\0' in
437 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000438#define STPCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000439 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
440 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000441 { \
442 const Char* src_orig = src; \
443 Char* dst_orig = dst; \
444 \
445 while (*src) *dst++ = *src++; \
446 *dst = 0; \
447 \
448 /* This checks for overlap after copying, unavoidable without */ \
449 /* pre-counting length... should be ok */ \
450 if (is_overlap(dst_orig, \
451 src_orig, \
452 (Addr)dst-(Addr)dst_orig+1, \
453 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000454 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
njn16eeb4e2005-06-16 03:56:58 +0000455 \
456 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000457 }
njn16eeb4e2005-06-16 03:56:58 +0000458
sewardj31b9ce12006-10-17 01:27:13 +0000459STPCPY(m_libc_soname, stpcpy)
tom10e1beb2005-07-21 15:25:04 +0000460STPCPY(m_ld_linux_so_2, stpcpy)
461STPCPY(m_ld_linux_x86_64_so_2, stpcpy)
njn16eeb4e2005-06-16 03:56:58 +0000462
463
464#define MEMSET(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000465 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \
466 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000467 { \
468 unsigned char *cp = s; \
469 \
470 while(n--) \
471 *cp++ = c; \
472 \
473 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000474 }
njn16eeb4e2005-06-16 03:56:58 +0000475
sewardj31b9ce12006-10-17 01:27:13 +0000476MEMSET(m_libc_soname, memset)
njn16eeb4e2005-06-16 03:56:58 +0000477
478
479#define MEMMOVE(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000480 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
481 (void *dstV, const void *srcV, SizeT n); \
482 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
483 (void *dstV, const void *srcV, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000484 { \
485 SizeT i; \
486 Char* dst = (Char*)dstV; \
487 Char* src = (Char*)srcV; \
488 if (dst < src) { \
489 for (i = 0; i < n; i++) \
490 dst[i] = src[i]; \
491 } \
492 else \
493 if (dst > src) { \
494 for (i = 0; i < n; i++) \
495 dst[n-i-1] = src[n-i-1]; \
496 } \
497 return dst; \
498 }
499
sewardj31b9ce12006-10-17 01:27:13 +0000500MEMMOVE(m_libc_soname, memmove)
sewardj44e495f2005-05-12 17:58:28 +0000501
jseward0845ef82003-12-22 22:31:27 +0000502
sewardj4e9a4b62004-11-23 00:20:17 +0000503/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000504#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000505 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
506 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000507 { \
508 unsigned char c = (unsigned char) c_in; \
509 unsigned char* char_ptr = (unsigned char *)s; \
510 while (1) { \
511 if (*char_ptr == 0) return char_ptr; \
512 if (*char_ptr == c) return char_ptr; \
513 char_ptr++; \
514 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000515 }
njn16eeb4e2005-06-16 03:56:58 +0000516
sewardj31b9ce12006-10-17 01:27:13 +0000517GLIBC232_STRCHRNUL(m_libc_soname, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000518
519
520/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000521#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000522 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
523 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000524 { \
525 unsigned char c = (unsigned char) c_in; \
526 unsigned char* char_ptr = (unsigned char *)s; \
527 while (1) { \
528 if (*char_ptr == c) return char_ptr; \
529 char_ptr++; \
530 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000531 }
njn16eeb4e2005-06-16 03:56:58 +0000532
sewardj31b9ce12006-10-17 01:27:13 +0000533GLIBC232_RAWMEMCHR(m_libc_soname, rawmemchr)
sewardj4e9a4b62004-11-23 00:20:17 +0000534
535
sewardj620e5262006-12-31 00:22:30 +0000536/* glibc variant of strcpy that checks the dest is big enough. */
537#define GLIBC25___STRCPY_CHK(soname,fnname) \
538 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
539 (char* dst, const char* src, SizeT len); \
540 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
541 (char* dst, const char* src, SizeT len) \
542 { \
543 extern void _exit(int status); \
544 char* ret = dst; \
545 if (! len) \
546 goto badness; \
547 while ((*dst++ = *src++) != '\0') \
548 if (--len == 0) \
549 goto badness; \
550 return ret; \
551 badness: \
552 VALGRIND_PRINTF_BACKTRACE( \
553 "***buffer overflow detected ***: program terminated"); \
554 _exit(127); \
555 /*NOTREACHED*/ \
556 return NULL; \
557 }
558
559GLIBC25___STRCPY_CHK(m_libc_soname, __strcpy_chk)
560
561
sewardj841b72d2006-12-31 18:55:56 +0000562/* mempcpy */
563#define GLIBC25_MEMPCPY(soname, fnname) \
564 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
565 ( void *dst, const void *src, SizeT len ); \
566 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
567 ( void *dst, const void *src, SizeT len ) \
568 { \
569 register char *d; \
570 register char *s; \
571 SizeT len_saved = len; \
572 \
573 if (len == 0) \
574 return dst; \
575 \
576 if (is_overlap(dst, src, len, len)) \
577 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
578 \
579 if ( dst > src ) { \
580 d = (char *)dst + len - 1; \
581 s = (char *)src + len - 1; \
582 while ( len-- ) { \
583 *d-- = *s--; \
584 } \
585 } else if ( dst < src ) { \
586 d = (char *)dst; \
587 s = (char *)src; \
588 while ( len-- ) { \
589 *d++ = *s++; \
590 } \
591 } \
592 return (void*)( ((char*)dst) + len_saved ); \
593 }
594
595GLIBC25_MEMPCPY(m_libc_soname, mempcpy)
596
597
sewardj31b9ce12006-10-17 01:27:13 +0000598/*------------------------------------------------------------*/
599/*--- AIX stuff only after this point ---*/
600/*------------------------------------------------------------*/
601
602/* Generate replacements for strcat, strncat, strcpy, strncpy,
603 in the given soname. */
604#define Str4FNs(_soname) \
605 STRCAT(_soname, strcat) \
606 STRNCAT(_soname, strncat) \
607 STRCPY(_soname, strcpy) \
608 STRNCPY(_soname, strncpy)
609
610#if defined(VGP_ppc32_aix5)
611Str4FNs(NONE) /* in main exe */
612Str4FNs(libCZdaZLshrcoreZdoZR) /* libC.a(shrcore.o) */
613Str4FNs(libX11ZdaZLshr4ZdoZR) /* libX11.a(shr4.o) */
614Str4FNs(libXmZdaZLshrZaZdoZR) /* libXm.a(shr*.o) */
615Str4FNs(libXtZdaZLshr4ZdoZR) /* libXt.a(shr4.o) */
616Str4FNs(libppeZurZdaZLdynamicZdoZR) /* libppe_r.a(dynamic.o) */
617Str4FNs(libodmZdaZLshrZdoZR) /* libodm.a(shr.o) */
618Str4FNs(libmpiZurZdaZLmpicoreZurZdoZR) /* libmpi_r.a(mpicore_r.o) */
619Str4FNs(libmpiZurZdaZLmpipoeZurZdoZR) /* libmpi_r.a(mpipoe_r.o) */
620Str4FNs(libmpiZurZdaZLmpciZurZdoZR) /* libmpi_r.a(mpci_r.o) */
621Str4FNs(libslurmZdso) /* libslurm.so */
622Str4FNs(libglibZdso) /* libglib.so */
623Str4FNs(libIMZdaZLshrZdoZR) /* libIM.a(shr.o) */
624Str4FNs(libiconvZdaZLshr4ZdoZR) /* libiconv.a(shr4.o) */
625Str4FNs(libGLZdaZLshrZdoZR) /* libGL.a(shr.o) */
626Str4FNs(libgdkZdso) /* libgdk.so */
627Str4FNs(libcursesZdaZLshr42ZdoZR) /* libcurses.a(shr42.o) */
628Str4FNs(libqtZda) /* libqt.a */
629#endif
630#if defined(VGP_ppc64_aix5)
631Str4FNs(NONE) /* in main exe */
632Str4FNs(libX11ZdaZLshrZu64ZdoZR) /* libX11.a(shr_64.o) */
633Str4FNs(libiconvZdaZLshr4Zu64ZdoZR) /* libiconv.a(shr4_64.o) */
634Str4FNs(libGLZdaZLshrZu64ZdoZR) /* libGL.a(shr_64.o) */
635Str4FNs(libppeZurZdaZLdynamic64ZdoZR) /* libppe_r.a(dynamic64.o) */
636Str4FNs(libodmZdaZLshrZu64ZdoZR) /* libodm.a(shr_64.o) */
637Str4FNs(libmpiZurZdaZLmpicore64ZurZdoZR) /* libmpi_r.a(mpicore64_r.o) */
638Str4FNs(libmpiZurZdaZLmpipoe64ZurZdoZR) /* libmpi_r.a(mpipoe64_r.o) */
639Str4FNs(libCZdaZLshrcoreZu64ZdoZR) /* libC.a(shrcore_64.o) */
640Str4FNs(libmpiZurZdaZLmpci64ZurZdoZR) /* libmpi_r.a(mpci64_r.o) */
641Str4FNs(libqtZda) /* libqt.a */
642#endif
643
644
645/* AIX's libm contains a sqrt implementation which does a nasty thing:
646 it loads the initial estimate of the root into a FP register, but
647 only the upper half of the number is initialised data. Hence the
648 least significant 32 mantissa bits are undefined, and it then uses
649 Newton-Raphson iteration to compute the final, defined result.
650 This fools memcheck completely; the only solution I can think of is
651 provide our own substitute. The _FAST variant is almost right
652 except the result is not correctly rounded. The _EXACT variant,
653 which is selected by default, is always right; but it's also pretty
654 darn slow. */
655
656#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
657#define SQRT_FAST(soname, fnname) \
658 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
659 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
660 { \
661 static UInt T1[32] = \
662 { 0, 1024, 3062, 5746, 9193, 13348, \
663 18162, 23592, 29598, 36145, 43202, 50740, \
664 58733, 67158, 75992, 85215, 83599, 71378, \
665 60428, 50647, 41945, 34246, 27478, 21581, \
666 16499, 12183, 8588, 5674, 3403, 1742, \
667 661, 130 }; \
668 UInt x0, x1, sign, expo, mant0, bIGENDIAN = 1; \
669 union { UInt w[2]; double d; } u; \
670 u.d = x; \
671 x0 = u.w[1 - bIGENDIAN]; /* high half */ \
672 x1 = u.w[bIGENDIAN]; /* low half */ \
673 sign = x0 >> 31; \
674 expo = (x0 >> 20) & 0x7FF; \
675 mant0 = x0 & 0xFFFFF; \
676 if ( (sign == 0 && expo >= 1 && expo <= 0x7FE) /* +normal */ \
677 || (sign == 0 && expo == 0 \
678 && (mant0 | x1) > 0) /* +denorm */) { \
679 /* common case; do Newton-Raphson */ \
680 /* technically k should be signed int32, but since we're \
681 always entering here with x > 0, doesn't matter that it's \
682 unsigned. */ \
683 double y; \
684 UInt k = (x0>>1) + 0x1ff80000; \
685 u.w[1 - bIGENDIAN] = k - T1[31&(k>>15)]; \
686 u.w[bIGENDIAN] = 0; \
687 y = u.d; \
688 y = (y+x/y)/2.0 ; \
689 y = (y+x/y)/2.0 ; \
690 y = y-(y-x/y)/2.0 ; \
691 return y; \
692 } \
693 if ( (sign == 1 && expo >= 1 && expo <= 0x7FE) /* -normal */ \
694 || (sign == 1 && expo == 0 \
695 && (mant0 | x1) > 0) /* -denorm */) { \
696 u.w[1 - bIGENDIAN] = 0xFFF00000; \
697 u.w[bIGENDIAN] = 0x1; \
698 return u.d; /* -Inf -> NaN */ \
699 } \
700 if ((expo | mant0 | x1) == 0) \
701 return x; /* +/-zero -> self */ \
702 if (expo == 0x7FF && (mant0 | x1) == 0) { \
703 if (sign == 0) \
704 return x; /* +Inf -> self */ \
705 u.w[1 - bIGENDIAN] = 0xFFF00000; \
706 u.w[bIGENDIAN] = 0x1; \
707 return u.d; /* -Inf -> NaN */ \
708 } \
709 /* must be +/- NaN */ \
710 return x; /* +/-NaN -> self */ \
711 }
712
713#define SQRT_EXACT(soname, fnname) \
714 /* \
715 * ==================================================== \
716 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. \
717 * \
718 * Developed at SunPro, a Sun Microsystems, Inc. business. \
719 * Permission to use, copy, modify, and distribute this \
720 * software is freely granted, provided that this notice \
721 * is preserved. \
722 * ==================================================== \
723 */ \
724 /* \
725 * Return correctly rounded sqrt. \
726 * ------------------------------------------ \
727 * | Use the hardware sqrt if you have one | \
728 * ------------------------------------------ \
729 * Method: \
730 * Bit by bit method using integer arithmetic. (Slow, but portable) \
731 * 1. Normalization \
732 * Scale x to y in [1,4) with even powers of 2: \
733 * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then \
734 * sqrt(x) = 2^k * sqrt(y) \
735 * 2. Bit by bit computation \
736 * Let q = sqrt(y) truncated to i bit after binary point (q = 1), \
737 * i 0 \
738 * i+1 2 \
739 * s = 2*q , and y = 2 * ( y - q ). (1) \
740 * i i i i \
741 * \
742 * To compute q from q , one checks whether \
743 * i+1 i \
744 * \
745 * -(i+1) 2 \
746 * (q + 2 ) <= y. (2) \
747 * i \
748 * -(i+1) \
749 * If (2) is false, then q = q ; otherwise q = q + 2 . \
750 * i+1 i i+1 i \
751 * \
752 * With some algebric manipulation, it is not difficult to see \
753 * that (2) is equivalent to \
754 * -(i+1) \
755 * s + 2 <= y (3) \
756 * i i \
757 * \
758 * The advantage of (3) is that s and y can be computed by \
759 * i i \
760 * the following recurrence formula: \
761 * if (3) is false \
762 * \
763 * s = s , y = y ; (4) \
764 * i+1 i i+1 i \
765 * \
766 * otherwise, \
767 * -i -(i+1) \
768 * s = s + 2 , y = y - s - 2 (5) \
769 * i+1 i i+1 i i \
770 * \
771 * \
772 * One may easily use induction to prove (4) and (5). \
773 * Note. Since the left hand side of (3) contain only i+2 bits, \
774 * it does not necessary to do a full (53-bit) comparison \
775 * in (3). \
776 * 3. Final rounding \
777 * After generating the 53 bits result, we compute one more bit. \
778 * Together with the remainder, we can decide whether the \
779 * result is exact, bigger than 1/2ulp, or less than 1/2ulp \
780 * (it will never equal to 1/2ulp). \
781 * The rounding mode can be detected by checking whether \
782 * huge + tiny is equal to huge, and whether huge - tiny is \
783 * equal to huge for some floating point number "huge" and "tiny". \
784 * \
785 * Special cases: \
786 * sqrt(+-0) = +-0 ... exact \
787 * sqrt(inf) = inf \
788 * sqrt(-ve) = NaN ... with invalid signal \
789 * sqrt(NaN) = NaN ... with invalid signal for signaling NaN \
790 * \
791 */ \
792 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
793 double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
794 { \
795 const Int bIGENDIAN = 1; \
796 const double one = 1.0, tiny=1.0e-300; \
797 double z; \
798 Int sign = (Int)0x80000000; \
799 Int ix0,s0,q,m,t,i; \
800 UInt r,t1,s1,ix1,q1; \
801 union { UInt w[2]; double d; } u; \
802 u.d = x; \
803 ix0 = u.w[1-bIGENDIAN]; \
804 ix1 = u.w[bIGENDIAN]; \
805 \
806 /* take care of Inf and NaN */ \
807 if((ix0&0x7ff00000)==0x7ff00000) { \
808 return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf \
809 sqrt(-inf)=sNaN */ \
810 } \
811 /* take care of zero */ \
812 if(ix0<=0) { \
813 if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ \
814 else if(ix0<0) \
815 return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ \
816 } \
817 /* normalize x */ \
818 m = (ix0>>20); \
819 if(m==0) { /* subnormal x */ \
820 while(ix0==0) { \
821 m -= 21; \
822 ix0 |= (ix1>>11); ix1 <<= 21; \
823 } \
824 for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; \
825 m -= i-1; \
826 ix0 |= (ix1>>(32-i)); \
827 ix1 <<= i; \
828 } \
829 m -= 1023; /* unbias exponent */ \
830 ix0 = (ix0&0x000fffff)|0x00100000; \
831 if(m&1){ /* odd m, double x to make it even */ \
832 ix0 += ix0 + ((ix1&sign)>>31); \
833 ix1 += ix1; \
834 } \
835 m >>= 1; /* m = [m/2] */ \
836 /* generate sqrt(x) bit by bit */ \
837 ix0 += ix0 + ((ix1&sign)>>31); \
838 ix1 += ix1; \
839 q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ \
840 r = 0x00200000; /* r = moving bit from right to left */ \
841 while(r!=0) { \
842 t = s0+r; \
843 if(t<=ix0) { \
844 s0 = t+r; \
845 ix0 -= t; \
846 q += r; \
847 } \
848 ix0 += ix0 + ((ix1&sign)>>31); \
849 ix1 += ix1; \
850 r>>=1; \
851 } \
852 r = sign; \
853 while(r!=0) { \
854 t1 = s1+r; \
855 t = s0; \
856 if((t<ix0)||((t==ix0)&&(t1<=ix1))) { \
857 s1 = t1+r; \
858 if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; \
859 ix0 -= t; \
860 if (ix1 < t1) ix0 -= 1; \
861 ix1 -= t1; \
862 q1 += r; \
863 } \
864 ix0 += ix0 + ((ix1&sign)>>31); \
865 ix1 += ix1; \
866 r>>=1; \
867 } \
868 /* use floating add to find out rounding direction */ \
869 if((ix0|ix1)!=0) { \
870 z = one-tiny; /* trigger inexact flag */ \
871 if (z>=one) { \
872 z = one+tiny; \
873 if (q1==(UInt)0xffffffff) { q1=0; q += 1;} \
874 else if (z>one) { \
875 if (q1==(UInt)0xfffffffe) q+=1; \
876 q1+=2; \
877 } else \
878 q1 += (q1&1); \
879 } \
880 } \
881 ix0 = (q>>1)+0x3fe00000; \
882 ix1 = q1>>1; \
883 if ((q&1)==1) ix1 |= sign; \
884 ix0 += (m <<20); \
885 ix0 = u.w[1-bIGENDIAN] = ix0; \
886 ix1 = u.w[bIGENDIAN] = ix1; \
887 z = u.d; \
888 return z; \
889 }
890
891#if 0
892SQRT_FAST(NONE, sqrt) /* xlC generates these */
893SQRT_FAST(NONE, _sqrt) /* xlf generates these */
894#else
895SQRT_EXACT(NONE, sqrt) /* xlC generates these */
896SQRT_EXACT(NONE, _sqrt) /* xlf generates these */
897#endif
898
899#endif /* defined(VGP_ppc32_aix5) */
900
njn3e884182003-04-15 13:03:23 +0000901/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +0000902/*--- end ---*/
njn3e884182003-04-15 13:03:23 +0000903/*--------------------------------------------------------------------*/