blob: 46e426dbf1305bbda036ea5e038e17e7864a664d [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
sewardj96044842011-08-18 13:09:55 +000056/* Assignment of behavioural equivalence class tags: 2NNNP is intended
sewardjbd2cff22011-08-16 21:45:28 +000057 to be reserved for Memcheck. Current usage:
58
sewardj96044842011-08-18 13:09:55 +000059 20010 STRRCHR
60 20020 STRCHR
61 20030 STRCAT
62 20040 STRNCAT
63 20050 STRLCAT
64 20060 STRNLEN
65 20070 STRLEN
66 20080 STRCPY
67 20090 STRNCPY
68 20100 STRLCPY
69 20110 STRNCMP
70 20120 STRCASECMP
71 20130 STRNCASECMP
72 20140 STRCASECMP_L
73 20150 STRNCASECMP_L
74 20160 STRCMP
75 20170 MEMCHR
76
77 20180 MEMCPY if there's a conflict between memcpy and
78 20181 MEMMOVE memmove, prefer memmove
79
80 20190 MEMCMP
81 20200 STPCPY
82 20210 MEMSET
83 2022P unused (was previously MEMMOVE)
84 20230 BCOPY
85 20240 GLIBC25___MEMMOVE_CHK
86 20250 GLIBC232_STRCHRNUL
87 20260 GLIBC232_RAWMEMCHR
88 20270 GLIBC25___STRCPY_CHK
89 20280 GLIBC25___STPCPY_CHK
90 20290 GLIBC25_MEMPCPY
91 20300 GLIBC26___MEMCPY_CHK
92 20310 STRSTR
93 20320 STRPBRK
94 20330 STRCSPN
95 20340 STRSPN
sewardjbd2cff22011-08-16 21:45:28 +000096*/
97
sewardj126e82d2011-07-12 13:33:00 +000098
sewardjdda830a2003-07-20 22:28:42 +000099/* Figure out if [dst .. dst+dstlen-1] overlaps with
100 [src .. src+srclen-1].
101 We assume that the address ranges do not wrap around
102 (which is safe since on Linux addresses >= 0xC0000000
103 are not accessible and the program will segfault in this
104 circumstance, presumably).
105*/
sewardj126e82d2011-07-12 13:33:00 +0000106static inline
njnc6168192004-11-29 13:54:10 +0000107Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
njn3e884182003-04-15 13:03:23 +0000108{
sewardjdda830a2003-07-20 22:28:42 +0000109 Addr loS, hiS, loD, hiD;
110
111 if (dstlen == 0 || srclen == 0)
112 return False;
113
114 loS = (Addr)src;
115 loD = (Addr)dst;
116 hiS = loS + srclen - 1;
117 hiD = loD + dstlen - 1;
118
119 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
120 if (loS < loD) {
121 return !(hiS < loD);
122 }
123 else if (loD < loS) {
124 return !(hiD < loS);
125 }
126 else {
127 /* They start at same place. Since we know neither of them has
128 zero length, they must overlap. */
129 return True;
130 }
njn3e884182003-04-15 13:03:23 +0000131}
132
sewardj126e82d2011-07-12 13:33:00 +0000133
134/* Call here to exit if we can't continue. On Android we can't call
135 _exit for some reason, so we have to blunt-instrument it. */
136__attribute__ ((__noreturn__))
137static inline void my_exit ( int x )
138{
139# if defined(VGPV_arm_linux_android)
140 __asm__ __volatile__(".word 0xFFFFFFFF");
141 while (1) {}
142# else
143 extern void _exit(int status);
sewardj49665422011-07-12 13:50:59 +0000144 _exit(x);
sewardj126e82d2011-07-12 13:33:00 +0000145# endif
146}
147
148
njn1f8b3e72005-03-22 04:27:14 +0000149// This is a macro rather than a function because we don't want to have an
150// extra function in the stack trace.
bart575ce8e2011-05-15 07:04:03 +0000151#define RECORD_OVERLAP_ERROR(s, src, dst, len) \
152 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
153 _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \
154 s, src, dst, len, 0)
njn3e884182003-04-15 13:03:23 +0000155
njn16eeb4e2005-06-16 03:56:58 +0000156
sewardj3c944452011-09-05 20:39:57 +0000157/*---------------------- strrchr ----------------------*/
158
njn16eeb4e2005-06-16 03:56:58 +0000159#define STRRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000160 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
161 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000162 { \
163 UChar ch = (UChar)((UInt)c); \
164 UChar* p = (UChar*)s; \
165 UChar* last = NULL; \
166 while (True) { \
167 if (*p == ch) last = p; \
168 if (*p == 0) return last; \
169 p++; \
170 } \
njn3e884182003-04-15 13:03:23 +0000171 }
njn3e884182003-04-15 13:03:23 +0000172
njn16eeb4e2005-06-16 03:56:58 +0000173// Apparently rindex() is the same thing as strrchr()
njnb4cfbc42009-05-04 04:20:02 +0000174#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000175 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
176 STRRCHR(VG_Z_LIBC_SONAME, rindex)
177 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
178 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
njnf76d27a2009-05-28 01:53:07 +0000179#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000180 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
181 STRRCHR(VG_Z_LIBC_SONAME, rindex)
182 STRRCHR(VG_Z_DYLD, strrchr)
183 STRRCHR(VG_Z_DYLD, rindex)
njnb4cfbc42009-05-04 04:20:02 +0000184#endif
njn16eeb4e2005-06-16 03:56:58 +0000185
186
sewardj3c944452011-09-05 20:39:57 +0000187/*---------------------- strchr ----------------------*/
188
njn16eeb4e2005-06-16 03:56:58 +0000189#define STRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000190 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
191 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000192 { \
193 UChar ch = (UChar)((UInt)c); \
194 UChar* p = (UChar*)s; \
195 while (True) { \
196 if (*p == ch) return p; \
197 if (*p == 0) return NULL; \
198 p++; \
199 } \
njn3e884182003-04-15 13:03:23 +0000200 }
njn3e884182003-04-15 13:03:23 +0000201
njn16eeb4e2005-06-16 03:56:58 +0000202// Apparently index() is the same thing as strchr()
njnb4cfbc42009-05-04 04:20:02 +0000203#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000204 STRCHR(VG_Z_LIBC_SONAME, strchr)
205 STRCHR(VG_Z_LIBC_SONAME, index)
206 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
207# if !defined(VGP_x86_linux)
208 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
209 STRCHR(VG_Z_LD_LINUX_SO_2, index)
210 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
211 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
212# endif
njnf76d27a2009-05-28 01:53:07 +0000213#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000214 STRCHR(VG_Z_LIBC_SONAME, strchr)
215 STRCHR(VG_Z_LIBC_SONAME, index)
216 STRCHR(VG_Z_DYLD, strchr)
217 STRCHR(VG_Z_DYLD, index)
njnb4cfbc42009-05-04 04:20:02 +0000218#endif
njn3e884182003-04-15 13:03:23 +0000219
njn3e884182003-04-15 13:03:23 +0000220
sewardj3c944452011-09-05 20:39:57 +0000221/*---------------------- strcat ----------------------*/
222
njn16eeb4e2005-06-16 03:56:58 +0000223#define STRCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000224 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000225 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000226 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000227 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000228 { \
229 const Char* src_orig = src; \
230 Char* dst_orig = dst; \
231 while (*dst) dst++; \
232 while (*src) *dst++ = *src++; \
233 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000234 \
njn16eeb4e2005-06-16 03:56:58 +0000235 /* This is a bit redundant, I think; any overlap and the strcat will */ \
236 /* go forever... or until a seg fault occurs. */ \
237 if (is_overlap(dst_orig, \
238 src_orig, \
239 (Addr)dst-(Addr)dst_orig+1, \
240 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000241 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000242 \
njn16eeb4e2005-06-16 03:56:58 +0000243 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000244 }
njn3e884182003-04-15 13:03:23 +0000245
tomd2645142009-10-29 09:27:11 +0000246#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000247 STRCAT(VG_Z_LIBC_SONAME, strcat)
248 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
249#elif defined(VGO_darwin)
250 STRCAT(VG_Z_LIBC_SONAME, strcat)
tomd2645142009-10-29 09:27:11 +0000251#endif
njn16eeb4e2005-06-16 03:56:58 +0000252
sewardj3c944452011-09-05 20:39:57 +0000253
254/*---------------------- strncat ----------------------*/
255
njn16eeb4e2005-06-16 03:56:58 +0000256#define STRNCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000257 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000258 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000259 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000260 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000261 { \
262 const Char* src_orig = src; \
263 Char* dst_orig = dst; \
264 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000265 \
njn16eeb4e2005-06-16 03:56:58 +0000266 while (*dst) dst++; \
267 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
268 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000269 \
njn16eeb4e2005-06-16 03:56:58 +0000270 /* This checks for overlap after copying, unavoidable without */ \
271 /* pre-counting lengths... should be ok */ \
272 if (is_overlap(dst_orig, \
273 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000274 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000275 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000276 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000277 \
njn16eeb4e2005-06-16 03:56:58 +0000278 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000279 }
njn3e884182003-04-15 13:03:23 +0000280
sewardj3c944452011-09-05 20:39:57 +0000281#if defined(VGO_linux)
282 STRNCAT(VG_Z_LIBC_SONAME, strncat)
283#elif defined(VGO_darwin)
284 STRNCAT(VG_Z_LIBC_SONAME, strncat)
285 STRNCAT(VG_Z_DYLD, strncat)
njnf76d27a2009-05-28 01:53:07 +0000286#endif
287
288
sewardj3c944452011-09-05 20:39:57 +0000289/*---------------------- strlcat ----------------------*/
290
njnf76d27a2009-05-28 01:53:07 +0000291/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
292 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
293 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
294 Truncation occurred if retval >= n.
295*/
296#define STRLCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000297 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000298 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000299 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000300 ( char* dst, const char* src, SizeT n ) \
301 { \
302 const Char* src_orig = src; \
303 Char* dst_orig = dst; \
304 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000305 \
njnf76d27a2009-05-28 01:53:07 +0000306 while (m < n && *dst) { m++; dst++; } \
307 if (m < n) { \
308 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
309 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
310 *dst = 0; \
311 } else { \
312 /* No space to copy anything to dst. m == n */ \
313 } \
314 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
315 while (*src) { m++; src++; } \
316 /* This checks for overlap after copying, unavoidable without */ \
317 /* pre-counting lengths... should be ok */ \
318 if (is_overlap(dst_orig, \
319 src_orig, \
320 (Addr)dst-(Addr)dst_orig+1, \
321 (Addr)src-(Addr)src_orig+1)) \
322 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
sewardjbd2cff22011-08-16 21:45:28 +0000323 \
njnf76d27a2009-05-28 01:53:07 +0000324 return m; \
325 }
326
sewardj3c944452011-09-05 20:39:57 +0000327#if defined(VGO_linux)
328#elif defined(VGO_darwin)
329 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
330 STRLCAT(VG_Z_DYLD, strlcat)
njnf76d27a2009-05-28 01:53:07 +0000331#endif
sewardj31b9ce12006-10-17 01:27:13 +0000332
njn3e884182003-04-15 13:03:23 +0000333
sewardj3c944452011-09-05 20:39:57 +0000334/*---------------------- strnlen ----------------------*/
335
njn16eeb4e2005-06-16 03:56:58 +0000336#define STRNLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000337 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000338 ( const char* str, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000339 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000340 ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000341 { \
342 SizeT i = 0; \
343 while (i < n && str[i] != 0) i++; \
344 return i; \
njn3e884182003-04-15 13:03:23 +0000345 }
njn3e884182003-04-15 13:03:23 +0000346
tomd2645142009-10-29 09:27:11 +0000347#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000348 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
349 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
350#elif defined(VGO_darwin)
351 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
tomd2645142009-10-29 09:27:11 +0000352#endif
njn16eeb4e2005-06-16 03:56:58 +0000353
sewardj3ceec242003-07-30 21:24:25 +0000354
sewardj3c944452011-09-05 20:39:57 +0000355/*---------------------- strlen ----------------------*/
356
njn5ec15ed2005-08-24 19:55:51 +0000357// Note that this replacement often doesn't get used because gcc inlines
358// calls to strlen() with its own built-in version. This can be very
sewardj3c944452011-09-05 20:39:57 +0000359// confusing if you aren't expecting it. Other small functions in
360// this file may also be inline by gcc.
361
njn16eeb4e2005-06-16 03:56:58 +0000362#define STRLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000363 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000364 ( const char* str ); \
sewardj96044842011-08-18 13:09:55 +0000365 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000366 ( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000367 { \
368 SizeT i = 0; \
369 while (str[i] != 0) i++; \
370 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000371 }
njn16eeb4e2005-06-16 03:56:58 +0000372
njnb4cfbc42009-05-04 04:20:02 +0000373#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000374 STRLEN(VG_Z_LIBC_SONAME, strlen)
375 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
376#elif defined(VGO_darwin)
377 STRLEN(VG_Z_LIBC_SONAME, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000378#endif
sewardj31b9ce12006-10-17 01:27:13 +0000379
njn16eeb4e2005-06-16 03:56:58 +0000380
sewardj3c944452011-09-05 20:39:57 +0000381/*---------------------- strcpy ----------------------*/
382
njn16eeb4e2005-06-16 03:56:58 +0000383#define STRCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000384 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000385 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000386 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000387 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000388 { \
389 const Char* src_orig = src; \
390 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000391 \
njn16eeb4e2005-06-16 03:56:58 +0000392 while (*src) *dst++ = *src++; \
393 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000394 \
njn16eeb4e2005-06-16 03:56:58 +0000395 /* This checks for overlap after copying, unavoidable without */ \
396 /* pre-counting length... should be ok */ \
397 if (is_overlap(dst_orig, \
398 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000399 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000400 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000401 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000402 \
njn16eeb4e2005-06-16 03:56:58 +0000403 return dst_orig; \
404 }
405
tomd2645142009-10-29 09:27:11 +0000406#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000407 STRCPY(VG_Z_LIBC_SONAME, strcpy)
408 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
tomd2645142009-10-29 09:27:11 +0000409#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000410 STRCPY(VG_Z_LIBC_SONAME, strcpy)
411 STRCPY(VG_Z_DYLD, strcpy)
njnf76d27a2009-05-28 01:53:07 +0000412#endif
njn16eeb4e2005-06-16 03:56:58 +0000413
414
sewardj3c944452011-09-05 20:39:57 +0000415/*---------------------- strncpy ----------------------*/
416
njn16eeb4e2005-06-16 03:56:58 +0000417#define STRNCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000418 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000419 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000420 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000421 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000422 { \
423 const Char* src_orig = src; \
424 Char* dst_orig = dst; \
425 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000426 \
njn16eeb4e2005-06-16 03:56:58 +0000427 while (m < n && *src) { m++; *dst++ = *src++; } \
428 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
429 /* but only m+1 bytes of src if terminator was found */ \
430 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000431 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000432 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
sewardj3c944452011-09-05 20:39:57 +0000433 \
njn16eeb4e2005-06-16 03:56:58 +0000434 return dst_orig; \
435 }
436
tomd2645142009-10-29 09:27:11 +0000437#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000438 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
439 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
tomd2645142009-10-29 09:27:11 +0000440#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000441 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
442 STRNCPY(VG_Z_DYLD, strncpy)
njnf76d27a2009-05-28 01:53:07 +0000443#endif
444
445
sewardj3c944452011-09-05 20:39:57 +0000446/*---------------------- strlcpy ----------------------*/
447
njnf76d27a2009-05-28 01:53:07 +0000448/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
449 Returns strlen(src). Does not zero-fill the remainder of dst. */
450#define STRLCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000451 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000452 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000453 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000454 ( char* dst, const char* src, SizeT n ) \
455 { \
456 const char* src_orig = src; \
457 char* dst_orig = dst; \
458 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000459 \
njnf76d27a2009-05-28 01:53:07 +0000460 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
461 /* m non-nul bytes have now been copied, and m <= n-1. */ \
462 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
463 /* but only m+1 bytes of src if terminator was found */ \
464 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
465 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
466 /* Nul-terminate dst. */ \
467 if (n > 0) *dst = 0; \
468 /* Finish counting strlen(src). */ \
469 while (*src) src++; \
470 return src - src_orig; \
471 }
472
sewardj3c944452011-09-05 20:39:57 +0000473#if defined(VGO_linux)
474#elif defined(VGO_darwin)
475 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
476 STRLCPY(VG_Z_DYLD, strlcpy)
njnf76d27a2009-05-28 01:53:07 +0000477#endif
njn16eeb4e2005-06-16 03:56:58 +0000478
479
sewardj3c944452011-09-05 20:39:57 +0000480/*---------------------- strncmp ----------------------*/
481
njn16eeb4e2005-06-16 03:56:58 +0000482#define STRNCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000483 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000484 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000485 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000486 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000487 { \
488 SizeT n = 0; \
489 while (True) { \
490 if (n >= nmax) return 0; \
491 if (*s1 == 0 && *s2 == 0) return 0; \
492 if (*s1 == 0) return -1; \
493 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000494 \
njn16eeb4e2005-06-16 03:56:58 +0000495 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
496 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000497 \
njn16eeb4e2005-06-16 03:56:58 +0000498 s1++; s2++; n++; \
499 } \
500 }
501
tomd2645142009-10-29 09:27:11 +0000502#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000503 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
504 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
tomd2645142009-10-29 09:27:11 +0000505#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000506 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
507 STRNCMP(VG_Z_DYLD, strncmp)
njnf76d27a2009-05-28 01:53:07 +0000508#endif
njn16eeb4e2005-06-16 03:56:58 +0000509
510
sewardj3c944452011-09-05 20:39:57 +0000511/*---------------------- strcasecmp ----------------------*/
512
tomce6d0ac2010-11-12 10:03:13 +0000513#define STRCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000514 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000515 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000516 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000517 ( const char* s1, const char* s2 ) \
518 { \
tome03c8c42010-11-12 10:40:20 +0000519 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000520 register unsigned char c1; \
521 register unsigned char c2; \
522 while (True) { \
523 c1 = tolower(*(unsigned char *)s1); \
524 c2 = tolower(*(unsigned char *)s2); \
525 if (c1 != c2) break; \
526 if (c1 == 0) break; \
527 s1++; s2++; \
528 } \
529 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
530 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
531 return 0; \
532 }
533
sewardj3c944452011-09-05 20:39:57 +0000534#if defined(VGO_linux)
535# if !defined(VGPV_arm_linux_android)
536 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
537 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
538# endif
539#elif defined(VGO_darwin)
540 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
tomce6d0ac2010-11-12 10:03:13 +0000541#endif
542
543
sewardj3c944452011-09-05 20:39:57 +0000544/*---------------------- strncasecmp ----------------------*/
545
tomce6d0ac2010-11-12 10:03:13 +0000546#define STRNCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000547 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000548 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000549 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000550 ( const char* s1, const char* s2, SizeT nmax ) \
551 { \
tome03c8c42010-11-12 10:40:20 +0000552 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000553 SizeT n = 0; \
554 while (True) { \
555 if (n >= nmax) return 0; \
556 if (*s1 == 0 && *s2 == 0) return 0; \
557 if (*s1 == 0) return -1; \
558 if (*s2 == 0) return 1; \
559 \
sewardjbd2cff22011-08-16 21:45:28 +0000560 if (tolower(*(unsigned char*)s1) \
561 < tolower(*(unsigned char*)s2)) return -1; \
562 if (tolower(*(unsigned char*)s1) \
563 > tolower(*(unsigned char*)s2)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000564 \
565 s1++; s2++; n++; \
566 } \
567 }
568
sewardj3c944452011-09-05 20:39:57 +0000569#if defined(VGO_linux)
570# if !defined(VGPV_arm_linux_android)
571 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
572 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
573# endif
tomce6d0ac2010-11-12 10:03:13 +0000574#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000575 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
576 STRNCASECMP(VG_Z_DYLD, strncasecmp)
tomce6d0ac2010-11-12 10:03:13 +0000577#endif
578
579
sewardj3c944452011-09-05 20:39:57 +0000580/*---------------------- strcasecmp_l ----------------------*/
581
tomce6d0ac2010-11-12 10:03:13 +0000582#define STRCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000583 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000584 ( const char* s1, const char* s2, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000585 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000586 ( const char* s1, const char* s2, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000587 { \
sewardj3c944452011-09-05 20:39:57 +0000588 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000589 register unsigned char c1; \
590 register unsigned char c2; \
591 while (True) { \
592 c1 = tolower_l(*(unsigned char *)s1, locale); \
593 c2 = tolower_l(*(unsigned char *)s2, locale); \
594 if (c1 != c2) break; \
595 if (c1 == 0) break; \
596 s1++; s2++; \
597 } \
598 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
599 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
600 return 0; \
601 }
602
tomce6d0ac2010-11-12 10:03:13 +0000603#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000604 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
605 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
606 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
607#elif defined(VGO_darwin)
608 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
tomce6d0ac2010-11-12 10:03:13 +0000609#endif
610
611
sewardj3c944452011-09-05 20:39:57 +0000612/*---------------------- strncasecmp_l ----------------------*/
613
tomce6d0ac2010-11-12 10:03:13 +0000614#define STRNCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000615 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000616 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000617 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000618 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000619 { \
tome03c8c42010-11-12 10:40:20 +0000620 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000621 SizeT n = 0; \
622 while (True) { \
623 if (n >= nmax) return 0; \
624 if (*s1 == 0 && *s2 == 0) return 0; \
625 if (*s1 == 0) return -1; \
626 if (*s2 == 0) return 1; \
627 \
sewardjbd2cff22011-08-16 21:45:28 +0000628 if (tolower_l(*(unsigned char*)s1, locale) \
629 < tolower_l(*(unsigned char*)s2, locale)) return -1; \
630 if (tolower_l(*(unsigned char*)s1, locale) \
631 > tolower_l(*(unsigned char*)s2, locale)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000632 \
633 s1++; s2++; n++; \
634 } \
635 }
636
tomce6d0ac2010-11-12 10:03:13 +0000637#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000638 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
639 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
tomce6d0ac2010-11-12 10:03:13 +0000640#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000641 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
642 STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
tomce6d0ac2010-11-12 10:03:13 +0000643#endif
644
645
sewardj3c944452011-09-05 20:39:57 +0000646/*---------------------- strcmp ----------------------*/
647
njn16eeb4e2005-06-16 03:56:58 +0000648#define STRCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000649 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000650 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000651 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000652 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000653 { \
654 register unsigned char c1; \
655 register unsigned char c2; \
656 while (True) { \
657 c1 = *(unsigned char *)s1; \
658 c2 = *(unsigned char *)s2; \
659 if (c1 != c2) break; \
660 if (c1 == 0) break; \
661 s1++; s2++; \
662 } \
663 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
664 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
665 return 0; \
666 }
667
njnb4cfbc42009-05-04 04:20:02 +0000668#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000669 STRCMP(VG_Z_LIBC_SONAME, strcmp)
670 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
671 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
672 STRCMP(VG_Z_LD64_SO_1, strcmp)
673#elif defined(VGO_darwin)
674 STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000675#endif
njn16eeb4e2005-06-16 03:56:58 +0000676
677
sewardj3c944452011-09-05 20:39:57 +0000678/*---------------------- memchr ----------------------*/
679
njn16eeb4e2005-06-16 03:56:58 +0000680#define MEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000681 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000682 (const void *s, int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000683 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000684 (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000685 { \
686 SizeT i; \
687 UChar c0 = (UChar)c; \
688 UChar* p = (UChar*)s; \
689 for (i = 0; i < n; i++) \
690 if (p[i] == c0) return (void*)(&p[i]); \
691 return NULL; \
692 }
693
sewardj3c944452011-09-05 20:39:57 +0000694#if defined(VGO_linux)
695 MEMCHR(VG_Z_LIBC_SONAME, memchr)
696#elif defined(VGO_darwin)
697 MEMCHR(VG_Z_LIBC_SONAME, memchr)
698 MEMCHR(VG_Z_DYLD, memchr)
njnf76d27a2009-05-28 01:53:07 +0000699#endif
njn16eeb4e2005-06-16 03:56:58 +0000700
701
sewardj3c944452011-09-05 20:39:57 +0000702/*---------------------- memcpy ----------------------*/
703
sewardjbd2cff22011-08-16 21:45:28 +0000704#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
sewardjd88797f2011-08-17 21:25:50 +0000705 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000706 ( void *dst, const void *src, SizeT len ); \
sewardjd88797f2011-08-17 21:25:50 +0000707 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000708 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000709 { \
sewardjbd2cff22011-08-16 21:45:28 +0000710 if (do_ol_check && is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000711 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000712 \
sewardj7b4e00b2010-08-24 09:05:52 +0000713 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
714 const Addr WM = WS - 1; /* 7 or 3 */ \
715 \
tom863ab7c2011-08-18 08:10:20 +0000716 if (len > 0) { \
717 if (dst < src) { \
sewardj7b4e00b2010-08-24 09:05:52 +0000718 \
tom863ab7c2011-08-18 08:10:20 +0000719 /* Copying backwards. */ \
720 SizeT n = len; \
721 Addr d = (Addr)dst; \
722 Addr s = (Addr)src; \
723 \
724 if (((s^d) & WM) == 0) { \
725 /* s and d have same UWord alignment. */ \
726 /* Pull up to a UWord boundary. */ \
727 while ((s & WM) != 0 && n >= 1) \
728 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
729 /* Copy UWords. */ \
730 while (n >= WS) \
731 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
732 if (n == 0) \
733 return dst; \
734 } \
735 if (((s|d) & 1) == 0) { \
736 /* Both are 16-aligned; copy what we can thusly. */ \
737 while (n >= 2) \
738 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
739 } \
740 /* Copy leftovers, or everything if misaligned. */ \
741 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000742 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
sewardj7b4e00b2010-08-24 09:05:52 +0000743 \
tom863ab7c2011-08-18 08:10:20 +0000744 } else if (dst > src) { \
745 \
746 SizeT n = len; \
747 Addr d = ((Addr)dst) + n; \
748 Addr s = ((Addr)src) + n; \
749 \
750 /* Copying forwards. */ \
751 if (((s^d) & WM) == 0) { \
752 /* s and d have same UWord alignment. */ \
753 /* Back down to a UWord boundary. */ \
754 while ((s & WM) != 0 && n >= 1) \
755 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
756 /* Copy UWords. */ \
757 while (n >= WS) \
758 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
759 if (n == 0) \
760 return dst; \
761 } \
762 if (((s|d) & 1) == 0) { \
763 /* Both are 16-aligned; copy what we can thusly. */ \
764 while (n >= 2) \
765 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
766 } \
767 /* Copy leftovers, or everything if misaligned. */ \
768 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000769 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
tom863ab7c2011-08-18 08:10:20 +0000770 \
njn16eeb4e2005-06-16 03:56:58 +0000771 } \
njn16eeb4e2005-06-16 03:56:58 +0000772 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000773 \
njn16eeb4e2005-06-16 03:56:58 +0000774 return dst; \
775 }
776
sewardjbd2cff22011-08-16 21:45:28 +0000777#define MEMMOVE(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000778 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
sewardjbd2cff22011-08-16 21:45:28 +0000779
780#define MEMCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000781 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
sewardjbd2cff22011-08-16 21:45:28 +0000782
njnb4cfbc42009-05-04 04:20:02 +0000783#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000784 /* For older memcpy we have to use memmove-like semantics and skip
785 the overlap check; sigh; see #275284. */
786 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
787 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
788 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
789 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
790 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnf76d27a2009-05-28 01:53:07 +0000791#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000792 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
793 MEMCPY(VG_Z_DYLD, memcpy)
794 /* icc9 blats these around all over the place. Not only in the main
795 executable but various .so's. They are highly tuned and read
796 memory beyond the source boundary (although work correctly and
797 never go across page boundaries), so give errors when run
798 natively, at least for misaligned source arg. Just intercepting
799 in the exe only until we understand more about the problem. See
800 http://bugs.kde.org/show_bug.cgi?id=139776
sewardjf0b34322007-01-16 21:42:28 +0000801 */
sewardj3c944452011-09-05 20:39:57 +0000802 MEMCPY(NONE, ZuintelZufastZumemcpy)
803#endif
sewardj31b9ce12006-10-17 01:27:13 +0000804
njn16eeb4e2005-06-16 03:56:58 +0000805
sewardj3c944452011-09-05 20:39:57 +0000806/*---------------------- memcmp ----------------------*/
807
njn16eeb4e2005-06-16 03:56:58 +0000808#define MEMCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000809 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000810 ( const void *s1V, const void *s2V, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000811 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000812 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000813 { \
814 int res; \
815 unsigned char a0; \
816 unsigned char b0; \
817 unsigned char* s1 = (unsigned char*)s1V; \
818 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000819 \
njn16eeb4e2005-06-16 03:56:58 +0000820 while (n != 0) { \
821 a0 = s1[0]; \
822 b0 = s2[0]; \
823 s1 += 1; \
824 s2 += 1; \
825 res = ((int)a0) - ((int)b0); \
826 if (res != 0) \
827 return res; \
828 n -= 1; \
829 } \
830 return 0; \
831 }
832
njnb4cfbc42009-05-04 04:20:02 +0000833#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000834 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
835 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
836 MEMCMP(VG_Z_LD_SO_1, bcmp)
njnf76d27a2009-05-28 01:53:07 +0000837#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000838 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
839 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
840 MEMCMP(VG_Z_DYLD, memcmp)
841 MEMCMP(VG_Z_DYLD, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000842#endif
njn3e884182003-04-15 13:03:23 +0000843
jseward0845ef82003-12-22 22:31:27 +0000844
sewardj3c944452011-09-05 20:39:57 +0000845/*---------------------- stpcpy ----------------------*/
846
jseward0845ef82003-12-22 22:31:27 +0000847/* Copy SRC to DEST, returning the address of the terminating '\0' in
848 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000849#define STPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000850 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000851 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000852 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000853 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000854 { \
855 const Char* src_orig = src; \
856 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000857 \
njn16eeb4e2005-06-16 03:56:58 +0000858 while (*src) *dst++ = *src++; \
859 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000860 \
njn16eeb4e2005-06-16 03:56:58 +0000861 /* This checks for overlap after copying, unavoidable without */ \
862 /* pre-counting length... should be ok */ \
863 if (is_overlap(dst_orig, \
864 src_orig, \
865 (Addr)dst-(Addr)dst_orig+1, \
866 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000867 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000868 \
njn16eeb4e2005-06-16 03:56:58 +0000869 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000870 }
njn16eeb4e2005-06-16 03:56:58 +0000871
njnb4cfbc42009-05-04 04:20:02 +0000872#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000873 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
874 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
875 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
876 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnf76d27a2009-05-28 01:53:07 +0000877#elif defined(VGO_darwin)
sewardj3c944452011-09-05 20:39:57 +0000878 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
879 STPCPY(VG_Z_DYLD, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000880#endif
881
njn16eeb4e2005-06-16 03:56:58 +0000882
sewardj3c944452011-09-05 20:39:57 +0000883/*---------------------- memset ----------------------*/
884
885/* Why are we bothering to intercept this? It seems entirely
886 pointless. */
njn16eeb4e2005-06-16 03:56:58 +0000887#define MEMSET(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000888 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000889 (void *s, Int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000890 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000891 (void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000892 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000893 Addr a = (Addr)s; \
894 UInt c4 = (c & 0xFF); \
895 c4 = (c4 << 8) | c4; \
896 c4 = (c4 << 16) | c4; \
897 while ((a & 3) != 0 && n >= 1) \
898 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
899 while (n >= 4) \
900 { *(UInt*)a = c4; a += 4; n -= 4; } \
901 while (n >= 1) \
902 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000903 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000904 }
njn16eeb4e2005-06-16 03:56:58 +0000905
sewardj3c944452011-09-05 20:39:57 +0000906#if defined(VGO_linux)
907 MEMSET(VG_Z_LIBC_SONAME, memset)
908#elif defined(VGO_darwin)
909 MEMSET(VG_Z_LIBC_SONAME, memset)
910 MEMSET(VG_Z_DYLD, memset)
njnf76d27a2009-05-28 01:53:07 +0000911#endif
njn16eeb4e2005-06-16 03:56:58 +0000912
913
sewardj3c944452011-09-05 20:39:57 +0000914/*---------------------- memmove ----------------------*/
915
sewardj96044842011-08-18 13:09:55 +0000916/* memmove -- use the MEMMOVE defn above. */
sewardj3c944452011-09-05 20:39:57 +0000917#if defined(VGO_linux)
918 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
919#elif defined(VGO_darwin)
920 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
921 MEMMOVE(VG_Z_DYLD, memmove)
njnf76d27a2009-05-28 01:53:07 +0000922#endif
923
924
sewardj3c944452011-09-05 20:39:57 +0000925/*---------------------- bcopy ----------------------*/
926
njnf76d27a2009-05-28 01:53:07 +0000927#define BCOPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000928 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000929 (const void *srcV, void *dstV, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000930 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000931 (const void *srcV, void *dstV, SizeT n) \
932 { \
933 SizeT i; \
934 Char* dst = (Char*)dstV; \
935 Char* src = (Char*)srcV; \
936 if (dst < src) { \
937 for (i = 0; i < n; i++) \
938 dst[i] = src[i]; \
939 } \
940 else \
941 if (dst > src) { \
942 for (i = 0; i < n; i++) \
943 dst[n-i-1] = src[n-i-1]; \
944 } \
945 }
946
sewardj3c944452011-09-05 20:39:57 +0000947#if defined(VGO_linux)
948#elif defined(VGO_darwin)
949 BCOPY(VG_Z_LIBC_SONAME, bcopy)
950 BCOPY(VG_Z_DYLD, bcopy)
njnf76d27a2009-05-28 01:53:07 +0000951#endif
sewardj44e495f2005-05-12 17:58:28 +0000952
jseward0845ef82003-12-22 22:31:27 +0000953
sewardj3c944452011-09-05 20:39:57 +0000954/*-------------------- memmove_chk --------------------*/
955
sewardj24cb2172007-02-23 09:03:26 +0000956/* glibc 2.5 variant of memmove which checks the dest is big enough.
957 There is no specific part of glibc that this is copied from. */
958#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000959 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +0000960 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
sewardj96044842011-08-18 13:09:55 +0000961 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +0000962 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
963 { \
sewardj24cb2172007-02-23 09:03:26 +0000964 SizeT i; \
965 Char* dst = (Char*)dstV; \
966 Char* src = (Char*)srcV; \
967 if (destlen < n) \
968 goto badness; \
969 if (dst < src) { \
970 for (i = 0; i < n; i++) \
971 dst[i] = src[i]; \
972 } \
973 else \
974 if (dst > src) { \
975 for (i = 0; i < n; i++) \
976 dst[n-i-1] = src[n-i-1]; \
977 } \
978 return dst; \
979 badness: \
980 VALGRIND_PRINTF_BACKTRACE( \
981 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000982 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000983 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +0000984 /*NOTREACHED*/ \
985 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +0000986 }
987
sewardj3c944452011-09-05 20:39:57 +0000988#if defined(VGO_linux)
989 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
990#elif defined(VGO_darwin)
991#endif
sewardj24cb2172007-02-23 09:03:26 +0000992
993
sewardj3c944452011-09-05 20:39:57 +0000994/*-------------------- strchrnul --------------------*/
995
sewardj4e9a4b62004-11-23 00:20:17 +0000996/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000997#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000998 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000999 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001000 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001001 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001002 { \
1003 unsigned char c = (unsigned char) c_in; \
1004 unsigned char* char_ptr = (unsigned char *)s; \
1005 while (1) { \
1006 if (*char_ptr == 0) return char_ptr; \
1007 if (*char_ptr == c) return char_ptr; \
1008 char_ptr++; \
1009 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001010 }
njn16eeb4e2005-06-16 03:56:58 +00001011
sewardj3c944452011-09-05 20:39:57 +00001012#if defined(VGO_linux)
1013 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1014#elif defined(VGO_darwin)
1015#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001016
1017
sewardj3c944452011-09-05 20:39:57 +00001018/*---------------------- rawmemchr ----------------------*/
1019
sewardj4e9a4b62004-11-23 00:20:17 +00001020/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +00001021#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001022 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001023 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001024 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001025 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001026 { \
1027 unsigned char c = (unsigned char) c_in; \
1028 unsigned char* char_ptr = (unsigned char *)s; \
1029 while (1) { \
1030 if (*char_ptr == c) return char_ptr; \
1031 char_ptr++; \
1032 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001033 }
njn16eeb4e2005-06-16 03:56:58 +00001034
tomd2645142009-10-29 09:27:11 +00001035#if defined (VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001036 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1037 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1038#elif defined(VGO_darwin)
tomd2645142009-10-29 09:27:11 +00001039#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001040
sewardj3c944452011-09-05 20:39:57 +00001041
1042/*---------------------- strcpy_chk ----------------------*/
1043
sewardjdc5d8322007-01-28 06:32:01 +00001044/* glibc variant of strcpy that checks the dest is big enough.
1045 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +00001046#define GLIBC25___STRCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001047 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001048 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001049 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001050 (char* dst, const char* src, SizeT len) \
sewardj620e5262006-12-31 00:22:30 +00001051 { \
sewardj620e5262006-12-31 00:22:30 +00001052 char* ret = dst; \
1053 if (! len) \
1054 goto badness; \
1055 while ((*dst++ = *src++) != '\0') \
1056 if (--len == 0) \
1057 goto badness; \
1058 return ret; \
1059 badness: \
1060 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001061 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001062 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001063 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +00001064 /*NOTREACHED*/ \
1065 return NULL; \
1066 }
1067
sewardj3c944452011-09-05 20:39:57 +00001068#if defined(VGO_linux)
1069 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1070#elif defined(VGO_darwin)
1071#endif
sewardj620e5262006-12-31 00:22:30 +00001072
1073
sewardj3c944452011-09-05 20:39:57 +00001074/*---------------------- stpcpy_chk ----------------------*/
1075
sewardjdc5d8322007-01-28 06:32:01 +00001076/* glibc variant of stpcpy that checks the dest is big enough.
1077 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +00001078#define GLIBC25___STPCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001079 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001080 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001081 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001082 (char* dst, const char* src, SizeT len) \
sewardjb8d03852007-01-27 00:49:44 +00001083 { \
sewardjdc5d8322007-01-28 06:32:01 +00001084 if (! len) \
1085 goto badness; \
1086 while ((*dst++ = *src++) != '\0') \
1087 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +00001088 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +00001089 return dst - 1; \
1090 badness: \
1091 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001092 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001093 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001094 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +00001095 /*NOTREACHED*/ \
1096 return NULL; \
1097 }
1098
sewardj3c944452011-09-05 20:39:57 +00001099#if defined(VGO_linux)
1100 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1101#elif defined(VGO_darwin)
1102#endif
sewardjb8d03852007-01-27 00:49:44 +00001103
1104
sewardj3c944452011-09-05 20:39:57 +00001105/*---------------------- mempcpy ----------------------*/
1106
sewardj841b72d2006-12-31 18:55:56 +00001107/* mempcpy */
1108#define GLIBC25_MEMPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001109 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001110 ( void *dst, const void *src, SizeT len ); \
sewardj96044842011-08-18 13:09:55 +00001111 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001112 ( void *dst, const void *src, SizeT len ) \
1113 { \
1114 register char *d; \
1115 register char *s; \
1116 SizeT len_saved = len; \
1117 \
1118 if (len == 0) \
1119 return dst; \
1120 \
1121 if (is_overlap(dst, src, len, len)) \
1122 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1123 \
1124 if ( dst > src ) { \
1125 d = (char *)dst + len - 1; \
1126 s = (char *)src + len - 1; \
1127 while ( len-- ) { \
1128 *d-- = *s--; \
1129 } \
1130 } else if ( dst < src ) { \
1131 d = (char *)dst; \
1132 s = (char *)src; \
1133 while ( len-- ) { \
1134 *d++ = *s++; \
1135 } \
1136 } \
1137 return (void*)( ((char*)dst) + len_saved ); \
1138 }
1139
njnb4cfbc42009-05-04 04:20:02 +00001140#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001141 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1142 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
1143#elif defined(VGO_darwin)
1144 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
njnb4cfbc42009-05-04 04:20:02 +00001145#endif
sewardj841b72d2006-12-31 18:55:56 +00001146
1147
sewardj3c944452011-09-05 20:39:57 +00001148/*-------------------- memcpy_chk --------------------*/
1149
sewardjb6c04032007-11-13 20:52:29 +00001150#define GLIBC26___MEMCPY_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001151 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001152 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
sewardj96044842011-08-18 13:09:55 +00001153 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001154 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1155 { \
sewardjb6c04032007-11-13 20:52:29 +00001156 register char *d; \
1157 register char *s; \
1158 \
1159 if (dstlen < len) goto badness; \
1160 \
1161 if (len == 0) \
1162 return dst; \
1163 \
1164 if (is_overlap(dst, src, len, len)) \
1165 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1166 \
1167 if ( dst > src ) { \
1168 d = (char *)dst + len - 1; \
1169 s = (char *)src + len - 1; \
1170 while ( len-- ) { \
1171 *d-- = *s--; \
1172 } \
1173 } else if ( dst < src ) { \
1174 d = (char *)dst; \
1175 s = (char *)src; \
1176 while ( len-- ) { \
1177 *d++ = *s++; \
1178 } \
1179 } \
1180 return dst; \
1181 badness: \
1182 VALGRIND_PRINTF_BACKTRACE( \
1183 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001184 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001185 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001186 /*NOTREACHED*/ \
1187 return NULL; \
1188 }
1189
sewardj3c944452011-09-05 20:39:57 +00001190#if defined(VGO_linux)
1191 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1192#elif defined(VGO_darwin)
1193#endif
sewardjb6c04032007-11-13 20:52:29 +00001194
1195
sewardj3c944452011-09-05 20:39:57 +00001196/*---------------------- strstr ----------------------*/
1197
sewardja77687c2010-08-19 13:22:34 +00001198#define STRSTR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001199 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001200 (void* haystack, void* needle); \
sewardj96044842011-08-18 13:09:55 +00001201 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001202 (void* haystack, void* needle) \
1203 { \
1204 UChar* h = (UChar*)haystack; \
1205 UChar* n = (UChar*)needle; \
1206 \
1207 /* find the length of n, not including terminating zero */ \
1208 UWord nlen = 0; \
1209 while (n[nlen]) nlen++; \
1210 \
1211 /* if n is the empty string, match immediately. */ \
1212 if (nlen == 0) return h; \
1213 \
1214 /* assert(nlen >= 1); */ \
1215 UChar n0 = n[0]; \
1216 \
1217 while (1) { \
1218 UChar hh = *h; \
1219 if (hh == 0) return NULL; \
1220 if (hh != n0) { h++; continue; } \
1221 \
1222 UWord i; \
1223 for (i = 0; i < nlen; i++) { \
1224 if (n[i] != h[i]) \
1225 break; \
1226 } \
1227 /* assert(i >= 0 && i <= nlen); */ \
1228 if (i == nlen) \
1229 return h; \
1230 \
1231 h++; \
1232 } \
1233 }
1234
1235#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001236 STRSTR(VG_Z_LIBC_SONAME, strstr)
1237#elif defined(VGO_darwin)
sewardja77687c2010-08-19 13:22:34 +00001238#endif
1239
1240
sewardj3c944452011-09-05 20:39:57 +00001241/*---------------------- strpbrk ----------------------*/
1242
sewardja77687c2010-08-19 13:22:34 +00001243#define STRPBRK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001244 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001245 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001246 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001247 (void* sV, void* acceptV) \
1248 { \
1249 UChar* s = (UChar*)sV; \
1250 UChar* accept = (UChar*)acceptV; \
1251 \
1252 /* find the length of 'accept', not including terminating zero */ \
1253 UWord nacc = 0; \
1254 while (accept[nacc]) nacc++; \
1255 \
1256 /* if n is the empty string, fail immediately. */ \
1257 if (nacc == 0) return NULL; \
1258 \
1259 /* assert(nacc >= 1); */ \
1260 while (1) { \
1261 UWord i; \
1262 UChar sc = *s; \
1263 if (sc == 0) \
1264 break; \
1265 for (i = 0; i < nacc; i++) { \
1266 if (sc == accept[i]) \
1267 return s; \
1268 } \
1269 s++; \
1270 } \
1271 \
1272 return NULL; \
1273 }
1274
1275#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001276 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1277#elif defined(VGO_darwin)
sewardja77687c2010-08-19 13:22:34 +00001278#endif
1279
1280
sewardj3c944452011-09-05 20:39:57 +00001281/*---------------------- strcspn ----------------------*/
1282
sewardja77687c2010-08-19 13:22:34 +00001283#define STRCSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001284 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001285 (void* sV, void* rejectV); \
sewardj96044842011-08-18 13:09:55 +00001286 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001287 (void* sV, void* rejectV) \
1288 { \
1289 UChar* s = (UChar*)sV; \
1290 UChar* reject = (UChar*)rejectV; \
1291 \
1292 /* find the length of 'reject', not including terminating zero */ \
1293 UWord nrej = 0; \
1294 while (reject[nrej]) nrej++; \
1295 \
1296 UWord len = 0; \
1297 while (1) { \
1298 UWord i; \
1299 UChar sc = *s; \
1300 if (sc == 0) \
1301 break; \
1302 for (i = 0; i < nrej; i++) { \
1303 if (sc == reject[i]) \
1304 break; \
1305 } \
1306 /* assert(i >= 0 && i <= nrej); */ \
1307 if (i < nrej) \
1308 break; \
1309 s++; \
1310 len++; \
1311 } \
1312 \
1313 return len; \
1314 }
1315
1316#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001317 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1318#elif defined(VGO_darwin)
sewardja77687c2010-08-19 13:22:34 +00001319#endif
1320
1321
sewardj3c944452011-09-05 20:39:57 +00001322/*---------------------- strspn ----------------------*/
1323
sewardjbd2cff22011-08-16 21:45:28 +00001324#define STRSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001325 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001326 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001327 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001328 (void* sV, void* acceptV) \
1329 { \
1330 UChar* s = (UChar*)sV; \
1331 UChar* accept = (UChar*)acceptV; \
1332 \
1333 /* find the length of 'accept', not including terminating zero */ \
1334 UWord nacc = 0; \
1335 while (accept[nacc]) nacc++; \
1336 if (nacc == 0) return 0; \
1337 \
1338 UWord len = 0; \
1339 while (1) { \
1340 UWord i; \
1341 UChar sc = *s; \
1342 if (sc == 0) \
1343 break; \
1344 for (i = 0; i < nacc; i++) { \
1345 if (sc == accept[i]) \
1346 break; \
1347 } \
1348 /* assert(i >= 0 && i <= nacc); */ \
1349 if (i == nacc) \
1350 break; \
1351 s++; \
1352 len++; \
1353 } \
1354 \
1355 return len; \
1356 }
1357
1358#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001359 STRSPN(VG_Z_LIBC_SONAME, strspn)
1360#elif defined(VGO_darwin)
sewardjbd2cff22011-08-16 21:45:28 +00001361#endif
sewardjba189352010-08-20 18:24:16 +00001362
1363
sewardj31b9ce12006-10-17 01:27:13 +00001364/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001365/*--- Improve definedness checking of process environment ---*/
1366/*------------------------------------------------------------*/
1367
sewardjddc00dd2007-11-27 11:42:47 +00001368#if defined(VGO_linux)
1369
sewardjbd2cff22011-08-16 21:45:28 +00001370/* If these wind up getting generated via a macro, so that multiple
1371 versions of each function exist (as above), use the _EZU variants
1372 to assign equivalance class tags. */
1373
sewardj3c944452011-09-05 20:39:57 +00001374/*---------------------- putenv ----------------------*/
1375
njne6154662009-02-10 04:23:41 +00001376int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1377int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001378{
1379 OrigFn fn;
1380 Word result;
1381 const char* p = string;
1382 VALGRIND_GET_ORIG_FN(fn);
1383 /* Now by walking over the string we magically produce
1384 traces when hitting undefined memory. */
1385 if (p)
1386 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001387 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001388 CALL_FN_W_W(result, fn, string);
1389 return result;
1390}
1391
sewardj3c944452011-09-05 20:39:57 +00001392
1393/*---------------------- unsetenv ----------------------*/
1394
njne6154662009-02-10 04:23:41 +00001395int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1396int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001397{
1398 OrigFn fn;
1399 Word result;
1400 const char* p = name;
1401 VALGRIND_GET_ORIG_FN(fn);
1402 /* Now by walking over the string we magically produce
1403 traces when hitting undefined memory. */
1404 if (p)
1405 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001406 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001407 CALL_FN_W_W(result, fn, name);
1408 return result;
1409}
1410
sewardj3c944452011-09-05 20:39:57 +00001411
1412/*---------------------- setenv ----------------------*/
1413
dirk09beb9e2007-04-19 09:47:32 +00001414/* setenv */
njne6154662009-02-10 04:23:41 +00001415int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001416 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001417int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001418 (const char* name, const char* value, int overwrite)
1419{
1420 OrigFn fn;
1421 Word result;
1422 const char* p;
1423 VALGRIND_GET_ORIG_FN(fn);
1424 /* Now by walking over the string we magically produce
1425 traces when hitting undefined memory. */
1426 if (name)
1427 for (p = name; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001428 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001429 if (value)
1430 for (p = value; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001431 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001432 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1433 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1434 return result;
1435}
1436
sewardjddc00dd2007-11-27 11:42:47 +00001437#endif /* defined(VGO_linux) */
1438
njn3e884182003-04-15 13:03:23 +00001439/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001440/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001441/*--------------------------------------------------------------------*/