blob: 5203306bd7c276c7d0e57db01233c7a5f32c1d8d [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)
mjwa9176d92015-01-13 16:10:20 +00001366 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, __GI_mempcpy)
bart9c7779b2013-11-24 17:48:13 +00001367 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
bartf2d86632014-03-15 12:47:28 +00001368 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_SO_3, mempcpy) /* ld-linux.so.3 */
1369 GLIBC25_MEMPCPY(VG_Z_LD_LINUX_X86_64_SO_2, mempcpy) /* ld-linux-x86-64.so.2 */
bart9c7779b2013-11-24 17:48:13 +00001370
1371#elif defined(VGO_darwin)
1372 //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy)
1373
1374#endif
1375
1376
1377/*-------------------- memcpy_chk --------------------*/
1378
1379#define GLIBC26___MEMCPY_CHK(soname, fnname) \
1380 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1381 (void* dst, const void* src, SizeT len, SizeT dstlen ); \
1382 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
1383 (void* dst, const void* src, SizeT len, SizeT dstlen ) \
1384 { \
1385 register HChar *d; \
1386 register const HChar *s; \
1387 \
1388 if (dstlen < len) goto badness; \
1389 \
1390 if (len == 0) \
1391 return dst; \
1392 \
1393 if (is_overlap(dst, src, len, len)) \
1394 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
1395 \
1396 if ( dst > src ) { \
1397 d = (HChar *)dst + len - 1; \
1398 s = (const HChar *)src + len - 1; \
1399 while ( len-- ) { \
1400 *d-- = *s--; \
1401 } \
1402 } else if ( dst < src ) { \
1403 d = (HChar *)dst; \
1404 s = (const HChar *)src; \
1405 while ( len-- ) { \
1406 *d++ = *s++; \
1407 } \
1408 } \
1409 return dst; \
1410 badness: \
1411 VALGRIND_PRINTF_BACKTRACE( \
1412 "*** memcpy_chk: buffer overflow detected ***: " \
1413 "program terminated\n"); \
1414 my_exit(127); \
1415 /*NOTREACHED*/ \
1416 return NULL; \
1417 }
1418
1419#if defined(VGO_linux)
1420 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
1421
1422#elif defined(VGO_darwin)
1423
1424#endif
1425
1426
1427/*---------------------- strstr ----------------------*/
1428
1429#define STRSTR(soname, fnname) \
1430 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1431 (const char* haystack, const char* needle); \
1432 char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
1433 (const char* haystack, const char* needle) \
1434 { \
1435 const HChar* h = haystack; \
1436 const HChar* n = needle; \
1437 \
1438 /* find the length of n, not including terminating zero */ \
1439 UWord nlen = 0; \
1440 while (n[nlen]) nlen++; \
1441 \
1442 /* if n is the empty string, match immediately. */ \
florian70a5de12014-10-22 12:53:16 +00001443 if (nlen == 0) return CONST_CAST(HChar *,h); \
bart9c7779b2013-11-24 17:48:13 +00001444 \
1445 /* assert(nlen >= 1); */ \
1446 HChar n0 = n[0]; \
1447 \
1448 while (1) { \
1449 const HChar hh = *h; \
1450 if (hh == 0) return NULL; \
1451 if (hh != n0) { h++; continue; } \
1452 \
1453 UWord i; \
1454 for (i = 0; i < nlen; i++) { \
1455 if (n[i] != h[i]) \
1456 break; \
1457 } \
1458 /* assert(i >= 0 && i <= nlen); */ \
1459 if (i == nlen) \
florian70a5de12014-10-22 12:53:16 +00001460 return CONST_CAST(HChar *,h); \
bart9c7779b2013-11-24 17:48:13 +00001461 \
1462 h++; \
1463 } \
1464 }
1465
1466#if defined(VGO_linux)
1467 STRSTR(VG_Z_LIBC_SONAME, strstr)
1468 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse2)
1469 STRSTR(VG_Z_LIBC_SONAME, __strstr_sse42)
1470
1471#elif defined(VGO_darwin)
1472
1473#endif
1474
1475
1476/*---------------------- strpbrk ----------------------*/
1477
1478#define STRPBRK(soname, fnname) \
1479 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1480 (const char* sV, const char* acceptV); \
1481 char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
1482 (const char* sV, const char* acceptV) \
1483 { \
1484 const HChar* s = sV; \
1485 const HChar* accept = acceptV; \
1486 \
1487 /* find the length of 'accept', not including terminating zero */ \
1488 UWord nacc = 0; \
1489 while (accept[nacc]) nacc++; \
1490 \
1491 /* if n is the empty string, fail immediately. */ \
1492 if (nacc == 0) return NULL; \
1493 \
1494 /* assert(nacc >= 1); */ \
1495 while (1) { \
1496 UWord i; \
1497 HChar sc = *s; \
1498 if (sc == 0) \
1499 break; \
1500 for (i = 0; i < nacc; i++) { \
1501 if (sc == accept[i]) \
florian70a5de12014-10-22 12:53:16 +00001502 return CONST_CAST(HChar *,s); \
bart9c7779b2013-11-24 17:48:13 +00001503 } \
1504 s++; \
1505 } \
1506 \
1507 return NULL; \
1508 }
1509
1510#if defined(VGO_linux)
1511 STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
1512
1513#elif defined(VGO_darwin)
1514
1515#endif
1516
1517
1518/*---------------------- strcspn ----------------------*/
1519
1520#define STRCSPN(soname, fnname) \
1521 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1522 (const char* sV, const char* rejectV); \
1523 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
1524 (const char* sV, const char* rejectV) \
1525 { \
1526 const HChar* s = sV; \
1527 const HChar* reject = rejectV; \
1528 \
1529 /* find the length of 'reject', not including terminating zero */ \
1530 UWord nrej = 0; \
1531 while (reject[nrej]) nrej++; \
1532 \
1533 UWord len = 0; \
1534 while (1) { \
1535 UWord i; \
1536 HChar sc = *s; \
1537 if (sc == 0) \
1538 break; \
1539 for (i = 0; i < nrej; i++) { \
1540 if (sc == reject[i]) \
1541 break; \
1542 } \
1543 /* assert(i >= 0 && i <= nrej); */ \
1544 if (i < nrej) \
1545 break; \
1546 s++; \
1547 len++; \
1548 } \
1549 \
1550 return len; \
1551 }
1552
1553#if defined(VGO_linux)
1554 STRCSPN(VG_Z_LIBC_SONAME, strcspn)
1555
1556#elif defined(VGO_darwin)
1557
1558#endif
1559
1560
1561/*---------------------- strspn ----------------------*/
1562
1563#define STRSPN(soname, fnname) \
1564 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1565 (const char* sV, const char* acceptV); \
1566 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
1567 (const char* sV, const char* acceptV) \
1568 { \
1569 const UChar* s = (const UChar *)sV; \
1570 const UChar* accept = (const UChar *)acceptV; \
1571 \
1572 /* find the length of 'accept', not including terminating zero */ \
1573 UWord nacc = 0; \
1574 while (accept[nacc]) nacc++; \
1575 if (nacc == 0) return 0; \
1576 \
1577 UWord len = 0; \
1578 while (1) { \
1579 UWord i; \
1580 HChar sc = *s; \
1581 if (sc == 0) \
1582 break; \
1583 for (i = 0; i < nacc; i++) { \
1584 if (sc == accept[i]) \
1585 break; \
1586 } \
1587 /* assert(i >= 0 && i <= nacc); */ \
1588 if (i == nacc) \
1589 break; \
1590 s++; \
1591 len++; \
1592 } \
1593 \
1594 return len; \
1595 }
1596
1597#if defined(VGO_linux)
1598 STRSPN(VG_Z_LIBC_SONAME, strspn)
1599
1600#elif defined(VGO_darwin)
1601
1602#endif
1603
1604
1605/*---------------------- strcasestr ----------------------*/
1606
1607#define STRCASESTR(soname, fnname) \
1608 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1609 (const char* haystack, const char* needle); \
1610 char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \
1611 (const char* haystack, const char* needle) \
1612 { \
1613 extern int tolower(int); \
1614 const HChar* h = haystack; \
1615 const HChar* n = needle; \
1616 \
1617 /* find the length of n, not including terminating zero */ \
1618 UWord nlen = 0; \
1619 while (n[nlen]) nlen++; \
1620 \
1621 /* if n is the empty string, match immediately. */ \
florian70a5de12014-10-22 12:53:16 +00001622 if (nlen == 0) return CONST_CAST(HChar *,h); \
bart9c7779b2013-11-24 17:48:13 +00001623 \
1624 /* assert(nlen >= 1); */ \
1625 UChar n0 = tolower(n[0]); \
1626 \
1627 while (1) { \
1628 UChar hh = tolower(*h); \
1629 if (hh == 0) return NULL; \
1630 if (hh != n0) { h++; continue; } \
1631 \
1632 UWord i; \
1633 for (i = 0; i < nlen; i++) { \
1634 if (tolower(n[i]) != tolower(h[i])) \
1635 break; \
1636 } \
1637 /* assert(i >= 0 && i <= nlen); */ \
1638 if (i == nlen) \
florian70a5de12014-10-22 12:53:16 +00001639 return CONST_CAST(HChar *,h); \
bart9c7779b2013-11-24 17:48:13 +00001640 \
1641 h++; \
1642 } \
1643 }
1644
1645#if defined(VGO_linux)
sewardj26ed4192014-11-04 17:44:21 +00001646# if !defined(VGPV_arm_linux_android) \
1647 && !defined(VGPV_x86_linux_android) \
1648 && !defined(VGPV_mips32_linux_android) \
1649 && !defined(VGPV_arm64_linux_android)
bart9c7779b2013-11-24 17:48:13 +00001650 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr)
1651# endif
1652
1653#elif defined(VGO_darwin)
1654
1655#endif
1656
1657
1658/*---------------------- wcslen ----------------------*/
1659
1660// This is a wchar_t equivalent to strlen. Unfortunately
1661// we don't have wchar_t available here, but it looks like
1662// a 32 bit int on Linux. I don't know if that is also
1663// valid on MacOSX.
1664
1665#define WCSLEN(soname, fnname) \
1666 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1667 ( const UInt* str ); \
1668 SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \
1669 ( const UInt* str ) \
1670 { \
1671 SizeT i = 0; \
1672 while (str[i] != 0) i++; \
1673 return i; \
1674 }
1675
1676#if defined(VGO_linux)
1677 WCSLEN(VG_Z_LIBC_SONAME, wcslen)
1678
1679#elif defined(VGO_darwin)
1680
1681#endif
1682
1683/*---------------------- wcscmp ----------------------*/
1684
1685// This is a wchar_t equivalent to strcmp. We don't
1686// have wchar_t available here, but in the GNU C Library
1687// wchar_t is always 32 bits wide and wcscmp uses signed
1688// comparison, not unsigned as in strcmp function.
1689
1690#define WCSCMP(soname, fnname) \
1691 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1692 ( const Int* s1, const Int* s2 ); \
1693 int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
1694 ( const Int* s1, const Int* s2 ) \
1695 { \
1696 register Int c1; \
1697 register Int c2; \
1698 while (True) { \
1699 c1 = *s1; \
1700 c2 = *s2; \
1701 if (c1 != c2) break; \
1702 if (c1 == 0) break; \
1703 s1++; s2++; \
1704 } \
1705 if (c1 < c2) return -1; \
1706 if (c1 > c2) return 1; \
1707 return 0; \
1708 }
1709
1710#if defined(VGO_linux)
1711 WCSCMP(VG_Z_LIBC_SONAME, wcscmp)
1712#endif
1713
1714/*---------------------- wcscpy ----------------------*/
1715
1716// This is a wchar_t equivalent to strcpy. We don't
1717// have wchar_t available here, but in the GNU C Library
1718// wchar_t is always 32 bits wide.
1719
1720#define WCSCPY(soname, fnname) \
1721 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1722 ( Int* dst, const Int* src ); \
1723 Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
1724 ( Int* dst, const Int* src ) \
1725 { \
1726 const Int* src_orig = src; \
1727 Int* dst_orig = dst; \
1728 \
1729 while (*src) *dst++ = *src++; \
1730 *dst = 0; \
1731 \
1732 /* This checks for overlap after copying, unavoidable without */ \
1733 /* pre-counting length... should be ok */ \
1734 if (is_overlap(dst_orig, \
1735 src_orig, \
1736 (Addr)dst-(Addr)dst_orig+1, \
1737 (Addr)src-(Addr)src_orig+1)) \
1738 RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
1739 \
1740 return dst_orig; \
1741 }
1742
1743#if defined(VGO_linux)
1744 WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
1745#endif
1746
1747
1748/*---------------------- wcschr ----------------------*/
1749
1750// This is a wchar_t equivalent to strchr. We don't
1751// have wchar_t available here, but in the GNU C Library
1752// wchar_t is always 32 bits wide.
1753
1754#define WCSCHR(soname, fnname) \
1755 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
1756 Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
1757 { \
florian70a5de12014-10-22 12:53:16 +00001758 const Int* p = s; \
bart9c7779b2013-11-24 17:48:13 +00001759 while (True) { \
florian70a5de12014-10-22 12:53:16 +00001760 if (*p == c) return CONST_CAST(Int *,p); \
bart9c7779b2013-11-24 17:48:13 +00001761 if (*p == 0) return NULL; \
1762 p++; \
1763 } \
1764 }
1765
1766#if defined(VGO_linux)
1767 WCSCHR(VG_Z_LIBC_SONAME, wcschr)
1768#endif
1769/*---------------------- wcsrchr ----------------------*/
1770
1771// This is a wchar_t equivalent to strrchr. We don't
1772// have wchar_t available here, but in the GNU C Library
1773// wchar_t is always 32 bits wide.
1774
1775#define WCSRCHR(soname, fnname) \
1776 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
1777 Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
1778 { \
florian70a5de12014-10-22 12:53:16 +00001779 const Int* p = s; \
1780 const Int* last = NULL; \
bart9c7779b2013-11-24 17:48:13 +00001781 while (True) { \
1782 if (*p == c) last = p; \
florian70a5de12014-10-22 12:53:16 +00001783 if (*p == 0) return CONST_CAST(Int *,last); \
bart9c7779b2013-11-24 17:48:13 +00001784 p++; \
1785 } \
1786 }
1787
1788#if defined(VGO_linux)
1789 WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
1790#endif
1791
1792/*------------------------------------------------------------*/
1793/*--- Improve definedness checking of process environment ---*/
1794/*------------------------------------------------------------*/
1795
1796#if defined(VGO_linux)
1797
1798/* If these wind up getting generated via a macro, so that multiple
1799 versions of each function exist (as above), use the _EZU variants
1800 to assign equivalance class tags. */
1801
1802/*---------------------- putenv ----------------------*/
1803
1804int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string);
1805int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)
1806{
1807 OrigFn fn;
1808 Word result;
1809 const HChar* p = string;
1810 VALGRIND_GET_ORIG_FN(fn);
1811 /* Now by walking over the string we magically produce
1812 traces when hitting undefined memory. */
1813 if (p)
1814 while (*p++)
1815 __asm__ __volatile__("" ::: "memory");
1816 CALL_FN_W_W(result, fn, string);
1817 return result;
1818}
1819
1820
1821/*---------------------- unsetenv ----------------------*/
1822
1823int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name);
1824int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name)
1825{
1826 OrigFn fn;
1827 Word result;
1828 const HChar* p = name;
1829 VALGRIND_GET_ORIG_FN(fn);
1830 /* Now by walking over the string we magically produce
1831 traces when hitting undefined memory. */
1832 if (p)
1833 while (*p++)
1834 __asm__ __volatile__("" ::: "memory");
1835 CALL_FN_W_W(result, fn, name);
1836 return result;
1837}
1838
1839
1840/*---------------------- setenv ----------------------*/
1841
1842/* setenv */
1843int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1844 (const char* name, const char* value, int overwrite);
1845int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv)
1846 (const char* name, const char* value, int overwrite)
1847{
1848 OrigFn fn;
1849 Word result;
1850 const HChar* p;
1851 VALGRIND_GET_ORIG_FN(fn);
1852 /* Now by walking over the string we magically produce
1853 traces when hitting undefined memory. */
1854 if (name)
1855 for (p = name; *p; p++)
1856 __asm__ __volatile__("" ::: "memory");
1857 if (value)
1858 for (p = value; *p; p++)
1859 __asm__ __volatile__("" ::: "memory");
1860 (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
1861 CALL_FN_W_WWW(result, fn, name, value, overwrite);
1862 return result;
1863}
1864
1865#endif /* defined(VGO_linux) */
1866
1867/*--------------------------------------------------------------------*/
1868/*--- end ---*/
1869/*--------------------------------------------------------------------*/