blob: ce78b9b8d148fd8c5d786e472dbc49b36f663377 [file] [log] [blame]
bart9c7779b2013-11-24 17:48:13 +00001
2/*--------------------------------------------------------------------*/
3/*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/
4/*--- simulated CPU. ---*/
5/*--- mc_replace_strmem.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
9 This file is part of Valgrind.
10
11 Copyright (C) 2000-2013 Julian Seward
12 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32#include "pub_tool_basics.h"
33#include "pub_tool_poolalloc.h"
34#include "pub_tool_hashtable.h"
35#include "pub_tool_redir.h"
36#include "pub_tool_tooliface.h"
37#include "pub_tool_clreq.h"
38
39/* ---------------------------------------------------------------------
40 We have our own versions of these functions for two reasons:
41 (a) it allows us to do overlap checking
42 (b) some of the normal versions are hyper-optimised, which fools
43 Memcheck and cause spurious value warnings. Our versions are
44 simpler.
45 (c) the glibc SSE-variants can read past the end of the input data
46 ranges. This can cause false-positive Memcheck / Helgrind / DRD
47 reports.
48
49 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
53 THEY RUN ON THE SIMD CPU!
54 ------------------------------------------------------------------ */
55
56/* Assignment of behavioural equivalence class tags: 2NNNP is intended
57 to be reserved for str/mem intercepts. Current usage:
58
59 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
96 20350 STRCASESTR
97 20360 MEMRCHR
98 20370 WCSLEN
99 20380 WCSCMP
100 20390 WCSCPY
101 20400 WCSCHR
102 20410 WCSRCHR
103 20420 STPNCPY
104*/
105
106
107/* Figure out if [dst .. dst+dstlen-1] overlaps with
108 [src .. src+srclen-1].
109 We assume that the address ranges do not wrap around
110 (which is safe since on Linux addresses >= 0xC0000000
111 are not accessible and the program will segfault in this
112 circumstance, presumably).
113*/
114static inline
115Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
116{
117 Addr loS, hiS, loD, hiD;
118
119 if (dstlen == 0 || srclen == 0)
120 return False;
121
122 loS = (Addr)src;
123 loD = (Addr)dst;
124 hiS = loS + srclen - 1;
125 hiD = loD + dstlen - 1;
126
127 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */
128 if (loS < loD) {
129 return !(hiS < loD);
130 }
131 else if (loD < loS) {
132 return !(hiD < loS);
133 }
134 else {
135 /* They start at same place. Since we know neither of them has
136 zero length, they must overlap. */
137 return True;
138 }
139}
140
141
142/* Call here to exit if we can't continue. On Android we can't call
143 _exit for some reason, so we have to blunt-instrument it. */
144__attribute__ ((__noreturn__))
145static inline void my_exit ( int x )
146{
dejanj9c6b05d2013-12-27 09:06:55 +0000147# if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android) \
148 || defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000149 __asm__ __volatile__(".word 0xFFFFFFFF");
150 while (1) {}
151# elif defined(VGPV_x86_linux_android)
152 __asm__ __volatile__("ud2");
153 while (1) {}
154# else
155 extern __attribute__ ((__noreturn__)) void _exit(int status);
156 _exit(x);
157# endif
158}
159
160
161// This is a macro rather than a function because we don't want to have an
162// extra function in the stack trace.
163#ifndef RECORD_OVERLAP_ERROR
164#define RECORD_OVERLAP_ERROR(s, src, dst, len) do { } while (0)
165#endif
166#ifndef VALGRIND_CHECK_VALUE_IS_DEFINED
167#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) 1
168#endif
169
170
171/*---------------------- strrchr ----------------------*/
172
173#define STRRCHR(soname, fnname) \
174 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
175 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
176 { \
177 HChar ch = (HChar)c; \
178 const HChar* p = s; \
179 const HChar* last = NULL; \
180 while (True) { \
181 if (*p == ch) last = p; \
182 if (*p == 0) return (HChar *)last; \
183 p++; \
184 } \
185 }
186
187// Apparently rindex() is the same thing as strrchr()
188#if defined(VGO_linux)
189 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
190 STRRCHR(VG_Z_LIBC_SONAME, rindex)
191 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
192 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2)
193 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse2_no_bsf)
194 STRRCHR(VG_Z_LIBC_SONAME, __strrchr_sse42)
195 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
dejanj9c6b05d2013-12-27 09:06:55 +0000196#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
197 || defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000198 STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */
199#endif
200
201#elif defined(VGO_darwin)
202 //STRRCHR(VG_Z_LIBC_SONAME, strrchr)
203 //STRRCHR(VG_Z_LIBC_SONAME, rindex)
204 //STRRCHR(VG_Z_DYLD, strrchr)
205 //STRRCHR(VG_Z_DYLD, rindex)
206 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
207
208#endif
209
210
211/*---------------------- strchr ----------------------*/
212
213#define STRCHR(soname, fnname) \
214 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
215 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
216 { \
217 HChar ch = (HChar)c ; \
218 const HChar* p = s; \
219 while (True) { \
220 if (*p == ch) return (HChar *)p; \
221 if (*p == 0) return NULL; \
222 p++; \
223 } \
224 }
225
226// Apparently index() is the same thing as strchr()
227#if defined(VGO_linux)
228 STRCHR(VG_Z_LIBC_SONAME, strchr)
229 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
230 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2)
231 STRCHR(VG_Z_LIBC_SONAME, __strchr_sse2_no_bsf)
232 STRCHR(VG_Z_LIBC_SONAME, index)
233# if !defined(VGP_x86_linux)
234 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
235 STRCHR(VG_Z_LD_LINUX_SO_2, index)
236 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
237 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
238# endif
239
240#elif defined(VGO_darwin)
bart9c7779b2013-11-24 17:48:13 +0000241 STRCHR(VG_Z_LIBC_SONAME, strchr)
sewardjc3e09f62014-06-21 09:40:19 +0000242# if DARWIN_VERS == DARWIN_10_9
243 STRCHR(libsystemZuplatformZddylib, _platform_strchr)
244# endif
bart9c7779b2013-11-24 17:48:13 +0000245#endif
246
247
248/*---------------------- strcat ----------------------*/
249
250#define STRCAT(soname, fnname) \
251 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
252 ( char* dst, const char* src ); \
253 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
254 ( char* dst, const char* src ) \
255 { \
256 const HChar* src_orig = src; \
257 HChar* dst_orig = dst; \
258 while (*dst) dst++; \
259 while (*src) *dst++ = *src++; \
260 *dst = 0; \
261 \
262 /* This is a bit redundant, I think; any overlap and the strcat will */ \
263 /* go forever... or until a seg fault occurs. */ \
264 if (is_overlap(dst_orig, \
265 src_orig, \
266 (Addr)dst-(Addr)dst_orig+1, \
267 (Addr)src-(Addr)src_orig+1)) \
268 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
269 \
270 return dst_orig; \
271 }
272
273#if defined(VGO_linux)
274 STRCAT(VG_Z_LIBC_SONAME, strcat)
275 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
276
277#elif defined(VGO_darwin)
278 //STRCAT(VG_Z_LIBC_SONAME, strcat)
279
280#endif
281
282
283/*---------------------- strncat ----------------------*/
284
285#define STRNCAT(soname, fnname) \
286 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
287 ( char* dst, const char* src, SizeT n ); \
288 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
289 ( char* dst, const char* src, SizeT n ) \
290 { \
291 const HChar* src_orig = src; \
292 HChar* dst_orig = dst; \
293 SizeT m = 0; \
294 \
295 while (*dst) dst++; \
296 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
297 *dst = 0; /* always add null */ \
298 \
299 /* This checks for overlap after copying, unavoidable without */ \
300 /* pre-counting lengths... should be ok */ \
301 if (is_overlap(dst_orig, \
302 src_orig, \
303 (Addr)dst-(Addr)dst_orig+1, \
304 (Addr)src-(Addr)src_orig+1)) \
305 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
306 \
307 return dst_orig; \
308 }
309
310#if defined(VGO_linux)
311 STRNCAT(VG_Z_LIBC_SONAME, strncat)
312
313#elif defined(VGO_darwin)
314 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
315 //STRNCAT(VG_Z_DYLD, strncat)
316
317#endif
318
319
320/*---------------------- strlcat ----------------------*/
321
322/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
323 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
324 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
325 Truncation occurred if retval >= n.
326*/
327#define STRLCAT(soname, fnname) \
328 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
329 ( char* dst, const char* src, SizeT n ); \
330 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
331 ( char* dst, const char* src, SizeT n ) \
332 { \
333 const HChar* src_orig = src; \
334 HChar* dst_orig = dst; \
335 SizeT m = 0; \
336 \
337 while (m < n && *dst) { m++; dst++; } \
338 if (m < n) { \
339 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
340 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
341 *dst = 0; \
342 } else { \
343 /* No space to copy anything to dst. m == n */ \
344 } \
345 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
346 while (*src) { m++; src++; } \
347 /* This checks for overlap after copying, unavoidable without */ \
348 /* pre-counting lengths... should be ok */ \
349 if (is_overlap(dst_orig, \
350 src_orig, \
351 (Addr)dst-(Addr)dst_orig+1, \
352 (Addr)src-(Addr)src_orig+1)) \
353 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
354 \
355 return m; \
356 }
357
358#if defined(VGO_linux)
359
360#elif defined(VGO_darwin)
361 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
362 //STRLCAT(VG_Z_DYLD, strlcat)
363 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
364
365#endif
366
367
368/*---------------------- strnlen ----------------------*/
369
370#define STRNLEN(soname, fnname) \
371 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
372 ( const char* str, SizeT n ); \
373 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
374 ( const char* str, SizeT n ) \
375 { \
376 SizeT i = 0; \
377 while (i < n && str[i] != 0) i++; \
378 return i; \
379 }
380
381#if defined(VGO_linux)
382 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
383 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
384
385#elif defined(VGO_darwin)
sewardjaec49a42014-06-23 16:03:45 +0000386# if DARWIN_VERS == DARWIN_10_9
387 STRNLEN(libsystemZucZddylib, strnlen)
388# endif
bart9c7779b2013-11-24 17:48:13 +0000389
390#endif
391
392
393/*---------------------- strlen ----------------------*/
394
395// Note that this replacement often doesn't get used because gcc inlines
396// calls to strlen() with its own built-in version. This can be very
397// confusing if you aren't expecting it. Other small functions in
398// this file may also be inline by gcc.
399
400#define STRLEN(soname, fnname) \
401 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
402 ( const char* str ); \
403 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
404 ( const char* str ) \
405 { \
406 SizeT i = 0; \
407 while (str[i] != 0) i++; \
408 return i; \
409 }
410
411#if defined(VGO_linux)
412 STRLEN(VG_Z_LIBC_SONAME, strlen)
413 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
414 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2)
415 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse2_no_bsf)
416 STRLEN(VG_Z_LIBC_SONAME, __strlen_sse42)
417 STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
418 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
dejanj9c6b05d2013-12-27 09:06:55 +0000419# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
420 || defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000421 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */
422# endif
423
424#elif defined(VGO_darwin)
bart9c7779b2013-11-24 17:48:13 +0000425 STRLEN(VG_Z_LIBC_SONAME, strlen)
sewardjc3e09f62014-06-21 09:40:19 +0000426# if DARWIN_VERS == DARWIN_10_9
427 STRLEN(libsystemZucZddylib, strlen)
428# endif
bart9c7779b2013-11-24 17:48:13 +0000429#endif
430
431
432/*---------------------- strcpy ----------------------*/
433
434#define STRCPY(soname, fnname) \
435 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
436 ( char* dst, const char* src ); \
437 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
438 ( char* dst, const char* src ) \
439 { \
440 const HChar* src_orig = src; \
441 HChar* dst_orig = dst; \
442 \
443 while (*src) *dst++ = *src++; \
444 *dst = 0; \
445 \
446 /* This checks for overlap after copying, unavoidable without */ \
447 /* pre-counting length... should be ok */ \
448 if (is_overlap(dst_orig, \
449 src_orig, \
450 (Addr)dst-(Addr)dst_orig+1, \
451 (Addr)src-(Addr)src_orig+1)) \
452 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
453 \
454 return dst_orig; \
455 }
456
457#if defined(VGO_linux)
458 STRCPY(VG_Z_LIBC_SONAME, strcpy)
459 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
460
461#elif defined(VGO_darwin)
bart9c7779b2013-11-24 17:48:13 +0000462 STRCPY(VG_Z_LIBC_SONAME, strcpy)
sewardjaec49a42014-06-23 16:03:45 +0000463# if DARWIN_VERS == DARWIN_10_9
464 STRCPY(libsystemZucZddylib, strcpy)
465# endif
bart9c7779b2013-11-24 17:48:13 +0000466
467#endif
468
469
470/*---------------------- strncpy ----------------------*/
471
472#define STRNCPY(soname, fnname) \
473 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
474 ( char* dst, const char* src, SizeT n ); \
475 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
476 ( char* dst, const char* src, SizeT n ) \
477 { \
478 const HChar* src_orig = src; \
479 HChar* dst_orig = dst; \
480 SizeT m = 0; \
481 \
482 while (m < n && *src) { m++; *dst++ = *src++; } \
483 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
484 /* but only m+1 bytes of src if terminator was found */ \
485 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
486 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
487 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
488 \
489 return dst_orig; \
490 }
491
492#if defined(VGO_linux)
493 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
494 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
495 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2)
496 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned)
497
498#elif defined(VGO_darwin)
bart9c7779b2013-11-24 17:48:13 +0000499 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
sewardjaec49a42014-06-23 16:03:45 +0000500# if DARWIN_VERS == DARWIN_10_9
501 STRNCPY(libsystemZucZddylib, strncpy)
502# endif
bart9c7779b2013-11-24 17:48:13 +0000503
504#endif
505
506
507/*---------------------- strlcpy ----------------------*/
508
509/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
510 Returns strlen(src). Does not zero-fill the remainder of dst. */
511#define STRLCPY(soname, fnname) \
512 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
513 ( char* dst, const char* src, SizeT n ); \
514 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
515 ( char* dst, const char* src, SizeT n ) \
516 { \
517 const HChar* src_orig = src; \
518 HChar* dst_orig = dst; \
519 SizeT m = 0; \
520 \
521 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
522 /* m non-nul bytes have now been copied, and m <= n-1. */ \
523 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
524 /* but only m+1 bytes of src if terminator was found */ \
525 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
526 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
527 /* Nul-terminate dst. */ \
528 if (n > 0) *dst = 0; \
529 /* Finish counting strlen(src). */ \
530 while (*src) src++; \
531 return src - src_orig; \
532 }
533
534#if defined(VGO_linux)
535
dejanj9c6b05d2013-12-27 09:06:55 +0000536#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
537 || defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000538 STRLCPY(VG_Z_LIBC_SONAME, strlcpy);
539#endif
540
541#elif defined(VGO_darwin)
542 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
543 //STRLCPY(VG_Z_DYLD, strlcpy)
544 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
545
546#endif
547
548
549/*---------------------- strncmp ----------------------*/
550
551#define STRNCMP(soname, fnname) \
552 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
553 ( const char* s1, const char* s2, SizeT nmax ); \
554 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
555 ( const char* s1, const char* s2, SizeT nmax ) \
556 { \
557 SizeT n = 0; \
558 while (True) { \
559 if (n >= nmax) return 0; \
560 if (*s1 == 0 && *s2 == 0) return 0; \
561 if (*s1 == 0) return -1; \
562 if (*s2 == 0) return 1; \
563 \
564 if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \
565 if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \
566 \
567 s1++; s2++; n++; \
568 } \
569 }
570
571#if defined(VGO_linux)
572 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
573 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
574 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2)
575 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42)
576
577#elif defined(VGO_darwin)
bart9c7779b2013-11-24 17:48:13 +0000578 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
sewardj798e95b2014-06-25 11:17:46 +0000579# if DARWIN_VERS == DARWIN_10_9
580 STRNCMP(libsystemZuplatformZddylib, _platform_strncmp)
581# endif
bart9c7779b2013-11-24 17:48:13 +0000582
583#endif
584
585
586/*---------------------- strcasecmp ----------------------*/
587
588#define STRCASECMP(soname, fnname) \
589 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
590 ( const char* s1, const char* s2 ); \
591 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
592 ( const char* s1, const char* s2 ) \
593 { \
594 extern int tolower(int); \
595 register UChar c1; \
596 register UChar c2; \
597 while (True) { \
598 c1 = tolower(*(const UChar *)s1); \
599 c2 = tolower(*(const UChar *)s2); \
600 if (c1 != c2) break; \
601 if (c1 == 0) break; \
602 s1++; s2++; \
603 } \
604 if ((UChar)c1 < (UChar)c2) return -1; \
605 if ((UChar)c1 > (UChar)c2) return 1; \
606 return 0; \
607 }
608
609#if defined(VGO_linux)
dejanj9c6b05d2013-12-27 09:06:55 +0000610# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
611 && !defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000612 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
613 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
614# endif
615
616#elif defined(VGO_darwin)
617 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
618
619#endif
620
621
622/*---------------------- strncasecmp ----------------------*/
623
624#define STRNCASECMP(soname, fnname) \
625 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
626 ( const char* s1, const char* s2, SizeT nmax ); \
627 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
628 ( const char* s1, const char* s2, SizeT nmax ) \
629 { \
630 extern int tolower(int); \
631 SizeT n = 0; \
632 while (True) { \
633 if (n >= nmax) return 0; \
634 if (*s1 == 0 && *s2 == 0) return 0; \
635 if (*s1 == 0) return -1; \
636 if (*s2 == 0) return 1; \
637 \
638 if (tolower(*(const UChar *)s1) \
639 < tolower(*(const UChar*)s2)) return -1; \
640 if (tolower(*(const UChar *)s1) \
641 > tolower(*(const UChar *)s2)) return 1; \
642 \
643 s1++; s2++; n++; \
644 } \
645 }
646
647#if defined(VGO_linux)
dejanj9c6b05d2013-12-27 09:06:55 +0000648# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
649 && !defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000650 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
651 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
652# endif
653
654#elif defined(VGO_darwin)
655 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
656 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
657
658#endif
659
660
661/*---------------------- strcasecmp_l ----------------------*/
662
663#define STRCASECMP_L(soname, fnname) \
664 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
665 ( const char* s1, const char* s2, void* locale ); \
666 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
667 ( const char* s1, const char* s2, void* locale ) \
668 { \
669 extern int tolower_l(int, void*) __attribute__((weak)); \
670 register UChar c1; \
671 register UChar c2; \
672 while (True) { \
673 c1 = tolower_l(*(const UChar *)s1, locale); \
674 c2 = tolower_l(*(const UChar *)s2, locale); \
675 if (c1 != c2) break; \
676 if (c1 == 0) break; \
677 s1++; s2++; \
678 } \
679 if ((UChar)c1 < (UChar)c2) return -1; \
680 if ((UChar)c1 > (UChar)c2) return 1; \
681 return 0; \
682 }
683
684#if defined(VGO_linux)
685 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
686 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
687 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
688
689#elif defined(VGO_darwin)
690 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
691
692#endif
693
694
695/*---------------------- strncasecmp_l ----------------------*/
696
697#define STRNCASECMP_L(soname, fnname) \
698 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
699 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
700 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
701 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
702 { \
703 extern int tolower_l(int, void*) __attribute__((weak)); \
704 SizeT n = 0; \
705 while (True) { \
706 if (n >= nmax) return 0; \
707 if (*s1 == 0 && *s2 == 0) return 0; \
708 if (*s1 == 0) return -1; \
709 if (*s2 == 0) return 1; \
710 \
711 if (tolower_l(*(const UChar *)s1, locale) \
712 < tolower_l(*(const UChar *)s2, locale)) return -1; \
713 if (tolower_l(*(const UChar *)s1, locale) \
714 > tolower_l(*(const UChar *)s2, locale)) return 1; \
715 \
716 s1++; s2++; n++; \
717 } \
718 }
719
720#if defined(VGO_linux)
721 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
722 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
723 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l)
724
725#elif defined(VGO_darwin)
726 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
727 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
728
729#endif
730
731
732/*---------------------- strcmp ----------------------*/
733
734#define STRCMP(soname, fnname) \
735 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
736 ( const char* s1, const char* s2 ); \
737 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
738 ( const char* s1, const char* s2 ) \
739 { \
740 register UChar c1; \
741 register UChar c2; \
742 while (True) { \
743 c1 = *(const UChar *)s1; \
744 c2 = *(const UChar *)s2; \
745 if (c1 != c2) break; \
746 if (c1 == 0) break; \
747 s1++; s2++; \
748 } \
749 if ((UChar)c1 < (UChar)c2) return -1; \
750 if ((UChar)c1 > (UChar)c2) return 1; \
751 return 0; \
752 }
753
754#if defined(VGO_linux)
755 STRCMP(VG_Z_LIBC_SONAME, strcmp)
756 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
757 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse2)
758 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse42)
759 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
760 STRCMP(VG_Z_LD64_SO_1, strcmp)
dejanj9c6b05d2013-12-27 09:06:55 +0000761# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
762 || defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000763 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
764# endif
765
766#elif defined(VGO_darwin)
bart9c7779b2013-11-24 17:48:13 +0000767 STRCMP(VG_Z_LIBC_SONAME, strcmp)
sewardjc3e09f62014-06-21 09:40:19 +0000768# if DARWIN_VERS == DARWIN_10_9
769 STRCMP(libsystemZuplatformZddylib, _platform_strcmp)
770# endif
bart9c7779b2013-11-24 17:48:13 +0000771
772#endif
773
774
775/*---------------------- memchr ----------------------*/
776
777#define MEMCHR(soname, fnname) \
778 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
779 (const void *s, int c, SizeT n); \
780 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
781 (const void *s, int c, SizeT n) \
782 { \
783 SizeT i; \
784 UChar c0 = (UChar)c; \
785 UChar* p = (UChar*)s; \
786 for (i = 0; i < n; i++) \
787 if (p[i] == c0) return (void*)(&p[i]); \
788 return NULL; \
789 }
790
791#if defined(VGO_linux)
792 MEMCHR(VG_Z_LIBC_SONAME, memchr)
793 MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr)
794
795#elif defined(VGO_darwin)
sewardjaec49a42014-06-23 16:03:45 +0000796# if DARWIN_VERS == DARWIN_10_9
sewardj798e95b2014-06-25 11:17:46 +0000797 MEMCHR(VG_Z_DYLD, memchr)
sewardjaec49a42014-06-23 16:03:45 +0000798 MEMCHR(libsystemZuplatformZddylib, _platform_memchr)
799# endif
bart9c7779b2013-11-24 17:48:13 +0000800
801#endif
802
803
804/*---------------------- memrchr ----------------------*/
805
806#define MEMRCHR(soname, fnname) \
807 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
808 (const void *s, int c, SizeT n); \
809 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
810 (const void *s, int c, SizeT n) \
811 { \
812 SizeT i; \
813 UChar c0 = (UChar)c; \
814 UChar* p = (UChar*)s; \
815 for (i = 0; i < n; i++) \
816 if (p[n-1-i] == c0) return (void*)(&p[n-1-i]); \
817 return NULL; \
818 }
819
820#if defined(VGO_linux)
821 MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
822
823#elif defined(VGO_darwin)
824 //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
825 //MEMRCHR(VG_Z_DYLD, memrchr)
826
827#endif
828
829
830/*---------------------- memcpy ----------------------*/
831
832#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
833 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
834 ( void *dst, const void *src, SizeT len ); \
835 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
836 ( void *dst, const void *src, SizeT len ) \
837 { \
838 if (do_ol_check && is_overlap(dst, src, len, len)) \
839 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
840 \
841 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
842 const Addr WM = WS - 1; /* 7 or 3 */ \
843 \
844 if (len > 0) { \
845 if (dst < src || !is_overlap(dst, src, len, len)) { \
846 \
847 /* Copying backwards. */ \
848 SizeT n = len; \
849 Addr d = (Addr)dst; \
850 Addr s = (Addr)src; \
851 \
852 if (((s^d) & WM) == 0) { \
853 /* s and d have same UWord alignment. */ \
854 /* Pull up to a UWord boundary. */ \
855 while ((s & WM) != 0 && n >= 1) \
856 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
857 /* Copy UWords. */ \
858 while (n >= WS) \
859 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
860 if (n == 0) \
861 return dst; \
862 } \
863 if (((s|d) & 1) == 0) { \
864 /* Both are 16-aligned; copy what we can thusly. */ \
865 while (n >= 2) \
866 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
867 } \
868 /* Copy leftovers, or everything if misaligned. */ \
869 while (n >= 1) \
870 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
871 \
872 } else if (dst > src) { \
873 \
874 SizeT n = len; \
875 Addr d = ((Addr)dst) + n; \
876 Addr s = ((Addr)src) + n; \
877 \
878 /* Copying forwards. */ \
879 if (((s^d) & WM) == 0) { \
880 /* s and d have same UWord alignment. */ \
881 /* Back down to a UWord boundary. */ \
882 while ((s & WM) != 0 && n >= 1) \
883 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
884 /* Copy UWords. */ \
885 while (n >= WS) \
886 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
887 if (n == 0) \
888 return dst; \
889 } \
890 if (((s|d) & 1) == 0) { \
891 /* Both are 16-aligned; copy what we can thusly. */ \
892 while (n >= 2) \
893 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
894 } \
895 /* Copy leftovers, or everything if misaligned. */ \
896 while (n >= 1) \
897 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
898 \
899 } \
900 } \
901 \
902 return dst; \
903 }
904
905#define MEMMOVE(soname, fnname) \
906 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
907
908#define MEMCPY(soname, fnname) \
909 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
910
911#if defined(VGO_linux)
912 /* For older memcpy we have to use memmove-like semantics and skip
913 the overlap check; sigh; see #275284. */
914 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
915 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
916 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
917 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy)
918 MEMCPY(VG_Z_LIBC_SONAME, __memcpy_sse2)
919 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
920 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
921 /* icc9 blats these around all over the place. Not only in the main
922 executable but various .so's. They are highly tuned and read
923 memory beyond the source boundary (although work correctly and
924 never go across page boundaries), so give errors when run
925 natively, at least for misaligned source arg. Just intercepting
926 in the exe only until we understand more about the problem. See
927 http://bugs.kde.org/show_bug.cgi?id=139776
928 */
929 MEMCPY(NONE, ZuintelZufastZumemcpy)
930
931#elif defined(VGO_darwin)
932# if DARWIN_VERS <= DARWIN_10_6
933 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
934# endif
935 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
936 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
937
938#endif
939
940
941/*---------------------- memcmp ----------------------*/
942
943#define MEMCMP(soname, fnname) \
944 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
945 ( const void *s1V, const void *s2V, SizeT n ); \
946 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
947 ( const void *s1V, const void *s2V, SizeT n ) \
948 { \
949 int res; \
950 UChar a0; \
951 UChar b0; \
952 const UChar* s1 = s1V; \
953 const UChar* s2 = s2V; \
954 \
955 while (n != 0) { \
956 a0 = s1[0]; \
957 b0 = s2[0]; \
958 s1 += 1; \
959 s2 += 1; \
960 res = ((int)a0) - ((int)b0); \
961 if (res != 0) \
962 return res; \
963 n -= 1; \
964 } \
965 return 0; \
966 }
967
968#if defined(VGO_linux)
969 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
970 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
971 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse2)
972 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse4_1)
973 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
974 MEMCMP(VG_Z_LD_SO_1, bcmp)
975
976#elif defined(VGO_darwin)
sewardjaec49a42014-06-23 16:03:45 +0000977# if DARWIN_VERS == DARWIN_10_9
978 MEMCMP(libsystemZuplatformZddylib, _platform_memcmp)
979# endif
bart9c7779b2013-11-24 17:48:13 +0000980
981#endif
982
983
984/*---------------------- stpcpy ----------------------*/
985
986/* Copy SRC to DEST, returning the address of the terminating '\0' in
987 DEST. (minor variant of strcpy) */
988#define STPCPY(soname, fnname) \
989 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
990 ( char* dst, const char* src ); \
991 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
992 ( char* dst, const char* src ) \
993 { \
994 const HChar* src_orig = src; \
995 HChar* dst_orig = dst; \
996 \
997 while (*src) *dst++ = *src++; \
998 *dst = 0; \
999 \
1000 /* This checks for overlap after copying, unavoidable without */ \
1001 /* pre-counting length... should be ok */ \
1002 if (is_overlap(dst_orig, \
1003 src_orig, \
1004 (Addr)dst-(Addr)dst_orig+1, \
1005 (Addr)src-(Addr)src_orig+1)) \
1006 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
1007 \
1008 return dst; \
1009 }
1010
1011#if defined(VGO_linux)
1012 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1013 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
1014 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2)
1015 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2_unaligned)
1016 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
1017 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
1018
1019#elif defined(VGO_darwin)
1020 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1021 //STPCPY(VG_Z_DYLD, stpcpy)
1022
1023#endif
1024
1025
1026/*---------------------- stpncpy ----------------------*/
1027
1028#define STPNCPY(soname, fnname) \
1029 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1030 ( char* dst, const char* src, SizeT n ); \
1031 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1032 ( char* dst, const char* src, SizeT n ) \
1033 { \
1034 const HChar* src_orig = src; \
1035 HChar* dst_str = dst; \
1036 SizeT m = 0; \
1037 \
1038 while (m < n && *src) { m++; *dst++ = *src++; } \
1039 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
1040 /* but only m+1 bytes of src if terminator was found */ \
1041 if (is_overlap(dst_str, src_orig, n, (m < n) ? m+1 : n)) \
1042 RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \
1043 dst_str = dst; \
1044 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
1045 \
1046 return dst_str; \
1047 }
1048
1049#if defined(VGO_linux)
1050 STPNCPY(VG_Z_LIBC_SONAME, stpncpy)
1051#endif
1052
1053
1054/*---------------------- memset ----------------------*/
1055
1056/* Why are we bothering to intercept this? It seems entirely
1057 pointless. */
1058
1059#define MEMSET(soname, fnname) \
1060 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1061 (void *s, Int c, SizeT n); \
1062 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1063 (void *s, Int c, SizeT n) \
1064 { \
1065 if (sizeof(void*) == 8) { \
1066 Addr a = (Addr)s; \
1067 ULong c8 = (c & 0xFF); \
1068 c8 = (c8 << 8) | c8; \
1069 c8 = (c8 << 16) | c8; \
1070 c8 = (c8 << 32) | c8; \
1071 while ((a & 7) != 0 && n >= 1) \
1072 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1073 while (n >= 8) \
1074 { *(ULong*)a = c8; a += 8; n -= 8; } \
1075 while (n >= 1) \
1076 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1077 return s; \
1078 } else { \
1079 Addr a = (Addr)s; \
1080 UInt c4 = (c & 0xFF); \
1081 c4 = (c4 << 8) | c4; \
1082 c4 = (c4 << 16) | c4; \
1083 while ((a & 3) != 0 && n >= 1) \
1084 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1085 while (n >= 4) \
1086 { *(UInt*)a = c4; a += 4; n -= 4; } \
1087 while (n >= 1) \
1088 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1089 return s; \
1090 } \
1091 }
1092
1093#if defined(VGO_linux)
1094 MEMSET(VG_Z_LIBC_SONAME, memset)
1095
1096#elif defined(VGO_darwin)
1097 //MEMSET(VG_Z_LIBC_SONAME, memset)
1098 //MEMSET(VG_Z_DYLD, memset)
1099 MEMSET(VG_Z_LIBC_SONAME, memset)
1100
1101#endif
1102
1103
1104/*---------------------- memmove ----------------------*/
1105
1106/* memmove -- use the MEMMOVE defn above. */
1107
1108#if defined(VGO_linux)
1109 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1110 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove)
1111
1112#elif defined(VGO_darwin)
1113# if DARWIN_VERS <= DARWIN_10_6
1114 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1115# endif
1116 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
1117 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
1118
1119#endif
1120
1121
1122/*---------------------- bcopy ----------------------*/
1123
1124#define BCOPY(soname, fnname) \
1125 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1126 (const void *srcV, void *dstV, SizeT n); \
1127 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1128 (const void *srcV, void *dstV, SizeT n) \
1129 { \
1130 SizeT i; \
1131 HChar* dst = dstV; \
1132 const HChar* src = srcV; \
1133 if (dst < src) { \
1134 for (i = 0; i < n; i++) \
1135 dst[i] = src[i]; \
1136 } \
1137 else \
1138 if (dst > src) { \
1139 for (i = 0; i < n; i++) \
1140 dst[n-i-1] = src[n-i-1]; \
1141 } \
1142 }
1143
1144#if defined(VGO_linux)
1145 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1146
1147#elif defined(VGO_darwin)
1148 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1149 //BCOPY(VG_Z_DYLD, bcopy)
1150
1151#endif
1152
1153
1154/*-------------------- memmove_chk --------------------*/
1155
1156/* glibc 2.5 variant of memmove which checks the dest is big enough.
1157 There is no specific part of glibc that this is copied from. */
1158#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1159 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1160 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1161 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1162 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1163 { \
1164 SizeT i; \
1165 HChar* dst = dstV; \
1166 const HChar* src = srcV; \
1167 if (destlen < n) \
1168 goto badness; \
1169 if (dst < src) { \
1170 for (i = 0; i < n; i++) \
1171 dst[i] = src[i]; \
1172 } \
1173 else \
1174 if (dst > src) { \
1175 for (i = 0; i < n; i++) \
1176 dst[n-i-1] = src[n-i-1]; \
1177 } \
1178 return dst; \
1179 badness: \
1180 VALGRIND_PRINTF_BACKTRACE( \
1181 "*** memmove_chk: buffer overflow detected ***: " \
1182 "program terminated\n"); \
1183 my_exit(127); \
1184 /*NOTREACHED*/ \
1185 return NULL; \
1186 }
1187
1188#if defined(VGO_linux)
1189 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
1190
1191#elif defined(VGO_darwin)
1192
1193#endif
1194
1195
1196/*-------------------- strchrnul --------------------*/
1197
1198/* Find the first occurrence of C in S or the final NUL byte. */
1199#define GLIBC232_STRCHRNUL(soname, fnname) \
1200 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1201 (const char* s, int c_in); \
1202 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1203 (const char* s, int c_in) \
1204 { \
1205 UChar c = (UChar) c_in; \
1206 UChar* char_ptr = (UChar *)s; \
1207 while (1) { \
1208 if (*char_ptr == 0) return (HChar *)char_ptr; \
1209 if (*char_ptr == c) return (HChar *)char_ptr; \
1210 char_ptr++; \
1211 } \
1212 }
1213
1214#if defined(VGO_linux)
1215 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1216
1217#elif defined(VGO_darwin)
1218
1219#endif
1220
1221
1222/*---------------------- rawmemchr ----------------------*/
1223
1224/* Find the first occurrence of C in S. */
1225#define GLIBC232_RAWMEMCHR(soname, fnname) \
1226 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1227 (const char* s, int c_in); \
1228 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1229 (const char* s, int c_in) \
1230 { \
1231 UChar c = (UChar) c_in; \
1232 UChar* char_ptr = (UChar *)s; \
1233 while (1) { \
1234 if (*char_ptr == c) return (HChar *)char_ptr; \
1235 char_ptr++; \
1236 } \
1237 }
1238
1239#if defined (VGO_linux)
1240 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1241 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1242
1243#elif defined(VGO_darwin)
1244
1245#endif
1246
1247
1248/*---------------------- strcpy_chk ----------------------*/
1249
1250/* glibc variant of strcpy that checks the dest is big enough.
1251 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1252#define GLIBC25___STRCPY_CHK(soname,fnname) \
1253 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1254 (char* dst, const char* src, SizeT len); \
1255 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1256 (char* dst, const char* src, SizeT len) \
1257 { \
1258 HChar* ret = dst; \
1259 if (! len) \
1260 goto badness; \
1261 while ((*dst++ = *src++) != '\0') \
1262 if (--len == 0) \
1263 goto badness; \
1264 return ret; \
1265 badness: \
1266 VALGRIND_PRINTF_BACKTRACE( \
1267 "*** strcpy_chk: buffer overflow detected ***: " \
1268 "program terminated\n"); \
1269 my_exit(127); \
1270 /*NOTREACHED*/ \
1271 return NULL; \
1272 }
1273
1274#if defined(VGO_linux)
1275 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1276
1277#elif defined(VGO_darwin)
1278
1279#endif
1280
1281
1282/*---------------------- stpcpy_chk ----------------------*/
1283
1284/* glibc variant of stpcpy that checks the dest is big enough.
1285 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1286#define GLIBC25___STPCPY_CHK(soname,fnname) \
1287 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1288 (char* dst, const char* src, SizeT len); \
1289 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1290 (char* dst, const char* src, SizeT len) \
1291 { \
1292 if (! len) \
1293 goto badness; \
1294 while ((*dst++ = *src++) != '\0') \
1295 if (--len == 0) \
1296 goto badness; \
1297 return dst - 1; \
1298 badness: \
1299 VALGRIND_PRINTF_BACKTRACE( \
1300 "*** stpcpy_chk: buffer overflow detected ***: " \
1301 "program terminated\n"); \
1302 my_exit(127); \
1303 /*NOTREACHED*/ \
1304 return NULL; \
1305 }
1306
1307#if defined(VGO_linux)
1308 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1309
1310#elif defined(VGO_darwin)
1311
1312#endif
1313
1314
1315/*---------------------- mempcpy ----------------------*/
1316
1317/* mempcpy */
1318#define GLIBC25_MEMPCPY(soname, fnname) \
1319 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1320 ( void *dst, const void *src, SizeT len ); \
1321 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1322 ( void *dst, const void *src, SizeT len ) \
1323 { \
1324 register HChar *d; \
1325 register HChar *s; \
1326 SizeT len_saved = len; \
1327 \
1328 if (len == 0) \
1329 return dst; \
1330 \
1331 if (is_overlap(dst, src, len, len)) \
1332 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1333 \
1334 if ( dst > src ) { \
1335 d = (char *)dst + len - 1; \
1336 s = (char *)src + len - 1; \
1337 while ( len-- ) { \
1338 *d-- = *s--; \
1339 } \
1340 } else if ( dst < src ) { \
1341 d = (char *)dst; \
1342 s = (char *)src; \
1343 while ( len-- ) { \
1344 *d++ = *s++; \
1345 } \
1346 } \
1347 return (void*)( ((char*)dst) + len_saved ); \
1348 }
1349
1350#if defined(VGO_linux)
1351 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1352 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
bartf2d86632014-03-15 12:47:28 +00001353 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */
1354 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */
bart9c7779b2013-11-24 17:48:13 +00001355
1356#elif defined(VGO_darwin)
1357 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1358
1359#endif
1360
1361
1362/*-------------------- memcpy_chk --------------------*/
1363
1364#define GLIBC26___MEMCPY_CHK(soname, fnname) \
1365 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1366 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1367 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1368 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1369 { \
1370 register HChar *d; \
1371 register const HChar *s; \
1372 \
1373 if (dstlen < len) goto badness; \
1374 \
1375 if (len == 0) \
1376 return dst; \
1377 \
1378 if (is_overlap(dst, src, len, len)) \
1379 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1380 \
1381 if ( dst > src ) { \
1382 d = (HChar *)dst + len - 1; \
1383 s = (const HChar *)src + len - 1; \
1384 while ( len-- ) { \
1385 *d-- = *s--; \
1386 } \
1387 } else if ( dst < src ) { \
1388 d = (HChar *)dst; \
1389 s = (const HChar *)src; \
1390 while ( len-- ) { \
1391 *d++ = *s++; \
1392 } \
1393 } \
1394 return dst; \
1395 badness: \
1396 VALGRIND_PRINTF_BACKTRACE( \
1397 "*** memcpy_chk: buffer overflow detected ***: " \
1398 "program terminated\n"); \
1399 my_exit(127); \
1400 /*NOTREACHED*/ \
1401 return NULL; \
1402 }
1403
1404#if defined(VGO_linux)
1405 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1406
1407#elif defined(VGO_darwin)
1408
1409#endif
1410
1411
1412/*---------------------- strstr ----------------------*/
1413
1414#define STRSTR(soname, fnname) \
1415 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1416 (const char* haystack, const char* needle); \
1417 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1418 (const char* haystack, const char* needle) \
1419 { \
1420 const HChar* h = haystack; \
1421 const HChar* n = needle; \
1422 \
1423 /* find the length of n, not including terminating zero */ \
1424 UWord nlen = 0; \
1425 while (n[nlen]) nlen++; \
1426 \
1427 /* if n is the empty string, match immediately. */ \
1428 if (nlen == 0) return (HChar *)h; \
1429 \
1430 /* assert(nlen >= 1); */ \
1431 HChar n0 = n[0]; \
1432 \
1433 while (1) { \
1434 const HChar hh = *h; \
1435 if (hh == 0) return NULL; \
1436 if (hh != n0) { h++; continue; } \
1437 \
1438 UWord i; \
1439 for (i = 0; i < nlen; i++) { \
1440 if (n[i] != h[i]) \
1441 break; \
1442 } \
1443 /* assert(i >= 0 && i <= nlen); */ \
1444 if (i == nlen) \
1445 return (HChar *)h; \
1446 \
1447 h++; \
1448 } \
1449 }
1450
1451#if defined(VGO_linux)
1452 STRSTR(VG_Z_LIBC_SONAME, strstr)
1453 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse2)
1454 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse42)
1455
1456#elif defined(VGO_darwin)
1457
1458#endif
1459
1460
1461/*---------------------- strpbrk ----------------------*/
1462
1463#define STRPBRK(soname, fnname) \
1464 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1465 (const char* sV, const char* acceptV); \
1466 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1467 (const char* sV, const char* acceptV) \
1468 { \
1469 const HChar* s = sV; \
1470 const HChar* accept = acceptV; \
1471 \
1472 /* find the length of 'accept', not including terminating zero */ \
1473 UWord nacc = 0; \
1474 while (accept[nacc]) nacc++; \
1475 \
1476 /* if n is the empty string, fail immediately. */ \
1477 if (nacc == 0) return NULL; \
1478 \
1479 /* assert(nacc >= 1); */ \
1480 while (1) { \
1481 UWord i; \
1482 HChar sc = *s; \
1483 if (sc == 0) \
1484 break; \
1485 for (i = 0; i < nacc; i++) { \
1486 if (sc == accept[i]) \
1487 return (HChar *)s; \
1488 } \
1489 s++; \
1490 } \
1491 \
1492 return NULL; \
1493 }
1494
1495#if defined(VGO_linux)
1496 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1497
1498#elif defined(VGO_darwin)
1499
1500#endif
1501
1502
1503/*---------------------- strcspn ----------------------*/
1504
1505#define STRCSPN(soname, fnname) \
1506 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1507 (const char* sV, const char* rejectV); \
1508 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1509 (const char* sV, const char* rejectV) \
1510 { \
1511 const HChar* s = sV; \
1512 const HChar* reject = rejectV; \
1513 \
1514 /* find the length of 'reject', not including terminating zero */ \
1515 UWord nrej = 0; \
1516 while (reject[nrej]) nrej++; \
1517 \
1518 UWord len = 0; \
1519 while (1) { \
1520 UWord i; \
1521 HChar sc = *s; \
1522 if (sc == 0) \
1523 break; \
1524 for (i = 0; i < nrej; i++) { \
1525 if (sc == reject[i]) \
1526 break; \
1527 } \
1528 /* assert(i >= 0 && i <= nrej); */ \
1529 if (i < nrej) \
1530 break; \
1531 s++; \
1532 len++; \
1533 } \
1534 \
1535 return len; \
1536 }
1537
1538#if defined(VGO_linux)
1539 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1540
1541#elif defined(VGO_darwin)
1542
1543#endif
1544
1545
1546/*---------------------- strspn ----------------------*/
1547
1548#define STRSPN(soname, fnname) \
1549 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1550 (const char* sV, const char* acceptV); \
1551 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1552 (const char* sV, const char* acceptV) \
1553 { \
1554 const UChar* s = (const UChar *)sV; \
1555 const UChar* accept = (const UChar *)acceptV; \
1556 \
1557 /* find the length of 'accept', not including terminating zero */ \
1558 UWord nacc = 0; \
1559 while (accept[nacc]) nacc++; \
1560 if (nacc == 0) return 0; \
1561 \
1562 UWord len = 0; \
1563 while (1) { \
1564 UWord i; \
1565 HChar sc = *s; \
1566 if (sc == 0) \
1567 break; \
1568 for (i = 0; i < nacc; i++) { \
1569 if (sc == accept[i]) \
1570 break; \
1571 } \
1572 /* assert(i >= 0 && i <= nacc); */ \
1573 if (i == nacc) \
1574 break; \
1575 s++; \
1576 len++; \
1577 } \
1578 \
1579 return len; \
1580 }
1581
1582#if defined(VGO_linux)
1583 STRSPN(VG_Z_LIBC_SONAME, strspn)
1584
1585#elif defined(VGO_darwin)
1586
1587#endif
1588
1589
1590/*---------------------- strcasestr ----------------------*/
1591
1592#define STRCASESTR(soname, fnname) \
1593 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1594 (const char* haystack, const char* needle); \
1595 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1596 (const char* haystack, const char* needle) \
1597 { \
1598 extern int tolower(int); \
1599 const HChar* h = haystack; \
1600 const HChar* n = needle; \
1601 \
1602 /* find the length of n, not including terminating zero */ \
1603 UWord nlen = 0; \
1604 while (n[nlen]) nlen++; \
1605 \
1606 /* if n is the empty string, match immediately. */ \
1607 if (nlen == 0) return (HChar *)h; \
1608 \
1609 /* assert(nlen >= 1); */ \
1610 UChar n0 = tolower(n[0]); \
1611 \
1612 while (1) { \
1613 UChar hh = tolower(*h); \
1614 if (hh == 0) return NULL; \
1615 if (hh != n0) { h++; continue; } \
1616 \
1617 UWord i; \
1618 for (i = 0; i < nlen; i++) { \
1619 if (tolower(n[i]) != tolower(h[i])) \
1620 break; \
1621 } \
1622 /* assert(i >= 0 && i <= nlen); */ \
1623 if (i == nlen) \
1624 return (HChar *)h; \
1625 \
1626 h++; \
1627 } \
1628 }
1629
1630#if defined(VGO_linux)
dejanj9c6b05d2013-12-27 09:06:55 +00001631# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
1632 && !defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +00001633 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1634# endif
1635
1636#elif defined(VGO_darwin)
1637
1638#endif
1639
1640
1641/*---------------------- wcslen ----------------------*/
1642
1643// This is a wchar_t equivalent to strlen. Unfortunately
1644// we don't have wchar_t available here, but it looks like
1645// a 32 bit int on Linux. I don't know if that is also
1646// valid on MacOSX.
1647
1648#define WCSLEN(soname, fnname) \
1649 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1650 ( const UInt* str ); \
1651 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1652 ( const UInt* str ) \
1653 { \
1654 SizeT i = 0; \
1655 while (str[i] != 0) i++; \
1656 return i; \
1657 }
1658
1659#if defined(VGO_linux)
1660 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
1661
1662#elif defined(VGO_darwin)
1663
1664#endif
1665
1666/*---------------------- wcscmp ----------------------*/
1667
1668// This is a wchar_t equivalent to strcmp. We don't
1669// have wchar_t available here, but in the GNU C Library
1670// wchar_t is always 32 bits wide and wcscmp uses signed
1671// comparison, not unsigned as in strcmp function.
1672
1673#define WCSCMP(soname, fnname) \
1674 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1675 ( const Int* s1, const Int* s2 ); \
1676 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1677 ( const Int* s1, const Int* s2 ) \
1678 { \
1679 register Int c1; \
1680 register Int c2; \
1681 while (True) { \
1682 c1 = *s1; \
1683 c2 = *s2; \
1684 if (c1 != c2) break; \
1685 if (c1 == 0) break; \
1686 s1++; s2++; \
1687 } \
1688 if (c1 < c2) return -1; \
1689 if (c1 > c2) return 1; \
1690 return 0; \
1691 }
1692
1693#if defined(VGO_linux)
1694 WCSCMP(VG_Z_LIBC_SONAME, wcscmp)
1695#endif
1696
1697/*---------------------- wcscpy ----------------------*/
1698
1699// This is a wchar_t equivalent to strcpy. We don't
1700// have wchar_t available here, but in the GNU C Library
1701// wchar_t is always 32 bits wide.
1702
1703#define WCSCPY(soname, fnname) \
1704 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1705 ( Int* dst, const Int* src ); \
1706 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1707 ( Int* dst, const Int* src ) \
1708 { \
1709 const Int* src_orig = src; \
1710 Int* dst_orig = dst; \
1711 \
1712 while (*src) *dst++ = *src++; \
1713 *dst = 0; \
1714 \
1715 /* This checks for overlap after copying, unavoidable without */ \
1716 /* pre-counting length... should be ok */ \
1717 if (is_overlap(dst_orig, \
1718 src_orig, \
1719 (Addr)dst-(Addr)dst_orig+1, \
1720 (Addr)src-(Addr)src_orig+1)) \
1721 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
1722 \
1723 return dst_orig; \
1724 }
1725
1726#if defined(VGO_linux)
1727 WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
1728#endif
1729
1730
1731/*---------------------- wcschr ----------------------*/
1732
1733// This is a wchar_t equivalent to strchr. We don't
1734// have wchar_t available here, but in the GNU C Library
1735// wchar_t is always 32 bits wide.
1736
1737#define WCSCHR(soname, fnname) \
1738 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
1739 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
1740 { \
1741 Int* p = (Int*)s; \
1742 while (True) { \
1743 if (*p == c) return p; \
1744 if (*p == 0) return NULL; \
1745 p++; \
1746 } \
1747 }
1748
1749#if defined(VGO_linux)
1750 WCSCHR(VG_Z_LIBC_SONAME, wcschr)
1751#endif
1752/*---------------------- wcsrchr ----------------------*/
1753
1754// This is a wchar_t equivalent to strrchr. We don't
1755// have wchar_t available here, but in the GNU C Library
1756// wchar_t is always 32 bits wide.
1757
1758#define WCSRCHR(soname, fnname) \
1759 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
1760 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
1761 { \
1762 Int* p = (Int*) s; \
1763 Int* last = NULL; \
1764 while (True) { \
1765 if (*p == c) last = p; \
1766 if (*p == 0) return last; \
1767 p++; \
1768 } \
1769 }
1770
1771#if defined(VGO_linux)
1772 WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
1773#endif
1774
1775/*------------------------------------------------------------*/
1776/*--- Improve definedness checking of process environment ---*/
1777/*------------------------------------------------------------*/
1778
1779#if defined(VGO_linux)
1780
1781/* If these wind up getting generated via a macro, so that multiple
1782 versions of each function exist (as above), use the _EZU variants
1783 to assign equivalance class tags. */
1784
1785/*---------------------- putenv ----------------------*/
1786
1787int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1788int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
1789{
1790 OrigFn fn;
1791 Word result;
1792 const HChar* p = string;
1793 VALGRIND_GET_ORIG_FN(fn);
1794 /* Now by walking over the string we magically produce
1795 traces when hitting undefined memory. */
1796 if (p)
1797 while (*p++)
1798 __asm__ __volatile__("" ::: "memory");
1799 CALL_FN_W_W(result, fn, string);
1800 return result;
1801}
1802
1803
1804/*---------------------- unsetenv ----------------------*/
1805
1806int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1807int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
1808{
1809 OrigFn fn;
1810 Word result;
1811 const HChar* p = name;
1812 VALGRIND_GET_ORIG_FN(fn);
1813 /* Now by walking over the string we magically produce
1814 traces when hitting undefined memory. */
1815 if (p)
1816 while (*p++)
1817 __asm__ __volatile__("" ::: "memory");
1818 CALL_FN_W_W(result, fn, name);
1819 return result;
1820}
1821
1822
1823/*---------------------- setenv ----------------------*/
1824
1825/* setenv */
1826int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1827 (const char* name, const char* value, int overwrite);
1828int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1829 (const char* name, const char* value, int overwrite)
1830{
1831 OrigFn fn;
1832 Word result;
1833 const HChar* p;
1834 VALGRIND_GET_ORIG_FN(fn);
1835 /* Now by walking over the string we magically produce
1836 traces when hitting undefined memory. */
1837 if (name)
1838 for (p = name; *p; p++)
1839 __asm__ __volatile__("" ::: "memory");
1840 if (value)
1841 for (p = value; *p; p++)
1842 __asm__ __volatile__("" ::: "memory");
1843 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1844 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1845 return result;
1846}
1847
1848#endif /* defined(VGO_linux) */
1849
1850/*--------------------------------------------------------------------*/
1851/*--- end ---*/
1852/*--------------------------------------------------------------------*/