blob: 3dc2a1ca10f33afeeff0edca2251388955420336 [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
sewardjec062e82011-10-23 07:32:08 +000012 Copyright (C) 2000-2011 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"
philippe6643e962012-01-17 21:16:30 +000034#include "pub_tool_poolalloc.h"
njnc7561b92005-06-19 01:24:32 +000035#include "pub_tool_hashtable.h"
njnc7561b92005-06-19 01:24:32 +000036#include "pub_tool_redir.h"
37#include "pub_tool_tooliface.h"
38#include "valgrind.h"
39
njn34419c12003-05-02 17:24:29 +000040#include "mc_include.h"
fitzhardinge98abfc72003-12-16 02:05:15 +000041#include "memcheck.h"
njn3e884182003-04-15 13:03:23 +000042
njn3e884182003-04-15 13:03:23 +000043/* ---------------------------------------------------------------------
njn1f8b3e72005-03-22 04:27:14 +000044 We have our own versions of these functions for two reasons:
45 (a) it allows us to do overlap checking
46 (b) some of the normal versions are hyper-optimised, which fools
47 Memcheck and cause spurious value warnings. Our versions are
48 simpler.
49
njn16eeb4e2005-06-16 03:56:58 +000050 Note that overenthusiastic use of PLT bypassing by the glibc people also
51 means that we need to patch multiple versions of some of the functions to
52 our own implementations.
53
njn1f8b3e72005-03-22 04:27:14 +000054 THEY RUN ON THE SIMD CPU!
njn3e884182003-04-15 13:03:23 +000055 ------------------------------------------------------------------ */
56
sewardj96044842011-08-18 13:09:55 +000057/* Assignment of behavioural equivalence class tags: 2NNNP is intended
sewardjbd2cff22011-08-16 21:45:28 +000058 to be reserved for Memcheck. Current usage:
59
sewardj96044842011-08-18 13:09:55 +000060 20010 STRRCHR
61 20020 STRCHR
62 20030 STRCAT
63 20040 STRNCAT
64 20050 STRLCAT
65 20060 STRNLEN
66 20070 STRLEN
67 20080 STRCPY
68 20090 STRNCPY
69 20100 STRLCPY
70 20110 STRNCMP
71 20120 STRCASECMP
72 20130 STRNCASECMP
73 20140 STRCASECMP_L
74 20150 STRNCASECMP_L
75 20160 STRCMP
76 20170 MEMCHR
77
78 20180 MEMCPY if there's a conflict between memcpy and
79 20181 MEMMOVE memmove, prefer memmove
80
81 20190 MEMCMP
82 20200 STPCPY
83 20210 MEMSET
84 2022P unused (was previously MEMMOVE)
85 20230 BCOPY
86 20240 GLIBC25___MEMMOVE_CHK
87 20250 GLIBC232_STRCHRNUL
88 20260 GLIBC232_RAWMEMCHR
89 20270 GLIBC25___STRCPY_CHK
90 20280 GLIBC25___STPCPY_CHK
91 20290 GLIBC25_MEMPCPY
92 20300 GLIBC26___MEMCPY_CHK
93 20310 STRSTR
94 20320 STRPBRK
95 20330 STRCSPN
96 20340 STRSPN
sewardj284f2a32011-10-21 08:07:13 +000097 20350 STRCASESTR
sewardjbd2cff22011-08-16 21:45:28 +000098*/
99
sewardj126e82d2011-07-12 13:33:00 +0000100
sewardjdda830a2003-07-20 22:28:42 +0000101/* Figure out if [dst .. dst+dstlen-1] overlaps with
102 [src .. src+srclen-1].
103 We assume that the address ranges do not wrap around
104 (which is safe since on Linux addresses >= 0xC0000000
105 are not accessible and the program will segfault in this
106 circumstance, presumably).
107*/
sewardj126e82d2011-07-12 13:33:00 +0000108static inline
njnc6168192004-11-29 13:54:10 +0000109Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
njn3e884182003-04-15 13:03:23 +0000110{
sewardjdda830a2003-07-20 22:28:42 +0000111 Addr loS, hiS, loD, hiD;
112
113 if (dstlen == 0 || srclen == 0)
114 return False;
115
116 loS = (Addr)src;
117 loD = (Addr)dst;
118 hiS = loS + srclen - 1;
119 hiD = loD + dstlen - 1;
120
121 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
122 if (loS < loD) {
123 return !(hiS < loD);
124 }
125 else if (loD < loS) {
126 return !(hiD < loS);
127 }
128 else {
129 /* They start at same place. Since we know neither of them has
130 zero length, they must overlap. */
131 return True;
132 }
njn3e884182003-04-15 13:03:23 +0000133}
134
sewardj126e82d2011-07-12 13:33:00 +0000135
136/* Call here to exit if we can't continue. On Android we can't call
137 _exit for some reason, so we have to blunt-instrument it. */
138__attribute__ ((__noreturn__))
139static inline void my_exit ( int x )
140{
141# if defined(VGPV_arm_linux_android)
142 __asm__ __volatile__(".word 0xFFFFFFFF");
143 while (1) {}
144# else
florian28936a82011-10-05 14:36:00 +0000145 extern __attribute__ ((__noreturn__)) void _exit(int status);
sewardj49665422011-07-12 13:50:59 +0000146 _exit(x);
sewardj126e82d2011-07-12 13:33:00 +0000147# endif
148}
149
150
njn1f8b3e72005-03-22 04:27:14 +0000151// This is a macro rather than a function because we don't want to have an
152// extra function in the stack trace.
bart575ce8e2011-05-15 07:04:03 +0000153#define RECORD_OVERLAP_ERROR(s, src, dst, len) \
sewardj4b3a7422011-10-24 13:21:57 +0000154 VALGRIND_DO_CLIENT_REQUEST_STMT( \
bart575ce8e2011-05-15 07:04:03 +0000155 _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \
156 s, src, dst, len, 0)
njn3e884182003-04-15 13:03:23 +0000157
njn16eeb4e2005-06-16 03:56:58 +0000158
sewardj3c944452011-09-05 20:39:57 +0000159/*---------------------- strrchr ----------------------*/
160
njn16eeb4e2005-06-16 03:56:58 +0000161#define STRRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000162 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
163 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000164 { \
165 UChar ch = (UChar)((UInt)c); \
166 UChar* p = (UChar*)s; \
167 UChar* last = NULL; \
168 while (True) { \
169 if (*p == ch) last = p; \
170 if (*p == 0) return last; \
171 p++; \
172 } \
njn3e884182003-04-15 13:03:23 +0000173 }
njn3e884182003-04-15 13:03:23 +0000174
njn16eeb4e2005-06-16 03:56:58 +0000175// Apparently rindex() is the same thing as strrchr()
njnb4cfbc42009-05-04 04:20:02 +0000176#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000177 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
178 STRRCHR(VG_Z_LIBC_SONAME, rindex)
179 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
180 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
sewardj4157d4f2011-09-05 22:18:13 +0000181
njnf76d27a2009-05-28 01:53:07 +0000182#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000183 //STRRCHR(VG_Z_LIBC_SONAME, strrchr)
184 //STRRCHR(VG_Z_LIBC_SONAME, rindex)
185 //STRRCHR(VG_Z_DYLD, strrchr)
186 //STRRCHR(VG_Z_DYLD, rindex)
187 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
sewardj4157d4f2011-09-05 22:18:13 +0000188
njnb4cfbc42009-05-04 04:20:02 +0000189#endif
njn16eeb4e2005-06-16 03:56:58 +0000190
191
sewardj3c944452011-09-05 20:39:57 +0000192/*---------------------- strchr ----------------------*/
193
njn16eeb4e2005-06-16 03:56:58 +0000194#define STRCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000195 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
196 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
njn16eeb4e2005-06-16 03:56:58 +0000197 { \
198 UChar ch = (UChar)((UInt)c); \
199 UChar* p = (UChar*)s; \
200 while (True) { \
201 if (*p == ch) return p; \
202 if (*p == 0) return NULL; \
203 p++; \
204 } \
njn3e884182003-04-15 13:03:23 +0000205 }
njn3e884182003-04-15 13:03:23 +0000206
njn16eeb4e2005-06-16 03:56:58 +0000207// Apparently index() is the same thing as strchr()
njnb4cfbc42009-05-04 04:20:02 +0000208#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000209 STRCHR(VG_Z_LIBC_SONAME, strchr)
210 STRCHR(VG_Z_LIBC_SONAME, index)
211 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
212# if !defined(VGP_x86_linux)
213 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
214 STRCHR(VG_Z_LD_LINUX_SO_2, index)
215 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
216 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
217# endif
sewardj4157d4f2011-09-05 22:18:13 +0000218
njnf76d27a2009-05-28 01:53:07 +0000219#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000220 //STRCHR(VG_Z_LIBC_SONAME, strchr)
221 //STRCHR(VG_Z_LIBC_SONAME, index)
222 //STRCHR(VG_Z_DYLD, strchr)
223 //STRCHR(VG_Z_DYLD, index)
224 STRCHR(VG_Z_LIBC_SONAME, strchr)
sewardj4157d4f2011-09-05 22:18:13 +0000225
njnb4cfbc42009-05-04 04:20:02 +0000226#endif
njn3e884182003-04-15 13:03:23 +0000227
njn3e884182003-04-15 13:03:23 +0000228
sewardj3c944452011-09-05 20:39:57 +0000229/*---------------------- strcat ----------------------*/
230
njn16eeb4e2005-06-16 03:56:58 +0000231#define STRCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000232 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000233 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000234 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000235 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000236 { \
237 const Char* src_orig = src; \
238 Char* dst_orig = dst; \
239 while (*dst) dst++; \
240 while (*src) *dst++ = *src++; \
241 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000242 \
njn16eeb4e2005-06-16 03:56:58 +0000243 /* This is a bit redundant, I think; any overlap and the strcat will */ \
244 /* go forever... or until a seg fault occurs. */ \
245 if (is_overlap(dst_orig, \
246 src_orig, \
247 (Addr)dst-(Addr)dst_orig+1, \
248 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000249 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000250 \
njn16eeb4e2005-06-16 03:56:58 +0000251 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000252 }
njn3e884182003-04-15 13:03:23 +0000253
tomd2645142009-10-29 09:27:11 +0000254#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000255 STRCAT(VG_Z_LIBC_SONAME, strcat)
256 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
sewardj4157d4f2011-09-05 22:18:13 +0000257
sewardj3c944452011-09-05 20:39:57 +0000258#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000259 //STRCAT(VG_Z_LIBC_SONAME, strcat)
sewardj4157d4f2011-09-05 22:18:13 +0000260
tomd2645142009-10-29 09:27:11 +0000261#endif
njn16eeb4e2005-06-16 03:56:58 +0000262
sewardj3c944452011-09-05 20:39:57 +0000263
264/*---------------------- strncat ----------------------*/
265
njn16eeb4e2005-06-16 03:56:58 +0000266#define STRNCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000267 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000268 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000269 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000270 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000271 { \
272 const Char* src_orig = src; \
273 Char* dst_orig = dst; \
274 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000275 \
njn16eeb4e2005-06-16 03:56:58 +0000276 while (*dst) dst++; \
277 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
278 *dst = 0; /* always add null */ \
sewardjb6c04032007-11-13 20:52:29 +0000279 \
njn16eeb4e2005-06-16 03:56:58 +0000280 /* This checks for overlap after copying, unavoidable without */ \
281 /* pre-counting lengths... should be ok */ \
282 if (is_overlap(dst_orig, \
283 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000284 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000285 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000286 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
sewardjb6c04032007-11-13 20:52:29 +0000287 \
njn16eeb4e2005-06-16 03:56:58 +0000288 return dst_orig; \
njn3e884182003-04-15 13:03:23 +0000289 }
njn3e884182003-04-15 13:03:23 +0000290
sewardj3c944452011-09-05 20:39:57 +0000291#if defined(VGO_linux)
292 STRNCAT(VG_Z_LIBC_SONAME, strncat)
sewardj4157d4f2011-09-05 22:18:13 +0000293
sewardj3c944452011-09-05 20:39:57 +0000294#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000295 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
296 //STRNCAT(VG_Z_DYLD, strncat)
sewardj4157d4f2011-09-05 22:18:13 +0000297
njnf76d27a2009-05-28 01:53:07 +0000298#endif
299
300
sewardj3c944452011-09-05 20:39:57 +0000301/*---------------------- strlcat ----------------------*/
302
njnf76d27a2009-05-28 01:53:07 +0000303/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
304 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
305 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
306 Truncation occurred if retval >= n.
307*/
308#define STRLCAT(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000309 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000310 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000311 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000312 ( char* dst, const char* src, SizeT n ) \
313 { \
314 const Char* src_orig = src; \
315 Char* dst_orig = dst; \
316 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000317 \
njnf76d27a2009-05-28 01:53:07 +0000318 while (m < n && *dst) { m++; dst++; } \
319 if (m < n) { \
320 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
321 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
322 *dst = 0; \
323 } else { \
324 /* No space to copy anything to dst. m == n */ \
325 } \
326 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
327 while (*src) { m++; src++; } \
328 /* This checks for overlap after copying, unavoidable without */ \
329 /* pre-counting lengths... should be ok */ \
330 if (is_overlap(dst_orig, \
331 src_orig, \
332 (Addr)dst-(Addr)dst_orig+1, \
333 (Addr)src-(Addr)src_orig+1)) \
334 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
sewardjbd2cff22011-08-16 21:45:28 +0000335 \
njnf76d27a2009-05-28 01:53:07 +0000336 return m; \
337 }
338
sewardj3c944452011-09-05 20:39:57 +0000339#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000340
sewardj3c944452011-09-05 20:39:57 +0000341#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000342 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
343 //STRLCAT(VG_Z_DYLD, strlcat)
sewardj3c944452011-09-05 20:39:57 +0000344 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
sewardj4157d4f2011-09-05 22:18:13 +0000345
njnf76d27a2009-05-28 01:53:07 +0000346#endif
sewardj31b9ce12006-10-17 01:27:13 +0000347
njn3e884182003-04-15 13:03:23 +0000348
sewardj3c944452011-09-05 20:39:57 +0000349/*---------------------- strnlen ----------------------*/
350
njn16eeb4e2005-06-16 03:56:58 +0000351#define STRNLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000352 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000353 ( const char* str, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000354 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000355 ( const char* str, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000356 { \
357 SizeT i = 0; \
358 while (i < n && str[i] != 0) i++; \
359 return i; \
njn3e884182003-04-15 13:03:23 +0000360 }
njn3e884182003-04-15 13:03:23 +0000361
tomd2645142009-10-29 09:27:11 +0000362#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000363 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
364 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
sewardj4157d4f2011-09-05 22:18:13 +0000365
sewardj3c944452011-09-05 20:39:57 +0000366#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000367 //STRNLEN(VG_Z_LIBC_SONAME, strnlen)
sewardj4157d4f2011-09-05 22:18:13 +0000368
tomd2645142009-10-29 09:27:11 +0000369#endif
njn16eeb4e2005-06-16 03:56:58 +0000370
sewardj3ceec242003-07-30 21:24:25 +0000371
sewardj3c944452011-09-05 20:39:57 +0000372/*---------------------- strlen ----------------------*/
373
njn5ec15ed2005-08-24 19:55:51 +0000374// Note that this replacement often doesn't get used because gcc inlines
375// calls to strlen() with its own built-in version. This can be very
sewardj3c944452011-09-05 20:39:57 +0000376// confusing if you aren't expecting it. Other small functions in
377// this file may also be inline by gcc.
378
njn16eeb4e2005-06-16 03:56:58 +0000379#define STRLEN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000380 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000381 ( const char* str ); \
sewardj96044842011-08-18 13:09:55 +0000382 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000383 ( const char* str ) \
njn16eeb4e2005-06-16 03:56:58 +0000384 { \
385 SizeT i = 0; \
386 while (str[i] != 0) i++; \
387 return i; \
sewardj3ceec242003-07-30 21:24:25 +0000388 }
njn16eeb4e2005-06-16 03:56:58 +0000389
njnb4cfbc42009-05-04 04:20:02 +0000390#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000391 STRLEN(VG_Z_LIBC_SONAME, strlen)
392 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
sewardj70f291d2011-09-26 20:20:19 +0000393# if defined(VGPV_arm_linux_android)
394 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
395# endif
sewardj4157d4f2011-09-05 22:18:13 +0000396
sewardj3c944452011-09-05 20:39:57 +0000397#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000398 //STRLEN(VG_Z_LIBC_SONAME, strlen)
399 STRLEN(VG_Z_LIBC_SONAME, strlen)
sewardj4157d4f2011-09-05 22:18:13 +0000400
njnb4cfbc42009-05-04 04:20:02 +0000401#endif
sewardj31b9ce12006-10-17 01:27:13 +0000402
njn16eeb4e2005-06-16 03:56:58 +0000403
sewardj3c944452011-09-05 20:39:57 +0000404/*---------------------- strcpy ----------------------*/
405
njn16eeb4e2005-06-16 03:56:58 +0000406#define STRCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000407 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000408 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000409 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000410 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000411 { \
412 const Char* src_orig = src; \
413 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000414 \
njn16eeb4e2005-06-16 03:56:58 +0000415 while (*src) *dst++ = *src++; \
416 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000417 \
njn16eeb4e2005-06-16 03:56:58 +0000418 /* This checks for overlap after copying, unavoidable without */ \
419 /* pre-counting length... should be ok */ \
420 if (is_overlap(dst_orig, \
421 src_orig, \
sewardjbd2cff22011-08-16 21:45:28 +0000422 (Addr)dst-(Addr)dst_orig+1, \
njn16eeb4e2005-06-16 03:56:58 +0000423 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000424 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000425 \
njn16eeb4e2005-06-16 03:56:58 +0000426 return dst_orig; \
427 }
428
tomd2645142009-10-29 09:27:11 +0000429#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000430 STRCPY(VG_Z_LIBC_SONAME, strcpy)
431 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000432
tomd2645142009-10-29 09:27:11 +0000433#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000434 //STRCPY(VG_Z_LIBC_SONAME, strcpy)
435 //STRCPY(VG_Z_DYLD, strcpy)
sewardj3c944452011-09-05 20:39:57 +0000436 STRCPY(VG_Z_LIBC_SONAME, strcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000437
njnf76d27a2009-05-28 01:53:07 +0000438#endif
njn16eeb4e2005-06-16 03:56:58 +0000439
440
sewardj3c944452011-09-05 20:39:57 +0000441/*---------------------- strncpy ----------------------*/
442
njn16eeb4e2005-06-16 03:56:58 +0000443#define STRNCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000444 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000445 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000446 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000447 ( char* dst, const char* src, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000448 { \
449 const Char* src_orig = src; \
450 Char* dst_orig = dst; \
451 SizeT m = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000452 \
njn16eeb4e2005-06-16 03:56:58 +0000453 while (m < n && *src) { m++; *dst++ = *src++; } \
454 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
455 /* but only m+1 bytes of src if terminator was found */ \
456 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
njn718d3b12006-12-16 00:54:12 +0000457 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
njn16eeb4e2005-06-16 03:56:58 +0000458 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
sewardj3c944452011-09-05 20:39:57 +0000459 \
njn16eeb4e2005-06-16 03:56:58 +0000460 return dst_orig; \
461 }
462
tomd2645142009-10-29 09:27:11 +0000463#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000464 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
465 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000466
tomd2645142009-10-29 09:27:11 +0000467#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000468 //STRNCPY(VG_Z_LIBC_SONAME, strncpy)
469 //STRNCPY(VG_Z_DYLD, strncpy)
sewardj3c944452011-09-05 20:39:57 +0000470 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
sewardj4157d4f2011-09-05 22:18:13 +0000471
njnf76d27a2009-05-28 01:53:07 +0000472#endif
473
474
sewardj3c944452011-09-05 20:39:57 +0000475/*---------------------- strlcpy ----------------------*/
476
njnf76d27a2009-05-28 01:53:07 +0000477/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
478 Returns strlen(src). Does not zero-fill the remainder of dst. */
479#define STRLCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000480 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000481 ( char* dst, const char* src, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000482 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000483 ( char* dst, const char* src, SizeT n ) \
484 { \
485 const char* src_orig = src; \
486 char* dst_orig = dst; \
487 SizeT m = 0; \
sewardjbd2cff22011-08-16 21:45:28 +0000488 \
njnf76d27a2009-05-28 01:53:07 +0000489 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
490 /* m non-nul bytes have now been copied, and m <= n-1. */ \
491 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
492 /* but only m+1 bytes of src if terminator was found */ \
493 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
494 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
495 /* Nul-terminate dst. */ \
496 if (n > 0) *dst = 0; \
497 /* Finish counting strlen(src). */ \
498 while (*src) src++; \
499 return src - src_orig; \
500 }
501
sewardj3c944452011-09-05 20:39:57 +0000502#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +0000503
sewardj3c944452011-09-05 20:39:57 +0000504#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000505 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
506 //STRLCPY(VG_Z_DYLD, strlcpy)
sewardj3c944452011-09-05 20:39:57 +0000507 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000508
njnf76d27a2009-05-28 01:53:07 +0000509#endif
njn16eeb4e2005-06-16 03:56:58 +0000510
511
sewardj3c944452011-09-05 20:39:57 +0000512/*---------------------- strncmp ----------------------*/
513
njn16eeb4e2005-06-16 03:56:58 +0000514#define STRNCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000515 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000516 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000517 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000518 ( const char* s1, const char* s2, SizeT nmax ) \
njn16eeb4e2005-06-16 03:56:58 +0000519 { \
520 SizeT n = 0; \
521 while (True) { \
522 if (n >= nmax) return 0; \
523 if (*s1 == 0 && *s2 == 0) return 0; \
524 if (*s1 == 0) return -1; \
525 if (*s2 == 0) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000526 \
njn16eeb4e2005-06-16 03:56:58 +0000527 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
528 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
sewardjb6c04032007-11-13 20:52:29 +0000529 \
njn16eeb4e2005-06-16 03:56:58 +0000530 s1++; s2++; n++; \
531 } \
532 }
533
tomd2645142009-10-29 09:27:11 +0000534#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000535 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
536 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000537
tomd2645142009-10-29 09:27:11 +0000538#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000539 //STRNCMP(VG_Z_LIBC_SONAME, strncmp)
540 //STRNCMP(VG_Z_DYLD, strncmp)
541 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
sewardj4157d4f2011-09-05 22:18:13 +0000542
njnf76d27a2009-05-28 01:53:07 +0000543#endif
njn16eeb4e2005-06-16 03:56:58 +0000544
545
sewardj3c944452011-09-05 20:39:57 +0000546/*---------------------- strcasecmp ----------------------*/
547
tomce6d0ac2010-11-12 10:03:13 +0000548#define STRCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000549 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000550 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000551 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000552 ( const char* s1, const char* s2 ) \
553 { \
tome03c8c42010-11-12 10:40:20 +0000554 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000555 register unsigned char c1; \
556 register unsigned char c2; \
557 while (True) { \
558 c1 = tolower(*(unsigned char *)s1); \
559 c2 = tolower(*(unsigned char *)s2); \
560 if (c1 != c2) break; \
561 if (c1 == 0) break; \
562 s1++; s2++; \
563 } \
564 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
565 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
566 return 0; \
567 }
568
sewardj3c944452011-09-05 20:39:57 +0000569#if defined(VGO_linux)
570# if !defined(VGPV_arm_linux_android)
571 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
572 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
573# endif
sewardj4157d4f2011-09-05 22:18:13 +0000574
sewardj3c944452011-09-05 20:39:57 +0000575#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000576 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000577
tomce6d0ac2010-11-12 10:03:13 +0000578#endif
579
580
sewardj3c944452011-09-05 20:39:57 +0000581/*---------------------- strncasecmp ----------------------*/
582
tomce6d0ac2010-11-12 10:03:13 +0000583#define STRNCASECMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000584 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000585 ( const char* s1, const char* s2, SizeT nmax ); \
sewardj96044842011-08-18 13:09:55 +0000586 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
tomce6d0ac2010-11-12 10:03:13 +0000587 ( const char* s1, const char* s2, SizeT nmax ) \
588 { \
tome03c8c42010-11-12 10:40:20 +0000589 extern int tolower(int); \
tomce6d0ac2010-11-12 10:03:13 +0000590 SizeT n = 0; \
591 while (True) { \
592 if (n >= nmax) return 0; \
593 if (*s1 == 0 && *s2 == 0) return 0; \
594 if (*s1 == 0) return -1; \
595 if (*s2 == 0) return 1; \
596 \
sewardjbd2cff22011-08-16 21:45:28 +0000597 if (tolower(*(unsigned char*)s1) \
598 < tolower(*(unsigned char*)s2)) return -1; \
599 if (tolower(*(unsigned char*)s1) \
600 > tolower(*(unsigned char*)s2)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000601 \
602 s1++; s2++; n++; \
603 } \
604 }
605
sewardj3c944452011-09-05 20:39:57 +0000606#if defined(VGO_linux)
607# if !defined(VGPV_arm_linux_android)
608 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
609 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
610# endif
sewardj4157d4f2011-09-05 22:18:13 +0000611
tomce6d0ac2010-11-12 10:03:13 +0000612#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000613 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
614 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
sewardj4157d4f2011-09-05 22:18:13 +0000615
tomce6d0ac2010-11-12 10:03:13 +0000616#endif
617
618
sewardj3c944452011-09-05 20:39:57 +0000619/*---------------------- strcasecmp_l ----------------------*/
620
tomce6d0ac2010-11-12 10:03:13 +0000621#define STRCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000622 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000623 ( const char* s1, const char* s2, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000624 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000625 ( const char* s1, const char* s2, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000626 { \
sewardj3c944452011-09-05 20:39:57 +0000627 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000628 register unsigned char c1; \
629 register unsigned char c2; \
630 while (True) { \
631 c1 = tolower_l(*(unsigned char *)s1, locale); \
632 c2 = tolower_l(*(unsigned char *)s2, locale); \
633 if (c1 != c2) break; \
634 if (c1 == 0) break; \
635 s1++; s2++; \
636 } \
637 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
638 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
639 return 0; \
640 }
641
tomce6d0ac2010-11-12 10:03:13 +0000642#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000643 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
644 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
645 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000646
sewardj3c944452011-09-05 20:39:57 +0000647#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000648 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000649
tomce6d0ac2010-11-12 10:03:13 +0000650#endif
651
652
sewardj3c944452011-09-05 20:39:57 +0000653/*---------------------- strncasecmp_l ----------------------*/
654
tomce6d0ac2010-11-12 10:03:13 +0000655#define STRNCASECMP_L(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000656 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000657 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
sewardj96044842011-08-18 13:09:55 +0000658 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
tome03c8c42010-11-12 10:40:20 +0000659 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
tomce6d0ac2010-11-12 10:03:13 +0000660 { \
tome03c8c42010-11-12 10:40:20 +0000661 extern int tolower_l(int, void*) __attribute__((weak)); \
tomce6d0ac2010-11-12 10:03:13 +0000662 SizeT n = 0; \
663 while (True) { \
664 if (n >= nmax) return 0; \
665 if (*s1 == 0 && *s2 == 0) return 0; \
666 if (*s1 == 0) return -1; \
667 if (*s2 == 0) return 1; \
668 \
sewardjbd2cff22011-08-16 21:45:28 +0000669 if (tolower_l(*(unsigned char*)s1, locale) \
670 < tolower_l(*(unsigned char*)s2, locale)) return -1; \
671 if (tolower_l(*(unsigned char*)s1, locale) \
672 > tolower_l(*(unsigned char*)s2, locale)) return 1; \
tomce6d0ac2010-11-12 10:03:13 +0000673 \
674 s1++; s2++; n++; \
675 } \
676 }
677
tomce6d0ac2010-11-12 10:03:13 +0000678#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000679 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
680 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000681
tomce6d0ac2010-11-12 10:03:13 +0000682#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000683 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
684 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
sewardj4157d4f2011-09-05 22:18:13 +0000685
tomce6d0ac2010-11-12 10:03:13 +0000686#endif
687
688
sewardj3c944452011-09-05 20:39:57 +0000689/*---------------------- strcmp ----------------------*/
690
njn16eeb4e2005-06-16 03:56:58 +0000691#define STRCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000692 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000693 ( const char* s1, const char* s2 ); \
sewardj96044842011-08-18 13:09:55 +0000694 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000695 ( const char* s1, const char* s2 ) \
njn16eeb4e2005-06-16 03:56:58 +0000696 { \
697 register unsigned char c1; \
698 register unsigned char c2; \
699 while (True) { \
700 c1 = *(unsigned char *)s1; \
701 c2 = *(unsigned char *)s2; \
702 if (c1 != c2) break; \
703 if (c1 == 0) break; \
704 s1++; s2++; \
705 } \
706 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
707 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
708 return 0; \
709 }
710
njnb4cfbc42009-05-04 04:20:02 +0000711#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000712 STRCMP(VG_Z_LIBC_SONAME, strcmp)
713 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
714 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
715 STRCMP(VG_Z_LD64_SO_1, strcmp)
sewardj70f291d2011-09-26 20:20:19 +0000716# if defined(VGPV_arm_linux_android)
717 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
718# endif
sewardj4157d4f2011-09-05 22:18:13 +0000719
sewardj3c944452011-09-05 20:39:57 +0000720#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000721 //STRCMP(VG_Z_LIBC_SONAME, strcmp)
722 STRCMP(VG_Z_LIBC_SONAME, strcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000723
njnb4cfbc42009-05-04 04:20:02 +0000724#endif
njn16eeb4e2005-06-16 03:56:58 +0000725
726
sewardj3c944452011-09-05 20:39:57 +0000727/*---------------------- memchr ----------------------*/
728
njn16eeb4e2005-06-16 03:56:58 +0000729#define MEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000730 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000731 (const void *s, int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000732 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000733 (const void *s, int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000734 { \
735 SizeT i; \
736 UChar c0 = (UChar)c; \
737 UChar* p = (UChar*)s; \
738 for (i = 0; i < n; i++) \
739 if (p[i] == c0) return (void*)(&p[i]); \
740 return NULL; \
741 }
742
sewardj3c944452011-09-05 20:39:57 +0000743#if defined(VGO_linux)
744 MEMCHR(VG_Z_LIBC_SONAME, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000745
sewardj3c944452011-09-05 20:39:57 +0000746#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000747 //MEMCHR(VG_Z_LIBC_SONAME, memchr)
748 //MEMCHR(VG_Z_DYLD, memchr)
sewardj4157d4f2011-09-05 22:18:13 +0000749
njnf76d27a2009-05-28 01:53:07 +0000750#endif
njn16eeb4e2005-06-16 03:56:58 +0000751
752
sewardj3c944452011-09-05 20:39:57 +0000753/*---------------------- memcpy ----------------------*/
754
sewardjbd2cff22011-08-16 21:45:28 +0000755#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
sewardjd88797f2011-08-17 21:25:50 +0000756 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000757 ( void *dst, const void *src, SizeT len ); \
sewardjd88797f2011-08-17 21:25:50 +0000758 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000759 ( void *dst, const void *src, SizeT len ) \
njn16eeb4e2005-06-16 03:56:58 +0000760 { \
sewardjbd2cff22011-08-16 21:45:28 +0000761 if (do_ol_check && is_overlap(dst, src, len, len)) \
njn718d3b12006-12-16 00:54:12 +0000762 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
sewardjb6c04032007-11-13 20:52:29 +0000763 \
sewardj7b4e00b2010-08-24 09:05:52 +0000764 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
765 const Addr WM = WS - 1; /* 7 or 3 */ \
766 \
tom863ab7c2011-08-18 08:10:20 +0000767 if (len > 0) { \
768 if (dst < src) { \
sewardj7b4e00b2010-08-24 09:05:52 +0000769 \
tom863ab7c2011-08-18 08:10:20 +0000770 /* Copying backwards. */ \
771 SizeT n = len; \
772 Addr d = (Addr)dst; \
773 Addr s = (Addr)src; \
774 \
775 if (((s^d) & WM) == 0) { \
776 /* s and d have same UWord alignment. */ \
777 /* Pull up to a UWord boundary. */ \
778 while ((s & WM) != 0 && n >= 1) \
779 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
780 /* Copy UWords. */ \
781 while (n >= WS) \
782 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
783 if (n == 0) \
784 return dst; \
785 } \
786 if (((s|d) & 1) == 0) { \
787 /* Both are 16-aligned; copy what we can thusly. */ \
788 while (n >= 2) \
789 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
790 } \
791 /* Copy leftovers, or everything if misaligned. */ \
792 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000793 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
sewardj7b4e00b2010-08-24 09:05:52 +0000794 \
tom863ab7c2011-08-18 08:10:20 +0000795 } else if (dst > src) { \
796 \
797 SizeT n = len; \
798 Addr d = ((Addr)dst) + n; \
799 Addr s = ((Addr)src) + n; \
800 \
801 /* Copying forwards. */ \
802 if (((s^d) & WM) == 0) { \
803 /* s and d have same UWord alignment. */ \
804 /* Back down to a UWord boundary. */ \
805 while ((s & WM) != 0 && n >= 1) \
806 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
807 /* Copy UWords. */ \
808 while (n >= WS) \
809 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
810 if (n == 0) \
811 return dst; \
812 } \
813 if (((s|d) & 1) == 0) { \
814 /* Both are 16-aligned; copy what we can thusly. */ \
815 while (n >= 2) \
816 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
817 } \
818 /* Copy leftovers, or everything if misaligned. */ \
819 while (n >= 1) \
sewardj7b4e00b2010-08-24 09:05:52 +0000820 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
tom863ab7c2011-08-18 08:10:20 +0000821 \
njn16eeb4e2005-06-16 03:56:58 +0000822 } \
njn16eeb4e2005-06-16 03:56:58 +0000823 } \
sewardj7b4e00b2010-08-24 09:05:52 +0000824 \
njn16eeb4e2005-06-16 03:56:58 +0000825 return dst; \
826 }
827
sewardjbd2cff22011-08-16 21:45:28 +0000828#define MEMMOVE(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000829 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
sewardjbd2cff22011-08-16 21:45:28 +0000830
831#define MEMCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000832 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
sewardjbd2cff22011-08-16 21:45:28 +0000833
njnb4cfbc42009-05-04 04:20:02 +0000834#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000835 /* For older memcpy we have to use memmove-like semantics and skip
836 the overlap check; sigh; see #275284. */
837 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
838 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
839 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
840 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
841 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
sewardj3c944452011-09-05 20:39:57 +0000842 /* icc9 blats these around all over the place. Not only in the main
843 executable but various .so's. They are highly tuned and read
844 memory beyond the source boundary (although work correctly and
845 never go across page boundaries), so give errors when run
846 natively, at least for misaligned source arg. Just intercepting
847 in the exe only until we understand more about the problem. See
848 http://bugs.kde.org/show_bug.cgi?id=139776
sewardjf0b34322007-01-16 21:42:28 +0000849 */
sewardj3c944452011-09-05 20:39:57 +0000850 MEMCPY(NONE, ZuintelZufastZumemcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000851
852#elif defined(VGO_darwin)
sewardja65f80c2012-03-07 15:26:50 +0000853# if DARWIN_VERS <= DARWIN_10_6
854 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
855# endif
sewardj731f9cf2011-09-21 08:43:08 +0000856 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
857 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
sewardj4157d4f2011-09-05 22:18:13 +0000858
sewardj3c944452011-09-05 20:39:57 +0000859#endif
sewardj31b9ce12006-10-17 01:27:13 +0000860
njn16eeb4e2005-06-16 03:56:58 +0000861
sewardj3c944452011-09-05 20:39:57 +0000862/*---------------------- memcmp ----------------------*/
863
njn16eeb4e2005-06-16 03:56:58 +0000864#define MEMCMP(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000865 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardj0ec07f32006-01-12 12:32:32 +0000866 ( const void *s1V, const void *s2V, SizeT n ); \
sewardj96044842011-08-18 13:09:55 +0000867 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000868 ( const void *s1V, const void *s2V, SizeT n ) \
njn16eeb4e2005-06-16 03:56:58 +0000869 { \
870 int res; \
871 unsigned char a0; \
872 unsigned char b0; \
873 unsigned char* s1 = (unsigned char*)s1V; \
874 unsigned char* s2 = (unsigned char*)s2V; \
sewardjb6c04032007-11-13 20:52:29 +0000875 \
njn16eeb4e2005-06-16 03:56:58 +0000876 while (n != 0) { \
877 a0 = s1[0]; \
878 b0 = s2[0]; \
879 s1 += 1; \
880 s2 += 1; \
881 res = ((int)a0) - ((int)b0); \
882 if (res != 0) \
883 return res; \
884 n -= 1; \
885 } \
886 return 0; \
887 }
888
njnb4cfbc42009-05-04 04:20:02 +0000889#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000890 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
891 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
892 MEMCMP(VG_Z_LD_SO_1, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000893
njnf76d27a2009-05-28 01:53:07 +0000894#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000895 //MEMCMP(VG_Z_LIBC_SONAME, memcmp)
896 //MEMCMP(VG_Z_LIBC_SONAME, bcmp)
897 //MEMCMP(VG_Z_DYLD, memcmp)
898 //MEMCMP(VG_Z_DYLD, bcmp)
sewardj4157d4f2011-09-05 22:18:13 +0000899
njnb4cfbc42009-05-04 04:20:02 +0000900#endif
njn3e884182003-04-15 13:03:23 +0000901
jseward0845ef82003-12-22 22:31:27 +0000902
sewardj3c944452011-09-05 20:39:57 +0000903/*---------------------- stpcpy ----------------------*/
904
jseward0845ef82003-12-22 22:31:27 +0000905/* Copy SRC to DEST, returning the address of the terminating '\0' in
906 DEST. (minor variant of strcpy) */
njn16eeb4e2005-06-16 03:56:58 +0000907#define STPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000908 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000909 ( char* dst, const char* src ); \
sewardj96044842011-08-18 13:09:55 +0000910 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000911 ( char* dst, const char* src ) \
njn16eeb4e2005-06-16 03:56:58 +0000912 { \
913 const Char* src_orig = src; \
914 Char* dst_orig = dst; \
sewardjb6c04032007-11-13 20:52:29 +0000915 \
njn16eeb4e2005-06-16 03:56:58 +0000916 while (*src) *dst++ = *src++; \
917 *dst = 0; \
sewardjb6c04032007-11-13 20:52:29 +0000918 \
njn16eeb4e2005-06-16 03:56:58 +0000919 /* This checks for overlap after copying, unavoidable without */ \
920 /* pre-counting length... should be ok */ \
921 if (is_overlap(dst_orig, \
922 src_orig, \
923 (Addr)dst-(Addr)dst_orig+1, \
924 (Addr)src-(Addr)src_orig+1)) \
njn718d3b12006-12-16 00:54:12 +0000925 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
sewardjb6c04032007-11-13 20:52:29 +0000926 \
njn16eeb4e2005-06-16 03:56:58 +0000927 return dst; \
sewardj44e495f2005-05-12 17:58:28 +0000928 }
njn16eeb4e2005-06-16 03:56:58 +0000929
njnb4cfbc42009-05-04 04:20:02 +0000930#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +0000931 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
932 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
933 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
934 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000935
njnf76d27a2009-05-28 01:53:07 +0000936#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000937 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
938 //STPCPY(VG_Z_DYLD, stpcpy)
sewardj4157d4f2011-09-05 22:18:13 +0000939
njnb4cfbc42009-05-04 04:20:02 +0000940#endif
941
njn16eeb4e2005-06-16 03:56:58 +0000942
sewardj3c944452011-09-05 20:39:57 +0000943/*---------------------- memset ----------------------*/
944
945/* Why are we bothering to intercept this? It seems entirely
946 pointless. */
sewardj731f9cf2011-09-21 08:43:08 +0000947
njn16eeb4e2005-06-16 03:56:58 +0000948#define MEMSET(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000949 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000950 (void *s, Int c, SizeT n); \
sewardj96044842011-08-18 13:09:55 +0000951 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +0000952 (void *s, Int c, SizeT n) \
njn16eeb4e2005-06-16 03:56:58 +0000953 { \
sewardj7b4e00b2010-08-24 09:05:52 +0000954 Addr a = (Addr)s; \
955 UInt c4 = (c & 0xFF); \
956 c4 = (c4 << 8) | c4; \
957 c4 = (c4 << 16) | c4; \
958 while ((a & 3) != 0 && n >= 1) \
959 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
960 while (n >= 4) \
961 { *(UInt*)a = c4; a += 4; n -= 4; } \
962 while (n >= 1) \
963 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
njn16eeb4e2005-06-16 03:56:58 +0000964 return s; \
sewardj44e495f2005-05-12 17:58:28 +0000965 }
njn16eeb4e2005-06-16 03:56:58 +0000966
sewardj3c944452011-09-05 20:39:57 +0000967#if defined(VGO_linux)
968 MEMSET(VG_Z_LIBC_SONAME, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000969
sewardj3c944452011-09-05 20:39:57 +0000970#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +0000971 //MEMSET(VG_Z_LIBC_SONAME, memset)
972 //MEMSET(VG_Z_DYLD, memset)
sewardj3c944452011-09-05 20:39:57 +0000973 MEMSET(VG_Z_LIBC_SONAME, memset)
sewardj4157d4f2011-09-05 22:18:13 +0000974
njnf76d27a2009-05-28 01:53:07 +0000975#endif
njn16eeb4e2005-06-16 03:56:58 +0000976
977
sewardj3c944452011-09-05 20:39:57 +0000978/*---------------------- memmove ----------------------*/
979
sewardj96044842011-08-18 13:09:55 +0000980/* memmove -- use the MEMMOVE defn above. */
sewardj731f9cf2011-09-21 08:43:08 +0000981
sewardj3c944452011-09-05 20:39:57 +0000982#if defined(VGO_linux)
983 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
sewardj4157d4f2011-09-05 22:18:13 +0000984
sewardj3c944452011-09-05 20:39:57 +0000985#elif defined(VGO_darwin)
sewardja65f80c2012-03-07 15:26:50 +0000986# if DARWIN_VERS <= DARWIN_10_6
987 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
988# endif
sewardj731f9cf2011-09-21 08:43:08 +0000989 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
990 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
sewardj4157d4f2011-09-05 22:18:13 +0000991
njnf76d27a2009-05-28 01:53:07 +0000992#endif
993
994
sewardj3c944452011-09-05 20:39:57 +0000995/*---------------------- bcopy ----------------------*/
996
njnf76d27a2009-05-28 01:53:07 +0000997#define BCOPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +0000998 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +0000999 (const void *srcV, void *dstV, SizeT n); \
sewardj96044842011-08-18 13:09:55 +00001000 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
njnf76d27a2009-05-28 01:53:07 +00001001 (const void *srcV, void *dstV, SizeT n) \
1002 { \
1003 SizeT i; \
1004 Char* dst = (Char*)dstV; \
1005 Char* src = (Char*)srcV; \
1006 if (dst < src) { \
1007 for (i = 0; i < n; i++) \
1008 dst[i] = src[i]; \
1009 } \
1010 else \
1011 if (dst > src) { \
1012 for (i = 0; i < n; i++) \
1013 dst[n-i-1] = src[n-i-1]; \
1014 } \
1015 }
1016
sewardj3c944452011-09-05 20:39:57 +00001017#if defined(VGO_linux)
sewardj4157d4f2011-09-05 22:18:13 +00001018
sewardj3c944452011-09-05 20:39:57 +00001019#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +00001020 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1021 //BCOPY(VG_Z_DYLD, bcopy)
sewardj4157d4f2011-09-05 22:18:13 +00001022
njnf76d27a2009-05-28 01:53:07 +00001023#endif
sewardj44e495f2005-05-12 17:58:28 +00001024
jseward0845ef82003-12-22 22:31:27 +00001025
sewardj3c944452011-09-05 20:39:57 +00001026/*-------------------- memmove_chk --------------------*/
1027
sewardj24cb2172007-02-23 09:03:26 +00001028/* glibc 2.5 variant of memmove which checks the dest is big enough.
1029 There is no specific part of glibc that this is copied from. */
1030#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001031 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001032 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
sewardj96044842011-08-18 13:09:55 +00001033 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
sewardj24cb2172007-02-23 09:03:26 +00001034 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1035 { \
sewardj24cb2172007-02-23 09:03:26 +00001036 SizeT i; \
1037 Char* dst = (Char*)dstV; \
1038 Char* src = (Char*)srcV; \
1039 if (destlen < n) \
1040 goto badness; \
1041 if (dst < src) { \
1042 for (i = 0; i < n; i++) \
1043 dst[i] = src[i]; \
1044 } \
1045 else \
1046 if (dst > src) { \
1047 for (i = 0; i < n; i++) \
1048 dst[n-i-1] = src[n-i-1]; \
1049 } \
1050 return dst; \
1051 badness: \
1052 VALGRIND_PRINTF_BACKTRACE( \
1053 "*** memmove_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001054 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001055 my_exit(127); \
sewardjc271ec82007-02-27 22:36:14 +00001056 /*NOTREACHED*/ \
1057 return NULL; \
sewardj24cb2172007-02-23 09:03:26 +00001058 }
1059
sewardj3c944452011-09-05 20:39:57 +00001060#if defined(VGO_linux)
1061 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001062
sewardj3c944452011-09-05 20:39:57 +00001063#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001064
sewardj3c944452011-09-05 20:39:57 +00001065#endif
sewardj24cb2172007-02-23 09:03:26 +00001066
1067
sewardj3c944452011-09-05 20:39:57 +00001068/*-------------------- strchrnul --------------------*/
1069
sewardj4e9a4b62004-11-23 00:20:17 +00001070/* Find the first occurrence of C in S or the final NUL byte. */
njn16eeb4e2005-06-16 03:56:58 +00001071#define GLIBC232_STRCHRNUL(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001072 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001073 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001074 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001075 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001076 { \
1077 unsigned char c = (unsigned char) c_in; \
1078 unsigned char* char_ptr = (unsigned char *)s; \
1079 while (1) { \
1080 if (*char_ptr == 0) return char_ptr; \
1081 if (*char_ptr == c) return char_ptr; \
1082 char_ptr++; \
1083 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001084 }
njn16eeb4e2005-06-16 03:56:58 +00001085
sewardj3c944452011-09-05 20:39:57 +00001086#if defined(VGO_linux)
1087 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
sewardj4157d4f2011-09-05 22:18:13 +00001088
sewardj3c944452011-09-05 20:39:57 +00001089#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001090
sewardj3c944452011-09-05 20:39:57 +00001091#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001092
1093
sewardj3c944452011-09-05 20:39:57 +00001094/*---------------------- rawmemchr ----------------------*/
1095
sewardj4e9a4b62004-11-23 00:20:17 +00001096/* Find the first occurrence of C in S. */
njn16eeb4e2005-06-16 03:56:58 +00001097#define GLIBC232_RAWMEMCHR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001098 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001099 (const char* s, int c_in); \
sewardj96044842011-08-18 13:09:55 +00001100 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001101 (const char* s, int c_in) \
njn16eeb4e2005-06-16 03:56:58 +00001102 { \
1103 unsigned char c = (unsigned char) c_in; \
1104 unsigned char* char_ptr = (unsigned char *)s; \
1105 while (1) { \
1106 if (*char_ptr == c) return char_ptr; \
1107 char_ptr++; \
1108 } \
sewardj4e9a4b62004-11-23 00:20:17 +00001109 }
njn16eeb4e2005-06-16 03:56:58 +00001110
tomd2645142009-10-29 09:27:11 +00001111#if defined (VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001112 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1113 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
sewardj4157d4f2011-09-05 22:18:13 +00001114
sewardj3c944452011-09-05 20:39:57 +00001115#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001116
tomd2645142009-10-29 09:27:11 +00001117#endif
sewardj4e9a4b62004-11-23 00:20:17 +00001118
sewardj3c944452011-09-05 20:39:57 +00001119
1120/*---------------------- strcpy_chk ----------------------*/
1121
sewardjdc5d8322007-01-28 06:32:01 +00001122/* glibc variant of strcpy that checks the dest is big enough.
1123 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
sewardj620e5262006-12-31 00:22:30 +00001124#define GLIBC25___STRCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001125 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001126 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001127 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001128 (char* dst, const char* src, SizeT len) \
sewardj620e5262006-12-31 00:22:30 +00001129 { \
sewardj620e5262006-12-31 00:22:30 +00001130 char* ret = dst; \
1131 if (! len) \
1132 goto badness; \
1133 while ((*dst++ = *src++) != '\0') \
1134 if (--len == 0) \
1135 goto badness; \
1136 return ret; \
1137 badness: \
1138 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001139 "*** strcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001140 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001141 my_exit(127); \
sewardj620e5262006-12-31 00:22:30 +00001142 /*NOTREACHED*/ \
1143 return NULL; \
1144 }
1145
sewardj3c944452011-09-05 20:39:57 +00001146#if defined(VGO_linux)
1147 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001148
sewardj3c944452011-09-05 20:39:57 +00001149#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001150
sewardj3c944452011-09-05 20:39:57 +00001151#endif
sewardj620e5262006-12-31 00:22:30 +00001152
1153
sewardj3c944452011-09-05 20:39:57 +00001154/*---------------------- stpcpy_chk ----------------------*/
1155
sewardjdc5d8322007-01-28 06:32:01 +00001156/* glibc variant of stpcpy that checks the dest is big enough.
1157 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
sewardjb8d03852007-01-27 00:49:44 +00001158#define GLIBC25___STPCPY_CHK(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001159 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001160 (char* dst, const char* src, SizeT len); \
sewardj96044842011-08-18 13:09:55 +00001161 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001162 (char* dst, const char* src, SizeT len) \
sewardjb8d03852007-01-27 00:49:44 +00001163 { \
sewardjdc5d8322007-01-28 06:32:01 +00001164 if (! len) \
1165 goto badness; \
1166 while ((*dst++ = *src++) != '\0') \
1167 if (--len == 0) \
sewardjb8d03852007-01-27 00:49:44 +00001168 goto badness; \
sewardjb8d03852007-01-27 00:49:44 +00001169 return dst - 1; \
1170 badness: \
1171 VALGRIND_PRINTF_BACKTRACE( \
sewardj24cb2172007-02-23 09:03:26 +00001172 "*** stpcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001173 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001174 my_exit(127); \
sewardjb8d03852007-01-27 00:49:44 +00001175 /*NOTREACHED*/ \
1176 return NULL; \
1177 }
1178
sewardj3c944452011-09-05 20:39:57 +00001179#if defined(VGO_linux)
1180 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001181
sewardj3c944452011-09-05 20:39:57 +00001182#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001183
sewardj3c944452011-09-05 20:39:57 +00001184#endif
sewardjb8d03852007-01-27 00:49:44 +00001185
1186
sewardj3c944452011-09-05 20:39:57 +00001187/*---------------------- mempcpy ----------------------*/
1188
sewardj841b72d2006-12-31 18:55:56 +00001189/* mempcpy */
1190#define GLIBC25_MEMPCPY(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001191 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001192 ( void *dst, const void *src, SizeT len ); \
sewardj96044842011-08-18 13:09:55 +00001193 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
sewardj841b72d2006-12-31 18:55:56 +00001194 ( void *dst, const void *src, SizeT len ) \
1195 { \
1196 register char *d; \
1197 register char *s; \
1198 SizeT len_saved = len; \
1199 \
1200 if (len == 0) \
1201 return dst; \
1202 \
1203 if (is_overlap(dst, src, len, len)) \
1204 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1205 \
1206 if ( dst > src ) { \
1207 d = (char *)dst + len - 1; \
1208 s = (char *)src + len - 1; \
1209 while ( len-- ) { \
1210 *d-- = *s--; \
1211 } \
1212 } else if ( dst < src ) { \
1213 d = (char *)dst; \
1214 s = (char *)src; \
1215 while ( len-- ) { \
1216 *d++ = *s++; \
1217 } \
1218 } \
1219 return (void*)( ((char*)dst) + len_saved ); \
1220 }
1221
njnb4cfbc42009-05-04 04:20:02 +00001222#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001223 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1224 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
sewardj4157d4f2011-09-05 22:18:13 +00001225
sewardj3c944452011-09-05 20:39:57 +00001226#elif defined(VGO_darwin)
sewardj731f9cf2011-09-21 08:43:08 +00001227 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
sewardj4157d4f2011-09-05 22:18:13 +00001228
njnb4cfbc42009-05-04 04:20:02 +00001229#endif
sewardj841b72d2006-12-31 18:55:56 +00001230
1231
sewardj3c944452011-09-05 20:39:57 +00001232/*-------------------- memcpy_chk --------------------*/
1233
sewardjb6c04032007-11-13 20:52:29 +00001234#define GLIBC26___MEMCPY_CHK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001235 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001236 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
sewardj96044842011-08-18 13:09:55 +00001237 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
sewardjb6c04032007-11-13 20:52:29 +00001238 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1239 { \
sewardjb6c04032007-11-13 20:52:29 +00001240 register char *d; \
1241 register char *s; \
1242 \
1243 if (dstlen < len) goto badness; \
1244 \
1245 if (len == 0) \
1246 return dst; \
1247 \
1248 if (is_overlap(dst, src, len, len)) \
1249 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1250 \
1251 if ( dst > src ) { \
1252 d = (char *)dst + len - 1; \
1253 s = (char *)src + len - 1; \
1254 while ( len-- ) { \
1255 *d-- = *s--; \
1256 } \
1257 } else if ( dst < src ) { \
1258 d = (char *)dst; \
1259 s = (char *)src; \
1260 while ( len-- ) { \
1261 *d++ = *s++; \
1262 } \
1263 } \
1264 return dst; \
1265 badness: \
1266 VALGRIND_PRINTF_BACKTRACE( \
1267 "*** memcpy_chk: buffer overflow detected ***: " \
njnd55f0d92009-08-03 01:38:56 +00001268 "program terminated\n"); \
sewardj126e82d2011-07-12 13:33:00 +00001269 my_exit(127); \
sewardjb6c04032007-11-13 20:52:29 +00001270 /*NOTREACHED*/ \
1271 return NULL; \
1272 }
1273
sewardj3c944452011-09-05 20:39:57 +00001274#if defined(VGO_linux)
1275 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
sewardj4157d4f2011-09-05 22:18:13 +00001276
sewardj3c944452011-09-05 20:39:57 +00001277#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001278
sewardj3c944452011-09-05 20:39:57 +00001279#endif
sewardjb6c04032007-11-13 20:52:29 +00001280
1281
sewardj3c944452011-09-05 20:39:57 +00001282/*---------------------- strstr ----------------------*/
1283
sewardja77687c2010-08-19 13:22:34 +00001284#define STRSTR(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001285 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001286 (void* haystack, void* needle); \
sewardj96044842011-08-18 13:09:55 +00001287 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001288 (void* haystack, void* needle) \
1289 { \
1290 UChar* h = (UChar*)haystack; \
1291 UChar* n = (UChar*)needle; \
1292 \
1293 /* find the length of n, not including terminating zero */ \
1294 UWord nlen = 0; \
1295 while (n[nlen]) nlen++; \
1296 \
1297 /* if n is the empty string, match immediately. */ \
1298 if (nlen == 0) return h; \
1299 \
1300 /* assert(nlen >= 1); */ \
1301 UChar n0 = n[0]; \
1302 \
1303 while (1) { \
1304 UChar hh = *h; \
1305 if (hh == 0) return NULL; \
1306 if (hh != n0) { h++; continue; } \
1307 \
1308 UWord i; \
1309 for (i = 0; i < nlen; i++) { \
1310 if (n[i] != h[i]) \
1311 break; \
1312 } \
1313 /* assert(i >= 0 && i <= nlen); */ \
1314 if (i == nlen) \
1315 return h; \
1316 \
1317 h++; \
1318 } \
1319 }
1320
1321#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001322 STRSTR(VG_Z_LIBC_SONAME, strstr)
sewardj4157d4f2011-09-05 22:18:13 +00001323
sewardj3c944452011-09-05 20:39:57 +00001324#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001325
sewardja77687c2010-08-19 13:22:34 +00001326#endif
1327
1328
sewardj3c944452011-09-05 20:39:57 +00001329/*---------------------- strpbrk ----------------------*/
1330
sewardja77687c2010-08-19 13:22:34 +00001331#define STRPBRK(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001332 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001333 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001334 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001335 (void* sV, void* acceptV) \
1336 { \
1337 UChar* s = (UChar*)sV; \
1338 UChar* accept = (UChar*)acceptV; \
1339 \
1340 /* find the length of 'accept', not including terminating zero */ \
1341 UWord nacc = 0; \
1342 while (accept[nacc]) nacc++; \
1343 \
1344 /* if n is the empty string, fail immediately. */ \
1345 if (nacc == 0) return NULL; \
1346 \
1347 /* assert(nacc >= 1); */ \
1348 while (1) { \
1349 UWord i; \
1350 UChar sc = *s; \
1351 if (sc == 0) \
1352 break; \
1353 for (i = 0; i < nacc; i++) { \
1354 if (sc == accept[i]) \
1355 return s; \
1356 } \
1357 s++; \
1358 } \
1359 \
1360 return NULL; \
1361 }
1362
1363#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001364 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
sewardj4157d4f2011-09-05 22:18:13 +00001365
sewardj3c944452011-09-05 20:39:57 +00001366#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001367
sewardja77687c2010-08-19 13:22:34 +00001368#endif
1369
1370
sewardj3c944452011-09-05 20:39:57 +00001371/*---------------------- strcspn ----------------------*/
1372
sewardja77687c2010-08-19 13:22:34 +00001373#define STRCSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001374 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001375 (void* sV, void* rejectV); \
sewardj96044842011-08-18 13:09:55 +00001376 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
sewardja77687c2010-08-19 13:22:34 +00001377 (void* sV, void* rejectV) \
1378 { \
1379 UChar* s = (UChar*)sV; \
1380 UChar* reject = (UChar*)rejectV; \
1381 \
1382 /* find the length of 'reject', not including terminating zero */ \
1383 UWord nrej = 0; \
1384 while (reject[nrej]) nrej++; \
1385 \
1386 UWord len = 0; \
1387 while (1) { \
1388 UWord i; \
1389 UChar sc = *s; \
1390 if (sc == 0) \
1391 break; \
1392 for (i = 0; i < nrej; i++) { \
1393 if (sc == reject[i]) \
1394 break; \
1395 } \
1396 /* assert(i >= 0 && i <= nrej); */ \
1397 if (i < nrej) \
1398 break; \
1399 s++; \
1400 len++; \
1401 } \
1402 \
1403 return len; \
1404 }
1405
1406#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001407 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
sewardj4157d4f2011-09-05 22:18:13 +00001408
sewardj3c944452011-09-05 20:39:57 +00001409#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001410
sewardja77687c2010-08-19 13:22:34 +00001411#endif
1412
1413
sewardj3c944452011-09-05 20:39:57 +00001414/*---------------------- strspn ----------------------*/
1415
sewardjbd2cff22011-08-16 21:45:28 +00001416#define STRSPN(soname, fnname) \
sewardj96044842011-08-18 13:09:55 +00001417 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001418 (void* sV, void* acceptV); \
sewardj96044842011-08-18 13:09:55 +00001419 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
sewardjbd2cff22011-08-16 21:45:28 +00001420 (void* sV, void* acceptV) \
1421 { \
1422 UChar* s = (UChar*)sV; \
1423 UChar* accept = (UChar*)acceptV; \
1424 \
1425 /* find the length of 'accept', not including terminating zero */ \
1426 UWord nacc = 0; \
1427 while (accept[nacc]) nacc++; \
1428 if (nacc == 0) return 0; \
1429 \
1430 UWord len = 0; \
1431 while (1) { \
1432 UWord i; \
1433 UChar sc = *s; \
1434 if (sc == 0) \
1435 break; \
1436 for (i = 0; i < nacc; i++) { \
1437 if (sc == accept[i]) \
1438 break; \
1439 } \
1440 /* assert(i >= 0 && i <= nacc); */ \
1441 if (i == nacc) \
1442 break; \
1443 s++; \
1444 len++; \
1445 } \
1446 \
1447 return len; \
1448 }
1449
1450#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00001451 STRSPN(VG_Z_LIBC_SONAME, strspn)
sewardj4157d4f2011-09-05 22:18:13 +00001452
sewardj3c944452011-09-05 20:39:57 +00001453#elif defined(VGO_darwin)
sewardj4157d4f2011-09-05 22:18:13 +00001454
sewardjbd2cff22011-08-16 21:45:28 +00001455#endif
sewardjba189352010-08-20 18:24:16 +00001456
1457
sewardj284f2a32011-10-21 08:07:13 +00001458/*---------------------- strcasestr ----------------------*/
1459
1460#define STRCASESTR(soname, fnname) \
1461 void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1462 (void* haystack, void* needle); \
1463 void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1464 (void* haystack, void* needle) \
1465 { \
1466 extern int tolower(int); \
1467 UChar* h = (UChar*)haystack; \
1468 UChar* n = (UChar*)needle; \
1469 \
1470 /* find the length of n, not including terminating zero */ \
1471 UWord nlen = 0; \
1472 while (n[nlen]) nlen++; \
1473 \
1474 /* if n is the empty string, match immediately. */ \
1475 if (nlen == 0) return h; \
1476 \
1477 /* assert(nlen >= 1); */ \
1478 UChar n0 = tolower(n[0]); \
1479 \
1480 while (1) { \
1481 UChar hh = tolower(*h); \
1482 if (hh == 0) return NULL; \
1483 if (hh != n0) { h++; continue; } \
1484 \
1485 UWord i; \
1486 for (i = 0; i < nlen; i++) { \
1487 if (tolower(n[i]) != tolower(h[i])) \
1488 break; \
1489 } \
1490 /* assert(i >= 0 && i <= nlen); */ \
1491 if (i == nlen) \
1492 return h; \
1493 \
1494 h++; \
1495 } \
1496 }
1497
1498#if defined(VGO_linux)
sewardj1b3a7a42011-10-26 15:10:49 +00001499# if !defined(VGPV_arm_linux_android)
1500 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1501# endif
sewardj284f2a32011-10-21 08:07:13 +00001502
1503#elif defined(VGO_darwin)
1504
1505#endif
1506
1507
sewardj31b9ce12006-10-17 01:27:13 +00001508/*------------------------------------------------------------*/
dirk09beb9e2007-04-19 09:47:32 +00001509/*--- Improve definedness checking of process environment ---*/
1510/*------------------------------------------------------------*/
1511
sewardjddc00dd2007-11-27 11:42:47 +00001512#if defined(VGO_linux)
1513
sewardjbd2cff22011-08-16 21:45:28 +00001514/* If these wind up getting generated via a macro, so that multiple
1515 versions of each function exist (as above), use the _EZU variants
1516 to assign equivalance class tags. */
1517
sewardj3c944452011-09-05 20:39:57 +00001518/*---------------------- putenv ----------------------*/
1519
njne6154662009-02-10 04:23:41 +00001520int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1521int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
dirk09beb9e2007-04-19 09:47:32 +00001522{
1523 OrigFn fn;
1524 Word result;
1525 const char* p = string;
1526 VALGRIND_GET_ORIG_FN(fn);
1527 /* Now by walking over the string we magically produce
1528 traces when hitting undefined memory. */
1529 if (p)
1530 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001531 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001532 CALL_FN_W_W(result, fn, string);
1533 return result;
1534}
1535
sewardj3c944452011-09-05 20:39:57 +00001536
1537/*---------------------- unsetenv ----------------------*/
1538
njne6154662009-02-10 04:23:41 +00001539int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1540int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
dirk09beb9e2007-04-19 09:47:32 +00001541{
1542 OrigFn fn;
1543 Word result;
1544 const char* p = name;
1545 VALGRIND_GET_ORIG_FN(fn);
1546 /* Now by walking over the string we magically produce
1547 traces when hitting undefined memory. */
1548 if (p)
1549 while (*p++)
sewardj3c944452011-09-05 20:39:57 +00001550 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001551 CALL_FN_W_W(result, fn, name);
1552 return result;
1553}
1554
sewardj3c944452011-09-05 20:39:57 +00001555
1556/*---------------------- setenv ----------------------*/
1557
dirk09beb9e2007-04-19 09:47:32 +00001558/* setenv */
njne6154662009-02-10 04:23:41 +00001559int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001560 (const char* name, const char* value, int overwrite);
njne6154662009-02-10 04:23:41 +00001561int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
dirk09beb9e2007-04-19 09:47:32 +00001562 (const char* name, const char* value, int overwrite)
1563{
1564 OrigFn fn;
1565 Word result;
1566 const char* p;
1567 VALGRIND_GET_ORIG_FN(fn);
1568 /* Now by walking over the string we magically produce
1569 traces when hitting undefined memory. */
1570 if (name)
1571 for (p = name; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001572 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001573 if (value)
1574 for (p = value; *p; p++)
sewardj3c944452011-09-05 20:39:57 +00001575 __asm__ __volatile__("" ::: "memory");
dirk09beb9e2007-04-19 09:47:32 +00001576 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1577 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1578 return result;
1579}
1580
sewardjddc00dd2007-11-27 11:42:47 +00001581#endif /* defined(VGO_linux) */
1582
njn3e884182003-04-15 13:03:23 +00001583/*--------------------------------------------------------------------*/
njn46275862005-03-24 04:00:03 +00001584/*--- end ---*/
njn3e884182003-04-15 13:03:23 +00001585/*--------------------------------------------------------------------*/