From: Julian Seward Date: Thu, 19 Aug 2010 13:22:34 +0000 (+0000) Subject: Add intercepts for strstr, strpbrk, strcspn. These are needed for X-Git-Tag: svn/VALGRIND_3_6_0~187 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a8dd3161aaee95df5631c937cb20e7b28c44546;p=thirdparty%2Fvalgrind.git Add intercepts for strstr, strpbrk, strcspn. These are needed for glibc-2.11 when running on SSE4-enabled (virtual) CPUs, for the usual reason: to avoid ultra-optimised routines using the SSE 4.2 PCMPxSTRx instructions. I would not be surprised if it turned out that strspn was required, but I haven't seen a need for it so far. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11268 --- diff --git a/memcheck/mc_replace_strmem.c b/memcheck/mc_replace_strmem.c index e7cae0494e..f928769dfb 100644 --- a/memcheck/mc_replace_strmem.c +++ b/memcheck/mc_replace_strmem.c @@ -867,6 +867,123 @@ GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */ GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk) +#define STRSTR(soname, fnname) \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + (void* haystack, void* needle); \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + (void* haystack, void* needle) \ + { \ + UChar* h = (UChar*)haystack; \ + UChar* n = (UChar*)needle; \ + \ + /* find the length of n, not including terminating zero */ \ + UWord nlen = 0; \ + while (n[nlen]) nlen++; \ + \ + /* if n is the empty string, match immediately. */ \ + if (nlen == 0) return h; \ + \ + /* assert(nlen >= 1); */ \ + UChar n0 = n[0]; \ + \ + while (1) { \ + UChar hh = *h; \ + if (hh == 0) return NULL; \ + if (hh != n0) { h++; continue; } \ + \ + UWord i; \ + for (i = 0; i < nlen; i++) { \ + if (n[i] != h[i]) \ + break; \ + } \ + /* assert(i >= 0 && i <= nlen); */ \ + if (i == nlen) \ + return h; \ + \ + h++; \ + } \ + } + +#if defined(VGO_linux) +STRSTR(VG_Z_LIBC_SONAME, strstr) +#endif + + +#define STRPBRK(soname, fnname) \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + (void* sV, void* acceptV); \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + (void* sV, void* acceptV) \ + { \ + UChar* s = (UChar*)sV; \ + UChar* accept = (UChar*)acceptV; \ + \ + /* find the length of 'accept', not including terminating zero */ \ + UWord nacc = 0; \ + while (accept[nacc]) nacc++; \ + \ + /* if n is the empty string, fail immediately. */ \ + if (nacc == 0) return NULL; \ + \ + /* assert(nacc >= 1); */ \ + while (1) { \ + UWord i; \ + UChar sc = *s; \ + if (sc == 0) \ + break; \ + for (i = 0; i < nacc; i++) { \ + if (sc == accept[i]) \ + return s; \ + } \ + s++; \ + } \ + \ + return NULL; \ + } + +#if defined(VGO_linux) +STRPBRK(VG_Z_LIBC_SONAME, strpbrk) +#endif + + +#define STRCSPN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + (void* sV, void* rejectV); \ + SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + (void* sV, void* rejectV) \ + { \ + UChar* s = (UChar*)sV; \ + UChar* reject = (UChar*)rejectV; \ + \ + /* find the length of 'reject', not including terminating zero */ \ + UWord nrej = 0; \ + while (reject[nrej]) nrej++; \ + \ + UWord len = 0; \ + while (1) { \ + UWord i; \ + UChar sc = *s; \ + if (sc == 0) \ + break; \ + for (i = 0; i < nrej; i++) { \ + if (sc == reject[i]) \ + break; \ + } \ + /* assert(i >= 0 && i <= nrej); */ \ + if (i < nrej) \ + break; \ + s++; \ + len++; \ + } \ + \ + return len; \ + } + +#if defined(VGO_linux) +STRCSPN(VG_Z_LIBC_SONAME, strcspn) +#endif + + /*------------------------------------------------------------*/ /*--- Improve definedness checking of process environment ---*/ /*------------------------------------------------------------*/