blob: 558282813529d4a9dce8e07b1fe4396e3aa65a22 [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
njn53612422005-03-12 16:22:54 +000012 Copyright (C) 2000-2005 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
njn46275862005-03-24 04:00:03 +0000124
njn16eeb4e2005-06-16 03:56:58 +0000125
126#define STRRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000127 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
128 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000129 { \
130 UChar ch = (UChar)((UInt)c); \
131 UChar* p = (UChar*)s; \
132 UChar* last = NULL; \
133 while (True) { \
134 if (*p == ch) last = p; \
135 if (*p == 0) return last; \
136 p++; \
137 } \
njn3e884182003-04-15 13:03:23 +0000138 }
njn3e884182003-04-15 13:03:23 +0000139
njn16eeb4e2005-06-16 03:56:58 +0000140// Apparently rindex() is the same thing as strrchr()
tom8f924092005-10-13 15:51:12 +0000141STRRCHR(m_libc_so_star, strrchr)
142STRRCHR(m_libc_so_star, rindex)
njn16eeb4e2005-06-16 03:56:58 +0000143STRRCHR(m_ld_linux_so_2, rindex)
144
145
146#define STRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000147 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
148 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000149 { \
150 UChar ch = (UChar)((UInt)c); \
151 UChar* p = (UChar*)s; \
152 while (True) { \
153 if (*p == ch) return p; \
154 if (*p == 0) return NULL; \
155 p++; \
156 } \
njn3e884182003-04-15 13:03:23 +0000157 }
njn3e884182003-04-15 13:03:23 +0000158
njn16eeb4e2005-06-16 03:56:58 +0000159// Apparently index() is the same thing as strchr()
tom8f924092005-10-13 15:51:12 +0000160STRCHR(m_libc_so_star, strchr)
njn16eeb4e2005-06-16 03:56:58 +0000161STRCHR(m_ld_linux_so_2, strchr)
tom10e1beb2005-07-21 15:25:04 +0000162STRCHR(m_ld_linux_x86_64_so_2, strchr)
tom8f924092005-10-13 15:51:12 +0000163STRCHR(m_libc_so_star, index)
njn16eeb4e2005-06-16 03:56:58 +0000164STRCHR(m_ld_linux_so_2, index)
165STRCHR(m_ld_linux_x86_64_so_2, index)
njn3e884182003-04-15 13:03:23 +0000166
njn3e884182003-04-15 13:03:23 +0000167
njn16eeb4e2005-06-16 03:56:58 +0000168#define STRCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000169 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
170 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000171 { \
172 const Char* src_orig = src; \
173 Char* dst_orig = dst; \
174 while (*dst) dst++; \
175 while (*src) *dst++ = *src++; \
176 *dst = 0; \
177 \
178 /* This is a bit redundant, I think; any overlap and the strcat will */ \
179 /* go forever... or until a seg fault occurs. */ \
180 if (is_overlap(dst_orig, \
181 src_orig, \
182 (Addr)dst-(Addr)dst_orig+1, \
183 (Addr)src-(Addr)src_orig+1)) \
184 complain2("strcat", dst_orig, src_orig); \
185 \
186 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000187 }
njn3e884182003-04-15 13:03:23 +0000188
tom8f924092005-10-13 15:51:12 +0000189STRCAT(m_libc_so_star, strcat)
njn16eeb4e2005-06-16 03:56:58 +0000190
191
192#define STRNCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000193 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
194 ( char* dst, const char* src, SizeT n ); \
195 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
196 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000197 { \
198 const Char* src_orig = src; \
199 Char* dst_orig = dst; \
200 SizeT m = 0; \
201 \
202 while (*dst) dst++; \
203 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
204 *dst = 0; /* always add null */ \
205 \
206 /* This checks for overlap after copying, unavoidable without */ \
207 /* pre-counting lengths... should be ok */ \
208 if (is_overlap(dst_orig, \
209 src_orig, \
210 (Addr)dst-(Addr)dst_orig+1, \
211 (Addr)src-(Addr)src_orig+1)) \
212 complain3("strncat", dst_orig, src_orig, n); \
213 \
214 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000215 }
njn3e884182003-04-15 13:03:23 +0000216
tom8f924092005-10-13 15:51:12 +0000217STRNCAT(m_libc_so_star, strncat)
njn16eeb4e2005-06-16 03:56:58 +0000218
njn3e884182003-04-15 13:03:23 +0000219
njn16eeb4e2005-06-16 03:56:58 +0000220#define STRNLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000221 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
222 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000223 { \
224 SizeT i = 0; \
225 while (i < n && str[i] != 0) i++; \
226 return i; \
njn3e884182003-04-15 13:03:23 +0000227 }
njn3e884182003-04-15 13:03:23 +0000228
tom8f924092005-10-13 15:51:12 +0000229STRNLEN(m_libc_so_star, strnlen)
njn16eeb4e2005-06-16 03:56:58 +0000230
sewardj3ceec242003-07-30 21:24:25 +0000231
njn5ec15ed2005-08-24 19:55:51 +0000232// Note that this replacement often doesn't get used because gcc inlines
233// calls to strlen() with its own built-in version. This can be very
234// confusing if you aren't expecting it. Other small functions in this file
235// may also be inline by gcc.
njn16eeb4e2005-06-16 03:56:58 +0000236#define STRLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000237 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
238 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000239 { \
240 SizeT i = 0; \
241 while (str[i] != 0) i++; \
242 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000243 }
njn16eeb4e2005-06-16 03:56:58 +0000244
tom8f924092005-10-13 15:51:12 +0000245STRLEN(m_libc_so_star, strlen)
njn16eeb4e2005-06-16 03:56:58 +0000246STRLEN(m_ld_linux_so_2, strlen)
247STRLEN(m_ld_linux_x86_64_so_2, strlen)
248
249
250#define STRCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000251 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
252 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000253 { \
254 const Char* src_orig = src; \
255 Char* dst_orig = dst; \
256 \
257 while (*src) *dst++ = *src++; \
258 *dst = 0; \
259 \
260 /* This checks for overlap after copying, unavoidable without */ \
261 /* pre-counting length... should be ok */ \
262 if (is_overlap(dst_orig, \
263 src_orig, \
264 (Addr)dst-(Addr)dst_orig+1, \
265 (Addr)src-(Addr)src_orig+1)) \
266 complain2("strcpy", dst_orig, src_orig); \
267 \
268 return dst_orig; \
269 }
270
tom8f924092005-10-13 15:51:12 +0000271STRCPY(m_libc_so_star, strcpy)
njn16eeb4e2005-06-16 03:56:58 +0000272
273
274#define STRNCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000275 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
276 ( char* dst, const char* src, SizeT n ); \
277 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
278 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000279 { \
280 const Char* src_orig = src; \
281 Char* dst_orig = dst; \
282 SizeT m = 0; \
283 \
284 while (m < n && *src) { m++; *dst++ = *src++; } \
285 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
286 /* but only m+1 bytes of src if terminator was found */ \
287 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
288 complain3("strncpy", dst, src, n); \
289 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
290 \
291 return dst_orig; \
292 }
293
tom8f924092005-10-13 15:51:12 +0000294STRNCPY(m_libc_so_star, strncpy)
njn16eeb4e2005-06-16 03:56:58 +0000295
296
297#define STRNCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000298 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
299 ( const char* s1, const char* s2, SizeT nmax ); \
300 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
301 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000302 { \
303 SizeT n = 0; \
304 while (True) { \
305 if (n >= nmax) return 0; \
306 if (*s1 == 0 && *s2 == 0) return 0; \
307 if (*s1 == 0) return -1; \
308 if (*s2 == 0) return 1; \
309 \
310 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
311 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
312 \
313 s1++; s2++; n++; \
314 } \
315 }
316
tom8f924092005-10-13 15:51:12 +0000317STRNCMP(m_libc_so_star, strncmp)
njn16eeb4e2005-06-16 03:56:58 +0000318
319
320#define STRCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000321 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
322 ( const char* s1, const char* s2 ); \
323 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
324 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000325 { \
326 register unsigned char c1; \
327 register unsigned char c2; \
328 while (True) { \
329 c1 = *(unsigned char *)s1; \
330 c2 = *(unsigned char *)s2; \
331 if (c1 != c2) break; \
332 if (c1 == 0) break; \
333 s1++; s2++; \
334 } \
335 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
336 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
337 return 0; \
338 }
339
tom8f924092005-10-13 15:51:12 +0000340STRCMP(m_libc_so_star, strcmp)
njn16eeb4e2005-06-16 03:56:58 +0000341STRCMP(m_ld_linux_x86_64_so_2, strcmp)
sewardj776de2c2006-02-14 21:55:11 +0000342STRCMP(m_ld64_so_1, strcmp)
njn16eeb4e2005-06-16 03:56:58 +0000343
344
345#define MEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000346 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
347 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000348 { \
349 SizeT i; \
350 UChar c0 = (UChar)c; \
351 UChar* p = (UChar*)s; \
352 for (i = 0; i < n; i++) \
353 if (p[i] == c0) return (void*)(&p[i]); \
354 return NULL; \
355 }
356
tom8f924092005-10-13 15:51:12 +0000357MEMCHR(m_libc_so_star, memchr)
njn16eeb4e2005-06-16 03:56:58 +0000358
359
360#define MEMCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000361 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
362 ( void *dst, const void *src, SizeT len ); \
363 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
364 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000365 { \
366 register char *d; \
367 register char *s; \
368 \
369 if (len == 0) \
370 return dst; \
371 \
372 if (is_overlap(dst, src, len, len)) \
373 complain3("memcpy", dst, src, len); \
374 \
375 if ( dst > src ) { \
376 d = (char *)dst + len - 1; \
377 s = (char *)src + len - 1; \
378 while ( len >= 4 ) { \
379 *d-- = *s--; \
380 *d-- = *s--; \
381 *d-- = *s--; \
382 *d-- = *s--; \
383 len -= 4; \
384 } \
385 while ( len-- ) { \
386 *d-- = *s--; \
387 } \
388 } else if ( dst < src ) { \
389 d = (char *)dst; \
390 s = (char *)src; \
391 while ( len >= 4 ) { \
392 *d++ = *s++; \
393 *d++ = *s++; \
394 *d++ = *s++; \
395 *d++ = *s++; \
396 len -= 4; \
397 } \
398 while ( len-- ) { \
399 *d++ = *s++; \
400 } \
401 } \
402 return dst; \
403 }
404
tom8f924092005-10-13 15:51:12 +0000405MEMCPY(m_libc_so_star, memcpy)
njn16eeb4e2005-06-16 03:56:58 +0000406
407
408#define MEMCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000409 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
410 ( const void *s1V, const void *s2V, SizeT n ); \
411 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
412 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000413 { \
414 int res; \
415 unsigned char a0; \
416 unsigned char b0; \
417 unsigned char* s1 = (unsigned char*)s1V; \
418 unsigned char* s2 = (unsigned char*)s2V; \
419 \
420 while (n != 0) { \
421 a0 = s1[0]; \
422 b0 = s2[0]; \
423 s1 += 1; \
424 s2 += 1; \
425 res = ((int)a0) - ((int)b0); \
426 if (res != 0) \
427 return res; \
428 n -= 1; \
429 } \
430 return 0; \
431 }
432
tom8f924092005-10-13 15:51:12 +0000433MEMCMP(m_libc_so_star, memcmp)
434MEMCMP(m_libc_so_star, bcmp)
njn3e884182003-04-15 13:03:23 +0000435
jseward0845ef82003-12-22 22:31:27 +0000436
437/* Copy SRC to DEST, returning the address of the terminating '\0' in
438 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000439#define STPCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000440 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
441 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000442 { \
443 const Char* src_orig = src; \
444 Char* dst_orig = dst; \
445 \
446 while (*src) *dst++ = *src++; \
447 *dst = 0; \
448 \
449 /* This checks for overlap after copying, unavoidable without */ \
450 /* pre-counting length... should be ok */ \
451 if (is_overlap(dst_orig, \
452 src_orig, \
453 (Addr)dst-(Addr)dst_orig+1, \
454 (Addr)src-(Addr)src_orig+1)) \
455 complain2("stpcpy", dst_orig, src_orig); \
456 \
457 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000458 }
njn16eeb4e2005-06-16 03:56:58 +0000459
tom8f924092005-10-13 15:51:12 +0000460STPCPY(m_libc_so_star, stpcpy)
tom10e1beb2005-07-21 15:25:04 +0000461STPCPY(m_ld_linux_so_2, stpcpy)
462STPCPY(m_ld_linux_x86_64_so_2, stpcpy)
njn16eeb4e2005-06-16 03:56:58 +0000463
464
465#define MEMSET(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000466 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \
467 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000468 { \
469 unsigned char *cp = s; \
470 \
471 while(n--) \
472 *cp++ = c; \
473 \
474 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000475 }
njn16eeb4e2005-06-16 03:56:58 +0000476
tom8f924092005-10-13 15:51:12 +0000477MEMSET(m_libc_so_star, memset)
njn16eeb4e2005-06-16 03:56:58 +0000478
479
480#define MEMMOVE(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000481 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
482 (void *dstV, const void *srcV, SizeT n); \
483 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
484 (void *dstV, const void *srcV, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000485 { \
486 SizeT i; \
487 Char* dst = (Char*)dstV; \
488 Char* src = (Char*)srcV; \
489 if (dst < src) { \
490 for (i = 0; i < n; i++) \
491 dst[i] = src[i]; \
492 } \
493 else \
494 if (dst > src) { \
495 for (i = 0; i < n; i++) \
496 dst[n-i-1] = src[n-i-1]; \
497 } \
498 return dst; \
499 }
500
tom8f924092005-10-13 15:51:12 +0000501MEMMOVE(m_libc_so_star, memmove)
sewardj44e495f2005-05-12 17:58:28 +0000502
jseward0845ef82003-12-22 22:31:27 +0000503
sewardj4e9a4b62004-11-23 00:20:17 +0000504/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000505#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000506 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
507 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000508 { \
509 unsigned char c = (unsigned char) c_in; \
510 unsigned char* char_ptr = (unsigned char *)s; \
511 while (1) { \
512 if (*char_ptr == 0) return char_ptr; \
513 if (*char_ptr == c) return char_ptr; \
514 char_ptr++; \
515 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000516 }
njn16eeb4e2005-06-16 03:56:58 +0000517
tom8f924092005-10-13 15:51:12 +0000518GLIBC232_STRCHRNUL(m_libc_so_star, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000519
520
521/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000522#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000523 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
524 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000525 { \
526 unsigned char c = (unsigned char) c_in; \
527 unsigned char* char_ptr = (unsigned char *)s; \
528 while (1) { \
529 if (*char_ptr == c) return char_ptr; \
530 char_ptr++; \
531 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000532 }
njn16eeb4e2005-06-16 03:56:58 +0000533
tom8f924092005-10-13 15:51:12 +0000534GLIBC232_RAWMEMCHR(m_libc_so_star, rawmemchr)
sewardj4e9a4b62004-11-23 00:20:17 +0000535
536
njn3e884182003-04-15 13:03:23 +0000537/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +0000538/*--- end ---*/
njn3e884182003-04-15 13:03:23 +0000539/*--------------------------------------------------------------------*/