blob: 7e680f998720e818fb7be9779490ed1389674bba [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
157#define STRRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000158 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
159 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000160 { \
161 UChar ch = (UChar)((UInt)c); \
162 UChar* p = (UChar*)s; \
163 UChar* last = NULL; \
164 while (True) { \
165 if (*p == ch) last = p; \
166 if (*p == 0) return last; \
167 p++; \
168 } \
njn3e884182003-04-15 13:03:23 +0000169 }
njn3e884182003-04-15 13:03:23 +0000170
njn16eeb4e2005-06-16 03:56:58 +0000171// Apparently rindex() is the same thing as strrchr()
njne6154662009-02-10 04:23:41 +0000172STRRCHR(VG_Z_LIBC_SONAME, strrchr)
173STRRCHR(VG_Z_LIBC_SONAME, rindex)
njnb4cfbc42009-05-04 04:20:02 +0000174#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000175STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
njne6154662009-02-10 04:23:41 +0000176STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
njnf76d27a2009-05-28 01:53:07 +0000177#elif defined(VGO_darwin)
178STRRCHR(VG_Z_DYLD, strrchr)
179STRRCHR(VG_Z_DYLD, rindex)
njnb4cfbc42009-05-04 04:20:02 +0000180#endif
njn16eeb4e2005-06-16 03:56:58 +0000181
182
183#define STRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000184 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
185 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000186 { \
187 UChar ch = (UChar)((UInt)c); \
188 UChar* p = (UChar*)s; \
189 while (True) { \
190 if (*p == ch) return p; \
191 if (*p == 0) return NULL; \
192 p++; \
193 } \
njn3e884182003-04-15 13:03:23 +0000194 }
njn3e884182003-04-15 13:03:23 +0000195
njn16eeb4e2005-06-16 03:56:58 +0000196// Apparently index() is the same thing as strchr()
njne6154662009-02-10 04:23:41 +0000197STRCHR(VG_Z_LIBC_SONAME, strchr)
njne6154662009-02-10 04:23:41 +0000198STRCHR(VG_Z_LIBC_SONAME, index)
njnb4cfbc42009-05-04 04:20:02 +0000199#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000200STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
sewardjc9b08542011-08-18 13:49:48 +0000201#if !defined(VGP_x86_linux)
202 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
203 STRCHR(VG_Z_LD_LINUX_SO_2, index)
204 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
205 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
206#endif
njnf76d27a2009-05-28 01:53:07 +0000207#elif defined(VGO_darwin)
208STRCHR(VG_Z_DYLD, strchr)
209STRCHR(VG_Z_DYLD, index)
njnb4cfbc42009-05-04 04:20:02 +0000210#endif
njn3e884182003-04-15 13:03:23 +0000211
njn3e884182003-04-15 13:03:23 +0000212
njn16eeb4e2005-06-16 03:56:58 +0000213#define STRCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000214 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000215 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000216 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000217 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000218 { \
219 const Char* src_orig = src; \
220 Char* dst_orig = dst; \
221 while (*dst) dst++; \
222 while (*src) *dst++ = *src++; \
223 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000224 \
njn16eeb4e2005-06-16 03:56:58 +0000225 /* This is a bit redundant, I think; any overlap and the strcat will */ \
226 /* go forever... or until a seg fault occurs. */ \
227 if (is_overlap(dst_orig, \
228 src_orig, \
229 (Addr)dst-(Addr)dst_orig+1, \
230 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000231 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000232 \
njn16eeb4e2005-06-16 03:56:58 +0000233 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000234 }
njn3e884182003-04-15 13:03:23 +0000235
njne6154662009-02-10 04:23:41 +0000236STRCAT(VG_Z_LIBC_SONAME, strcat)
tomd2645142009-10-29 09:27:11 +0000237#if defined(VGO_linux)
238STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
239#endif
njn16eeb4e2005-06-16 03:56:58 +0000240
241#define STRNCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000242 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000243 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000244 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000245 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000246 { \
247 const Char* src_orig = src; \
248 Char* dst_orig = dst; \
249 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000250 \
njn16eeb4e2005-06-16 03:56:58 +0000251 while (*dst) dst++; \
252 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
253 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000254 \
njn16eeb4e2005-06-16 03:56:58 +0000255 /* This checks for overlap after copying, unavoidable without */ \
256 /* pre-counting lengths... should be ok */ \
257 if (is_overlap(dst_orig, \
258 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000259 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000260 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000261 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000262 \
njn16eeb4e2005-06-16 03:56:58 +0000263 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000264 }
njn3e884182003-04-15 13:03:23 +0000265
njne6154662009-02-10 04:23:41 +0000266STRNCAT(VG_Z_LIBC_SONAME, strncat)
njnf76d27a2009-05-28 01:53:07 +0000267#if defined(VGO_darwin)
268STRNCAT(VG_Z_DYLD, strncat)
269#endif
270
271
272/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
273 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
274 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
275 Truncation occurred if retval >= n.
276*/
277#define STRLCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000278 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000279 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000280 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000281 ( char* dst, const char* src, SizeT n ) \
282 { \
283 const Char* src_orig = src; \
284 Char* dst_orig = dst; \
285 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000286 \
njnf76d27a2009-05-28 01:53:07 +0000287 while (m < n && *dst) { m++; dst++; } \
288 if (m < n) { \
289 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
290 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
291 *dst = 0; \
292 } else { \
293 /* No space to copy anything to dst. m == n */ \
294 } \
295 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
296 while (*src) { m++; src++; } \
297 /* This checks for overlap after copying, unavoidable without */ \
298 /* pre-counting lengths... should be ok */ \
299 if (is_overlap(dst_orig, \
300 src_orig, \
301 (Addr)dst-(Addr)dst_orig+1, \
302 (Addr)src-(Addr)src_orig+1)) \
303 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
sewardjbd2cff22011-08-16 21:45:28 +0000304 \
njnf76d27a2009-05-28 01:53:07 +0000305 return m; \
306 }
307
308#if defined(VGO_darwin)
309STRLCAT(VG_Z_LIBC_SONAME, strlcat)
310STRLCAT(VG_Z_DYLD, strlcat)
311#endif
sewardj31b9ce12006-10-17 01:27:13 +0000312
njn3e884182003-04-15 13:03:23 +0000313
njn16eeb4e2005-06-16 03:56:58 +0000314#define STRNLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000315 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000316 ( const char* str, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000317 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000318 ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000319 { \
320 SizeT i = 0; \
321 while (i < n && str[i] != 0) i++; \
322 return i; \
njn3e884182003-04-15 13:03:23 +0000323 }
njn3e884182003-04-15 13:03:23 +0000324
njne6154662009-02-10 04:23:41 +0000325STRNLEN(VG_Z_LIBC_SONAME, strnlen)
tomd2645142009-10-29 09:27:11 +0000326#if defined(VGO_linux)
327STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
328#endif
njn16eeb4e2005-06-16 03:56:58 +0000329
sewardj3ceec242003-07-30 21:24:25 +0000330
njn5ec15ed2005-08-24 19:55:51 +0000331// Note that this replacement often doesn't get used because gcc inlines
332// calls to strlen() with its own built-in version. This can be very
333// confusing if you aren't expecting it. Other small functions in this file
334// may also be inline by gcc.
njn16eeb4e2005-06-16 03:56:58 +0000335#define STRLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000336 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000337 ( const char* str ); \
sewardj96044842011-08-18 13:09:55 +0000338 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000339 ( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000340 { \
341 SizeT i = 0; \
342 while (str[i] != 0) i++; \
343 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000344 }
njn16eeb4e2005-06-16 03:56:58 +0000345
njnb4cfbc42009-05-04 04:20:02 +0000346STRLEN(VG_Z_LIBC_SONAME, strlen)
347#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000348STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
njnb4cfbc42009-05-04 04:20:02 +0000349#endif
sewardj31b9ce12006-10-17 01:27:13 +0000350
njn16eeb4e2005-06-16 03:56:58 +0000351
352#define STRCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000353 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000354 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000355 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000356 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000357 { \
358 const Char* src_orig = src; \
359 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000360 \
njn16eeb4e2005-06-16 03:56:58 +0000361 while (*src) *dst++ = *src++; \
362 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000363 \
njn16eeb4e2005-06-16 03:56:58 +0000364 /* This checks for overlap after copying, unavoidable without */ \
365 /* pre-counting length... should be ok */ \
366 if (is_overlap(dst_orig, \
367 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000368 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000369 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000370 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000371 \
njn16eeb4e2005-06-16 03:56:58 +0000372 return dst_orig; \
373 }
374
njne6154662009-02-10 04:23:41 +0000375STRCPY(VG_Z_LIBC_SONAME, strcpy)
tomd2645142009-10-29 09:27:11 +0000376#if defined(VGO_linux)
377STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
378#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000379STRCPY(VG_Z_DYLD, strcpy)
380#endif
njn16eeb4e2005-06-16 03:56:58 +0000381
382
383#define STRNCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000384 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000385 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000386 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000387 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000388 { \
389 const Char* src_orig = src; \
390 Char* dst_orig = dst; \
391 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000392 \
njn16eeb4e2005-06-16 03:56:58 +0000393 while (m < n && *src) { m++; *dst++ = *src++; } \
394 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
395 /* but only m+1 bytes of src if terminator was found */ \
396 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000397 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000398 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
399 \
400 return dst_orig; \
401 }
402
njne6154662009-02-10 04:23:41 +0000403STRNCPY(VG_Z_LIBC_SONAME, strncpy)
tomd2645142009-10-29 09:27:11 +0000404#if defined(VGO_linux)
405STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
406#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000407STRNCPY(VG_Z_DYLD, strncpy)
408#endif
409
410
411/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
412 Returns strlen(src). Does not zero-fill the remainder of dst. */
413#define STRLCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000414 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000415 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000416 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000417 ( char* dst, const char* src, SizeT n ) \
418 { \
419 const char* src_orig = src; \
420 char* dst_orig = dst; \
421 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000422 \
njnf76d27a2009-05-28 01:53:07 +0000423 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
424 /* m non-nul bytes have now been copied, and m <= n-1. */ \
425 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
426 /* but only m+1 bytes of src if terminator was found */ \
427 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
428 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
429 /* Nul-terminate dst. */ \
430 if (n > 0) *dst = 0; \
431 /* Finish counting strlen(src). */ \
432 while (*src) src++; \
433 return src - src_orig; \
434 }
435
436#if defined(VGO_darwin)
437STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
438STRLCPY(VG_Z_DYLD, strlcpy)
439#endif
njn16eeb4e2005-06-16 03:56:58 +0000440
441
442#define STRNCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000443 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000444 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000445 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000446 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000447 { \
448 SizeT n = 0; \
449 while (True) { \
450 if (n >= nmax) return 0; \
451 if (*s1 == 0 && *s2 == 0) return 0; \
452 if (*s1 == 0) return -1; \
453 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000454 \
njn16eeb4e2005-06-16 03:56:58 +0000455 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
456 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000457 \
njn16eeb4e2005-06-16 03:56:58 +0000458 s1++; s2++; n++; \
459 } \
460 }
461
njne6154662009-02-10 04:23:41 +0000462STRNCMP(VG_Z_LIBC_SONAME, strncmp)
tomd2645142009-10-29 09:27:11 +0000463#if defined(VGO_linux)
464STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
465#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000466STRNCMP(VG_Z_DYLD, strncmp)
467#endif
njn16eeb4e2005-06-16 03:56:58 +0000468
469
tomce6d0ac2010-11-12 10:03:13 +0000470#define STRCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000471 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000472 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000473 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000474 ( const char* s1, const char* s2 ) \
475 { \
tome03c8c42010-11-12 10:40:20 +0000476 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000477 register unsigned char c1; \
478 register unsigned char c2; \
479 while (True) { \
480 c1 = tolower(*(unsigned char *)s1); \
481 c2 = tolower(*(unsigned char *)s2); \
482 if (c1 != c2) break; \
483 if (c1 == 0) break; \
484 s1++; s2++; \
485 } \
486 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
487 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
488 return 0; \
489 }
490
sewardj126e82d2011-07-12 13:33:00 +0000491#if !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000492STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
sewardj126e82d2011-07-12 13:33:00 +0000493#endif
494#if defined(VGO_linux) && !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000495STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
496#endif
497
498
499#define STRNCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000500 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000501 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000502 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000503 ( const char* s1, const char* s2, SizeT nmax ) \
504 { \
tome03c8c42010-11-12 10:40:20 +0000505 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000506 SizeT n = 0; \
507 while (True) { \
508 if (n >= nmax) return 0; \
509 if (*s1 == 0 && *s2 == 0) return 0; \
510 if (*s1 == 0) return -1; \
511 if (*s2 == 0) return 1; \
512 \
sewardjbd2cff22011-08-16 21:45:28 +0000513 if (tolower(*(unsigned char*)s1) \
514 < tolower(*(unsigned char*)s2)) return -1; \
515 if (tolower(*(unsigned char*)s1) \
516 > tolower(*(unsigned char*)s2)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000517 \
518 s1++; s2++; n++; \
519 } \
520 }
521
sewardj126e82d2011-07-12 13:33:00 +0000522#if !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000523STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
sewardj126e82d2011-07-12 13:33:00 +0000524#endif
525#if defined(VGO_linux) && !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000526STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
527#elif defined(VGO_darwin)
528STRNCASECMP(VG_Z_DYLD, strncasecmp)
529#endif
530
531
tomce6d0ac2010-11-12 10:03:13 +0000532#define STRCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000533 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000534 ( const char* s1, const char* s2, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000535 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000536 ( const char* s1, const char* s2, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000537 { \
tome03c8c42010-11-12 10:40:20 +0000538 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000539 register unsigned char c1; \
540 register unsigned char c2; \
541 while (True) { \
542 c1 = tolower_l(*(unsigned char *)s1, locale); \
543 c2 = tolower_l(*(unsigned char *)s2, locale); \
544 if (c1 != c2) break; \
545 if (c1 == 0) break; \
546 s1++; s2++; \
547 } \
548 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
549 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
550 return 0; \
551 }
552
553STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
554#if defined(VGO_linux)
555STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
sewardjbd2cff22011-08-16 21:45:28 +0000556STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
tomce6d0ac2010-11-12 10:03:13 +0000557#endif
558
559
560#define STRNCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000561 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000562 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000563 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000564 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000565 { \
tome03c8c42010-11-12 10:40:20 +0000566 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000567 SizeT n = 0; \
568 while (True) { \
569 if (n >= nmax) return 0; \
570 if (*s1 == 0 && *s2 == 0) return 0; \
571 if (*s1 == 0) return -1; \
572 if (*s2 == 0) return 1; \
573 \
sewardjbd2cff22011-08-16 21:45:28 +0000574 if (tolower_l(*(unsigned char*)s1, locale) \
575 < tolower_l(*(unsigned char*)s2, locale)) return -1; \
576 if (tolower_l(*(unsigned char*)s1, locale) \
577 > tolower_l(*(unsigned char*)s2, locale)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000578 \
579 s1++; s2++; n++; \
580 } \
581 }
582
583STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
584#if defined(VGO_linux)
585STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
586#elif defined(VGO_darwin)
587STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
588#endif
589
590
njn16eeb4e2005-06-16 03:56:58 +0000591#define STRCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000592 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000593 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000594 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000595 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000596 { \
597 register unsigned char c1; \
598 register unsigned char c2; \
599 while (True) { \
600 c1 = *(unsigned char *)s1; \
601 c2 = *(unsigned char *)s2; \
602 if (c1 != c2) break; \
603 if (c1 == 0) break; \
604 s1++; s2++; \
605 } \
606 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
607 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
608 return 0; \
609 }
610
njne6154662009-02-10 04:23:41 +0000611STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000612#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000613STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
njne6154662009-02-10 04:23:41 +0000614STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
615STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000616#endif
njn16eeb4e2005-06-16 03:56:58 +0000617
618
619#define MEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000620 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000621 (const void *s, int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000622 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000623 (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000624 { \
625 SizeT i; \
626 UChar c0 = (UChar)c; \
627 UChar* p = (UChar*)s; \
628 for (i = 0; i < n; i++) \
629 if (p[i] == c0) return (void*)(&p[i]); \
630 return NULL; \
631 }
632
njne6154662009-02-10 04:23:41 +0000633MEMCHR(VG_Z_LIBC_SONAME, memchr)
njnf76d27a2009-05-28 01:53:07 +0000634#if defined(VGO_darwin)
635MEMCHR(VG_Z_DYLD, memchr)
636#endif
njn16eeb4e2005-06-16 03:56:58 +0000637
638
sewardjbd2cff22011-08-16 21:45:28 +0000639#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
sewardjd88797f2011-08-17 21:25:50 +0000640 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000641 ( void *dst, const void *src, SizeT len ); \
sewardjd88797f2011-08-17 21:25:50 +0000642 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000643 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000644 { \
sewardjbd2cff22011-08-16 21:45:28 +0000645 if (do_ol_check && is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000646 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000647 \
sewardj7b4e00b2010-08-24 09:05:52 +0000648 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
649 const Addr WM = WS - 1; /* 7 or 3 */ \
650 \
tom863ab7c2011-08-18 08:10:20 +0000651 if (len > 0) { \
652 if (dst < src) { \
sewardj7b4e00b2010-08-24 09:05:52 +0000653 \
tom863ab7c2011-08-18 08:10:20 +0000654 /* Copying backwards. */ \
655 SizeT n = len; \
656 Addr d = (Addr)dst; \
657 Addr s = (Addr)src; \
658 \
659 if (((s^d) & WM) == 0) { \
660 /* s and d have same UWord alignment. */ \
661 /* Pull up to a UWord boundary. */ \
662 while ((s & WM) != 0 && n >= 1) \
663 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
664 /* Copy UWords. */ \
665 while (n >= WS) \
666 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
667 if (n == 0) \
668 return dst; \
669 } \
670 if (((s|d) & 1) == 0) { \
671 /* Both are 16-aligned; copy what we can thusly. */ \
672 while (n >= 2) \
673 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
674 } \
675 /* Copy leftovers, or everything if misaligned. */ \
676 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000677 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
sewardj7b4e00b2010-08-24 09:05:52 +0000678 \
tom863ab7c2011-08-18 08:10:20 +0000679 } else if (dst > src) { \
680 \
681 SizeT n = len; \
682 Addr d = ((Addr)dst) + n; \
683 Addr s = ((Addr)src) + n; \
684 \
685 /* Copying forwards. */ \
686 if (((s^d) & WM) == 0) { \
687 /* s and d have same UWord alignment. */ \
688 /* Back down to a UWord boundary. */ \
689 while ((s & WM) != 0 && n >= 1) \
690 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
691 /* Copy UWords. */ \
692 while (n >= WS) \
693 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
694 if (n == 0) \
695 return dst; \
696 } \
697 if (((s|d) & 1) == 0) { \
698 /* Both are 16-aligned; copy what we can thusly. */ \
699 while (n >= 2) \
700 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
701 } \
702 /* Copy leftovers, or everything if misaligned. */ \
703 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000704 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
tom863ab7c2011-08-18 08:10:20 +0000705 \
njn16eeb4e2005-06-16 03:56:58 +0000706 } \
njn16eeb4e2005-06-16 03:56:58 +0000707 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000708 \
njn16eeb4e2005-06-16 03:56:58 +0000709 return dst; \
710 }
711
sewardjbd2cff22011-08-16 21:45:28 +0000712#define MEMMOVE(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000713 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
sewardjbd2cff22011-08-16 21:45:28 +0000714
715#define MEMCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000716 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
sewardjbd2cff22011-08-16 21:45:28 +0000717
njnb4cfbc42009-05-04 04:20:02 +0000718#if defined(VGO_linux)
sewardjbd2cff22011-08-16 21:45:28 +0000719/* For older memcpy we have to use memmove-like semantics and skip the
720 overlap check; sigh; see #275284. */
sewardjd88797f2011-08-17 21:25:50 +0000721MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
722MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
sewardj96044842011-08-18 13:09:55 +0000723MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
sewardjd88797f2011-08-17 21:25:50 +0000724MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
725MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnf76d27a2009-05-28 01:53:07 +0000726#elif defined(VGO_darwin)
sewardjd88797f2011-08-17 21:25:50 +0000727MEMCPY(VG_Z_LIBC_SONAME, memcpy)
728MEMCPY(VG_Z_DYLD, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000729#endif
sewardjf0b34322007-01-16 21:42:28 +0000730/* icc9 blats these around all over the place. Not only in the main
731 executable but various .so's. They are highly tuned and read
732 memory beyond the source boundary (although work correctly and
733 never go across page boundaries), so give errors when run natively,
734 at least for misaligned source arg. Just intercepting in the exe
735 only until we understand more about the problem. See
736 http://bugs.kde.org/show_bug.cgi?id=139776
737 */
sewardjd88797f2011-08-17 21:25:50 +0000738MEMCPY(NONE, ZuintelZufastZumemcpy)
sewardj31b9ce12006-10-17 01:27:13 +0000739
njn16eeb4e2005-06-16 03:56:58 +0000740
741#define MEMCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000742 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000743 ( const void *s1V, const void *s2V, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000744 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000745 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000746 { \
747 int res; \
748 unsigned char a0; \
749 unsigned char b0; \
750 unsigned char* s1 = (unsigned char*)s1V; \
751 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000752 \
njn16eeb4e2005-06-16 03:56:58 +0000753 while (n != 0) { \
754 a0 = s1[0]; \
755 b0 = s2[0]; \
756 s1 += 1; \
757 s2 += 1; \
758 res = ((int)a0) - ((int)b0); \
759 if (res != 0) \
760 return res; \
761 n -= 1; \
762 } \
763 return 0; \
764 }
765
njne6154662009-02-10 04:23:41 +0000766MEMCMP(VG_Z_LIBC_SONAME, memcmp)
767MEMCMP(VG_Z_LIBC_SONAME, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000768#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000769MEMCMP(VG_Z_LD_SO_1, bcmp)
njnf76d27a2009-05-28 01:53:07 +0000770#elif defined(VGO_darwin)
771MEMCMP(VG_Z_DYLD, memcmp)
772MEMCMP(VG_Z_DYLD, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000773#endif
njn3e884182003-04-15 13:03:23 +0000774
jseward0845ef82003-12-22 22:31:27 +0000775
776/* Copy SRC to DEST, returning the address of the terminating '\0' in
777 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000778#define STPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000779 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000780 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000781 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000782 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000783 { \
784 const Char* src_orig = src; \
785 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000786 \
njn16eeb4e2005-06-16 03:56:58 +0000787 while (*src) *dst++ = *src++; \
788 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000789 \
njn16eeb4e2005-06-16 03:56:58 +0000790 /* This checks for overlap after copying, unavoidable without */ \
791 /* pre-counting length... should be ok */ \
792 if (is_overlap(dst_orig, \
793 src_orig, \
794 (Addr)dst-(Addr)dst_orig+1, \
795 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000796 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000797 \
njn16eeb4e2005-06-16 03:56:58 +0000798 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000799 }
njn16eeb4e2005-06-16 03:56:58 +0000800
njne6154662009-02-10 04:23:41 +0000801STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000802#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000803STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
njne6154662009-02-10 04:23:41 +0000804STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
805STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnf76d27a2009-05-28 01:53:07 +0000806#elif defined(VGO_darwin)
807STPCPY(VG_Z_DYLD, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000808#endif
809
njn16eeb4e2005-06-16 03:56:58 +0000810
811#define MEMSET(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000812 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000813 (void *s, Int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000814 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000815 (void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000816 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000817 Addr a = (Addr)s; \
818 UInt c4 = (c & 0xFF); \
819 c4 = (c4 << 8) | c4; \
820 c4 = (c4 << 16) | c4; \
821 while ((a & 3) != 0 && n >= 1) \
822 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
823 while (n >= 4) \
824 { *(UInt*)a = c4; a += 4; n -= 4; } \
825 while (n >= 1) \
826 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000827 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000828 }
njn16eeb4e2005-06-16 03:56:58 +0000829
njne6154662009-02-10 04:23:41 +0000830MEMSET(VG_Z_LIBC_SONAME, memset)
njnf76d27a2009-05-28 01:53:07 +0000831#if defined(VGO_darwin)
832MEMSET(VG_Z_DYLD, memset)
833#endif
njn16eeb4e2005-06-16 03:56:58 +0000834
835
sewardj96044842011-08-18 13:09:55 +0000836/* memmove -- use the MEMMOVE defn above. */
njne6154662009-02-10 04:23:41 +0000837MEMMOVE(VG_Z_LIBC_SONAME, memmove)
njnf76d27a2009-05-28 01:53:07 +0000838#if defined(VGO_darwin)
839MEMMOVE(VG_Z_DYLD, memmove)
840#endif
841
842
843#define BCOPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000844 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000845 (const void *srcV, void *dstV, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000846 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000847 (const void *srcV, void *dstV, SizeT n) \
848 { \
849 SizeT i; \
850 Char* dst = (Char*)dstV; \
851 Char* src = (Char*)srcV; \
852 if (dst < src) { \
853 for (i = 0; i < n; i++) \
854 dst[i] = src[i]; \
855 } \
856 else \
857 if (dst > src) { \
858 for (i = 0; i < n; i++) \
859 dst[n-i-1] = src[n-i-1]; \
860 } \
861 }
862
863#if defined(VGO_darwin)
864BCOPY(VG_Z_LIBC_SONAME, bcopy)
865BCOPY(VG_Z_DYLD, bcopy)
866#endif
sewardj44e495f2005-05-12 17:58:28 +0000867
jseward0845ef82003-12-22 22:31:27 +0000868
sewardj24cb2172007-02-23 09:03:26 +0000869/* glibc 2.5 variant of memmove which checks the dest is big enough.
870 There is no specific part of glibc that this is copied from. */
871#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000872 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +0000873 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
sewardj96044842011-08-18 13:09:55 +0000874 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +0000875 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
876 { \
sewardj24cb2172007-02-23 09:03:26 +0000877 SizeT i; \
878 Char* dst = (Char*)dstV; \
879 Char* src = (Char*)srcV; \
880 if (destlen < n) \
881 goto badness; \
882 if (dst < src) { \
883 for (i = 0; i < n; i++) \
884 dst[i] = src[i]; \
885 } \
886 else \
887 if (dst > src) { \
888 for (i = 0; i < n; i++) \
889 dst[n-i-1] = src[n-i-1]; \
890 } \
891 return dst; \
892 badness: \
893 VALGRIND_PRINTF_BACKTRACE( \
894 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000895 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000896 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +0000897 /*NOTREACHED*/ \
898 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +0000899 }
900
njne6154662009-02-10 04:23:41 +0000901GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj24cb2172007-02-23 09:03:26 +0000902
903
sewardj4e9a4b62004-11-23 00:20:17 +0000904/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000905#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000906 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000907 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +0000908 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000909 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000910 { \
911 unsigned char c = (unsigned char) c_in; \
912 unsigned char* char_ptr = (unsigned char *)s; \
913 while (1) { \
914 if (*char_ptr == 0) return char_ptr; \
915 if (*char_ptr == c) return char_ptr; \
916 char_ptr++; \
917 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000918 }
njn16eeb4e2005-06-16 03:56:58 +0000919
njne6154662009-02-10 04:23:41 +0000920GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000921
922
923/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000924#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000925 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000926 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +0000927 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000928 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +0000929 { \
930 unsigned char c = (unsigned char) c_in; \
931 unsigned char* char_ptr = (unsigned char *)s; \
932 while (1) { \
933 if (*char_ptr == c) return char_ptr; \
934 char_ptr++; \
935 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000936 }
njn16eeb4e2005-06-16 03:56:58 +0000937
njne6154662009-02-10 04:23:41 +0000938GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
tomd2645142009-10-29 09:27:11 +0000939#if defined (VGO_linux)
940GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
941#endif
sewardj4e9a4b62004-11-23 00:20:17 +0000942
sewardjdc5d8322007-01-28 06:32:01 +0000943/* glibc variant of strcpy that checks the dest is big enough.
944 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +0000945#define GLIBC25___STRCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000946 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000947 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +0000948 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000949 (char* dst, const char* src, SizeT len) \
sewardj620e5262006-12-31 00:22:30 +0000950 { \
sewardj620e5262006-12-31 00:22:30 +0000951 char* ret = dst; \
952 if (! len) \
953 goto badness; \
954 while ((*dst++ = *src++) != '\0') \
955 if (--len == 0) \
956 goto badness; \
957 return ret; \
958 badness: \
959 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000960 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000961 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000962 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +0000963 /*NOTREACHED*/ \
964 return NULL; \
965 }
966
njne6154662009-02-10 04:23:41 +0000967GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj620e5262006-12-31 00:22:30 +0000968
969
sewardjdc5d8322007-01-28 06:32:01 +0000970/* glibc variant of stpcpy that checks the dest is big enough.
971 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +0000972#define GLIBC25___STPCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000973 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000974 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +0000975 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000976 (char* dst, const char* src, SizeT len) \
sewardjb8d03852007-01-27 00:49:44 +0000977 { \
sewardjdc5d8322007-01-28 06:32:01 +0000978 if (! len) \
979 goto badness; \
980 while ((*dst++ = *src++) != '\0') \
981 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +0000982 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +0000983 return dst - 1; \
984 badness: \
985 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000986 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000987 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000988 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +0000989 /*NOTREACHED*/ \
990 return NULL; \
991 }
992
njne6154662009-02-10 04:23:41 +0000993GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardjb8d03852007-01-27 00:49:44 +0000994
995
sewardj841b72d2006-12-31 18:55:56 +0000996/* mempcpy */
997#define GLIBC25_MEMPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000998 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +0000999 ( void *dst, const void *src, SizeT len ); \
sewardj96044842011-08-18 13:09:55 +00001000 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001001 ( void *dst, const void *src, SizeT len ) \
1002 { \
1003 register char *d; \
1004 register char *s; \
1005 SizeT len_saved = len; \
1006 \
1007 if (len == 0) \
1008 return dst; \
1009 \
1010 if (is_overlap(dst, src, len, len)) \
1011 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1012 \
1013 if ( dst > src ) { \
1014 d = (char *)dst + len - 1; \
1015 s = (char *)src + len - 1; \
1016 while ( len-- ) { \
1017 *d-- = *s--; \
1018 } \
1019 } else if ( dst < src ) { \
1020 d = (char *)dst; \
1021 s = (char *)src; \
1022 while ( len-- ) { \
1023 *d++ = *s++; \
1024 } \
1025 } \
1026 return (void*)( ((char*)dst) + len_saved ); \
1027 }
1028
njne6154662009-02-10 04:23:41 +00001029GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
njnb4cfbc42009-05-04 04:20:02 +00001030#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00001031GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
njnb4cfbc42009-05-04 04:20:02 +00001032#endif
sewardj841b72d2006-12-31 18:55:56 +00001033
1034
sewardjb6c04032007-11-13 20:52:29 +00001035#define GLIBC26___MEMCPY_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001036 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001037 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
sewardj96044842011-08-18 13:09:55 +00001038 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001039 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1040 { \
sewardjb6c04032007-11-13 20:52:29 +00001041 register char *d; \
1042 register char *s; \
1043 \
1044 if (dstlen < len) goto badness; \
1045 \
1046 if (len == 0) \
1047 return dst; \
1048 \
1049 if (is_overlap(dst, src, len, len)) \
1050 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1051 \
1052 if ( dst > src ) { \
1053 d = (char *)dst + len - 1; \
1054 s = (char *)src + len - 1; \
1055 while ( len-- ) { \
1056 *d-- = *s--; \
1057 } \
1058 } else if ( dst < src ) { \
1059 d = (char *)dst; \
1060 s = (char *)src; \
1061 while ( len-- ) { \
1062 *d++ = *s++; \
1063 } \
1064 } \
1065 return dst; \
1066 badness: \
1067 VALGRIND_PRINTF_BACKTRACE( \
1068 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001069 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001070 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001071 /*NOTREACHED*/ \
1072 return NULL; \
1073 }
1074
njne6154662009-02-10 04:23:41 +00001075GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardjb6c04032007-11-13 20:52:29 +00001076
1077
sewardja77687c2010-08-19 13:22:34 +00001078#define STRSTR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001079 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001080 (void* haystack, void* needle); \
sewardj96044842011-08-18 13:09:55 +00001081 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001082 (void* haystack, void* needle) \
1083 { \
1084 UChar* h = (UChar*)haystack; \
1085 UChar* n = (UChar*)needle; \
1086 \
1087 /* find the length of n, not including terminating zero */ \
1088 UWord nlen = 0; \
1089 while (n[nlen]) nlen++; \
1090 \
1091 /* if n is the empty string, match immediately. */ \
1092 if (nlen == 0) return h; \
1093 \
1094 /* assert(nlen >= 1); */ \
1095 UChar n0 = n[0]; \
1096 \
1097 while (1) { \
1098 UChar hh = *h; \
1099 if (hh == 0) return NULL; \
1100 if (hh != n0) { h++; continue; } \
1101 \
1102 UWord i; \
1103 for (i = 0; i < nlen; i++) { \
1104 if (n[i] != h[i]) \
1105 break; \
1106 } \
1107 /* assert(i >= 0 && i <= nlen); */ \
1108 if (i == nlen) \
1109 return h; \
1110 \
1111 h++; \
1112 } \
1113 }
1114
1115#if defined(VGO_linux)
1116STRSTR(VG_Z_LIBC_SONAME, strstr)
1117#endif
1118
1119
1120#define STRPBRK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001121 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001122 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001123 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001124 (void* sV, void* acceptV) \
1125 { \
1126 UChar* s = (UChar*)sV; \
1127 UChar* accept = (UChar*)acceptV; \
1128 \
1129 /* find the length of 'accept', not including terminating zero */ \
1130 UWord nacc = 0; \
1131 while (accept[nacc]) nacc++; \
1132 \
1133 /* if n is the empty string, fail immediately. */ \
1134 if (nacc == 0) return NULL; \
1135 \
1136 /* assert(nacc >= 1); */ \
1137 while (1) { \
1138 UWord i; \
1139 UChar sc = *s; \
1140 if (sc == 0) \
1141 break; \
1142 for (i = 0; i < nacc; i++) { \
1143 if (sc == accept[i]) \
1144 return s; \
1145 } \
1146 s++; \
1147 } \
1148 \
1149 return NULL; \
1150 }
1151
1152#if defined(VGO_linux)
1153STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1154#endif
1155
1156
1157#define STRCSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001158 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001159 (void* sV, void* rejectV); \
sewardj96044842011-08-18 13:09:55 +00001160 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001161 (void* sV, void* rejectV) \
1162 { \
1163 UChar* s = (UChar*)sV; \
1164 UChar* reject = (UChar*)rejectV; \
1165 \
1166 /* find the length of 'reject', not including terminating zero */ \
1167 UWord nrej = 0; \
1168 while (reject[nrej]) nrej++; \
1169 \
1170 UWord len = 0; \
1171 while (1) { \
1172 UWord i; \
1173 UChar sc = *s; \
1174 if (sc == 0) \
1175 break; \
1176 for (i = 0; i < nrej; i++) { \
1177 if (sc == reject[i]) \
1178 break; \
1179 } \
1180 /* assert(i >= 0 && i <= nrej); */ \
1181 if (i < nrej) \
1182 break; \
1183 s++; \
1184 len++; \
1185 } \
1186 \
1187 return len; \
1188 }
1189
1190#if defined(VGO_linux)
1191STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1192#endif
1193
1194
sewardjbd2cff22011-08-16 21:45:28 +00001195#define STRSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001196 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001197 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001198 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001199 (void* sV, void* acceptV) \
1200 { \
1201 UChar* s = (UChar*)sV; \
1202 UChar* accept = (UChar*)acceptV; \
1203 \
1204 /* find the length of 'accept', not including terminating zero */ \
1205 UWord nacc = 0; \
1206 while (accept[nacc]) nacc++; \
1207 if (nacc == 0) return 0; \
1208 \
1209 UWord len = 0; \
1210 while (1) { \
1211 UWord i; \
1212 UChar sc = *s; \
1213 if (sc == 0) \
1214 break; \
1215 for (i = 0; i < nacc; i++) { \
1216 if (sc == accept[i]) \
1217 break; \
1218 } \
1219 /* assert(i >= 0 && i <= nacc); */ \
1220 if (i == nacc) \
1221 break; \
1222 s++; \
1223 len++; \
1224 } \
1225 \
1226 return len; \
1227 }
1228
1229#if defined(VGO_linux)
1230STRSPN(VG_Z_LIBC_SONAME, strspn)
1231#endif
sewardjba189352010-08-20 18:24:16 +00001232
1233
sewardj31b9ce12006-10-17 01:27:13 +00001234/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001235/*--- Improve definedness checking of process environment ---*/
1236/*------------------------------------------------------------*/
1237
sewardjddc00dd2007-11-27 11:42:47 +00001238#if defined(VGO_linux)
1239
sewardjbd2cff22011-08-16 21:45:28 +00001240/* If these wind up getting generated via a macro, so that multiple
1241 versions of each function exist (as above), use the _EZU variants
1242 to assign equivalance class tags. */
1243
dirk09beb9e2007-04-19 09:47:32 +00001244/* putenv */
njne6154662009-02-10 04:23:41 +00001245int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1246int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001247{
1248 OrigFn fn;
1249 Word result;
1250 const char* p = string;
1251 VALGRIND_GET_ORIG_FN(fn);
1252 /* Now by walking over the string we magically produce
1253 traces when hitting undefined memory. */
1254 if (p)
1255 while (*p++)
1256 ;
1257 CALL_FN_W_W(result, fn, string);
1258 return result;
1259}
1260
1261/* unsetenv */
njne6154662009-02-10 04:23:41 +00001262int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1263int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001264{
1265 OrigFn fn;
1266 Word result;
1267 const char* p = name;
1268 VALGRIND_GET_ORIG_FN(fn);
1269 /* Now by walking over the string we magically produce
1270 traces when hitting undefined memory. */
1271 if (p)
1272 while (*p++)
1273 ;
1274 CALL_FN_W_W(result, fn, name);
1275 return result;
1276}
1277
1278/* setenv */
njne6154662009-02-10 04:23:41 +00001279int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001280 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001281int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001282 (const char* name, const char* value, int overwrite)
1283{
1284 OrigFn fn;
1285 Word result;
1286 const char* p;
1287 VALGRIND_GET_ORIG_FN(fn);
1288 /* Now by walking over the string we magically produce
1289 traces when hitting undefined memory. */
1290 if (name)
1291 for (p = name; *p; p++)
1292 ;
1293 if (value)
1294 for (p = value; *p; p++)
1295 ;
1296 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1297 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1298 return result;
1299}
1300
sewardjddc00dd2007-11-27 11:42:47 +00001301#endif /* defined(VGO_linux) */
1302
njn3e884182003-04-15 13:03:23 +00001303/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001304/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001305/*--------------------------------------------------------------------*/