blob: 42f8eceae5eaa66d9ea0361dcffae69a6fbb8c14 [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)
njnb4cfbc42009-05-04 04:20:02 +0000201STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
njne6154662009-02-10 04:23:41 +0000202STRCHR(VG_Z_LD_LINUX_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +0000203STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
njne6154662009-02-10 04:23:41 +0000204STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
njnf76d27a2009-05-28 01:53:07 +0000205#elif defined(VGO_darwin)
206STRCHR(VG_Z_DYLD, strchr)
207STRCHR(VG_Z_DYLD, index)
njnb4cfbc42009-05-04 04:20:02 +0000208#endif
njn3e884182003-04-15 13:03:23 +0000209
njn3e884182003-04-15 13:03:23 +0000210
njn16eeb4e2005-06-16 03:56:58 +0000211#define STRCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000212 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000213 ( char* dst, const char* src ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000216 { \
217 const Char* src_orig = src; \
218 Char* dst_orig = dst; \
219 while (*dst) dst++; \
220 while (*src) *dst++ = *src++; \
221 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000222 \
njn16eeb4e2005-06-16 03:56:58 +0000223 /* This is a bit redundant, I think; any overlap and the strcat will */ \
224 /* go forever... or until a seg fault occurs. */ \
225 if (is_overlap(dst_orig, \
226 src_orig, \
227 (Addr)dst-(Addr)dst_orig+1, \
228 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000229 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000230 \
njn16eeb4e2005-06-16 03:56:58 +0000231 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000232 }
njn3e884182003-04-15 13:03:23 +0000233
njne6154662009-02-10 04:23:41 +0000234STRCAT(VG_Z_LIBC_SONAME, strcat)
tomd2645142009-10-29 09:27:11 +0000235#if defined(VGO_linux)
236STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
237#endif
njn16eeb4e2005-06-16 03:56:58 +0000238
239#define STRNCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000240 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000241 ( char* dst, const char* src, SizeT n ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000244 { \
245 const Char* src_orig = src; \
246 Char* dst_orig = dst; \
247 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000248 \
njn16eeb4e2005-06-16 03:56:58 +0000249 while (*dst) dst++; \
250 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
251 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000252 \
njn16eeb4e2005-06-16 03:56:58 +0000253 /* This checks for overlap after copying, unavoidable without */ \
254 /* pre-counting lengths... should be ok */ \
255 if (is_overlap(dst_orig, \
256 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000257 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000258 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000259 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000260 \
njn16eeb4e2005-06-16 03:56:58 +0000261 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000262 }
njn3e884182003-04-15 13:03:23 +0000263
njne6154662009-02-10 04:23:41 +0000264STRNCAT(VG_Z_LIBC_SONAME, strncat)
njnf76d27a2009-05-28 01:53:07 +0000265#if defined(VGO_darwin)
266STRNCAT(VG_Z_DYLD, strncat)
267#endif
268
269
270/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
271 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
272 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
273 Truncation occurred if retval >= n.
274*/
275#define STRLCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000276 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000277 ( char* dst, const char* src, SizeT n ); \
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 ) \
280 { \
281 const Char* src_orig = src; \
282 Char* dst_orig = dst; \
283 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000284 \
njnf76d27a2009-05-28 01:53:07 +0000285 while (m < n && *dst) { m++; dst++; } \
286 if (m < n) { \
287 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
288 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
289 *dst = 0; \
290 } else { \
291 /* No space to copy anything to dst. m == n */ \
292 } \
293 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
294 while (*src) { m++; src++; } \
295 /* This checks for overlap after copying, unavoidable without */ \
296 /* pre-counting lengths... should be ok */ \
297 if (is_overlap(dst_orig, \
298 src_orig, \
299 (Addr)dst-(Addr)dst_orig+1, \
300 (Addr)src-(Addr)src_orig+1)) \
301 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
sewardjbd2cff22011-08-16 21:45:28 +0000302 \
njnf76d27a2009-05-28 01:53:07 +0000303 return m; \
304 }
305
306#if defined(VGO_darwin)
307STRLCAT(VG_Z_LIBC_SONAME, strlcat)
308STRLCAT(VG_Z_DYLD, strlcat)
309#endif
sewardj31b9ce12006-10-17 01:27:13 +0000310
njn3e884182003-04-15 13:03:23 +0000311
njn16eeb4e2005-06-16 03:56:58 +0000312#define STRNLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000313 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000314 ( const char* str, SizeT n ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000317 { \
318 SizeT i = 0; \
319 while (i < n && str[i] != 0) i++; \
320 return i; \
njn3e884182003-04-15 13:03:23 +0000321 }
njn3e884182003-04-15 13:03:23 +0000322
njne6154662009-02-10 04:23:41 +0000323STRNLEN(VG_Z_LIBC_SONAME, strnlen)
tomd2645142009-10-29 09:27:11 +0000324#if defined(VGO_linux)
325STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
326#endif
njn16eeb4e2005-06-16 03:56:58 +0000327
sewardj3ceec242003-07-30 21:24:25 +0000328
njn5ec15ed2005-08-24 19:55:51 +0000329// Note that this replacement often doesn't get used because gcc inlines
330// calls to strlen() with its own built-in version. This can be very
331// confusing if you aren't expecting it. Other small functions in this file
332// may also be inline by gcc.
njn16eeb4e2005-06-16 03:56:58 +0000333#define STRLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000334 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000335 ( const char* str ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000338 { \
339 SizeT i = 0; \
340 while (str[i] != 0) i++; \
341 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000342 }
njn16eeb4e2005-06-16 03:56:58 +0000343
njnb4cfbc42009-05-04 04:20:02 +0000344STRLEN(VG_Z_LIBC_SONAME, strlen)
345#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000346STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
njnb4cfbc42009-05-04 04:20:02 +0000347#endif
sewardj31b9ce12006-10-17 01:27:13 +0000348
njn16eeb4e2005-06-16 03:56:58 +0000349
350#define STRCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000351 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000352 ( char* dst, const char* src ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000355 { \
356 const Char* src_orig = src; \
357 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000358 \
njn16eeb4e2005-06-16 03:56:58 +0000359 while (*src) *dst++ = *src++; \
360 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000361 \
njn16eeb4e2005-06-16 03:56:58 +0000362 /* This checks for overlap after copying, unavoidable without */ \
363 /* pre-counting length... should be ok */ \
364 if (is_overlap(dst_orig, \
365 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000366 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000367 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000368 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000369 \
njn16eeb4e2005-06-16 03:56:58 +0000370 return dst_orig; \
371 }
372
njne6154662009-02-10 04:23:41 +0000373STRCPY(VG_Z_LIBC_SONAME, strcpy)
tomd2645142009-10-29 09:27:11 +0000374#if defined(VGO_linux)
375STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
376#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000377STRCPY(VG_Z_DYLD, strcpy)
378#endif
njn16eeb4e2005-06-16 03:56:58 +0000379
380
381#define STRNCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000382 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000383 ( char* dst, const char* src, SizeT n ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000386 { \
387 const Char* src_orig = src; \
388 Char* dst_orig = dst; \
389 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000390 \
njn16eeb4e2005-06-16 03:56:58 +0000391 while (m < n && *src) { m++; *dst++ = *src++; } \
392 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
393 /* but only m+1 bytes of src if terminator was found */ \
394 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000395 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000396 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
397 \
398 return dst_orig; \
399 }
400
njne6154662009-02-10 04:23:41 +0000401STRNCPY(VG_Z_LIBC_SONAME, strncpy)
tomd2645142009-10-29 09:27:11 +0000402#if defined(VGO_linux)
403STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
404#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000405STRNCPY(VG_Z_DYLD, strncpy)
406#endif
407
408
409/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
410 Returns strlen(src). Does not zero-fill the remainder of dst. */
411#define STRLCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000412 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000413 ( char* dst, const char* src, SizeT n ); \
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 ) \
416 { \
417 const char* src_orig = src; \
418 char* dst_orig = dst; \
419 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000420 \
njnf76d27a2009-05-28 01:53:07 +0000421 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
422 /* m non-nul bytes have now been copied, and m <= n-1. */ \
423 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
424 /* but only m+1 bytes of src if terminator was found */ \
425 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
426 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
427 /* Nul-terminate dst. */ \
428 if (n > 0) *dst = 0; \
429 /* Finish counting strlen(src). */ \
430 while (*src) src++; \
431 return src - src_orig; \
432 }
433
434#if defined(VGO_darwin)
435STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
436STRLCPY(VG_Z_DYLD, strlcpy)
437#endif
njn16eeb4e2005-06-16 03:56:58 +0000438
439
440#define STRNCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000441 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000442 ( const char* s1, const char* s2, SizeT nmax ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000445 { \
446 SizeT n = 0; \
447 while (True) { \
448 if (n >= nmax) return 0; \
449 if (*s1 == 0 && *s2 == 0) return 0; \
450 if (*s1 == 0) return -1; \
451 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000452 \
njn16eeb4e2005-06-16 03:56:58 +0000453 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
454 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000455 \
njn16eeb4e2005-06-16 03:56:58 +0000456 s1++; s2++; n++; \
457 } \
458 }
459
njne6154662009-02-10 04:23:41 +0000460STRNCMP(VG_Z_LIBC_SONAME, strncmp)
tomd2645142009-10-29 09:27:11 +0000461#if defined(VGO_linux)
462STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
463#elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000464STRNCMP(VG_Z_DYLD, strncmp)
465#endif
njn16eeb4e2005-06-16 03:56:58 +0000466
467
tomce6d0ac2010-11-12 10:03:13 +0000468#define STRCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000469 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000470 ( const char* s1, const char* s2 ); \
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 ) \
473 { \
tome03c8c42010-11-12 10:40:20 +0000474 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000475 register unsigned char c1; \
476 register unsigned char c2; \
477 while (True) { \
478 c1 = tolower(*(unsigned char *)s1); \
479 c2 = tolower(*(unsigned char *)s2); \
480 if (c1 != c2) break; \
481 if (c1 == 0) break; \
482 s1++; s2++; \
483 } \
484 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
485 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
486 return 0; \
487 }
488
sewardj126e82d2011-07-12 13:33:00 +0000489#if !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000490STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
sewardj126e82d2011-07-12 13:33:00 +0000491#endif
492#if defined(VGO_linux) && !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000493STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
494#endif
495
496
497#define STRNCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000498 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000499 ( const char* s1, const char* s2, SizeT nmax ); \
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 ) \
502 { \
tome03c8c42010-11-12 10:40:20 +0000503 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000504 SizeT n = 0; \
505 while (True) { \
506 if (n >= nmax) return 0; \
507 if (*s1 == 0 && *s2 == 0) return 0; \
508 if (*s1 == 0) return -1; \
509 if (*s2 == 0) return 1; \
510 \
sewardjbd2cff22011-08-16 21:45:28 +0000511 if (tolower(*(unsigned char*)s1) \
512 < tolower(*(unsigned char*)s2)) return -1; \
513 if (tolower(*(unsigned char*)s1) \
514 > tolower(*(unsigned char*)s2)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000515 \
516 s1++; s2++; n++; \
517 } \
518 }
519
sewardj126e82d2011-07-12 13:33:00 +0000520#if !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000521STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
sewardj126e82d2011-07-12 13:33:00 +0000522#endif
523#if defined(VGO_linux) && !defined(VGPV_arm_linux_android)
tomce6d0ac2010-11-12 10:03:13 +0000524STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
525#elif defined(VGO_darwin)
526STRNCASECMP(VG_Z_DYLD, strncasecmp)
527#endif
528
529
tomce6d0ac2010-11-12 10:03:13 +0000530#define STRCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000531 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000532 ( const char* s1, const char* s2, void* locale ); \
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 ) \
tomce6d0ac2010-11-12 10:03:13 +0000535 { \
tome03c8c42010-11-12 10:40:20 +0000536 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000537 register unsigned char c1; \
538 register unsigned char c2; \
539 while (True) { \
540 c1 = tolower_l(*(unsigned char *)s1, locale); \
541 c2 = tolower_l(*(unsigned char *)s2, locale); \
542 if (c1 != c2) break; \
543 if (c1 == 0) break; \
544 s1++; s2++; \
545 } \
546 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
547 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
548 return 0; \
549 }
550
551STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
552#if defined(VGO_linux)
553STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
sewardjbd2cff22011-08-16 21:45:28 +0000554STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
tomce6d0ac2010-11-12 10:03:13 +0000555#endif
556
557
558#define STRNCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000559 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000560 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
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 ) \
tomce6d0ac2010-11-12 10:03:13 +0000563 { \
tome03c8c42010-11-12 10:40:20 +0000564 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000565 SizeT n = 0; \
566 while (True) { \
567 if (n >= nmax) return 0; \
568 if (*s1 == 0 && *s2 == 0) return 0; \
569 if (*s1 == 0) return -1; \
570 if (*s2 == 0) return 1; \
571 \
sewardjbd2cff22011-08-16 21:45:28 +0000572 if (tolower_l(*(unsigned char*)s1, locale) \
573 < tolower_l(*(unsigned char*)s2, locale)) return -1; \
574 if (tolower_l(*(unsigned char*)s1, locale) \
575 > tolower_l(*(unsigned char*)s2, locale)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000576 \
577 s1++; s2++; n++; \
578 } \
579 }
580
581STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
582#if defined(VGO_linux)
583STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
584#elif defined(VGO_darwin)
585STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
586#endif
587
588
njn16eeb4e2005-06-16 03:56:58 +0000589#define STRCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000590 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000591 ( const char* s1, const char* s2 ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000594 { \
595 register unsigned char c1; \
596 register unsigned char c2; \
597 while (True) { \
598 c1 = *(unsigned char *)s1; \
599 c2 = *(unsigned char *)s2; \
600 if (c1 != c2) break; \
601 if (c1 == 0) break; \
602 s1++; s2++; \
603 } \
604 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
605 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
606 return 0; \
607 }
608
njne6154662009-02-10 04:23:41 +0000609STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000610#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000611STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
njne6154662009-02-10 04:23:41 +0000612STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
613STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000614#endif
njn16eeb4e2005-06-16 03:56:58 +0000615
616
617#define MEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000618 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000619 (const void *s, int c, SizeT n); \
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) \
njn16eeb4e2005-06-16 03:56:58 +0000622 { \
623 SizeT i; \
624 UChar c0 = (UChar)c; \
625 UChar* p = (UChar*)s; \
626 for (i = 0; i < n; i++) \
627 if (p[i] == c0) return (void*)(&p[i]); \
628 return NULL; \
629 }
630
njne6154662009-02-10 04:23:41 +0000631MEMCHR(VG_Z_LIBC_SONAME, memchr)
njnf76d27a2009-05-28 01:53:07 +0000632#if defined(VGO_darwin)
633MEMCHR(VG_Z_DYLD, memchr)
634#endif
njn16eeb4e2005-06-16 03:56:58 +0000635
636
sewardjbd2cff22011-08-16 21:45:28 +0000637#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
sewardjd88797f2011-08-17 21:25:50 +0000638 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000639 ( void *dst, const void *src, SizeT len ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000642 { \
sewardjbd2cff22011-08-16 21:45:28 +0000643 if (do_ol_check && is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000644 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000645 \
sewardj7b4e00b2010-08-24 09:05:52 +0000646 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
647 const Addr WM = WS - 1; /* 7 or 3 */ \
648 \
tom863ab7c2011-08-18 08:10:20 +0000649 if (len > 0) { \
650 if (dst < src) { \
sewardj7b4e00b2010-08-24 09:05:52 +0000651 \
tom863ab7c2011-08-18 08:10:20 +0000652 /* Copying backwards. */ \
653 SizeT n = len; \
654 Addr d = (Addr)dst; \
655 Addr s = (Addr)src; \
656 \
657 if (((s^d) & WM) == 0) { \
658 /* s and d have same UWord alignment. */ \
659 /* Pull up to a UWord boundary. */ \
660 while ((s & WM) != 0 && n >= 1) \
661 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
662 /* Copy UWords. */ \
663 while (n >= WS) \
664 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
665 if (n == 0) \
666 return dst; \
667 } \
668 if (((s|d) & 1) == 0) { \
669 /* Both are 16-aligned; copy what we can thusly. */ \
670 while (n >= 2) \
671 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
672 } \
673 /* Copy leftovers, or everything if misaligned. */ \
674 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000675 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
sewardj7b4e00b2010-08-24 09:05:52 +0000676 \
tom863ab7c2011-08-18 08:10:20 +0000677 } else if (dst > src) { \
678 \
679 SizeT n = len; \
680 Addr d = ((Addr)dst) + n; \
681 Addr s = ((Addr)src) + n; \
682 \
683 /* Copying forwards. */ \
684 if (((s^d) & WM) == 0) { \
685 /* s and d have same UWord alignment. */ \
686 /* Back down to a UWord boundary. */ \
687 while ((s & WM) != 0 && n >= 1) \
688 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
689 /* Copy UWords. */ \
690 while (n >= WS) \
691 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
692 if (n == 0) \
693 return dst; \
694 } \
695 if (((s|d) & 1) == 0) { \
696 /* Both are 16-aligned; copy what we can thusly. */ \
697 while (n >= 2) \
698 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
699 } \
700 /* Copy leftovers, or everything if misaligned. */ \
701 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000702 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
tom863ab7c2011-08-18 08:10:20 +0000703 \
njn16eeb4e2005-06-16 03:56:58 +0000704 } \
njn16eeb4e2005-06-16 03:56:58 +0000705 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000706 \
njn16eeb4e2005-06-16 03:56:58 +0000707 return dst; \
708 }
709
sewardjbd2cff22011-08-16 21:45:28 +0000710#define MEMMOVE(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000711 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
sewardjbd2cff22011-08-16 21:45:28 +0000712
713#define MEMCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000714 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
sewardjbd2cff22011-08-16 21:45:28 +0000715
njnb4cfbc42009-05-04 04:20:02 +0000716#if defined(VGO_linux)
sewardjbd2cff22011-08-16 21:45:28 +0000717/* For older memcpy we have to use memmove-like semantics and skip the
718 overlap check; sigh; see #275284. */
sewardjd88797f2011-08-17 21:25:50 +0000719MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
720MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
sewardj96044842011-08-18 13:09:55 +0000721MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
sewardjd88797f2011-08-17 21:25:50 +0000722MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
723MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnf76d27a2009-05-28 01:53:07 +0000724#elif defined(VGO_darwin)
sewardjd88797f2011-08-17 21:25:50 +0000725MEMCPY(VG_Z_LIBC_SONAME, memcpy)
726MEMCPY(VG_Z_DYLD, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000727#endif
sewardjf0b34322007-01-16 21:42:28 +0000728/* icc9 blats these around all over the place. Not only in the main
729 executable but various .so's. They are highly tuned and read
730 memory beyond the source boundary (although work correctly and
731 never go across page boundaries), so give errors when run natively,
732 at least for misaligned source arg. Just intercepting in the exe
733 only until we understand more about the problem. See
734 http://bugs.kde.org/show_bug.cgi?id=139776
735 */
sewardjd88797f2011-08-17 21:25:50 +0000736MEMCPY(NONE, ZuintelZufastZumemcpy)
sewardj31b9ce12006-10-17 01:27:13 +0000737
njn16eeb4e2005-06-16 03:56:58 +0000738
739#define MEMCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000740 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000741 ( const void *s1V, const void *s2V, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000742 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000743 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000744 { \
745 int res; \
746 unsigned char a0; \
747 unsigned char b0; \
748 unsigned char* s1 = (unsigned char*)s1V; \
749 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000750 \
njn16eeb4e2005-06-16 03:56:58 +0000751 while (n != 0) { \
752 a0 = s1[0]; \
753 b0 = s2[0]; \
754 s1 += 1; \
755 s2 += 1; \
756 res = ((int)a0) - ((int)b0); \
757 if (res != 0) \
758 return res; \
759 n -= 1; \
760 } \
761 return 0; \
762 }
763
njne6154662009-02-10 04:23:41 +0000764MEMCMP(VG_Z_LIBC_SONAME, memcmp)
765MEMCMP(VG_Z_LIBC_SONAME, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000766#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000767MEMCMP(VG_Z_LD_SO_1, bcmp)
njnf76d27a2009-05-28 01:53:07 +0000768#elif defined(VGO_darwin)
769MEMCMP(VG_Z_DYLD, memcmp)
770MEMCMP(VG_Z_DYLD, bcmp)
njnb4cfbc42009-05-04 04:20:02 +0000771#endif
njn3e884182003-04-15 13:03:23 +0000772
jseward0845ef82003-12-22 22:31:27 +0000773
774/* Copy SRC to DEST, returning the address of the terminating '\0' in
775 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000776#define STPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000777 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000778 ( char* dst, const char* src ); \
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 ) \
njn16eeb4e2005-06-16 03:56:58 +0000781 { \
782 const Char* src_orig = src; \
783 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000784 \
njn16eeb4e2005-06-16 03:56:58 +0000785 while (*src) *dst++ = *src++; \
786 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000787 \
njn16eeb4e2005-06-16 03:56:58 +0000788 /* This checks for overlap after copying, unavoidable without */ \
789 /* pre-counting length... should be ok */ \
790 if (is_overlap(dst_orig, \
791 src_orig, \
792 (Addr)dst-(Addr)dst_orig+1, \
793 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000794 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000795 \
njn16eeb4e2005-06-16 03:56:58 +0000796 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000797 }
njn16eeb4e2005-06-16 03:56:58 +0000798
njne6154662009-02-10 04:23:41 +0000799STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000800#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +0000801STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
njne6154662009-02-10 04:23:41 +0000802STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
803STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnf76d27a2009-05-28 01:53:07 +0000804#elif defined(VGO_darwin)
805STPCPY(VG_Z_DYLD, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000806#endif
807
njn16eeb4e2005-06-16 03:56:58 +0000808
809#define MEMSET(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000810 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000811 (void *s, Int c, SizeT n); \
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) \
njn16eeb4e2005-06-16 03:56:58 +0000814 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000815 Addr a = (Addr)s; \
816 UInt c4 = (c & 0xFF); \
817 c4 = (c4 << 8) | c4; \
818 c4 = (c4 << 16) | c4; \
819 while ((a & 3) != 0 && n >= 1) \
820 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
821 while (n >= 4) \
822 { *(UInt*)a = c4; a += 4; n -= 4; } \
823 while (n >= 1) \
824 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000825 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000826 }
njn16eeb4e2005-06-16 03:56:58 +0000827
njne6154662009-02-10 04:23:41 +0000828MEMSET(VG_Z_LIBC_SONAME, memset)
njnf76d27a2009-05-28 01:53:07 +0000829#if defined(VGO_darwin)
830MEMSET(VG_Z_DYLD, memset)
831#endif
njn16eeb4e2005-06-16 03:56:58 +0000832
833
sewardj96044842011-08-18 13:09:55 +0000834/* memmove -- use the MEMMOVE defn above. */
njne6154662009-02-10 04:23:41 +0000835MEMMOVE(VG_Z_LIBC_SONAME, memmove)
njnf76d27a2009-05-28 01:53:07 +0000836#if defined(VGO_darwin)
837MEMMOVE(VG_Z_DYLD, memmove)
838#endif
839
840
841#define BCOPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000842 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000843 (const void *srcV, void *dstV, SizeT n); \
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) \
846 { \
847 SizeT i; \
848 Char* dst = (Char*)dstV; \
849 Char* src = (Char*)srcV; \
850 if (dst < src) { \
851 for (i = 0; i < n; i++) \
852 dst[i] = src[i]; \
853 } \
854 else \
855 if (dst > src) { \
856 for (i = 0; i < n; i++) \
857 dst[n-i-1] = src[n-i-1]; \
858 } \
859 }
860
861#if defined(VGO_darwin)
862BCOPY(VG_Z_LIBC_SONAME, bcopy)
863BCOPY(VG_Z_DYLD, bcopy)
864#endif
sewardj44e495f2005-05-12 17:58:28 +0000865
jseward0845ef82003-12-22 22:31:27 +0000866
sewardj24cb2172007-02-23 09:03:26 +0000867/* glibc 2.5 variant of memmove which checks the dest is big enough.
868 There is no specific part of glibc that this is copied from. */
869#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000870 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +0000871 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
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) \
874 { \
sewardj24cb2172007-02-23 09:03:26 +0000875 SizeT i; \
876 Char* dst = (Char*)dstV; \
877 Char* src = (Char*)srcV; \
878 if (destlen < n) \
879 goto badness; \
880 if (dst < src) { \
881 for (i = 0; i < n; i++) \
882 dst[i] = src[i]; \
883 } \
884 else \
885 if (dst > src) { \
886 for (i = 0; i < n; i++) \
887 dst[n-i-1] = src[n-i-1]; \
888 } \
889 return dst; \
890 badness: \
891 VALGRIND_PRINTF_BACKTRACE( \
892 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000893 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000894 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +0000895 /*NOTREACHED*/ \
896 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +0000897 }
898
njne6154662009-02-10 04:23:41 +0000899GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj24cb2172007-02-23 09:03:26 +0000900
901
sewardj4e9a4b62004-11-23 00:20:17 +0000902/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +0000903#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000904 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000905 (const char* s, int c_in); \
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) \
njn16eeb4e2005-06-16 03:56:58 +0000908 { \
909 unsigned char c = (unsigned char) c_in; \
910 unsigned char* char_ptr = (unsigned char *)s; \
911 while (1) { \
912 if (*char_ptr == 0) return char_ptr; \
913 if (*char_ptr == c) return char_ptr; \
914 char_ptr++; \
915 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000916 }
njn16eeb4e2005-06-16 03:56:58 +0000917
njne6154662009-02-10 04:23:41 +0000918GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4e9a4b62004-11-23 00:20:17 +0000919
920
921/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +0000922#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000923 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000924 (const char* s, int c_in); \
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) \
njn16eeb4e2005-06-16 03:56:58 +0000927 { \
928 unsigned char c = (unsigned char) c_in; \
929 unsigned char* char_ptr = (unsigned char *)s; \
930 while (1) { \
931 if (*char_ptr == c) return char_ptr; \
932 char_ptr++; \
933 } \
sewardj4e9a4b62004-11-23 00:20:17 +0000934 }
njn16eeb4e2005-06-16 03:56:58 +0000935
njne6154662009-02-10 04:23:41 +0000936GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
tomd2645142009-10-29 09:27:11 +0000937#if defined (VGO_linux)
938GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
939#endif
sewardj4e9a4b62004-11-23 00:20:17 +0000940
sewardjdc5d8322007-01-28 06:32:01 +0000941/* glibc variant of strcpy that checks the dest is big enough.
942 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +0000943#define GLIBC25___STRCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000944 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000945 (char* dst, const char* src, SizeT len); \
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) \
sewardj620e5262006-12-31 00:22:30 +0000948 { \
sewardj620e5262006-12-31 00:22:30 +0000949 char* ret = dst; \
950 if (! len) \
951 goto badness; \
952 while ((*dst++ = *src++) != '\0') \
953 if (--len == 0) \
954 goto badness; \
955 return ret; \
956 badness: \
957 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000958 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000959 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000960 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +0000961 /*NOTREACHED*/ \
962 return NULL; \
963 }
964
njne6154662009-02-10 04:23:41 +0000965GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj620e5262006-12-31 00:22:30 +0000966
967
sewardjdc5d8322007-01-28 06:32:01 +0000968/* glibc variant of stpcpy that checks the dest is big enough.
969 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +0000970#define GLIBC25___STPCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000971 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000972 (char* dst, const char* src, SizeT len); \
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) \
sewardjb8d03852007-01-27 00:49:44 +0000975 { \
sewardjdc5d8322007-01-28 06:32:01 +0000976 if (! len) \
977 goto badness; \
978 while ((*dst++ = *src++) != '\0') \
979 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +0000980 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +0000981 return dst - 1; \
982 badness: \
983 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +0000984 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +0000985 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +0000986 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +0000987 /*NOTREACHED*/ \
988 return NULL; \
989 }
990
njne6154662009-02-10 04:23:41 +0000991GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardjb8d03852007-01-27 00:49:44 +0000992
993
sewardj841b72d2006-12-31 18:55:56 +0000994/* mempcpy */
995#define GLIBC25_MEMPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000996 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +0000997 ( void *dst, const void *src, SizeT len ); \
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 ) \
1000 { \
1001 register char *d; \
1002 register char *s; \
1003 SizeT len_saved = len; \
1004 \
1005 if (len == 0) \
1006 return dst; \
1007 \
1008 if (is_overlap(dst, src, len, len)) \
1009 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1010 \
1011 if ( dst > src ) { \
1012 d = (char *)dst + len - 1; \
1013 s = (char *)src + len - 1; \
1014 while ( len-- ) { \
1015 *d-- = *s--; \
1016 } \
1017 } else if ( dst < src ) { \
1018 d = (char *)dst; \
1019 s = (char *)src; \
1020 while ( len-- ) { \
1021 *d++ = *s++; \
1022 } \
1023 } \
1024 return (void*)( ((char*)dst) + len_saved ); \
1025 }
1026
njne6154662009-02-10 04:23:41 +00001027GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
njnb4cfbc42009-05-04 04:20:02 +00001028#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00001029GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
njnb4cfbc42009-05-04 04:20:02 +00001030#endif
sewardj841b72d2006-12-31 18:55:56 +00001031
1032
sewardjb6c04032007-11-13 20:52:29 +00001033#define GLIBC26___MEMCPY_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001034 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001035 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
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 ) \
1038 { \
sewardjb6c04032007-11-13 20:52:29 +00001039 register char *d; \
1040 register char *s; \
1041 \
1042 if (dstlen < len) goto badness; \
1043 \
1044 if (len == 0) \
1045 return dst; \
1046 \
1047 if (is_overlap(dst, src, len, len)) \
1048 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1049 \
1050 if ( dst > src ) { \
1051 d = (char *)dst + len - 1; \
1052 s = (char *)src + len - 1; \
1053 while ( len-- ) { \
1054 *d-- = *s--; \
1055 } \
1056 } else if ( dst < src ) { \
1057 d = (char *)dst; \
1058 s = (char *)src; \
1059 while ( len-- ) { \
1060 *d++ = *s++; \
1061 } \
1062 } \
1063 return dst; \
1064 badness: \
1065 VALGRIND_PRINTF_BACKTRACE( \
1066 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001067 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001068 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001069 /*NOTREACHED*/ \
1070 return NULL; \
1071 }
1072
njne6154662009-02-10 04:23:41 +00001073GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardjb6c04032007-11-13 20:52:29 +00001074
1075
sewardja77687c2010-08-19 13:22:34 +00001076#define STRSTR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001077 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001078 (void* haystack, void* needle); \
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) \
1081 { \
1082 UChar* h = (UChar*)haystack; \
1083 UChar* n = (UChar*)needle; \
1084 \
1085 /* find the length of n, not including terminating zero */ \
1086 UWord nlen = 0; \
1087 while (n[nlen]) nlen++; \
1088 \
1089 /* if n is the empty string, match immediately. */ \
1090 if (nlen == 0) return h; \
1091 \
1092 /* assert(nlen >= 1); */ \
1093 UChar n0 = n[0]; \
1094 \
1095 while (1) { \
1096 UChar hh = *h; \
1097 if (hh == 0) return NULL; \
1098 if (hh != n0) { h++; continue; } \
1099 \
1100 UWord i; \
1101 for (i = 0; i < nlen; i++) { \
1102 if (n[i] != h[i]) \
1103 break; \
1104 } \
1105 /* assert(i >= 0 && i <= nlen); */ \
1106 if (i == nlen) \
1107 return h; \
1108 \
1109 h++; \
1110 } \
1111 }
1112
1113#if defined(VGO_linux)
1114STRSTR(VG_Z_LIBC_SONAME, strstr)
1115#endif
1116
1117
1118#define STRPBRK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001119 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001120 (void* sV, void* acceptV); \
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) \
1123 { \
1124 UChar* s = (UChar*)sV; \
1125 UChar* accept = (UChar*)acceptV; \
1126 \
1127 /* find the length of 'accept', not including terminating zero */ \
1128 UWord nacc = 0; \
1129 while (accept[nacc]) nacc++; \
1130 \
1131 /* if n is the empty string, fail immediately. */ \
1132 if (nacc == 0) return NULL; \
1133 \
1134 /* assert(nacc >= 1); */ \
1135 while (1) { \
1136 UWord i; \
1137 UChar sc = *s; \
1138 if (sc == 0) \
1139 break; \
1140 for (i = 0; i < nacc; i++) { \
1141 if (sc == accept[i]) \
1142 return s; \
1143 } \
1144 s++; \
1145 } \
1146 \
1147 return NULL; \
1148 }
1149
1150#if defined(VGO_linux)
1151STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1152#endif
1153
1154
1155#define STRCSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001156 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001157 (void* sV, void* rejectV); \
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) \
1160 { \
1161 UChar* s = (UChar*)sV; \
1162 UChar* reject = (UChar*)rejectV; \
1163 \
1164 /* find the length of 'reject', not including terminating zero */ \
1165 UWord nrej = 0; \
1166 while (reject[nrej]) nrej++; \
1167 \
1168 UWord len = 0; \
1169 while (1) { \
1170 UWord i; \
1171 UChar sc = *s; \
1172 if (sc == 0) \
1173 break; \
1174 for (i = 0; i < nrej; i++) { \
1175 if (sc == reject[i]) \
1176 break; \
1177 } \
1178 /* assert(i >= 0 && i <= nrej); */ \
1179 if (i < nrej) \
1180 break; \
1181 s++; \
1182 len++; \
1183 } \
1184 \
1185 return len; \
1186 }
1187
1188#if defined(VGO_linux)
1189STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1190#endif
1191
1192
sewardjbd2cff22011-08-16 21:45:28 +00001193#define STRSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001194 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001195 (void* sV, void* acceptV); \
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) \
1198 { \
1199 UChar* s = (UChar*)sV; \
1200 UChar* accept = (UChar*)acceptV; \
1201 \
1202 /* find the length of 'accept', not including terminating zero */ \
1203 UWord nacc = 0; \
1204 while (accept[nacc]) nacc++; \
1205 if (nacc == 0) return 0; \
1206 \
1207 UWord len = 0; \
1208 while (1) { \
1209 UWord i; \
1210 UChar sc = *s; \
1211 if (sc == 0) \
1212 break; \
1213 for (i = 0; i < nacc; i++) { \
1214 if (sc == accept[i]) \
1215 break; \
1216 } \
1217 /* assert(i >= 0 && i <= nacc); */ \
1218 if (i == nacc) \
1219 break; \
1220 s++; \
1221 len++; \
1222 } \
1223 \
1224 return len; \
1225 }
1226
1227#if defined(VGO_linux)
1228STRSPN(VG_Z_LIBC_SONAME, strspn)
1229#endif
sewardjba189352010-08-20 18:24:16 +00001230
1231
sewardj31b9ce12006-10-17 01:27:13 +00001232/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001233/*--- Improve definedness checking of process environment ---*/
1234/*------------------------------------------------------------*/
1235
sewardjddc00dd2007-11-27 11:42:47 +00001236#if defined(VGO_linux)
1237
sewardjbd2cff22011-08-16 21:45:28 +00001238/* If these wind up getting generated via a macro, so that multiple
1239 versions of each function exist (as above), use the _EZU variants
1240 to assign equivalance class tags. */
1241
dirk09beb9e2007-04-19 09:47:32 +00001242/* putenv */
njne6154662009-02-10 04:23:41 +00001243int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1244int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001245{
1246 OrigFn fn;
1247 Word result;
1248 const char* p = string;
1249 VALGRIND_GET_ORIG_FN(fn);
1250 /* Now by walking over the string we magically produce
1251 traces when hitting undefined memory. */
1252 if (p)
1253 while (*p++)
1254 ;
1255 CALL_FN_W_W(result, fn, string);
1256 return result;
1257}
1258
1259/* unsetenv */
njne6154662009-02-10 04:23:41 +00001260int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1261int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001262{
1263 OrigFn fn;
1264 Word result;
1265 const char* p = name;
1266 VALGRIND_GET_ORIG_FN(fn);
1267 /* Now by walking over the string we magically produce
1268 traces when hitting undefined memory. */
1269 if (p)
1270 while (*p++)
1271 ;
1272 CALL_FN_W_W(result, fn, name);
1273 return result;
1274}
1275
1276/* setenv */
njne6154662009-02-10 04:23:41 +00001277int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001278 (const char* name, const char* value, int overwrite);
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)
1281{
1282 OrigFn fn;
1283 Word result;
1284 const char* p;
1285 VALGRIND_GET_ORIG_FN(fn);
1286 /* Now by walking over the string we magically produce
1287 traces when hitting undefined memory. */
1288 if (name)
1289 for (p = name; *p; p++)
1290 ;
1291 if (value)
1292 for (p = value; *p; p++)
1293 ;
1294 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1295 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1296 return result;
1297}
1298
sewardjddc00dd2007-11-27 11:42:47 +00001299#endif /* defined(VGO_linux) */
1300
njn3e884182003-04-15 13:03:23 +00001301/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001302/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001303/*--------------------------------------------------------------------*/