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