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