blob: 782e492f352b6cdda7f81680f62ecc292bbd6f71 [file] [log] [blame]
njn3e884182003-04-15 13:03:23 +00001
2/*--------------------------------------------------------------------*/
3/*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/
4/*--- simulated CPU. ---*/
njn1d0825f2006-03-27 11:37:07 +00005/*--- mc_replace_strmem.c ---*/
njn3e884182003-04-15 13:03:23 +00006/*--------------------------------------------------------------------*/
7
8/*
nethercote137bc552003-11-14 17:47:54 +00009 This file is part of MemCheck, a heavyweight Valgrind tool for
njn0e1b5142003-04-15 14:58:06 +000010 detecting memory errors.
njn3e884182003-04-15 13:03:23 +000011
sewardj9eecbbb2010-05-03 21:37:12 +000012 Copyright (C) 2000-2010 Julian Seward
njn3e884182003-04-15 13:03:23 +000013 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
njnc7561b92005-06-19 01:24:32 +000033#include "pub_tool_basics.h"
njnc7561b92005-06-19 01:24:32 +000034#include "pub_tool_hashtable.h"
njnc7561b92005-06-19 01:24:32 +000035#include "pub_tool_redir.h"
36#include "pub_tool_tooliface.h"
37#include "valgrind.h"
38
njn34419c12003-05-02 17:24:29 +000039#include "mc_include.h"
fitzhardinge98abfc72003-12-16 02:05:15 +000040#include "memcheck.h"
njn3e884182003-04-15 13:03:23 +000041
njn3e884182003-04-15 13:03:23 +000042/* ---------------------------------------------------------------------
njn1f8b3e72005-03-22 04:27:14 +000043 We have our own versions of these functions for two reasons:
44 (a) it allows us to do overlap checking
45 (b) some of the normal versions are hyper-optimised, which fools
46 Memcheck and cause spurious value warnings. Our versions are
47 simpler.
48
njn16eeb4e2005-06-16 03:56:58 +000049 Note that overenthusiastic use of PLT bypassing by the glibc people also
50 means that we need to patch multiple versions of some of the functions to
51 our own implementations.
52
njn1f8b3e72005-03-22 04:27:14 +000053 THEY RUN ON THE SIMD CPU!
njn3e884182003-04-15 13:03:23 +000054 ------------------------------------------------------------------ */
55
sewardj126e82d2011-07-12 13:33:00 +000056
sewardjdda830a2003-07-20 22:28:42 +000057/* Figure out if [dst .. dst+dstlen-1] overlaps with
58 [src .. src+srclen-1].
59 We assume that the address ranges do not wrap around
60 (which is safe since on Linux addresses >= 0xC0000000
61 are not accessible and the program will segfault in this
62 circumstance, presumably).
63*/
sewardj126e82d2011-07-12 13:33:00 +000064static inline
njnc6168192004-11-29 13:54:10 +000065Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
njn3e884182003-04-15 13:03:23 +000066{
sewardjdda830a2003-07-20 22:28:42 +000067 Addr loS, hiS, loD, hiD;
68
69 if (dstlen == 0 || srclen == 0)
70 return False;
71
72 loS = (Addr)src;
73 loD = (Addr)dst;
74 hiS = loS + srclen - 1;
75 hiD = loD + dstlen - 1;
76
77 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
78 if (loS < loD) {
79 return !(hiS < loD);
80 }
81 else if (loD < loS) {
82 return !(hiD < loS);
83 }
84 else {
85 /* They start at same place. Since we know neither of them has
86 zero length, they must overlap. */
87 return True;
88 }
njn3e884182003-04-15 13:03:23 +000089}
90
sewardj126e82d2011-07-12 13:33:00 +000091
92/* Call here to exit if we can't continue. On Android we can't call
93 _exit for some reason, so we have to blunt-instrument it. */
94__attribute__ ((__noreturn__))
95static inline void my_exit ( int x )
96{
97# if defined(VGPV_arm_linux_android)
98 __asm__ __volatile__(".word 0xFFFFFFFF");
99 while (1) {}
100# else
101 extern void _exit(int status);
sewardj49665422011-07-12 13:50:59 +0000102 _exit(x);
sewardj126e82d2011-07-12 13:33:00 +0000103# endif
104}
105
106
njn1f8b3e72005-03-22 04:27:14 +0000107// This is a macro rather than a function because we don't want to have an
108// extra function in the stack trace.
bart575ce8e2011-05-15 07:04:03 +0000109#define RECORD_OVERLAP_ERROR(s, src, dst, len) \
110 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
111 _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \
112 s, src, dst, len, 0)
njn3e884182003-04-15 13:03:23 +0000113
njn16eeb4e2005-06-16 03:56:58 +0000114
115#define STRRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000116 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
117 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000118 { \
119 UChar ch = (UChar)((UInt)c); \
120 UChar* p = (UChar*)s; \
121 UChar* last = NULL; \
122 while (True) { \
123 if (*p == ch) last = p; \
124 if (*p == 0) return last; \
125 p++; \
126 } \
njn3e884182003-04-15 13:03:23 +0000127 }
njn3e884182003-04-15 13:03:23 +0000128
njn16eeb4e2005-06-16 03:56:58 +0000129// Apparently rindex() is the same thing as strrchr()
njne6154662009-02-10 04:23:41 +0000130STRRCHR(VG_Z_LIBC_SONAME, strrchr)
131STRRCHR(VG_Z_LIBC_SONAME, rindex)
njnb4cfbc42009-05-04 04:20:02 +0000132#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000133STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
njne6154662009-02-10 04:23:41 +0000134STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
njnf76d27a2009-05-28 01:53:07 +0000135#elif defined(VGO_darwin)
136STRRCHR(VG_Z_DYLD, strrchr)
137STRRCHR(VG_Z_DYLD, rindex)
njnb4cfbc42009-05-04 04:20:02 +0000138#endif
njn16eeb4e2005-06-16 03:56:58 +0000139
140
141#define STRCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000142 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
143 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000144 { \
145 UChar ch = (UChar)((UInt)c); \
146 UChar* p = (UChar*)s; \
147 while (True) { \
148 if (*p == ch) return p; \
149 if (*p == 0) return NULL; \
150 p++; \
151 } \
njn3e884182003-04-15 13:03:23 +0000152 }
njn3e884182003-04-15 13:03:23 +0000153
njn16eeb4e2005-06-16 03:56:58 +0000154// Apparently index() is the same thing as strchr()
njne6154662009-02-10 04:23:41 +0000155STRCHR(VG_Z_LIBC_SONAME, strchr)
njne6154662009-02-10 04:23:41 +0000156STRCHR(VG_Z_LIBC_SONAME, index)
njnb4cfbc42009-05-04 04:20:02 +0000157#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000158STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
njnb4cfbc42009-05-04 04:20:02 +0000159STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
njne6154662009-02-10 04:23:41 +0000160STRCHR(VG_Z_LD_LINUX_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +0000161STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
njne6154662009-02-10 04:23:41 +0000162STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
njnf76d27a2009-05-28 01:53:07 +0000163#elif defined(VGO_darwin)
164STRCHR(VG_Z_DYLD, strchr)
165STRCHR(VG_Z_DYLD, index)
njnb4cfbc42009-05-04 04:20:02 +0000166#endif
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; \
sewardjb6c04032007-11-13 20:52:29 +0000178 \
njn16eeb4e2005-06-16 03:56:58 +0000179 /* 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)) \
njn718d3b12006-12-16 00:54:12 +0000185 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000186 \
njn16eeb4e2005-06-16 03:56:58 +0000187 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000188 }
njn3e884182003-04-15 13:03:23 +0000189
njne6154662009-02-10 04:23:41 +0000190STRCAT(VG_Z_LIBC_SONAME, strcat)
tomd2645142009-10-29 09:27:11 +0000191#if defined(VGO_linux)
192STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
193#endif
njn16eeb4e2005-06-16 03:56:58 +0000194
195#define STRNCAT(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000196 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
197 ( char* dst, const char* src, SizeT n ); \
198 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
199 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000200 { \
201 const Char* src_orig = src; \
202 Char* dst_orig = dst; \
203 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000204 \
njn16eeb4e2005-06-16 03:56:58 +0000205 while (*dst) dst++; \
206 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
207 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000208 \
njn16eeb4e2005-06-16 03:56:58 +0000209 /* This checks for overlap after copying, unavoidable without */ \
210 /* pre-counting lengths... should be ok */ \
211 if (is_overlap(dst_orig, \
212 src_orig, \
213 (Addr)dst-(Addr)dst_orig+1, \
214 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000215 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000216 \
njn16eeb4e2005-06-16 03:56:58 +0000217 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000218 }
njn3e884182003-04-15 13:03:23 +0000219
njne6154662009-02-10 04:23:41 +0000220STRNCAT(VG_Z_LIBC_SONAME, strncat)
njnf76d27a2009-05-28 01:53:07 +0000221#if defined(VGO_darwin)
222STRNCAT(VG_Z_DYLD, strncat)
223#endif
224
225
226/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
227 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
228 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
229 Truncation occurred if retval >= n.
230*/
231#define STRLCAT(soname, fnname) \
232 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
233 ( char* dst, const char* src, SizeT n ); \
234 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
235 ( char* dst, const char* src, SizeT n ) \
236 { \
237 const Char* src_orig = src; \
238 Char* dst_orig = dst; \
239 SizeT m = 0; \
240\
241 while (m < n && *dst) { m++; dst++; } \
242 if (m < n) { \
243 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
244 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
245 *dst = 0; \
246 } else { \
247 /* No space to copy anything to dst. m == n */ \
248 } \
249 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
250 while (*src) { m++; src++; } \
251 /* This checks for overlap after copying, unavoidable without */ \
252 /* pre-counting lengths... should be ok */ \
253 if (is_overlap(dst_orig, \
254 src_orig, \
255 (Addr)dst-(Addr)dst_orig+1, \
256 (Addr)src-(Addr)src_orig+1)) \
257 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
258\
259 return m; \
260 }
261
262#if defined(VGO_darwin)
263STRLCAT(VG_Z_LIBC_SONAME, strlcat)
264STRLCAT(VG_Z_DYLD, strlcat)
265#endif
sewardj31b9ce12006-10-17 01:27:13 +0000266
njn3e884182003-04-15 13:03:23 +0000267
njn16eeb4e2005-06-16 03:56:58 +0000268#define STRNLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000269 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
270 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000271 { \
272 SizeT i = 0; \
273 while (i < n && str[i] != 0) i++; \
274 return i; \
njn3e884182003-04-15 13:03:23 +0000275 }
njn3e884182003-04-15 13:03:23 +0000276
njne6154662009-02-10 04:23:41 +0000277STRNLEN(VG_Z_LIBC_SONAME, strnlen)
tomd2645142009-10-29 09:27:11 +0000278#if defined(VGO_linux)
279STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
280#endif
njn16eeb4e2005-06-16 03:56:58 +0000281
sewardj3ceec242003-07-30 21:24:25 +0000282
njn5ec15ed2005-08-24 19:55:51 +0000283// Note that this replacement often doesn't get used because gcc inlines
284// calls to strlen() with its own built-in version. This can be very
285// confusing if you aren't expecting it. Other small functions in this file
286// may also be inline by gcc.
njn16eeb4e2005-06-16 03:56:58 +0000287#define STRLEN(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000288 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
289 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000290 { \
291 SizeT i = 0; \
292 while (str[i] != 0) i++; \
293 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000294 }
njn16eeb4e2005-06-16 03:56:58 +0000295
njnb4cfbc42009-05-04 04:20:02 +0000296STRLEN(VG_Z_LIBC_SONAME, strlen)
297#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000298STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
njne6154662009-02-10 04:23:41 +0000299STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
300STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000301#endif
sewardj31b9ce12006-10-17 01:27:13 +0000302
njn16eeb4e2005-06-16 03:56:58 +0000303
304#define STRCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000305 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
306 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000307 { \
308 const Char* src_orig = src; \
309 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000310 \
njn16eeb4e2005-06-16 03:56:58 +0000311 while (*src) *dst++ = *src++; \
312 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000313 \
njn16eeb4e2005-06-16 03:56:58 +0000314 /* This checks for overlap after copying, unavoidable without */ \
315 /* pre-counting length... should be ok */ \
316 if (is_overlap(dst_orig, \
317 src_orig, \
318 (Addr)dst-(Addr)dst_orig+1, \
319 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000320 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000321 \
njn16eeb4e2005-06-16 03:56:58 +0000322 return dst_orig; \
323 }
324
njne6154662009-02-10 04:23:41 +0000325STRCPY(VG_Z_LIBC_SONAME, strcpy)
tomd2645142009-10-29 09:27:11 +0000326#if defined(VGO_linux)
327STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
328#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000329STRCPY(VG_Z_DYLD, strcpy)
330#endif
njn16eeb4e2005-06-16 03:56:58 +0000331
332
333#define STRNCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000334 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
335 ( char* dst, const char* src, SizeT n ); \
336 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \
337 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000338 { \
339 const Char* src_orig = src; \
340 Char* dst_orig = dst; \
341 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000342 \
njn16eeb4e2005-06-16 03:56:58 +0000343 while (m < n && *src) { m++; *dst++ = *src++; } \
344 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
345 /* but only m+1 bytes of src if terminator was found */ \
346 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000347 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000348 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
349 \
350 return dst_orig; \
351 }
352
njne6154662009-02-10 04:23:41 +0000353STRNCPY(VG_Z_LIBC_SONAME, strncpy)
tomd2645142009-10-29 09:27:11 +0000354#if defined(VGO_linux)
355STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
356#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000357STRNCPY(VG_Z_DYLD, strncpy)
358#endif
359
360
361/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
362 Returns strlen(src). Does not zero-fill the remainder of dst. */
363#define STRLCPY(soname, fnname) \
364 SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \
365 ( char* dst, const char* src, SizeT n ); \
366 SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \
367 ( char* dst, const char* src, SizeT n ) \
368 { \
369 const char* src_orig = src; \
370 char* dst_orig = dst; \
371 SizeT m = 0; \
372\
373 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
374 /* m non-nul bytes have now been copied, and m <= n-1. */ \
375 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
376 /* but only m+1 bytes of src if terminator was found */ \
377 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
378 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
379 /* Nul-terminate dst. */ \
380 if (n > 0) *dst = 0; \
381 /* Finish counting strlen(src). */ \
382 while (*src) src++; \
383 return src - src_orig; \
384 }
385
386#if defined(VGO_darwin)
387STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
388STRLCPY(VG_Z_DYLD, strlcpy)
389#endif
njn16eeb4e2005-06-16 03:56:58 +0000390
391
392#define STRNCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000393 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
394 ( const char* s1, const char* s2, SizeT nmax ); \
395 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
396 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000397 { \
398 SizeT n = 0; \
399 while (True) { \
400 if (n >= nmax) return 0; \
401 if (*s1 == 0 && *s2 == 0) return 0; \
402 if (*s1 == 0) return -1; \
403 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000404 \
njn16eeb4e2005-06-16 03:56:58 +0000405 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
406 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000407 \
njn16eeb4e2005-06-16 03:56:58 +0000408 s1++; s2++; n++; \
409 } \
410 }
411
njne6154662009-02-10 04:23:41 +0000412STRNCMP(VG_Z_LIBC_SONAME, strncmp)
tomd2645142009-10-29 09:27:11 +0000413#if defined(VGO_linux)
414STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
415#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000416STRNCMP(VG_Z_DYLD, strncmp)
417#endif
njn16eeb4e2005-06-16 03:56:58 +0000418
419
tomce6d0ac2010-11-12 10:03:13 +0000420#define STRCASECMP(soname, fnname) \
421 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
422 ( const char* s1, const char* s2 ); \
423 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
424 ( const char* s1, const char* s2 ) \
425 { \
tome03c8c42010-11-12 10:40:20 +0000426 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000427 register unsigned char c1; \
428 register unsigned char c2; \
429 while (True) { \
430 c1 = tolower(*(unsigned char *)s1); \
431 c2 = tolower(*(unsigned char *)s2); \
432 if (c1 != c2) break; \
433 if (c1 == 0) break; \
434 s1++; s2++; \
435 } \
436 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
437 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
438 return 0; \
439 }
440
sewardj126e82d2011-07-12 13:33:00 +0000441#if !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000442STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
sewardj126e82d2011-07-12 13:33:00 +0000443#endif
444#if defined(VGO_linux) && !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000445STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
446#endif
447
448
449#define STRNCASECMP(soname, fnname) \
450 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
451 ( const char* s1, const char* s2, SizeT nmax ); \
452 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
453 ( const char* s1, const char* s2, SizeT nmax ) \
454 { \
tome03c8c42010-11-12 10:40:20 +0000455 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000456 SizeT n = 0; \
457 while (True) { \
458 if (n >= nmax) return 0; \
459 if (*s1 == 0 && *s2 == 0) return 0; \
460 if (*s1 == 0) return -1; \
461 if (*s2 == 0) return 1; \
462 \
463 if (tolower(*(unsigned char*)s1) < tolower(*(unsigned char*)s2)) return -1; \
464 if (tolower(*(unsigned char*)s1) > tolower(*(unsigned char*)s2)) return 1; \
465 \
466 s1++; s2++; n++; \
467 } \
468 }
469
sewardj126e82d2011-07-12 13:33:00 +0000470#if !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000471STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
sewardj126e82d2011-07-12 13:33:00 +0000472#endif
473#if defined(VGO_linux) && !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000474STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
475#elif defined(VGO_darwin)
476STRNCASECMP(VG_Z_DYLD, strncasecmp)
477#endif
478
479
tomce6d0ac2010-11-12 10:03:13 +0000480#define STRCASECMP_L(soname, fnname) \
481 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000482 ( const char* s1, const char* s2, void* locale ); \
tomce6d0ac2010-11-12 10:03:13 +0000483 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000484 ( const char* s1, const char* s2, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000485 { \
tome03c8c42010-11-12 10:40:20 +0000486 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000487 register unsigned char c1; \
488 register unsigned char c2; \
489 while (True) { \
490 c1 = tolower_l(*(unsigned char *)s1, locale); \
491 c2 = tolower_l(*(unsigned char *)s2, locale); \
492 if (c1 != c2) break; \
493 if (c1 == 0) break; \
494 s1++; s2++; \
495 } \
496 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
497 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
498 return 0; \
499 }
500
501STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
502#if defined(VGO_linux)
503STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
504#endif
505
506
507#define STRNCASECMP_L(soname, fnname) \
508 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000509 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
tomce6d0ac2010-11-12 10:03:13 +0000510 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000511 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000512 { \
tome03c8c42010-11-12 10:40:20 +0000513 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000514 SizeT n = 0; \
515 while (True) { \
516 if (n >= nmax) return 0; \
517 if (*s1 == 0 && *s2 == 0) return 0; \
518 if (*s1 == 0) return -1; \
519 if (*s2 == 0) return 1; \
520 \
521 if (tolower_l(*(unsigned char*)s1, locale) < tolower_l(*(unsigned char*)s2, locale)) return -1; \
522 if (tolower_l(*(unsigned char*)s1, locale) > tolower_l(*(unsigned char*)s2, locale)) return 1; \
523 \
524 s1++; s2++; n++; \
525 } \
526 }
527
528STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
529#if defined(VGO_linux)
530STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
531#elif defined(VGO_darwin)
532STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
533#endif
534
535
njn16eeb4e2005-06-16 03:56:58 +0000536#define STRCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000537 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
538 ( const char* s1, const char* s2 ); \
539 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
540 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000541 { \
542 register unsigned char c1; \
543 register unsigned char c2; \
544 while (True) { \
545 c1 = *(unsigned char *)s1; \
546 c2 = *(unsigned char *)s2; \
547 if (c1 != c2) break; \
548 if (c1 == 0) break; \
549 s1++; s2++; \
550 } \
551 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
552 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
553 return 0; \
554 }
555
njne6154662009-02-10 04:23:41 +0000556STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000557#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000558STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
njne6154662009-02-10 04:23:41 +0000559STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
560STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000561#endif
njn16eeb4e2005-06-16 03:56:58 +0000562
563
564#define MEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000565 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
566 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000567 { \
568 SizeT i; \
569 UChar c0 = (UChar)c; \
570 UChar* p = (UChar*)s; \
571 for (i = 0; i < n; i++) \
572 if (p[i] == c0) return (void*)(&p[i]); \
573 return NULL; \
574 }
575
njne6154662009-02-10 04:23:41 +0000576MEMCHR(VG_Z_LIBC_SONAME, memchr)
njnf76d27a2009-05-28 01:53:07 +0000577#if defined(VGO_darwin)
578MEMCHR(VG_Z_DYLD, memchr)
579#endif
njn16eeb4e2005-06-16 03:56:58 +0000580
581
582#define MEMCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000583 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
584 ( void *dst, const void *src, SizeT len ); \
585 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
586 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000587 { \
njn16eeb4e2005-06-16 03:56:58 +0000588 if (is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000589 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000590 \
sewardj7b4e00b2010-08-24 09:05:52 +0000591 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
592 const Addr WM = WS - 1; /* 7 or 3 */ \
593 \
594 if (dst < src) { \
595 \
596 /* Copying backwards. */ \
597 SizeT n = len; \
598 Addr d = (Addr)dst; \
599 Addr s = (Addr)src; \
600 \
601 if (((s^d) & WM) == 0) { \
602 /* s and d have same UWord alignment. */ \
603 /* Pull up to a UWord boundary. */ \
604 while ((s & WM) != 0 && n >= 1) \
605 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
606 /* Copy UWords. */ \
607 while (n >= WS) \
608 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
609 if (n == 0) \
610 return dst; \
njn16eeb4e2005-06-16 03:56:58 +0000611 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000612 if (((s|d) & 1) == 0) { \
613 /* Both are 16-aligned; copy what we can thusly. */ \
614 while (n >= 2) \
615 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
njn16eeb4e2005-06-16 03:56:58 +0000616 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000617 /* Copy leftovers, or everything if misaligned. */ \
618 while (n >= 1) \
619 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
620 \
621 } else if (dst > src) { \
622 \
623 SizeT n = len; \
624 Addr d = ((Addr)dst) + n; \
625 Addr s = ((Addr)src) + n; \
626 \
627 /* Copying forwards. */ \
628 if (((s^d) & WM) == 0) { \
629 /* s and d have same UWord alignment. */ \
630 /* Back down to a UWord boundary. */ \
631 while ((s & WM) != 0 && n >= 1) \
632 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
633 /* Copy UWords. */ \
634 while (n >= WS) \
635 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
636 if (n == 0) \
637 return dst; \
njn16eeb4e2005-06-16 03:56:58 +0000638 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000639 if (((s|d) & 1) == 0) { \
640 /* Both are 16-aligned; copy what we can thusly. */ \
641 while (n >= 2) \
642 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
njn16eeb4e2005-06-16 03:56:58 +0000643 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000644 /* Copy leftovers, or everything if misaligned. */ \
645 while (n >= 1) \
646 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
647 \
njn16eeb4e2005-06-16 03:56:58 +0000648 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000649 \
njn16eeb4e2005-06-16 03:56:58 +0000650 return dst; \
651 }
652
njne6154662009-02-10 04:23:41 +0000653MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000654#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000655MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
656MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnf76d27a2009-05-28 01:53:07 +0000657#elif defined(VGO_darwin)
658MEMCPY(VG_Z_DYLD, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000659#endif
sewardjf0b34322007-01-16 21:42:28 +0000660/* icc9 blats these around all over the place. Not only in the main
661 executable but various .so's. They are highly tuned and read
662 memory beyond the source boundary (although work correctly and
663 never go across page boundaries), so give errors when run natively,
664 at least for misaligned source arg. Just intercepting in the exe
665 only until we understand more about the problem. See
666 http://bugs.kde.org/show_bug.cgi?id=139776
667 */
668MEMCPY(NONE, _intel_fast_memcpy)
sewardj31b9ce12006-10-17 01:27:13 +0000669
njn16eeb4e2005-06-16 03:56:58 +0000670
671#define MEMCMP(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000672 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
673 ( const void *s1V, const void *s2V, SizeT n ); \
674 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
675 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000676 { \
677 int res; \
678 unsigned char a0; \
679 unsigned char b0; \
680 unsigned char* s1 = (unsigned char*)s1V; \
681 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000682 \
njn16eeb4e2005-06-16 03:56:58 +0000683 while (n != 0) { \
684 a0 = s1[0]; \
685 b0 = s2[0]; \
686 s1 += 1; \
687 s2 += 1; \
688 res = ((int)a0) - ((int)b0); \
689 if (res != 0) \
690 return res; \
691 n -= 1; \
692 } \
693 return 0; \
694 }
695
njne6154662009-02-10 04:23:41 +0000696MEMCMP(VG_Z_LIBC_SONAME, memcmp)
697MEMCMP(VG_Z_LIBC_SONAME, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000698#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000699MEMCMP(VG_Z_LD_SO_1, bcmp)
njnf76d27a2009-05-28 01:53:07 +0000700#elif defined(VGO_darwin)
701MEMCMP(VG_Z_DYLD, memcmp)
702MEMCMP(VG_Z_DYLD, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000703#endif
njn3e884182003-04-15 13:03:23 +0000704
jseward0845ef82003-12-22 22:31:27 +0000705
706/* Copy SRC to DEST, returning the address of the terminating '\0' in
707 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000708#define STPCPY(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000709 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
710 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000711 { \
712 const Char* src_orig = src; \
713 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000714 \
njn16eeb4e2005-06-16 03:56:58 +0000715 while (*src) *dst++ = *src++; \
716 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000717 \
njn16eeb4e2005-06-16 03:56:58 +0000718 /* This checks for overlap after copying, unavoidable without */ \
719 /* pre-counting length... should be ok */ \
720 if (is_overlap(dst_orig, \
721 src_orig, \
722 (Addr)dst-(Addr)dst_orig+1, \
723 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000724 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000725 \
njn16eeb4e2005-06-16 03:56:58 +0000726 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000727 }
njn16eeb4e2005-06-16 03:56:58 +0000728
njne6154662009-02-10 04:23:41 +0000729STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000730#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000731STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
njne6154662009-02-10 04:23:41 +0000732STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
733STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnf76d27a2009-05-28 01:53:07 +0000734#elif defined(VGO_darwin)
735STPCPY(VG_Z_DYLD, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000736#endif
737
njn16eeb4e2005-06-16 03:56:58 +0000738
739#define MEMSET(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000740 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \
741 void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000742 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000743 Addr a = (Addr)s; \
744 UInt c4 = (c & 0xFF); \
745 c4 = (c4 << 8) | c4; \
746 c4 = (c4 << 16) | c4; \
747 while ((a & 3) != 0 && n >= 1) \
748 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
749 while (n >= 4) \
750 { *(UInt*)a = c4; a += 4; n -= 4; } \
751 while (n >= 1) \
752 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000753 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000754 }
njn16eeb4e2005-06-16 03:56:58 +0000755
njne6154662009-02-10 04:23:41 +0000756MEMSET(VG_Z_LIBC_SONAME, memset)
njnf76d27a2009-05-28 01:53:07 +0000757#if defined(VGO_darwin)
758MEMSET(VG_Z_DYLD, memset)
759#endif
njn16eeb4e2005-06-16 03:56:58 +0000760
761
762#define MEMMOVE(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000763 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
764 (void *dstV, const void *srcV, SizeT n); \
765 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
766 (void *dstV, const void *srcV, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000767 { \
768 SizeT i; \
769 Char* dst = (Char*)dstV; \
770 Char* src = (Char*)srcV; \
771 if (dst < src) { \
772 for (i = 0; i < n; i++) \
773 dst[i] = src[i]; \
774 } \
775 else \
776 if (dst > src) { \
777 for (i = 0; i < n; i++) \
778 dst[n-i-1] = src[n-i-1]; \
779 } \
780 return dst; \
781 }
782
njne6154662009-02-10 04:23:41 +0000783MEMMOVE(VG_Z_LIBC_SONAME, memmove)
njnf76d27a2009-05-28 01:53:07 +0000784#if defined(VGO_darwin)
785MEMMOVE(VG_Z_DYLD, memmove)
786#endif
787
788
789#define BCOPY(soname, fnname) \
790 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
791 (const void *srcV, void *dstV, SizeT n); \
792 void VG_REPLACE_FUNCTION_ZU(soname,fnname) \
793 (const void *srcV, void *dstV, SizeT n) \
794 { \
795 SizeT i; \
796 Char* dst = (Char*)dstV; \
797 Char* src = (Char*)srcV; \
798 if (dst < src) { \
799 for (i = 0; i < n; i++) \
800 dst[i] = src[i]; \
801 } \
802 else \
803 if (dst > src) { \
804 for (i = 0; i < n; i++) \
805 dst[n-i-1] = src[n-i-1]; \
806 } \
807 }
808
809#if defined(VGO_darwin)
810BCOPY(VG_Z_LIBC_SONAME, bcopy)
811BCOPY(VG_Z_DYLD, bcopy)
812#endif
sewardj44e495f2005-05-12 17:58:28 +0000813
jseward0845ef82003-12-22 22:31:27 +0000814
sewardj24cb2172007-02-23 09:03:26 +0000815/* glibc 2.5 variant of memmove which checks the dest is big enough.
816 There is no specific part of glibc that this is copied from. */
817#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
818 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
819 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
820 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
821 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
822 { \
sewardj24cb2172007-02-23 09:03:26 +0000823 SizeT i; \
824 Char* dst = (Char*)dstV; \
825 Char* src = (Char*)srcV; \
826 if (destlen < n) \
827 goto badness; \
828 if (dst < src) { \
829 for (i = 0; i < n; i++) \
830 dst[i] = src[i]; \
831 } \
832 else \
833 if (dst > src) { \
834 for (i = 0; i < n; i++) \
835 dst[n-i-1] = src[n-i-1]; \
836 } \
837 return dst; \
838 badness: \
839 VALGRIND_PRINTF_BACKTRACE( \
840 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000841 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000842 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +0000843 /*NOTREACHED*/ \
844 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +0000845 }
846
njne6154662009-02-10 04:23:41 +0000847GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj24cb2172007-02-23 09:03:26 +0000848
849
sewardj4e9a4b62004-11-23 00:20:17 +0000850/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000851#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000852 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
853 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000854 { \
855 unsigned char c = (unsigned char) c_in; \
856 unsigned char* char_ptr = (unsigned char *)s; \
857 while (1) { \
858 if (*char_ptr == 0) return char_ptr; \
859 if (*char_ptr == c) return char_ptr; \
860 char_ptr++; \
861 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000862 }
njn16eeb4e2005-06-16 03:56:58 +0000863
njne6154662009-02-10 04:23:41 +0000864GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000865
866
867/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000868#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000869 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
870 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000871 { \
872 unsigned char c = (unsigned char) c_in; \
873 unsigned char* char_ptr = (unsigned char *)s; \
874 while (1) { \
875 if (*char_ptr == c) return char_ptr; \
876 char_ptr++; \
877 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000878 }
njn16eeb4e2005-06-16 03:56:58 +0000879
njne6154662009-02-10 04:23:41 +0000880GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
tomd2645142009-10-29 09:27:11 +0000881#if defined (VGO_linux)
882GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
883#endif
sewardj4e9a4b62004-11-23 00:20:17 +0000884
sewardjdc5d8322007-01-28 06:32:01 +0000885/* glibc variant of strcpy that checks the dest is big enough.
886 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +0000887#define GLIBC25___STRCPY_CHK(soname,fnname) \
888 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
889 (char* dst, const char* src, SizeT len); \
890 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
891 (char* dst, const char* src, SizeT len) \
892 { \
sewardj620e5262006-12-31 00:22:30 +0000893 char* ret = dst; \
894 if (! len) \
895 goto badness; \
896 while ((*dst++ = *src++) != '\0') \
897 if (--len == 0) \
898 goto badness; \
899 return ret; \
900 badness: \
901 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000902 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000903 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000904 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +0000905 /*NOTREACHED*/ \
906 return NULL; \
907 }
908
njne6154662009-02-10 04:23:41 +0000909GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj620e5262006-12-31 00:22:30 +0000910
911
sewardjdc5d8322007-01-28 06:32:01 +0000912/* glibc variant of stpcpy that checks the dest is big enough.
913 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +0000914#define GLIBC25___STPCPY_CHK(soname,fnname) \
915 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
916 (char* dst, const char* src, SizeT len); \
917 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
918 (char* dst, const char* src, SizeT len) \
919 { \
sewardjdc5d8322007-01-28 06:32:01 +0000920 if (! len) \
921 goto badness; \
922 while ((*dst++ = *src++) != '\0') \
923 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +0000924 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +0000925 return dst - 1; \
926 badness: \
927 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000928 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000929 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000930 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +0000931 /*NOTREACHED*/ \
932 return NULL; \
933 }
934
njne6154662009-02-10 04:23:41 +0000935GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardjb8d03852007-01-27 00:49:44 +0000936
937
sewardj841b72d2006-12-31 18:55:56 +0000938/* mempcpy */
939#define GLIBC25_MEMPCPY(soname, fnname) \
940 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
941 ( void *dst, const void *src, SizeT len ); \
942 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
943 ( void *dst, const void *src, SizeT len ) \
944 { \
945 register char *d; \
946 register char *s; \
947 SizeT len_saved = len; \
948 \
949 if (len == 0) \
950 return dst; \
951 \
952 if (is_overlap(dst, src, len, len)) \
953 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
954 \
955 if ( dst > src ) { \
956 d = (char *)dst + len - 1; \
957 s = (char *)src + len - 1; \
958 while ( len-- ) { \
959 *d-- = *s--; \
960 } \
961 } else if ( dst < src ) { \
962 d = (char *)dst; \
963 s = (char *)src; \
964 while ( len-- ) { \
965 *d++ = *s++; \
966 } \
967 } \
968 return (void*)( ((char*)dst) + len_saved ); \
969 }
970
njne6154662009-02-10 04:23:41 +0000971GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
njnb4cfbc42009-05-04 04:20:02 +0000972#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000973GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
njnb4cfbc42009-05-04 04:20:02 +0000974#endif
sewardj841b72d2006-12-31 18:55:56 +0000975
976
sewardjb6c04032007-11-13 20:52:29 +0000977#define GLIBC26___MEMCPY_CHK(soname, fnname) \
978 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
979 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
980 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
981 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
982 { \
sewardjb6c04032007-11-13 20:52:29 +0000983 register char *d; \
984 register char *s; \
985 \
986 if (dstlen < len) goto badness; \
987 \
988 if (len == 0) \
989 return dst; \
990 \
991 if (is_overlap(dst, src, len, len)) \
992 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
993 \
994 if ( dst > src ) { \
995 d = (char *)dst + len - 1; \
996 s = (char *)src + len - 1; \
997 while ( len-- ) { \
998 *d-- = *s--; \
999 } \
1000 } else if ( dst < src ) { \
1001 d = (char *)dst; \
1002 s = (char *)src; \
1003 while ( len-- ) { \
1004 *d++ = *s++; \
1005 } \
1006 } \
1007 return dst; \
1008 badness: \
1009 VALGRIND_PRINTF_BACKTRACE( \
1010 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001011 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001012 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001013 /*NOTREACHED*/ \
1014 return NULL; \
1015 }
1016
njne6154662009-02-10 04:23:41 +00001017GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardjb6c04032007-11-13 20:52:29 +00001018
1019
sewardja77687c2010-08-19 13:22:34 +00001020#define STRSTR(soname, fnname) \
1021 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1022 (void* haystack, void* needle); \
1023 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1024 (void* haystack, void* needle) \
1025 { \
1026 UChar* h = (UChar*)haystack; \
1027 UChar* n = (UChar*)needle; \
1028 \
1029 /* find the length of n, not including terminating zero */ \
1030 UWord nlen = 0; \
1031 while (n[nlen]) nlen++; \
1032 \
1033 /* if n is the empty string, match immediately. */ \
1034 if (nlen == 0) return h; \
1035 \
1036 /* assert(nlen >= 1); */ \
1037 UChar n0 = n[0]; \
1038 \
1039 while (1) { \
1040 UChar hh = *h; \
1041 if (hh == 0) return NULL; \
1042 if (hh != n0) { h++; continue; } \
1043 \
1044 UWord i; \
1045 for (i = 0; i < nlen; i++) { \
1046 if (n[i] != h[i]) \
1047 break; \
1048 } \
1049 /* assert(i >= 0 && i <= nlen); */ \
1050 if (i == nlen) \
1051 return h; \
1052 \
1053 h++; \
1054 } \
1055 }
1056
1057#if defined(VGO_linux)
1058STRSTR(VG_Z_LIBC_SONAME, strstr)
1059#endif
1060
1061
1062#define STRPBRK(soname, fnname) \
1063 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1064 (void* sV, void* acceptV); \
1065 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1066 (void* sV, void* acceptV) \
1067 { \
1068 UChar* s = (UChar*)sV; \
1069 UChar* accept = (UChar*)acceptV; \
1070 \
1071 /* find the length of 'accept', not including terminating zero */ \
1072 UWord nacc = 0; \
1073 while (accept[nacc]) nacc++; \
1074 \
1075 /* if n is the empty string, fail immediately. */ \
1076 if (nacc == 0) return NULL; \
1077 \
1078 /* assert(nacc >= 1); */ \
1079 while (1) { \
1080 UWord i; \
1081 UChar sc = *s; \
1082 if (sc == 0) \
1083 break; \
1084 for (i = 0; i < nacc; i++) { \
1085 if (sc == accept[i]) \
1086 return s; \
1087 } \
1088 s++; \
1089 } \
1090 \
1091 return NULL; \
1092 }
1093
1094#if defined(VGO_linux)
1095STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1096#endif
1097
1098
1099#define STRCSPN(soname, fnname) \
1100 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1101 (void* sV, void* rejectV); \
1102 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1103 (void* sV, void* rejectV) \
1104 { \
1105 UChar* s = (UChar*)sV; \
1106 UChar* reject = (UChar*)rejectV; \
1107 \
1108 /* find the length of 'reject', not including terminating zero */ \
1109 UWord nrej = 0; \
1110 while (reject[nrej]) nrej++; \
1111 \
1112 UWord len = 0; \
1113 while (1) { \
1114 UWord i; \
1115 UChar sc = *s; \
1116 if (sc == 0) \
1117 break; \
1118 for (i = 0; i < nrej; i++) { \
1119 if (sc == reject[i]) \
1120 break; \
1121 } \
1122 /* assert(i >= 0 && i <= nrej); */ \
1123 if (i < nrej) \
1124 break; \
1125 s++; \
1126 len++; \
1127 } \
1128 \
1129 return len; \
1130 }
1131
1132#if defined(VGO_linux)
1133STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1134#endif
1135
1136
sewardjba189352010-08-20 18:24:16 +00001137// And here's a validated strspn replacement, should it
1138// become necessary.
1139//UWord mystrspn( UChar* s, UChar* accept )
1140//{
1141// /* find the length of 'accept', not including terminating zero */
1142// UWord nacc = 0;
1143// while (accept[nacc]) nacc++;
1144// if (nacc == 0) return 0;
1145//
1146// UWord len = 0;
1147// while (1) {
1148// UWord i;
1149// UChar sc = *s;
1150// if (sc == 0)
1151// break;
1152// for (i = 0; i < nacc; i++) {
1153// if (sc == accept[i])
1154// break;
1155// }
1156// assert(i >= 0 && i <= nacc);
1157// if (i == nacc)
1158// break;
1159// s++;
1160// len++;
1161// }
1162//
1163// return len;
1164//}
1165
1166
sewardj31b9ce12006-10-17 01:27:13 +00001167/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001168/*--- Improve definedness checking of process environment ---*/
1169/*------------------------------------------------------------*/
1170
sewardjddc00dd2007-11-27 11:42:47 +00001171#if defined(VGO_linux)
1172
dirk09beb9e2007-04-19 09:47:32 +00001173/* putenv */
njne6154662009-02-10 04:23:41 +00001174int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1175int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001176{
1177 OrigFn fn;
1178 Word result;
1179 const char* p = string;
1180 VALGRIND_GET_ORIG_FN(fn);
1181 /* Now by walking over the string we magically produce
1182 traces when hitting undefined memory. */
1183 if (p)
1184 while (*p++)
1185 ;
1186 CALL_FN_W_W(result, fn, string);
1187 return result;
1188}
1189
1190/* unsetenv */
njne6154662009-02-10 04:23:41 +00001191int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1192int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001193{
1194 OrigFn fn;
1195 Word result;
1196 const char* p = name;
1197 VALGRIND_GET_ORIG_FN(fn);
1198 /* Now by walking over the string we magically produce
1199 traces when hitting undefined memory. */
1200 if (p)
1201 while (*p++)
1202 ;
1203 CALL_FN_W_W(result, fn, name);
1204 return result;
1205}
1206
1207/* setenv */
njne6154662009-02-10 04:23:41 +00001208int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001209 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001210int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001211 (const char* name, const char* value, int overwrite)
1212{
1213 OrigFn fn;
1214 Word result;
1215 const char* p;
1216 VALGRIND_GET_ORIG_FN(fn);
1217 /* Now by walking over the string we magically produce
1218 traces when hitting undefined memory. */
1219 if (name)
1220 for (p = name; *p; p++)
1221 ;
1222 if (value)
1223 for (p = value; *p; p++)
1224 ;
1225 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1226 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1227 return result;
1228}
1229
sewardjddc00dd2007-11-27 11:42:47 +00001230#endif /* defined(VGO_linux) */
1231
njn3e884182003-04-15 13:03:23 +00001232/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001233/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001234/*--------------------------------------------------------------------*/