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