blob: 27fe0464d0b6b95a4387d6872b3d2a67fdeccafc [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
sewardje4b0bf02006-06-05 23:21:15 +000012 Copyright (C) 2000-2006 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.
92#define RECORD_OVERLAP_ERROR(s, p_extra) \
93{ \
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, \
sewardj9af10a12006-02-01 14:59:42 +000097 s, p_extra, 0, 0, 0); \
njn1f8b3e72005-03-22 04:27:14 +000098}
sewardjdda830a2003-07-20 22:28:42 +000099
njn3e884182003-04-15 13:03:23 +0000100static __inline__
101void complain2 ( Char* s, char* dst, const char* src )
102{
njnb6cae9f2003-09-04 20:50:47 +0000103 OverlapExtra extra = {
104 .src = (Addr)src, .dst = (Addr)dst, .len = -1,
105 };
njn1f8b3e72005-03-22 04:27:14 +0000106 RECORD_OVERLAP_ERROR( s, &extra );
njn3e884182003-04-15 13:03:23 +0000107}
108
109static __inline__
110void complain3 ( Char* s, void* dst, const void* src, int n )
111{
njnb6cae9f2003-09-04 20:50:47 +0000112 /* Must wrap it up here, because we cannot pass 4 args to core */
113 OverlapExtra extra = {
114 .src = (Addr)src, .dst = (Addr)dst, .len = n,
115 };
njn1f8b3e72005-03-22 04:27:14 +0000116 RECORD_OVERLAP_ERROR( s, &extra );
njn3e884182003-04-15 13:03:23 +0000117}
118
njn16eeb4e2005-06-16 03:56:58 +0000119// Some handy Z-encoded names
tom8f924092005-10-13 15:51:12 +0000120#define m_libc_so_star libcZdsoZa // libc.so*
njn16eeb4e2005-06-16 03:56:58 +0000121#define m_ld_linux_so_2 ldZhlinuxZdsoZd2 // ld-linux.so.2
122#define m_ld_linux_x86_64_so_2 ldZhlinuxZhx86Zh64ZdsoZd2 // ld-linux-x86-64.so.2
sewardj776de2c2006-02-14 21:55:11 +0000123#define m_ld64_so_1 ld64ZdsoZd1 // ld64.so.1
sewardj79820562006-09-11 20:33:55 +0000124#define m_ld_so_1 ldZdsoZd1 // ld.so.1
njn46275862005-03-24 04:00:03 +0000125
njn16eeb4e2005-06-16 03:56:58 +0000126
127#define STRRCHR(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 UChar* last = NULL; \
134 while (True) { \
135 if (*p == ch) last = p; \
136 if (*p == 0) return last; \
137 p++; \
138 } \
njn3e884182003-04-15 13:03:23 +0000139 }
njn3e884182003-04-15 13:03:23 +0000140
njn16eeb4e2005-06-16 03:56:58 +0000141// Apparently rindex() is the same thing as strrchr()
tom8f924092005-10-13 15:51:12 +0000142STRRCHR(m_libc_so_star, strrchr)
143STRRCHR(m_libc_so_star, rindex)
njn16eeb4e2005-06-16 03:56:58 +0000144STRRCHR(m_ld_linux_so_2, rindex)
145
146
147#define STRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000148 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
149 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000150 { \
151 UChar ch = (UChar)((UInt)c); \
152 UChar* p = (UChar*)s; \
153 while (True) { \
154 if (*p == ch) return p; \
155 if (*p == 0) return NULL; \
156 p++; \
157 } \
njn3e884182003-04-15 13:03:23 +0000158 }
njn3e884182003-04-15 13:03:23 +0000159
njn16eeb4e2005-06-16 03:56:58 +0000160// Apparently index() is the same thing as strchr()
tom8f924092005-10-13 15:51:12 +0000161STRCHR(m_libc_so_star, strchr)
njn16eeb4e2005-06-16 03:56:58 +0000162STRCHR(m_ld_linux_so_2, strchr)
tom10e1beb2005-07-21 15:25:04 +0000163STRCHR(m_ld_linux_x86_64_so_2, strchr)
tom8f924092005-10-13 15:51:12 +0000164STRCHR(m_libc_so_star, index)
njn16eeb4e2005-06-16 03:56:58 +0000165STRCHR(m_ld_linux_so_2, index)
166STRCHR(m_ld_linux_x86_64_so_2, index)
njn3e884182003-04-15 13:03:23 +0000167
njn3e884182003-04-15 13:03:23 +0000168
njn16eeb4e2005-06-16 03:56:58 +0000169#define STRCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000170 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
171 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000172 { \
173 const Char* src_orig = src; \
174 Char* dst_orig = dst; \
175 while (*dst) dst++; \
176 while (*src) *dst++ = *src++; \
177 *dst = 0; \
178 \
179 /* This is a bit redundant, I think; any overlap and the strcat will */ \
180 /* go forever... or until a seg fault occurs. */ \
181 if (is_overlap(dst_orig, \
182 src_orig, \
183 (Addr)dst-(Addr)dst_orig+1, \
184 (Addr)src-(Addr)src_orig+1)) \
185 complain2("strcat", dst_orig, src_orig); \
186 \
187 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000188 }
njn3e884182003-04-15 13:03:23 +0000189
tom8f924092005-10-13 15:51:12 +0000190STRCAT(m_libc_so_star, strcat)
njn16eeb4e2005-06-16 03:56:58 +0000191
192
193#define STRNCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000194 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
195 ( char* dst, const char* src, SizeT n ); \
196 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
197 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000198 { \
199 const Char* src_orig = src; \
200 Char* dst_orig = dst; \
201 SizeT m = 0; \
202 \
203 while (*dst) dst++; \
204 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
205 *dst = 0; /* always add null */ \
206 \
207 /* This checks for overlap after copying, unavoidable without */ \
208 /* pre-counting lengths... should be ok */ \
209 if (is_overlap(dst_orig, \
210 src_orig, \
211 (Addr)dst-(Addr)dst_orig+1, \
212 (Addr)src-(Addr)src_orig+1)) \
213 complain3("strncat", dst_orig, src_orig, n); \
214 \
215 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000216 }
njn3e884182003-04-15 13:03:23 +0000217
tom8f924092005-10-13 15:51:12 +0000218STRNCAT(m_libc_so_star, strncat)
njn16eeb4e2005-06-16 03:56:58 +0000219
njn3e884182003-04-15 13:03:23 +0000220
njn16eeb4e2005-06-16 03:56:58 +0000221#define STRNLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000222 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
223 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000224 { \
225 SizeT i = 0; \
226 while (i < n && str[i] != 0) i++; \
227 return i; \
njn3e884182003-04-15 13:03:23 +0000228 }
njn3e884182003-04-15 13:03:23 +0000229
tom8f924092005-10-13 15:51:12 +0000230STRNLEN(m_libc_so_star, strnlen)
njn16eeb4e2005-06-16 03:56:58 +0000231
sewardj3ceec242003-07-30 21:24:25 +0000232
njn5ec15ed2005-08-24 19:55:51 +0000233// Note that this replacement often doesn't get used because gcc inlines
234// calls to strlen() with its own built-in version. This can be very
235// confusing if you aren't expecting it. Other small functions in this file
236// may also be inline by gcc.
njn16eeb4e2005-06-16 03:56:58 +0000237#define STRLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000238 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
239 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000240 { \
241 SizeT i = 0; \
242 while (str[i] != 0) i++; \
243 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000244 }
njn16eeb4e2005-06-16 03:56:58 +0000245
tom8f924092005-10-13 15:51:12 +0000246STRLEN(m_libc_so_star, strlen)
njn16eeb4e2005-06-16 03:56:58 +0000247STRLEN(m_ld_linux_so_2, strlen)
248STRLEN(m_ld_linux_x86_64_so_2, strlen)
249
250
251#define STRCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000252 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
253 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000254 { \
255 const Char* src_orig = src; \
256 Char* dst_orig = dst; \
257 \
258 while (*src) *dst++ = *src++; \
259 *dst = 0; \
260 \
261 /* This checks for overlap after copying, unavoidable without */ \
262 /* pre-counting length... should be ok */ \
263 if (is_overlap(dst_orig, \
264 src_orig, \
265 (Addr)dst-(Addr)dst_orig+1, \
266 (Addr)src-(Addr)src_orig+1)) \
267 complain2("strcpy", dst_orig, src_orig); \
268 \
269 return dst_orig; \
270 }
271
tom8f924092005-10-13 15:51:12 +0000272STRCPY(m_libc_so_star, strcpy)
njn16eeb4e2005-06-16 03:56:58 +0000273
274
275#define STRNCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000276 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
277 ( char* dst, const char* src, SizeT n ); \
278 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
279 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000280 { \
281 const Char* src_orig = src; \
282 Char* dst_orig = dst; \
283 SizeT m = 0; \
284 \
285 while (m < n && *src) { m++; *dst++ = *src++; } \
286 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
287 /* but only m+1 bytes of src if terminator was found */ \
288 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
289 complain3("strncpy", dst, src, n); \
290 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
291 \
292 return dst_orig; \
293 }
294
tom8f924092005-10-13 15:51:12 +0000295STRNCPY(m_libc_so_star, strncpy)
njn16eeb4e2005-06-16 03:56:58 +0000296
297
298#define STRNCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000299 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
300 ( const char* s1, const char* s2, SizeT nmax ); \
301 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
302 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000303 { \
304 SizeT n = 0; \
305 while (True) { \
306 if (n >= nmax) return 0; \
307 if (*s1 == 0 && *s2 == 0) return 0; \
308 if (*s1 == 0) return -1; \
309 if (*s2 == 0) return 1; \
310 \
311 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
312 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
313 \
314 s1++; s2++; n++; \
315 } \
316 }
317
tom8f924092005-10-13 15:51:12 +0000318STRNCMP(m_libc_so_star, strncmp)
njn16eeb4e2005-06-16 03:56:58 +0000319
320
321#define STRCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000322 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
323 ( const char* s1, const char* s2 ); \
324 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
325 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000326 { \
327 register unsigned char c1; \
328 register unsigned char c2; \
329 while (True) { \
330 c1 = *(unsigned char *)s1; \
331 c2 = *(unsigned char *)s2; \
332 if (c1 != c2) break; \
333 if (c1 == 0) break; \
334 s1++; s2++; \
335 } \
336 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
337 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
338 return 0; \
339 }
340
tom8f924092005-10-13 15:51:12 +0000341STRCMP(m_libc_so_star, strcmp)
njn16eeb4e2005-06-16 03:56:58 +0000342STRCMP(m_ld_linux_x86_64_so_2, strcmp)
sewardj776de2c2006-02-14 21:55:11 +0000343STRCMP(m_ld64_so_1, strcmp)
njn16eeb4e2005-06-16 03:56:58 +0000344
345
346#define MEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000347 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
348 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000349 { \
350 SizeT i; \
351 UChar c0 = (UChar)c; \
352 UChar* p = (UChar*)s; \
353 for (i = 0; i < n; i++) \
354 if (p[i] == c0) return (void*)(&p[i]); \
355 return NULL; \
356 }
357
tom8f924092005-10-13 15:51:12 +0000358MEMCHR(m_libc_so_star, memchr)
njn16eeb4e2005-06-16 03:56:58 +0000359
360
361#define MEMCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000362 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
363 ( void *dst, const void *src, SizeT len ); \
364 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
365 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000366 { \
367 register char *d; \
368 register char *s; \
369 \
370 if (len == 0) \
371 return dst; \
372 \
373 if (is_overlap(dst, src, len, len)) \
374 complain3("memcpy", dst, src, len); \
375 \
376 if ( dst > src ) { \
377 d = (char *)dst + len - 1; \
378 s = (char *)src + len - 1; \
379 while ( len >= 4 ) { \
380 *d-- = *s--; \
381 *d-- = *s--; \
382 *d-- = *s--; \
383 *d-- = *s--; \
384 len -= 4; \
385 } \
386 while ( len-- ) { \
387 *d-- = *s--; \
388 } \
389 } else if ( dst < src ) { \
390 d = (char *)dst; \
391 s = (char *)src; \
392 while ( len >= 4 ) { \
393 *d++ = *s++; \
394 *d++ = *s++; \
395 *d++ = *s++; \
396 *d++ = *s++; \
397 len -= 4; \
398 } \
399 while ( len-- ) { \
400 *d++ = *s++; \
401 } \
402 } \
403 return dst; \
404 }
405
tom8f924092005-10-13 15:51:12 +0000406MEMCPY(m_libc_so_star, memcpy)
sewardj79820562006-09-11 20:33:55 +0000407MEMCPY(m_ld_so_1, memcpy) /* ld.so.1 */
njn16eeb4e2005-06-16 03:56:58 +0000408
409
410#define MEMCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000411 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
412 ( const void *s1V, const void *s2V, SizeT n ); \
413 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
414 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000415 { \
416 int res; \
417 unsigned char a0; \
418 unsigned char b0; \
419 unsigned char* s1 = (unsigned char*)s1V; \
420 unsigned char* s2 = (unsigned char*)s2V; \
421 \
422 while (n != 0) { \
423 a0 = s1[0]; \
424 b0 = s2[0]; \
425 s1 += 1; \
426 s2 += 1; \
427 res = ((int)a0) - ((int)b0); \
428 if (res != 0) \
429 return res; \
430 n -= 1; \
431 } \
432 return 0; \
433 }
434
tom8f924092005-10-13 15:51:12 +0000435MEMCMP(m_libc_so_star, memcmp)
436MEMCMP(m_libc_so_star, bcmp)
njn3e884182003-04-15 13:03:23 +0000437
jseward0845ef82003-12-22 22:31:27 +0000438
439/* Copy SRC to DEST, returning the address of the terminating '\0' in
440 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000441#define STPCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000442 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
443 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000444 { \
445 const Char* src_orig = src; \
446 Char* dst_orig = dst; \
447 \
448 while (*src) *dst++ = *src++; \
449 *dst = 0; \
450 \
451 /* This checks for overlap after copying, unavoidable without */ \
452 /* pre-counting length... should be ok */ \
453 if (is_overlap(dst_orig, \
454 src_orig, \
455 (Addr)dst-(Addr)dst_orig+1, \
456 (Addr)src-(Addr)src_orig+1)) \
457 complain2("stpcpy", dst_orig, src_orig); \
458 \
459 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000460 }
njn16eeb4e2005-06-16 03:56:58 +0000461
tom8f924092005-10-13 15:51:12 +0000462STPCPY(m_libc_so_star, stpcpy)
tom10e1beb2005-07-21 15:25:04 +0000463STPCPY(m_ld_linux_so_2, stpcpy)
464STPCPY(m_ld_linux_x86_64_so_2, stpcpy)
njn16eeb4e2005-06-16 03:56:58 +0000465
466
467#define MEMSET(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000468 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \
469 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000470 { \
471 unsigned char *cp = s; \
472 \
473 while(n--) \
474 *cp++ = c; \
475 \
476 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000477 }
njn16eeb4e2005-06-16 03:56:58 +0000478
tom8f924092005-10-13 15:51:12 +0000479MEMSET(m_libc_so_star, memset)
njn16eeb4e2005-06-16 03:56:58 +0000480
481
482#define MEMMOVE(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000483 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
484 (void *dstV, const void *srcV, SizeT n); \
485 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
486 (void *dstV, const void *srcV, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000487 { \
488 SizeT i; \
489 Char* dst = (Char*)dstV; \
490 Char* src = (Char*)srcV; \
491 if (dst < src) { \
492 for (i = 0; i < n; i++) \
493 dst[i] = src[i]; \
494 } \
495 else \
496 if (dst > src) { \
497 for (i = 0; i < n; i++) \
498 dst[n-i-1] = src[n-i-1]; \
499 } \
500 return dst; \
501 }
502
tom8f924092005-10-13 15:51:12 +0000503MEMMOVE(m_libc_so_star, memmove)
sewardj44e495f2005-05-12 17:58:28 +0000504
jseward0845ef82003-12-22 22:31:27 +0000505
sewardj4e9a4b62004-11-23 00:20:17 +0000506/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000507#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000508 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
509 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000510 { \
511 unsigned char c = (unsigned char) c_in; \
512 unsigned char* char_ptr = (unsigned char *)s; \
513 while (1) { \
514 if (*char_ptr == 0) return char_ptr; \
515 if (*char_ptr == c) return char_ptr; \
516 char_ptr++; \
517 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000518 }
njn16eeb4e2005-06-16 03:56:58 +0000519
tom8f924092005-10-13 15:51:12 +0000520GLIBC232_STRCHRNUL(m_libc_so_star, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000521
522
523/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000524#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000525 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
526 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000527 { \
528 unsigned char c = (unsigned char) c_in; \
529 unsigned char* char_ptr = (unsigned char *)s; \
530 while (1) { \
531 if (*char_ptr == c) return char_ptr; \
532 char_ptr++; \
533 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000534 }
njn16eeb4e2005-06-16 03:56:58 +0000535
tom8f924092005-10-13 15:51:12 +0000536GLIBC232_RAWMEMCHR(m_libc_so_star, rawmemchr)
sewardj4e9a4b62004-11-23 00:20:17 +0000537
538
njn3e884182003-04-15 13:03:23 +0000539/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +0000540/*--- end ---*/
njn3e884182003-04-15 13:03:23 +0000541/*--------------------------------------------------------------------*/