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
This commit is contained in:
Julian Seward 2010-08-19 13:22:34 +00:00
parent ebe90cdda2
commit 9a8dd3161a

View File

@ -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 ---*/
/*------------------------------------------------------------*/