blob: a6bde65c40151d3861bc8b94396a44c88f33b5f6 [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)
241 //STRCHR(VG_Z_LIBC_SONAME, strchr)
242 //STRCHR(VG_Z_LIBC_SONAME, index)
243 //STRCHR(VG_Z_DYLD, strchr)
244 //STRCHR(VG_Z_DYLD, index)
245 STRCHR(VG_Z_LIBC_SONAME, strchr)
246
247#endif
248
249
250/*---------------------- strcat ----------------------*/
251
252#define STRCAT(soname, fnname) \
253 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
254 ( char* dst, const char* src ); \
255 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
256 ( char* dst, const char* src ) \
257 { \
258 const HChar* src_orig = src; \
259 HChar* dst_orig = dst; \
260 while (*dst) dst++; \
261 while (*src) *dst++ = *src++; \
262 *dst = 0; \
263 \
264 /* This is a bit redundant, I think; any overlap and the strcat will */ \
265 /* go forever... or until a seg fault occurs. */ \
266 if (is_overlap(dst_orig, \
267 src_orig, \
268 (Addr)dst-(Addr)dst_orig+1, \
269 (Addr)src-(Addr)src_orig+1)) \
270 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
271 \
272 return dst_orig; \
273 }
274
275#if defined(VGO_linux)
276 STRCAT(VG_Z_LIBC_SONAME, strcat)
277 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
278
279#elif defined(VGO_darwin)
280 //STRCAT(VG_Z_LIBC_SONAME, strcat)
281
282#endif
283
284
285/*---------------------- strncat ----------------------*/
286
287#define STRNCAT(soname, fnname) \
288 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
289 ( char* dst, const char* src, SizeT n ); \
290 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
291 ( char* dst, const char* src, SizeT n ) \
292 { \
293 const HChar* src_orig = src; \
294 HChar* dst_orig = dst; \
295 SizeT m = 0; \
296 \
297 while (*dst) dst++; \
298 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
299 *dst = 0; /* always add null */ \
300 \
301 /* This checks for overlap after copying, unavoidable without */ \
302 /* pre-counting lengths... should be ok */ \
303 if (is_overlap(dst_orig, \
304 src_orig, \
305 (Addr)dst-(Addr)dst_orig+1, \
306 (Addr)src-(Addr)src_orig+1)) \
307 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
308 \
309 return dst_orig; \
310 }
311
312#if defined(VGO_linux)
313 STRNCAT(VG_Z_LIBC_SONAME, strncat)
314
315#elif defined(VGO_darwin)
316 //STRNCAT(VG_Z_LIBC_SONAME, strncat)
317 //STRNCAT(VG_Z_DYLD, strncat)
318
319#endif
320
321
322/*---------------------- strlcat ----------------------*/
323
324/* Append src to dst. n is the size of dst's buffer. dst is guaranteed
325 to be nul-terminated after the copy, unless n <= strlen(dst_orig).
326 Returns min(n, strlen(dst_orig)) + strlen(src_orig).
327 Truncation occurred if retval >= n.
328*/
329#define STRLCAT(soname, fnname) \
330 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
331 ( char* dst, const char* src, SizeT n ); \
332 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
333 ( char* dst, const char* src, SizeT n ) \
334 { \
335 const HChar* src_orig = src; \
336 HChar* dst_orig = dst; \
337 SizeT m = 0; \
338 \
339 while (m < n && *dst) { m++; dst++; } \
340 if (m < n) { \
341 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \
342 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
343 *dst = 0; \
344 } else { \
345 /* No space to copy anything to dst. m == n */ \
346 } \
347 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \
348 while (*src) { m++; src++; } \
349 /* This checks for overlap after copying, unavoidable without */ \
350 /* pre-counting lengths... should be ok */ \
351 if (is_overlap(dst_orig, \
352 src_orig, \
353 (Addr)dst-(Addr)dst_orig+1, \
354 (Addr)src-(Addr)src_orig+1)) \
355 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \
356 \
357 return m; \
358 }
359
360#if defined(VGO_linux)
361
362#elif defined(VGO_darwin)
363 //STRLCAT(VG_Z_LIBC_SONAME, strlcat)
364 //STRLCAT(VG_Z_DYLD, strlcat)
365 STRLCAT(VG_Z_LIBC_SONAME, strlcat)
366
367#endif
368
369
370/*---------------------- strnlen ----------------------*/
371
372#define STRNLEN(soname, fnname) \
373 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
374 ( const char* str, SizeT n ); \
375 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
376 ( const char* str, SizeT n ) \
377 { \
378 SizeT i = 0; \
379 while (i < n && str[i] != 0) i++; \
380 return i; \
381 }
382
383#if defined(VGO_linux)
384 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
385 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
386
387#elif defined(VGO_darwin)
388 //STRNLEN(VG_Z_LIBC_SONAME, strnlen)
389
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)
425 //STRLEN(VG_Z_LIBC_SONAME, strlen)
426 STRLEN(VG_Z_LIBC_SONAME, strlen)
427
428#endif
429
430
431/*---------------------- strcpy ----------------------*/
432
433#define STRCPY(soname, fnname) \
434 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
435 ( char* dst, const char* src ); \
436 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
437 ( char* dst, const char* src ) \
438 { \
439 const HChar* src_orig = src; \
440 HChar* dst_orig = dst; \
441 \
442 while (*src) *dst++ = *src++; \
443 *dst = 0; \
444 \
445 /* This checks for overlap after copying, unavoidable without */ \
446 /* pre-counting length... should be ok */ \
447 if (is_overlap(dst_orig, \
448 src_orig, \
449 (Addr)dst-(Addr)dst_orig+1, \
450 (Addr)src-(Addr)src_orig+1)) \
451 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
452 \
453 return dst_orig; \
454 }
455
456#if defined(VGO_linux)
457 STRCPY(VG_Z_LIBC_SONAME, strcpy)
458 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
459
460#elif defined(VGO_darwin)
461 //STRCPY(VG_Z_LIBC_SONAME, strcpy)
462 //STRCPY(VG_Z_DYLD, strcpy)
463 STRCPY(VG_Z_LIBC_SONAME, strcpy)
464
465#endif
466
467
468/*---------------------- strncpy ----------------------*/
469
470#define STRNCPY(soname, fnname) \
471 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
472 ( char* dst, const char* src, SizeT n ); \
473 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
474 ( char* dst, const char* src, SizeT n ) \
475 { \
476 const HChar* src_orig = src; \
477 HChar* dst_orig = dst; \
478 SizeT m = 0; \
479 \
480 while (m < n && *src) { m++; *dst++ = *src++; } \
481 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
482 /* but only m+1 bytes of src if terminator was found */ \
483 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
484 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
485 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
486 \
487 return dst_orig; \
488 }
489
490#if defined(VGO_linux)
491 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
492 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
493 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2)
494 STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned)
495
496#elif defined(VGO_darwin)
497 //STRNCPY(VG_Z_LIBC_SONAME, strncpy)
498 //STRNCPY(VG_Z_DYLD, strncpy)
499 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
500
501#endif
502
503
504/*---------------------- strlcpy ----------------------*/
505
506/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0.
507 Returns strlen(src). Does not zero-fill the remainder of dst. */
508#define STRLCPY(soname, fnname) \
509 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
510 ( char* dst, const char* src, SizeT n ); \
511 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
512 ( char* dst, const char* src, SizeT n ) \
513 { \
514 const HChar* src_orig = src; \
515 HChar* dst_orig = dst; \
516 SizeT m = 0; \
517 \
518 while (m < n-1 && *src) { m++; *dst++ = *src++; } \
519 /* m non-nul bytes have now been copied, and m <= n-1. */ \
520 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
521 /* but only m+1 bytes of src if terminator was found */ \
522 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
523 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \
524 /* Nul-terminate dst. */ \
525 if (n > 0) *dst = 0; \
526 /* Finish counting strlen(src). */ \
527 while (*src) src++; \
528 return src - src_orig; \
529 }
530
531#if defined(VGO_linux)
532
dejanj9c6b05d2013-12-27 09:06:55 +0000533#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
534 || defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000535 STRLCPY(VG_Z_LIBC_SONAME, strlcpy);
536#endif
537
538#elif defined(VGO_darwin)
539 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
540 //STRLCPY(VG_Z_DYLD, strlcpy)
541 STRLCPY(VG_Z_LIBC_SONAME, strlcpy)
542
543#endif
544
545
546/*---------------------- strncmp ----------------------*/
547
548#define STRNCMP(soname, fnname) \
549 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
550 ( const char* s1, const char* s2, SizeT nmax ); \
551 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
552 ( const char* s1, const char* s2, SizeT nmax ) \
553 { \
554 SizeT n = 0; \
555 while (True) { \
556 if (n >= nmax) return 0; \
557 if (*s1 == 0 && *s2 == 0) return 0; \
558 if (*s1 == 0) return -1; \
559 if (*s2 == 0) return 1; \
560 \
561 if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \
562 if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \
563 \
564 s1++; s2++; n++; \
565 } \
566 }
567
568#if defined(VGO_linux)
569 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
570 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
571 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2)
572 STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42)
573
574#elif defined(VGO_darwin)
575 //STRNCMP(VG_Z_LIBC_SONAME, strncmp)
576 //STRNCMP(VG_Z_DYLD, strncmp)
577 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
578
579#endif
580
581
582/*---------------------- strcasecmp ----------------------*/
583
584#define STRCASECMP(soname, fnname) \
585 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
586 ( const char* s1, const char* s2 ); \
587 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
588 ( const char* s1, const char* s2 ) \
589 { \
590 extern int tolower(int); \
591 register UChar c1; \
592 register UChar c2; \
593 while (True) { \
594 c1 = tolower(*(const UChar *)s1); \
595 c2 = tolower(*(const UChar *)s2); \
596 if (c1 != c2) break; \
597 if (c1 == 0) break; \
598 s1++; s2++; \
599 } \
600 if ((UChar)c1 < (UChar)c2) return -1; \
601 if ((UChar)c1 > (UChar)c2) return 1; \
602 return 0; \
603 }
604
605#if defined(VGO_linux)
dejanj9c6b05d2013-12-27 09:06:55 +0000606# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
607 && !defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000608 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
609 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
610# endif
611
612#elif defined(VGO_darwin)
613 //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
614
615#endif
616
617
618/*---------------------- strncasecmp ----------------------*/
619
620#define STRNCASECMP(soname, fnname) \
621 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
622 ( const char* s1, const char* s2, SizeT nmax ); \
623 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
624 ( const char* s1, const char* s2, SizeT nmax ) \
625 { \
626 extern int tolower(int); \
627 SizeT n = 0; \
628 while (True) { \
629 if (n >= nmax) return 0; \
630 if (*s1 == 0 && *s2 == 0) return 0; \
631 if (*s1 == 0) return -1; \
632 if (*s2 == 0) return 1; \
633 \
634 if (tolower(*(const UChar *)s1) \
635 < tolower(*(const UChar*)s2)) return -1; \
636 if (tolower(*(const UChar *)s1) \
637 > tolower(*(const UChar *)s2)) return 1; \
638 \
639 s1++; s2++; n++; \
640 } \
641 }
642
643#if defined(VGO_linux)
dejanj9c6b05d2013-12-27 09:06:55 +0000644# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
645 && !defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000646 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
647 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
648# endif
649
650#elif defined(VGO_darwin)
651 //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
652 //STRNCASECMP(VG_Z_DYLD, strncasecmp)
653
654#endif
655
656
657/*---------------------- strcasecmp_l ----------------------*/
658
659#define STRCASECMP_L(soname, fnname) \
660 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
661 ( const char* s1, const char* s2, void* locale ); \
662 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
663 ( const char* s1, const char* s2, void* locale ) \
664 { \
665 extern int tolower_l(int, void*) __attribute__((weak)); \
666 register UChar c1; \
667 register UChar c2; \
668 while (True) { \
669 c1 = tolower_l(*(const UChar *)s1, locale); \
670 c2 = tolower_l(*(const UChar *)s2, locale); \
671 if (c1 != c2) break; \
672 if (c1 == 0) break; \
673 s1++; s2++; \
674 } \
675 if ((UChar)c1 < (UChar)c2) return -1; \
676 if ((UChar)c1 > (UChar)c2) return 1; \
677 return 0; \
678 }
679
680#if defined(VGO_linux)
681 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
682 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
683 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
684
685#elif defined(VGO_darwin)
686 //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
687
688#endif
689
690
691/*---------------------- strncasecmp_l ----------------------*/
692
693#define STRNCASECMP_L(soname, fnname) \
694 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
695 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
696 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
697 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
698 { \
699 extern int tolower_l(int, void*) __attribute__((weak)); \
700 SizeT n = 0; \
701 while (True) { \
702 if (n >= nmax) return 0; \
703 if (*s1 == 0 && *s2 == 0) return 0; \
704 if (*s1 == 0) return -1; \
705 if (*s2 == 0) return 1; \
706 \
707 if (tolower_l(*(const UChar *)s1, locale) \
708 < tolower_l(*(const UChar *)s2, locale)) return -1; \
709 if (tolower_l(*(const UChar *)s1, locale) \
710 > tolower_l(*(const UChar *)s2, locale)) return 1; \
711 \
712 s1++; s2++; n++; \
713 } \
714 }
715
716#if defined(VGO_linux)
717 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
718 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
719 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l)
720
721#elif defined(VGO_darwin)
722 //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
723 //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
724
725#endif
726
727
728/*---------------------- strcmp ----------------------*/
729
730#define STRCMP(soname, fnname) \
731 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
732 ( const char* s1, const char* s2 ); \
733 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
734 ( const char* s1, const char* s2 ) \
735 { \
736 register UChar c1; \
737 register UChar c2; \
738 while (True) { \
739 c1 = *(const UChar *)s1; \
740 c2 = *(const UChar *)s2; \
741 if (c1 != c2) break; \
742 if (c1 == 0) break; \
743 s1++; s2++; \
744 } \
745 if ((UChar)c1 < (UChar)c2) return -1; \
746 if ((UChar)c1 > (UChar)c2) return 1; \
747 return 0; \
748 }
749
750#if defined(VGO_linux)
751 STRCMP(VG_Z_LIBC_SONAME, strcmp)
752 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
753 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse2)
754 STRCMP(VG_Z_LIBC_SONAME, __strcmp_sse42)
755 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
756 STRCMP(VG_Z_LD64_SO_1, strcmp)
dejanj9c6b05d2013-12-27 09:06:55 +0000757# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
758 || defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +0000759 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */
760# endif
761
762#elif defined(VGO_darwin)
763 //STRCMP(VG_Z_LIBC_SONAME, strcmp)
764 STRCMP(VG_Z_LIBC_SONAME, strcmp)
765
766#endif
767
768
769/*---------------------- memchr ----------------------*/
770
771#define MEMCHR(soname, fnname) \
772 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
773 (const void *s, int c, SizeT n); \
774 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
775 (const void *s, int c, SizeT n) \
776 { \
777 SizeT i; \
778 UChar c0 = (UChar)c; \
779 UChar* p = (UChar*)s; \
780 for (i = 0; i < n; i++) \
781 if (p[i] == c0) return (void*)(&p[i]); \
782 return NULL; \
783 }
784
785#if defined(VGO_linux)
786 MEMCHR(VG_Z_LIBC_SONAME, memchr)
787 MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr)
788
789#elif defined(VGO_darwin)
790 //MEMCHR(VG_Z_LIBC_SONAME, memchr)
791 //MEMCHR(VG_Z_DYLD, memchr)
792
793#endif
794
795
796/*---------------------- memrchr ----------------------*/
797
798#define MEMRCHR(soname, fnname) \
799 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
800 (const void *s, int c, SizeT n); \
801 void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \
802 (const void *s, int c, SizeT n) \
803 { \
804 SizeT i; \
805 UChar c0 = (UChar)c; \
806 UChar* p = (UChar*)s; \
807 for (i = 0; i < n; i++) \
808 if (p[n-1-i] == c0) return (void*)(&p[n-1-i]); \
809 return NULL; \
810 }
811
812#if defined(VGO_linux)
813 MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
814
815#elif defined(VGO_darwin)
816 //MEMRCHR(VG_Z_LIBC_SONAME, memrchr)
817 //MEMRCHR(VG_Z_DYLD, memrchr)
818
819#endif
820
821
822/*---------------------- memcpy ----------------------*/
823
824#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \
825 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
826 ( void *dst, const void *src, SizeT len ); \
827 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \
828 ( void *dst, const void *src, SizeT len ) \
829 { \
830 if (do_ol_check && is_overlap(dst, src, len, len)) \
831 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
832 \
833 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
834 const Addr WM = WS - 1; /* 7 or 3 */ \
835 \
836 if (len > 0) { \
837 if (dst < src || !is_overlap(dst, src, len, len)) { \
838 \
839 /* Copying backwards. */ \
840 SizeT n = len; \
841 Addr d = (Addr)dst; \
842 Addr s = (Addr)src; \
843 \
844 if (((s^d) & WM) == 0) { \
845 /* s and d have same UWord alignment. */ \
846 /* Pull up to a UWord boundary. */ \
847 while ((s & WM) != 0 && n >= 1) \
848 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
849 /* Copy UWords. */ \
850 while (n >= WS) \
851 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
852 if (n == 0) \
853 return dst; \
854 } \
855 if (((s|d) & 1) == 0) { \
856 /* Both are 16-aligned; copy what we can thusly. */ \
857 while (n >= 2) \
858 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
859 } \
860 /* Copy leftovers, or everything if misaligned. */ \
861 while (n >= 1) \
862 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
863 \
864 } else if (dst > src) { \
865 \
866 SizeT n = len; \
867 Addr d = ((Addr)dst) + n; \
868 Addr s = ((Addr)src) + n; \
869 \
870 /* Copying forwards. */ \
871 if (((s^d) & WM) == 0) { \
872 /* s and d have same UWord alignment. */ \
873 /* Back down to a UWord boundary. */ \
874 while ((s & WM) != 0 && n >= 1) \
875 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
876 /* Copy UWords. */ \
877 while (n >= WS) \
878 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
879 if (n == 0) \
880 return dst; \
881 } \
882 if (((s|d) & 1) == 0) { \
883 /* Both are 16-aligned; copy what we can thusly. */ \
884 while (n >= 2) \
885 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
886 } \
887 /* Copy leftovers, or everything if misaligned. */ \
888 while (n >= 1) \
889 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
890 \
891 } \
892 } \
893 \
894 return dst; \
895 }
896
897#define MEMMOVE(soname, fnname) \
898 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
899
900#define MEMCPY(soname, fnname) \
901 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
902
903#if defined(VGO_linux)
904 /* For older memcpy we have to use memmove-like semantics and skip
905 the overlap check; sigh; see #275284. */
906 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
907 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
908 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
909 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy)
910 MEMCPY(VG_Z_LIBC_SONAME, __memcpy_sse2)
911 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
912 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
913 /* icc9 blats these around all over the place. Not only in the main
914 executable but various .so's. They are highly tuned and read
915 memory beyond the source boundary (although work correctly and
916 never go across page boundaries), so give errors when run
917 natively, at least for misaligned source arg. Just intercepting
918 in the exe only until we understand more about the problem. See
919 http://bugs.kde.org/show_bug.cgi?id=139776
920 */
921 MEMCPY(NONE, ZuintelZufastZumemcpy)
922
923#elif defined(VGO_darwin)
924# if DARWIN_VERS <= DARWIN_10_6
925 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
926# endif
927 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */
928 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */
929
930#endif
931
932
933/*---------------------- memcmp ----------------------*/
934
935#define MEMCMP(soname, fnname) \
936 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
937 ( const void *s1V, const void *s2V, SizeT n ); \
938 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
939 ( const void *s1V, const void *s2V, SizeT n ) \
940 { \
941 int res; \
942 UChar a0; \
943 UChar b0; \
944 const UChar* s1 = s1V; \
945 const UChar* s2 = s2V; \
946 \
947 while (n != 0) { \
948 a0 = s1[0]; \
949 b0 = s2[0]; \
950 s1 += 1; \
951 s2 += 1; \
952 res = ((int)a0) - ((int)b0); \
953 if (res != 0) \
954 return res; \
955 n -= 1; \
956 } \
957 return 0; \
958 }
959
960#if defined(VGO_linux)
961 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
962 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
963 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse2)
964 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_sse4_1)
965 MEMCMP(VG_Z_LIBC_SONAME, bcmp)
966 MEMCMP(VG_Z_LD_SO_1, bcmp)
967
968#elif defined(VGO_darwin)
969 //MEMCMP(VG_Z_LIBC_SONAME, memcmp)
970 //MEMCMP(VG_Z_LIBC_SONAME, bcmp)
971 //MEMCMP(VG_Z_DYLD, memcmp)
972 //MEMCMP(VG_Z_DYLD, bcmp)
973
974#endif
975
976
977/*---------------------- stpcpy ----------------------*/
978
979/* Copy SRC to DEST, returning the address of the terminating '\0' in
980 DEST. (minor variant of strcpy) */
981#define STPCPY(soname, fnname) \
982 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
983 ( char* dst, const char* src ); \
984 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
985 ( char* dst, const char* src ) \
986 { \
987 const HChar* src_orig = src; \
988 HChar* dst_orig = dst; \
989 \
990 while (*src) *dst++ = *src++; \
991 *dst = 0; \
992 \
993 /* This checks for overlap after copying, unavoidable without */ \
994 /* pre-counting length... should be ok */ \
995 if (is_overlap(dst_orig, \
996 src_orig, \
997 (Addr)dst-(Addr)dst_orig+1, \
998 (Addr)src-(Addr)src_orig+1)) \
999 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
1000 \
1001 return dst; \
1002 }
1003
1004#if defined(VGO_linux)
1005 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1006 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
1007 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2)
1008 STPCPY(VG_Z_LIBC_SONAME, __stpcpy_sse2_unaligned)
1009 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
1010 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
1011
1012#elif defined(VGO_darwin)
1013 //STPCPY(VG_Z_LIBC_SONAME, stpcpy)
1014 //STPCPY(VG_Z_DYLD, stpcpy)
1015
1016#endif
1017
1018
1019/*---------------------- stpncpy ----------------------*/
1020
1021#define STPNCPY(soname, fnname) \
1022 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1023 ( char* dst, const char* src, SizeT n ); \
1024 char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \
1025 ( char* dst, const char* src, SizeT n ) \
1026 { \
1027 const HChar* src_orig = src; \
1028 HChar* dst_str = dst; \
1029 SizeT m = 0; \
1030 \
1031 while (m < n && *src) { m++; *dst++ = *src++; } \
1032 /* Check for overlap after copying; all n bytes of dst are relevant, */ \
1033 /* but only m+1 bytes of src if terminator was found */ \
1034 if (is_overlap(dst_str, src_orig, n, (m < n) ? m+1 : n)) \
1035 RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \
1036 dst_str = dst; \
1037 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \
1038 \
1039 return dst_str; \
1040 }
1041
1042#if defined(VGO_linux)
1043 STPNCPY(VG_Z_LIBC_SONAME, stpncpy)
1044#endif
1045
1046
1047/*---------------------- memset ----------------------*/
1048
1049/* Why are we bothering to intercept this? It seems entirely
1050 pointless. */
1051
1052#define MEMSET(soname, fnname) \
1053 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1054 (void *s, Int c, SizeT n); \
1055 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
1056 (void *s, Int c, SizeT n) \
1057 { \
1058 if (sizeof(void*) == 8) { \
1059 Addr a = (Addr)s; \
1060 ULong c8 = (c & 0xFF); \
1061 c8 = (c8 << 8) | c8; \
1062 c8 = (c8 << 16) | c8; \
1063 c8 = (c8 << 32) | c8; \
1064 while ((a & 7) != 0 && n >= 1) \
1065 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1066 while (n >= 8) \
1067 { *(ULong*)a = c8; a += 8; n -= 8; } \
1068 while (n >= 1) \
1069 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1070 return s; \
1071 } else { \
1072 Addr a = (Addr)s; \
1073 UInt c4 = (c & 0xFF); \
1074 c4 = (c4 << 8) | c4; \
1075 c4 = (c4 << 16) | c4; \
1076 while ((a & 3) != 0 && n >= 1) \
1077 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1078 while (n >= 4) \
1079 { *(UInt*)a = c4; a += 4; n -= 4; } \
1080 while (n >= 1) \
1081 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \
1082 return s; \
1083 } \
1084 }
1085
1086#if defined(VGO_linux)
1087 MEMSET(VG_Z_LIBC_SONAME, memset)
1088
1089#elif defined(VGO_darwin)
1090 //MEMSET(VG_Z_LIBC_SONAME, memset)
1091 //MEMSET(VG_Z_DYLD, memset)
1092 MEMSET(VG_Z_LIBC_SONAME, memset)
1093
1094#endif
1095
1096
1097/*---------------------- memmove ----------------------*/
1098
1099/* memmove -- use the MEMMOVE defn above. */
1100
1101#if defined(VGO_linux)
1102 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1103 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove)
1104
1105#elif defined(VGO_darwin)
1106# if DARWIN_VERS <= DARWIN_10_6
1107 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
1108# endif
1109 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */
1110 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */
1111
1112#endif
1113
1114
1115/*---------------------- bcopy ----------------------*/
1116
1117#define BCOPY(soname, fnname) \
1118 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1119 (const void *srcV, void *dstV, SizeT n); \
1120 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
1121 (const void *srcV, void *dstV, SizeT n) \
1122 { \
1123 SizeT i; \
1124 HChar* dst = dstV; \
1125 const HChar* src = srcV; \
1126 if (dst < src) { \
1127 for (i = 0; i < n; i++) \
1128 dst[i] = src[i]; \
1129 } \
1130 else \
1131 if (dst > src) { \
1132 for (i = 0; i < n; i++) \
1133 dst[n-i-1] = src[n-i-1]; \
1134 } \
1135 }
1136
1137#if defined(VGO_linux)
1138 BCOPY(VG_Z_LIBC_SONAME, bcopy)
1139
1140#elif defined(VGO_darwin)
1141 //BCOPY(VG_Z_LIBC_SONAME, bcopy)
1142 //BCOPY(VG_Z_DYLD, bcopy)
1143
1144#endif
1145
1146
1147/*-------------------- memmove_chk --------------------*/
1148
1149/* glibc 2.5 variant of memmove which checks the dest is big enough.
1150 There is no specific part of glibc that this is copied from. */
1151#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
1152 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1153 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
1154 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
1155 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
1156 { \
1157 SizeT i; \
1158 HChar* dst = dstV; \
1159 const HChar* src = srcV; \
1160 if (destlen < n) \
1161 goto badness; \
1162 if (dst < src) { \
1163 for (i = 0; i < n; i++) \
1164 dst[i] = src[i]; \
1165 } \
1166 else \
1167 if (dst > src) { \
1168 for (i = 0; i < n; i++) \
1169 dst[n-i-1] = src[n-i-1]; \
1170 } \
1171 return dst; \
1172 badness: \
1173 VALGRIND_PRINTF_BACKTRACE( \
1174 "*** memmove_chk: buffer overflow detected ***: " \
1175 "program terminated\n"); \
1176 my_exit(127); \
1177 /*NOTREACHED*/ \
1178 return NULL; \
1179 }
1180
1181#if defined(VGO_linux)
1182 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk)
1183
1184#elif defined(VGO_darwin)
1185
1186#endif
1187
1188
1189/*-------------------- strchrnul --------------------*/
1190
1191/* Find the first occurrence of C in S or the final NUL byte. */
1192#define GLIBC232_STRCHRNUL(soname, fnname) \
1193 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1194 (const char* s, int c_in); \
1195 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
1196 (const char* s, int c_in) \
1197 { \
1198 UChar c = (UChar) c_in; \
1199 UChar* char_ptr = (UChar *)s; \
1200 while (1) { \
1201 if (*char_ptr == 0) return (HChar *)char_ptr; \
1202 if (*char_ptr == c) return (HChar *)char_ptr; \
1203 char_ptr++; \
1204 } \
1205 }
1206
1207#if defined(VGO_linux)
1208 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
1209
1210#elif defined(VGO_darwin)
1211
1212#endif
1213
1214
1215/*---------------------- rawmemchr ----------------------*/
1216
1217/* Find the first occurrence of C in S. */
1218#define GLIBC232_RAWMEMCHR(soname, fnname) \
1219 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1220 (const char* s, int c_in); \
1221 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
1222 (const char* s, int c_in) \
1223 { \
1224 UChar c = (UChar) c_in; \
1225 UChar* char_ptr = (UChar *)s; \
1226 while (1) { \
1227 if (*char_ptr == c) return (HChar *)char_ptr; \
1228 char_ptr++; \
1229 } \
1230 }
1231
1232#if defined (VGO_linux)
1233 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
1234 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
1235
1236#elif defined(VGO_darwin)
1237
1238#endif
1239
1240
1241/*---------------------- strcpy_chk ----------------------*/
1242
1243/* glibc variant of strcpy that checks the dest is big enough.
1244 Copied from glibc-2.5/debug/test-strcpy_chk.c. */
1245#define GLIBC25___STRCPY_CHK(soname,fnname) \
1246 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1247 (char* dst, const char* src, SizeT len); \
1248 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
1249 (char* dst, const char* src, SizeT len) \
1250 { \
1251 HChar* ret = dst; \
1252 if (! len) \
1253 goto badness; \
1254 while ((*dst++ = *src++) != '\0') \
1255 if (--len == 0) \
1256 goto badness; \
1257 return ret; \
1258 badness: \
1259 VALGRIND_PRINTF_BACKTRACE( \
1260 "*** strcpy_chk: buffer overflow detected ***: " \
1261 "program terminated\n"); \
1262 my_exit(127); \
1263 /*NOTREACHED*/ \
1264 return NULL; \
1265 }
1266
1267#if defined(VGO_linux)
1268 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk)
1269
1270#elif defined(VGO_darwin)
1271
1272#endif
1273
1274
1275/*---------------------- stpcpy_chk ----------------------*/
1276
1277/* glibc variant of stpcpy that checks the dest is big enough.
1278 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
1279#define GLIBC25___STPCPY_CHK(soname,fnname) \
1280 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1281 (char* dst, const char* src, SizeT len); \
1282 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
1283 (char* dst, const char* src, SizeT len) \
1284 { \
1285 if (! len) \
1286 goto badness; \
1287 while ((*dst++ = *src++) != '\0') \
1288 if (--len == 0) \
1289 goto badness; \
1290 return dst - 1; \
1291 badness: \
1292 VALGRIND_PRINTF_BACKTRACE( \
1293 "*** stpcpy_chk: buffer overflow detected ***: " \
1294 "program terminated\n"); \
1295 my_exit(127); \
1296 /*NOTREACHED*/ \
1297 return NULL; \
1298 }
1299
1300#if defined(VGO_linux)
1301 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
1302
1303#elif defined(VGO_darwin)
1304
1305#endif
1306
1307
1308/*---------------------- mempcpy ----------------------*/
1309
1310/* mempcpy */
1311#define GLIBC25_MEMPCPY(soname, fnname) \
1312 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1313 ( void *dst, const void *src, SizeT len ); \
1314 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
1315 ( void *dst, const void *src, SizeT len ) \
1316 { \
1317 register HChar *d; \
1318 register HChar *s; \
1319 SizeT len_saved = len; \
1320 \
1321 if (len == 0) \
1322 return dst; \
1323 \
1324 if (is_overlap(dst, src, len, len)) \
1325 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
1326 \
1327 if ( dst > src ) { \
1328 d = (char *)dst + len - 1; \
1329 s = (char *)src + len - 1; \
1330 while ( len-- ) { \
1331 *d-- = *s--; \
1332 } \
1333 } else if ( dst < src ) { \
1334 d = (char *)dst; \
1335 s = (char *)src; \
1336 while ( len-- ) { \
1337 *d++ = *s++; \
1338 } \
1339 } \
1340 return (void*)( ((char*)dst) + len_saved ); \
1341 }
1342
1343#if defined(VGO_linux)
1344 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1345 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
bartf2d86632014-03-15 12:47:28 +00001346 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */
1347 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */
bart9c7779b2013-11-24 17:48:13 +00001348
1349#elif defined(VGO_darwin)
1350 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1351
1352#endif
1353
1354
1355/*-------------------- memcpy_chk --------------------*/
1356
1357#define GLIBC26___MEMCPY_CHK(soname, fnname) \
1358 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1359 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1360 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1361 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1362 { \
1363 register HChar *d; \
1364 register const HChar *s; \
1365 \
1366 if (dstlen < len) goto badness; \
1367 \
1368 if (len == 0) \
1369 return dst; \
1370 \
1371 if (is_overlap(dst, src, len, len)) \
1372 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1373 \
1374 if ( dst > src ) { \
1375 d = (HChar *)dst + len - 1; \
1376 s = (const HChar *)src + len - 1; \
1377 while ( len-- ) { \
1378 *d-- = *s--; \
1379 } \
1380 } else if ( dst < src ) { \
1381 d = (HChar *)dst; \
1382 s = (const HChar *)src; \
1383 while ( len-- ) { \
1384 *d++ = *s++; \
1385 } \
1386 } \
1387 return dst; \
1388 badness: \
1389 VALGRIND_PRINTF_BACKTRACE( \
1390 "*** memcpy_chk: buffer overflow detected ***: " \
1391 "program terminated\n"); \
1392 my_exit(127); \
1393 /*NOTREACHED*/ \
1394 return NULL; \
1395 }
1396
1397#if defined(VGO_linux)
1398 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1399
1400#elif defined(VGO_darwin)
1401
1402#endif
1403
1404
1405/*---------------------- strstr ----------------------*/
1406
1407#define STRSTR(soname, fnname) \
1408 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1409 (const char* haystack, const char* needle); \
1410 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1411 (const char* haystack, const char* needle) \
1412 { \
1413 const HChar* h = haystack; \
1414 const HChar* n = needle; \
1415 \
1416 /* find the length of n, not including terminating zero */ \
1417 UWord nlen = 0; \
1418 while (n[nlen]) nlen++; \
1419 \
1420 /* if n is the empty string, match immediately. */ \
1421 if (nlen == 0) return (HChar *)h; \
1422 \
1423 /* assert(nlen >= 1); */ \
1424 HChar n0 = n[0]; \
1425 \
1426 while (1) { \
1427 const HChar hh = *h; \
1428 if (hh == 0) return NULL; \
1429 if (hh != n0) { h++; continue; } \
1430 \
1431 UWord i; \
1432 for (i = 0; i < nlen; i++) { \
1433 if (n[i] != h[i]) \
1434 break; \
1435 } \
1436 /* assert(i >= 0 && i <= nlen); */ \
1437 if (i == nlen) \
1438 return (HChar *)h; \
1439 \
1440 h++; \
1441 } \
1442 }
1443
1444#if defined(VGO_linux)
1445 STRSTR(VG_Z_LIBC_SONAME, strstr)
1446 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse2)
1447 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse42)
1448
1449#elif defined(VGO_darwin)
1450
1451#endif
1452
1453
1454/*---------------------- strpbrk ----------------------*/
1455
1456#define STRPBRK(soname, fnname) \
1457 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1458 (const char* sV, const char* acceptV); \
1459 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1460 (const char* sV, const char* acceptV) \
1461 { \
1462 const HChar* s = sV; \
1463 const HChar* accept = acceptV; \
1464 \
1465 /* find the length of 'accept', not including terminating zero */ \
1466 UWord nacc = 0; \
1467 while (accept[nacc]) nacc++; \
1468 \
1469 /* if n is the empty string, fail immediately. */ \
1470 if (nacc == 0) return NULL; \
1471 \
1472 /* assert(nacc >= 1); */ \
1473 while (1) { \
1474 UWord i; \
1475 HChar sc = *s; \
1476 if (sc == 0) \
1477 break; \
1478 for (i = 0; i < nacc; i++) { \
1479 if (sc == accept[i]) \
1480 return (HChar *)s; \
1481 } \
1482 s++; \
1483 } \
1484 \
1485 return NULL; \
1486 }
1487
1488#if defined(VGO_linux)
1489 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1490
1491#elif defined(VGO_darwin)
1492
1493#endif
1494
1495
1496/*---------------------- strcspn ----------------------*/
1497
1498#define STRCSPN(soname, fnname) \
1499 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1500 (const char* sV, const char* rejectV); \
1501 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1502 (const char* sV, const char* rejectV) \
1503 { \
1504 const HChar* s = sV; \
1505 const HChar* reject = rejectV; \
1506 \
1507 /* find the length of 'reject', not including terminating zero */ \
1508 UWord nrej = 0; \
1509 while (reject[nrej]) nrej++; \
1510 \
1511 UWord len = 0; \
1512 while (1) { \
1513 UWord i; \
1514 HChar sc = *s; \
1515 if (sc == 0) \
1516 break; \
1517 for (i = 0; i < nrej; i++) { \
1518 if (sc == reject[i]) \
1519 break; \
1520 } \
1521 /* assert(i >= 0 && i <= nrej); */ \
1522 if (i < nrej) \
1523 break; \
1524 s++; \
1525 len++; \
1526 } \
1527 \
1528 return len; \
1529 }
1530
1531#if defined(VGO_linux)
1532 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1533
1534#elif defined(VGO_darwin)
1535
1536#endif
1537
1538
1539/*---------------------- strspn ----------------------*/
1540
1541#define STRSPN(soname, fnname) \
1542 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1543 (const char* sV, const char* acceptV); \
1544 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1545 (const char* sV, const char* acceptV) \
1546 { \
1547 const UChar* s = (const UChar *)sV; \
1548 const UChar* accept = (const UChar *)acceptV; \
1549 \
1550 /* find the length of 'accept', not including terminating zero */ \
1551 UWord nacc = 0; \
1552 while (accept[nacc]) nacc++; \
1553 if (nacc == 0) return 0; \
1554 \
1555 UWord len = 0; \
1556 while (1) { \
1557 UWord i; \
1558 HChar sc = *s; \
1559 if (sc == 0) \
1560 break; \
1561 for (i = 0; i < nacc; i++) { \
1562 if (sc == accept[i]) \
1563 break; \
1564 } \
1565 /* assert(i >= 0 && i <= nacc); */ \
1566 if (i == nacc) \
1567 break; \
1568 s++; \
1569 len++; \
1570 } \
1571 \
1572 return len; \
1573 }
1574
1575#if defined(VGO_linux)
1576 STRSPN(VG_Z_LIBC_SONAME, strspn)
1577
1578#elif defined(VGO_darwin)
1579
1580#endif
1581
1582
1583/*---------------------- strcasestr ----------------------*/
1584
1585#define STRCASESTR(soname, fnname) \
1586 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1587 (const char* haystack, const char* needle); \
1588 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1589 (const char* haystack, const char* needle) \
1590 { \
1591 extern int tolower(int); \
1592 const HChar* h = haystack; \
1593 const HChar* n = needle; \
1594 \
1595 /* find the length of n, not including terminating zero */ \
1596 UWord nlen = 0; \
1597 while (n[nlen]) nlen++; \
1598 \
1599 /* if n is the empty string, match immediately. */ \
1600 if (nlen == 0) return (HChar *)h; \
1601 \
1602 /* assert(nlen >= 1); */ \
1603 UChar n0 = tolower(n[0]); \
1604 \
1605 while (1) { \
1606 UChar hh = tolower(*h); \
1607 if (hh == 0) return NULL; \
1608 if (hh != n0) { h++; continue; } \
1609 \
1610 UWord i; \
1611 for (i = 0; i < nlen; i++) { \
1612 if (tolower(n[i]) != tolower(h[i])) \
1613 break; \
1614 } \
1615 /* assert(i >= 0 && i <= nlen); */ \
1616 if (i == nlen) \
1617 return (HChar *)h; \
1618 \
1619 h++; \
1620 } \
1621 }
1622
1623#if defined(VGO_linux)
dejanj9c6b05d2013-12-27 09:06:55 +00001624# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
1625 && !defined(VGPV_mips32_linux_android)
bart9c7779b2013-11-24 17:48:13 +00001626 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1627# endif
1628
1629#elif defined(VGO_darwin)
1630
1631#endif
1632
1633
1634/*---------------------- wcslen ----------------------*/
1635
1636// This is a wchar_t equivalent to strlen. Unfortunately
1637// we don't have wchar_t available here, but it looks like
1638// a 32 bit int on Linux. I don't know if that is also
1639// valid on MacOSX.
1640
1641#define WCSLEN(soname, fnname) \
1642 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1643 ( const UInt* str ); \
1644 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1645 ( const UInt* str ) \
1646 { \
1647 SizeT i = 0; \
1648 while (str[i] != 0) i++; \
1649 return i; \
1650 }
1651
1652#if defined(VGO_linux)
1653 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
1654
1655#elif defined(VGO_darwin)
1656
1657#endif
1658
1659/*---------------------- wcscmp ----------------------*/
1660
1661// This is a wchar_t equivalent to strcmp. We don't
1662// have wchar_t available here, but in the GNU C Library
1663// wchar_t is always 32 bits wide and wcscmp uses signed
1664// comparison, not unsigned as in strcmp function.
1665
1666#define WCSCMP(soname, fnname) \
1667 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1668 ( const Int* s1, const Int* s2 ); \
1669 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1670 ( const Int* s1, const Int* s2 ) \
1671 { \
1672 register Int c1; \
1673 register Int c2; \
1674 while (True) { \
1675 c1 = *s1; \
1676 c2 = *s2; \
1677 if (c1 != c2) break; \
1678 if (c1 == 0) break; \
1679 s1++; s2++; \
1680 } \
1681 if (c1 < c2) return -1; \
1682 if (c1 > c2) return 1; \
1683 return 0; \
1684 }
1685
1686#if defined(VGO_linux)
1687 WCSCMP(VG_Z_LIBC_SONAME, wcscmp)
1688#endif
1689
1690/*---------------------- wcscpy ----------------------*/
1691
1692// This is a wchar_t equivalent to strcpy. We don't
1693// have wchar_t available here, but in the GNU C Library
1694// wchar_t is always 32 bits wide.
1695
1696#define WCSCPY(soname, fnname) \
1697 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1698 ( Int* dst, const Int* src ); \
1699 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1700 ( Int* dst, const Int* src ) \
1701 { \
1702 const Int* src_orig = src; \
1703 Int* dst_orig = dst; \
1704 \
1705 while (*src) *dst++ = *src++; \
1706 *dst = 0; \
1707 \
1708 /* This checks for overlap after copying, unavoidable without */ \
1709 /* pre-counting length... should be ok */ \
1710 if (is_overlap(dst_orig, \
1711 src_orig, \
1712 (Addr)dst-(Addr)dst_orig+1, \
1713 (Addr)src-(Addr)src_orig+1)) \
1714 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
1715 \
1716 return dst_orig; \
1717 }
1718
1719#if defined(VGO_linux)
1720 WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
1721#endif
1722
1723
1724/*---------------------- wcschr ----------------------*/
1725
1726// This is a wchar_t equivalent to strchr. We don't
1727// have wchar_t available here, but in the GNU C Library
1728// wchar_t is always 32 bits wide.
1729
1730#define WCSCHR(soname, fnname) \
1731 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
1732 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
1733 { \
1734 Int* p = (Int*)s; \
1735 while (True) { \
1736 if (*p == c) return p; \
1737 if (*p == 0) return NULL; \
1738 p++; \
1739 } \
1740 }
1741
1742#if defined(VGO_linux)
1743 WCSCHR(VG_Z_LIBC_SONAME, wcschr)
1744#endif
1745/*---------------------- wcsrchr ----------------------*/
1746
1747// This is a wchar_t equivalent to strrchr. We don't
1748// have wchar_t available here, but in the GNU C Library
1749// wchar_t is always 32 bits wide.
1750
1751#define WCSRCHR(soname, fnname) \
1752 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
1753 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
1754 { \
1755 Int* p = (Int*) s; \
1756 Int* last = NULL; \
1757 while (True) { \
1758 if (*p == c) last = p; \
1759 if (*p == 0) return last; \
1760 p++; \
1761 } \
1762 }
1763
1764#if defined(VGO_linux)
1765 WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
1766#endif
1767
1768/*------------------------------------------------------------*/
1769/*--- Improve definedness checking of process environment ---*/
1770/*------------------------------------------------------------*/
1771
1772#if defined(VGO_linux)
1773
1774/* If these wind up getting generated via a macro, so that multiple
1775 versions of each function exist (as above), use the _EZU variants
1776 to assign equivalance class tags. */
1777
1778/*---------------------- putenv ----------------------*/
1779
1780int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1781int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
1782{
1783 OrigFn fn;
1784 Word result;
1785 const HChar* p = string;
1786 VALGRIND_GET_ORIG_FN(fn);
1787 /* Now by walking over the string we magically produce
1788 traces when hitting undefined memory. */
1789 if (p)
1790 while (*p++)
1791 __asm__ __volatile__("" ::: "memory");
1792 CALL_FN_W_W(result, fn, string);
1793 return result;
1794}
1795
1796
1797/*---------------------- unsetenv ----------------------*/
1798
1799int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1800int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
1801{
1802 OrigFn fn;
1803 Word result;
1804 const HChar* p = name;
1805 VALGRIND_GET_ORIG_FN(fn);
1806 /* Now by walking over the string we magically produce
1807 traces when hitting undefined memory. */
1808 if (p)
1809 while (*p++)
1810 __asm__ __volatile__("" ::: "memory");
1811 CALL_FN_W_W(result, fn, name);
1812 return result;
1813}
1814
1815
1816/*---------------------- setenv ----------------------*/
1817
1818/* setenv */
1819int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1820 (const char* name, const char* value, int overwrite);
1821int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1822 (const char* name, const char* value, int overwrite)
1823{
1824 OrigFn fn;
1825 Word result;
1826 const HChar* p;
1827 VALGRIND_GET_ORIG_FN(fn);
1828 /* Now by walking over the string we magically produce
1829 traces when hitting undefined memory. */
1830 if (name)
1831 for (p = name; *p; p++)
1832 __asm__ __volatile__("" ::: "memory");
1833 if (value)
1834 for (p = value; *p; p++)
1835 __asm__ __volatile__("" ::: "memory");
1836 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1837 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1838 return result;
1839}
1840
1841#endif /* defined(VGO_linux) */
1842
1843/*--------------------------------------------------------------------*/
1844/*--- end ---*/
1845/*--------------------------------------------------------------------*/