From: Julian Seward Date: Tue, 16 Aug 2011 21:45:28 +0000 (+0000) Subject: Fix for #275284 (initial fix, at least). Will break OSX; fix X-Git-Tag: svn/VALGRIND_3_7_0~252 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c61d1be73576dce38882b1ff346e0fd5699eb56;p=thirdparty%2Fvalgrind.git Fix for #275284 (initial fix, at least). Will break OSX; fix to follow. * add behavioural eclass tags for most functions in mc_replace_strmem.c and vg_replace_malloc.c. * add a wrapper for strspn() (see bug 270925) * coregrind/m_redir.c: add logic to use eclass tags for resolving conflicting redirections. Improve debug printing in that situation. * mc_replace_strmem.c: add a wrapper for "__GI___strcasecmp_l". Gark. Is this correct? Does __GI___strcasecmp_l behave the same as __GI_strcasecmp_l and strcasecmp_l ? git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11985 --- diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index 7208d394b8..dbed439c96 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -708,7 +708,7 @@ void generate_and_add_actives ( static void maybe_add_active ( Active act ) { HChar* what = NULL; - Active* old; + Active* old = NULL; /* Complain and ignore manifestly bogus 'from' addresses. @@ -735,10 +735,24 @@ static void maybe_add_active ( Active act ) /* Dodgy. Conflicting binding. */ vg_assert(old->from_addr == act.from_addr); if (old->to_addr != act.to_addr) { - /* we have to ignore it -- otherwise activeSet would contain - conflicting bindings. */ - what = "new redirection conflicts with existing -- ignoring it"; - goto bad; + /* We've got a conflicting binding -- that is, from_addr is + specified to redirect to two different destinations, + old->to_addr and act.to_addr. If we can prove that they + are behaviourally equivalent then that's no problem. So + we can look at the behavioural eclass tags for both + functions to see if that's so. If they are equal, and + nonzero, then that's fine. But if not, we can't show they + are equivalent, so we have to complain, and ignore the new + binding. */ + vg_assert(old->becTag >= 0 && old->becTag <= 9999); + vg_assert(act.becTag >= 0 && act.becTag <= 9999); + if (old->becTag != 0 && act.becTag != 0 && old->becTag == act.becTag) { + /* the replacements are behaviourally equivalent, so we can + safely ignore this conflict, and not add the new one. */ + } else { + what = "new redirection conflicts with existing -- ignoring it"; + goto bad; + } } else { /* This appears to be a duplicate of an existing binding. Safe(ish) -- ignore. */ @@ -765,6 +779,9 @@ static void maybe_add_active ( Active act ) vg_assert(what); if (VG_(clo_verbosity) > 1) { VG_(message)(Vg_UserMsg, "WARNING: %s\n", what); + if (old) { + show_active( " old: ", old); + } show_active( " new: ", &act); } } diff --git a/coregrind/m_replacemalloc/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c index 19b9f3be69..110e0e170d 100644 --- a/coregrind/m_replacemalloc/vg_replace_malloc.c +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c @@ -70,6 +70,32 @@ #include "pub_core_redir.h" // for VG_REPLACE_FUNCTION_* #include "pub_core_replacemalloc.h" +/* Assignment of behavioural equivalence class tags: 1NNN is intended + to be reserved for the Valgrind core. Current usage: + + 1001 ALLOC_or_NULL + 1002 ZONEALLOC_or_NULL + 1003 ALLOC_or_BOMB + 1004 ZONEFREE + 1005 FREE + 1006 ZONECALLOC + 1007 CALLOC + 1008 ZONEREALLOC + 1009 REALLOC + 1010 ZONEMEMALIGN + 1011 MEMALIGN + 1012 VALLOC + 1013 ZONEVALLOC + 1014 MALLOPT + 1015 MALLOC_TRIM + 1016 POSIX_MEMALIGN + 1017 MALLOC_USABLE_SIZE + 1018 PANIC + 1019 MALLOC_STATS + 1020 MALLINFO + 1021 DEFAULT_ZONE + 1022 ZONE_CHECK +*/ /* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style mangling, could be supported properly by the redirects in this @@ -172,8 +198,8 @@ static void init(void); */ #define ALLOC_or_NULL(soname, fnname, vg_replacement) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n) \ + void* VG_REPLACE_FUNCTION_EZU(1001,soname,fnname) (SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(1001,soname,fnname) (SizeT n) \ { \ void* v; \ \ @@ -187,8 +213,8 @@ static void init(void); #define ZONEALLOC_or_NULL(soname, fnname, vg_replacement) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, SizeT n); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, SizeT n) \ + void* VG_REPLACE_FUNCTION_EZU(1002,soname,fnname) (void *zone, SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(1002,soname,fnname) (void *zone, SizeT n) \ { \ void* v; \ \ @@ -207,8 +233,8 @@ static void init(void); */ #define ALLOC_or_BOMB(soname, fnname, vg_replacement) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n) \ + void* VG_REPLACE_FUNCTION_EZU(1003,soname,fnname) (SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(1003,soname,fnname) (SizeT n) \ { \ void* v; \ \ @@ -316,8 +342,8 @@ ALLOC_or_BOMB(VG_Z_LIBC_SONAME, __builtin_vec_new, __builtin_vec_new ); */ #define ZONEFREE(soname, fnname, vg_replacement) \ \ - void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, void *p); \ - void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, void *p) \ + void VG_REPLACE_FUNCTION_EZU(1004,soname,fnname) (void *zone, void *p); \ + void VG_REPLACE_FUNCTION_EZU(1004,soname,fnname) (void *zone, void *p) \ { \ if (!init_done) init(); \ MALLOC_TRACE(#vg_replacement "(%p, %p)\n", zone, p ); \ @@ -328,8 +354,8 @@ ALLOC_or_BOMB(VG_Z_LIBC_SONAME, __builtin_vec_new, __builtin_vec_new ); #define FREE(soname, fnname, vg_replacement) \ \ - void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p); \ - void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p) \ + void VG_REPLACE_FUNCTION_EZU(1005,soname,fnname) (void *p); \ + void VG_REPLACE_FUNCTION_EZU(1005,soname,fnname) (void *p) \ { \ if (!init_done) init(); \ MALLOC_TRACE(#vg_replacement "(%p)\n", p ); \ @@ -391,8 +417,10 @@ FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); #define ZONECALLOC(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT nmemb, SizeT size ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT nmemb, SizeT size ) \ + void* VG_REPLACE_FUNCTION_EZU(1006,soname,fnname) \ + ( void *zone, SizeT nmemb, SizeT size ); \ + void* VG_REPLACE_FUNCTION_EZU(1006,soname,fnname) \ + ( void *zone, SizeT nmemb, SizeT size ) \ { \ void* v; \ \ @@ -406,8 +434,10 @@ FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); #define CALLOC(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size ) \ + void* VG_REPLACE_FUNCTION_EZU(1007,soname,fnname) \ + ( SizeT nmemb, SizeT size ); \ + void* VG_REPLACE_FUNCTION_EZU(1007,soname,fnname) \ + ( SizeT nmemb, SizeT size ) \ { \ void* v; \ \ @@ -439,8 +469,10 @@ ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc); #define ZONEREALLOC(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, void* ptrV, SizeT new_size );\ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, void* ptrV, SizeT new_size ) \ + void* VG_REPLACE_FUNCTION_EZU(1008,soname,fnname) \ + ( void *zone, void* ptrV, SizeT new_size ); \ + void* VG_REPLACE_FUNCTION_EZU(1008,soname,fnname) \ + ( void *zone, void* ptrV, SizeT new_size ) \ { \ void* v; \ \ @@ -463,8 +495,10 @@ ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc); #define REALLOC(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size );\ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size ) \ + void* VG_REPLACE_FUNCTION_EZU(1009,soname,fnname) \ + ( void* ptrV, SizeT new_size );\ + void* VG_REPLACE_FUNCTION_EZU(1009,soname,fnname) \ + ( void* ptrV, SizeT new_size ) \ { \ void* v; \ \ @@ -474,9 +508,10 @@ ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc); if (ptrV == NULL) \ /* We need to call a malloc-like function; so let's use \ one which we know exists. */ \ - return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,malloc) (new_size); \ + return VG_REPLACE_FUNCTION_EZU(1001,VG_Z_LIBC_SONAME,malloc) \ + (new_size); \ if (new_size <= 0) { \ - VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,free)(ptrV); \ + VG_REPLACE_FUNCTION_EZU(1005,VG_Z_LIBC_SONAME,free)(ptrV); \ MALLOC_TRACE(" = 0\n"); \ return NULL; \ } \ @@ -495,8 +530,10 @@ ZONEREALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc); #define ZONEMEMALIGN(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT alignment, SizeT n ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT alignment, SizeT n ) \ + void* VG_REPLACE_FUNCTION_EZU(1010,soname,fnname) \ + ( void *zone, SizeT alignment, SizeT n ); \ + void* VG_REPLACE_FUNCTION_EZU(1010,soname,fnname) \ + ( void *zone, SizeT alignment, SizeT n ) \ { \ void* v; \ \ @@ -518,8 +555,10 @@ ZONEREALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc); #define MEMALIGN(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n ) \ + void* VG_REPLACE_FUNCTION_EZU(1011,soname,fnname) \ + ( SizeT alignment, SizeT n ); \ + void* VG_REPLACE_FUNCTION_EZU(1011,soname,fnname) \ + ( SizeT alignment, SizeT n ) \ { \ void* v; \ \ @@ -549,20 +588,22 @@ ZONEMEMALIGN(VG_Z_LIBC_SONAME, malloc_zone_memalign); #define VALLOC(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ) \ + void* VG_REPLACE_FUNCTION_EZU(1012,soname,fnname) ( SizeT size ); \ + void* VG_REPLACE_FUNCTION_EZU(1012,soname,fnname) ( SizeT size ) \ { \ static int pszB = 0; \ if (pszB == 0) \ pszB = my_getpagesize(); \ - return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,memalign) \ + return VG_REPLACE_FUNCTION_EZU(1011,VG_Z_LIBC_SONAME,memalign) \ ((SizeT)pszB, size); \ } #define ZONEVALLOC(soname, fnname) \ \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT size ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT size ) \ + void* VG_REPLACE_FUNCTION_EZU(1013,soname,fnname) \ + ( void *zone, SizeT size ); \ + void* VG_REPLACE_FUNCTION_EZU(1013,soname,fnname) \ + ( void *zone, SizeT size ) \ { \ static int pszB = 0; \ if (pszB == 0) \ @@ -583,8 +624,8 @@ ZONEVALLOC(VG_Z_LIBC_SONAME, malloc_zone_valloc); #define MALLOPT(soname, fnname) \ \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value ); \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value ) \ + int VG_REPLACE_FUNCTION_EZU(1014,soname,fnname) ( int cmd, int value ); \ + int VG_REPLACE_FUNCTION_EZU(1014,soname,fnname) ( int cmd, int value ) \ { \ /* In glibc-2.2.4, 1 denotes a successful return value for \ mallopt */ \ @@ -619,8 +660,8 @@ MALLOPT(VG_Z_LIBC_SONAME, mallopt); // For simplicity, we always return 0. #define MALLOC_TRIM(soname, fnname) \ \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad ); \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad ) \ + int VG_REPLACE_FUNCTION_EZU(1015,soname,fnname) ( SizeT pad ); \ + int VG_REPLACE_FUNCTION_EZU(1015,soname,fnname) ( SizeT pad ) \ { \ /* 0 denotes that malloc_trim() either wasn't able \ to do anything, or was not implemented */ \ @@ -634,10 +675,10 @@ MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim); #define POSIX_MEMALIGN(soname, fnname) \ \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \ - SizeT alignment, SizeT size ); \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \ - SizeT alignment, SizeT size ) \ + int VG_REPLACE_FUNCTION_EZU(1016,soname,fnname) \ + ( void **memptr, SizeT alignment, SizeT size ); \ + int VG_REPLACE_FUNCTION_EZU(1016,soname,fnname) \ + ( void **memptr, SizeT alignment, SizeT size ) \ { \ void *mem; \ \ @@ -647,7 +688,8 @@ MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim); || (alignment & (alignment - 1)) != 0) \ return VKI_EINVAL; \ \ - mem = VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,memalign)(alignment, size); \ + mem = VG_REPLACE_FUNCTION_EZU(1011,VG_Z_LIBC_SONAME,memalign) \ + (alignment, size); \ \ if (mem != NULL) { \ *memptr = mem; \ @@ -664,8 +706,8 @@ POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign); #define MALLOC_USABLE_SIZE(soname, fnname) \ \ - SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p ) \ + SizeT VG_REPLACE_FUNCTION_EZU(1017,soname,fnname) ( void* p ); \ + SizeT VG_REPLACE_FUNCTION_EZU(1017,soname,fnname) ( void* p ) \ { \ SizeT pszB; \ \ @@ -697,8 +739,8 @@ static void panic(const char *str) #define PANIC(soname, fnname) \ \ - void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \ - void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \ + void VG_REPLACE_FUNCTION_EZU(1018,soname,fnname) ( void ); \ + void VG_REPLACE_FUNCTION_EZU(1018,soname,fnname) ( void ) \ { \ panic(#fnname); \ } @@ -709,8 +751,8 @@ PANIC(VG_Z_LIBC_SONAME, malloc_set_state); #define MALLOC_STATS(soname, fnname) \ \ - void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \ - void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \ + void VG_REPLACE_FUNCTION_EZU(1019,soname,fnname) ( void ); \ + void VG_REPLACE_FUNCTION_EZU(1019,soname,fnname) ( void ) \ { \ /* Valgrind's malloc_stats implementation does nothing. */ \ } @@ -725,8 +767,8 @@ MALLOC_STATS(VG_Z_LIBC_SONAME, malloc_stats); // doesn't know that the call to mallinfo fills in mi. #define MALLINFO(soname, fnname) \ \ - struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \ - struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \ + struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(1020,soname,fnname) ( void ); \ + struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(1020,soname,fnname) ( void ) \ { \ static struct vg_mallinfo mi; \ if (!init_done) init(); \ @@ -763,8 +805,8 @@ static vki_malloc_zone_t vg_default_zone = { #define DEFAULT_ZONE(soname, fnname) \ \ - void *VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \ - void *VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \ + void *VG_REPLACE_FUNCTION_EZU(1021,soname,fnname) ( void ); \ + void *VG_REPLACE_FUNCTION_EZU(1021,soname,fnname) ( void ) \ { \ return &vg_default_zone; \ } @@ -776,9 +818,9 @@ DEFAULT_ZONE(VG_Z_LIBC_SONAME, malloc_default_zone); // GrP fixme bypass libc's use of zone->introspect->check #define ZONE_CHECK(soname, fnname) \ - \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname)(void* zone); \ - int VG_REPLACE_FUNCTION_ZU(soname, fnname)(void* zone) \ + \ + int VG_REPLACE_FUNCTION_EZU(1022,soname,fnname)(void* zone); \ + int VG_REPLACE_FUNCTION_EZU(1022,soname,fnname)(void* zone) \ { \ return 1; \ } diff --git a/memcheck/mc_replace_strmem.c b/memcheck/mc_replace_strmem.c index 782e492f35..9b8dba971e 100644 --- a/memcheck/mc_replace_strmem.c +++ b/memcheck/mc_replace_strmem.c @@ -53,6 +53,45 @@ THEY RUN ON THE SIMD CPU! ------------------------------------------------------------------ */ +/* Assignment of behavioural equivalence class tags: 2NNN is intended + to be reserved for Memcheck. Current usage: + + 2001 STRRCHR + 2002 STRCHR + 2003 STRCAT + 2004 STRNCAT + 2005 STRLCAT + 2006 STRNLEN + 2007 STRLEN + 2008 STRCPY + 2009 STRNCPY + 2010 STRLCPY + 2011 STRNCMP + 2012 STRCASECMP + 2013 STRNCASECMP + 2014 STRCASECMP_L + 2015 STRNCASECMP_L + 2016 STRCMP + 2017 MEMCHR + 2018 MEMMOVE + 2019 MEMCMP + 2020 STPCPY + 2021 MEMSET + 2022 MEMCPY + 2023 BCOPY + 2024 GLIBC25___MEMMOVE_CHK + 2025 GLIBC232_STRCHRNUL + 2026 GLIBC232_RAWMEMCHR + 2027 GLIBC25___STRCPY_CHK + 2028 GLIBC25___STPCPY_CHK + 2029 GLIBC25_MEMPCPY + 2030 GLIBC26___MEMCPY_CHK + 2031 STRSTR + 2032 STRPBRK + 2033 STRCSPN + 2034 STRSPN +*/ + /* Figure out if [dst .. dst+dstlen-1] overlaps with [src .. src+srclen-1]. @@ -113,8 +152,8 @@ static inline void my_exit ( int x ) #define STRRCHR(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \ + char* VG_REPLACE_FUNCTION_EZU(2001,soname,fnname)( const char* s, int c ); \ + char* VG_REPLACE_FUNCTION_EZU(2001,soname,fnname)( const char* s, int c ) \ { \ UChar ch = (UChar)((UInt)c); \ UChar* p = (UChar*)s; \ @@ -139,8 +178,8 @@ STRRCHR(VG_Z_DYLD, rindex) #define STRCHR(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \ + char* VG_REPLACE_FUNCTION_EZU(2002,soname,fnname) ( const char* s, int c ); \ + char* VG_REPLACE_FUNCTION_EZU(2002,soname,fnname) ( const char* s, int c ) \ { \ UChar ch = (UChar)((UInt)c); \ UChar* p = (UChar*)s; \ @@ -167,8 +206,10 @@ STRCHR(VG_Z_DYLD, index) #define STRCAT(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \ + char* VG_REPLACE_FUNCTION_EZU(2003,soname,fnname) \ + ( char* dst, const char* src ); \ + char* VG_REPLACE_FUNCTION_EZU(2003,soname,fnname) \ + ( char* dst, const char* src ) \ { \ const Char* src_orig = src; \ Char* dst_orig = dst; \ @@ -193,9 +234,9 @@ STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) #endif #define STRNCAT(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + char* VG_REPLACE_FUNCTION_EZU(2004,soname,fnname) \ ( char* dst, const char* src, SizeT n ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + char* VG_REPLACE_FUNCTION_EZU(2004,soname,fnname) \ ( char* dst, const char* src, SizeT n ) \ { \ const Char* src_orig = src; \ @@ -210,7 +251,7 @@ STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) /* pre-counting lengths... should be ok */ \ if (is_overlap(dst_orig, \ src_orig, \ - (Addr)dst-(Addr)dst_orig+1, \ + (Addr)dst-(Addr)dst_orig+1, \ (Addr)src-(Addr)src_orig+1)) \ RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \ \ @@ -229,15 +270,15 @@ STRNCAT(VG_Z_DYLD, strncat) Truncation occurred if retval >= n. */ #define STRLCAT(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(2005,soname,fnname) \ ( char* dst, const char* src, SizeT n ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(2005,soname,fnname) \ ( char* dst, const char* src, SizeT n ) \ { \ const Char* src_orig = src; \ Char* dst_orig = dst; \ SizeT m = 0; \ -\ + \ while (m < n && *dst) { m++; dst++; } \ if (m < n) { \ /* Fill as far as dst_orig[n-2], then nul-terminate. */ \ @@ -255,7 +296,7 @@ STRNCAT(VG_Z_DYLD, strncat) (Addr)dst-(Addr)dst_orig+1, \ (Addr)src-(Addr)src_orig+1)) \ RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \ -\ + \ return m; \ } @@ -266,8 +307,10 @@ STRLCAT(VG_Z_DYLD, strlcat) #define STRNLEN(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \ + SizeT VG_REPLACE_FUNCTION_EZU(2006,soname,fnname) \ + ( const char* str, SizeT n ); \ + SizeT VG_REPLACE_FUNCTION_EZU(2006,soname,fnname) \ + ( const char* str, SizeT n ) \ { \ SizeT i = 0; \ while (i < n && str[i] != 0) i++; \ @@ -285,8 +328,10 @@ STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen) // confusing if you aren't expecting it. Other small functions in this file // may also be inline by gcc. #define STRLEN(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \ + SizeT VG_REPLACE_FUNCTION_EZU(2007,soname,fnname) \ + ( const char* str ); \ + SizeT VG_REPLACE_FUNCTION_EZU(2007,soname,fnname) \ + ( const char* str ) \ { \ SizeT i = 0; \ while (str[i] != 0) i++; \ @@ -296,14 +341,14 @@ STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen) STRLEN(VG_Z_LIBC_SONAME, strlen) #if defined(VGO_linux) STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) -STRLEN(VG_Z_LD_LINUX_SO_2, strlen) -STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen) #endif #define STRCPY(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \ - char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \ + char* VG_REPLACE_FUNCTION_EZU(2008,soname,fnname) \ + ( char* dst, const char* src ); \ + char* VG_REPLACE_FUNCTION_EZU(2008,soname,fnname) \ + ( char* dst, const char* src ) \ { \ const Char* src_orig = src; \ Char* dst_orig = dst; \ @@ -315,7 +360,7 @@ STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen) /* pre-counting length... should be ok */ \ if (is_overlap(dst_orig, \ src_orig, \ - (Addr)dst-(Addr)dst_orig+1, \ + (Addr)dst-(Addr)dst_orig+1, \ (Addr)src-(Addr)src_orig+1)) \ RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \ \ @@ -331,9 +376,9 @@ STRCPY(VG_Z_DYLD, strcpy) #define STRNCPY(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(2009,soname,fnname) \ ( char* dst, const char* src, SizeT n ); \ - char* VG_REPLACE_FUNCTION_ZU(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(2009,soname,fnname) \ ( char* dst, const char* src, SizeT n ) \ { \ const Char* src_orig = src; \ @@ -361,15 +406,15 @@ STRNCPY(VG_Z_DYLD, strncpy) /* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0. Returns strlen(src). Does not zero-fill the remainder of dst. */ #define STRLCPY(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(2010,soname,fnname) \ ( char* dst, const char* src, SizeT n ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(2010,soname,fnname) \ ( char* dst, const char* src, SizeT n ) \ { \ const char* src_orig = src; \ char* dst_orig = dst; \ SizeT m = 0; \ -\ + \ while (m < n-1 && *src) { m++; *dst++ = *src++; } \ /* m non-nul bytes have now been copied, and m <= n-1. */ \ /* Check for overlap after copying; all n bytes of dst are relevant, */ \ @@ -390,9 +435,9 @@ STRLCPY(VG_Z_DYLD, strlcpy) #define STRNCMP(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2011,soname,fnname) \ ( const char* s1, const char* s2, SizeT nmax ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2011,soname,fnname) \ ( const char* s1, const char* s2, SizeT nmax ) \ { \ SizeT n = 0; \ @@ -418,9 +463,9 @@ STRNCMP(VG_Z_DYLD, strncmp) #define STRCASECMP(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2012,soname,fnname) \ ( const char* s1, const char* s2 ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2012,soname,fnname) \ ( const char* s1, const char* s2 ) \ { \ extern int tolower(int); \ @@ -447,9 +492,9 @@ STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp) #define STRNCASECMP(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2013,soname,fnname) \ ( const char* s1, const char* s2, SizeT nmax ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2013,soname,fnname) \ ( const char* s1, const char* s2, SizeT nmax ) \ { \ extern int tolower(int); \ @@ -460,8 +505,10 @@ STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp) if (*s1 == 0) return -1; \ if (*s2 == 0) return 1; \ \ - if (tolower(*(unsigned char*)s1) < tolower(*(unsigned char*)s2)) return -1; \ - if (tolower(*(unsigned char*)s1) > tolower(*(unsigned char*)s2)) return 1; \ + if (tolower(*(unsigned char*)s1) \ + < tolower(*(unsigned char*)s2)) return -1; \ + if (tolower(*(unsigned char*)s1) \ + > tolower(*(unsigned char*)s2)) return 1; \ \ s1++; s2++; n++; \ } \ @@ -478,9 +525,9 @@ STRNCASECMP(VG_Z_DYLD, strncasecmp) #define STRCASECMP_L(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2014,soname,fnname) \ ( const char* s1, const char* s2, void* locale ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2014,soname,fnname) \ ( const char* s1, const char* s2, void* locale ) \ { \ extern int tolower_l(int, void*) __attribute__((weak)); \ @@ -501,13 +548,14 @@ STRNCASECMP(VG_Z_DYLD, strncasecmp) STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) #if defined(VGO_linux) STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l) +STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l) #endif #define STRNCASECMP_L(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2015,soname,fnname) \ ( const char* s1, const char* s2, SizeT nmax, void* locale ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2015,soname,fnname) \ ( const char* s1, const char* s2, SizeT nmax, void* locale ) \ { \ extern int tolower_l(int, void*) __attribute__((weak)); \ @@ -518,8 +566,10 @@ STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l) if (*s1 == 0) return -1; \ if (*s2 == 0) return 1; \ \ - if (tolower_l(*(unsigned char*)s1, locale) < tolower_l(*(unsigned char*)s2, locale)) return -1; \ - if (tolower_l(*(unsigned char*)s1, locale) > tolower_l(*(unsigned char*)s2, locale)) return 1; \ + if (tolower_l(*(unsigned char*)s1, locale) \ + < tolower_l(*(unsigned char*)s2, locale)) return -1; \ + if (tolower_l(*(unsigned char*)s1, locale) \ + > tolower_l(*(unsigned char*)s2, locale)) return 1; \ \ s1++; s2++; n++; \ } \ @@ -534,9 +584,9 @@ STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l) #define STRCMP(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2016,soname,fnname) \ ( const char* s1, const char* s2 ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2016,soname,fnname) \ ( const char* s1, const char* s2 ) \ { \ register unsigned char c1; \ @@ -562,8 +612,10 @@ STRCMP(VG_Z_LD64_SO_1, strcmp) #define MEMCHR(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \ + void* VG_REPLACE_FUNCTION_EZU(2017,soname,fnname) \ + (const void *s, int c, SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(2017,soname,fnname) \ + (const void *s, int c, SizeT n) \ { \ SizeT i; \ UChar c0 = (UChar)c; \ @@ -579,13 +631,13 @@ MEMCHR(VG_Z_DYLD, memchr) #endif -#define MEMCPY(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ +#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \ + void* VG_REPLACE_FUNCTION_EZU(becTag,soname,fnname) \ ( void *dst, const void *src, SizeT len ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(becTag,soname,fnname) \ ( void *dst, const void *src, SizeT len ) \ { \ - if (is_overlap(dst, src, len, len)) \ + if (do_ol_check && is_overlap(dst, src, len, len)) \ RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \ \ const Addr WS = sizeof(UWord); /* 8 or 4 */ \ @@ -650,11 +702,20 @@ MEMCHR(VG_Z_DYLD, memchr) return dst; \ } -MEMCPY(VG_Z_LIBC_SONAME, memcpy) +#define MEMMOVE(soname, fnname) \ + MEMMOVE_OR_MEMCPY(2018, soname, fnname, 0) + +#define MEMCPY(soname, fnname) \ + MEMMOVE_OR_MEMCPY(2022, soname, fnname, 1) + #if defined(VGO_linux) -MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ -MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ +/* For older memcpy we have to use memmove-like semantics and skip the + overlap check; sigh; see #275284. */ +MEMMOVE(VG_Z_LIBC_SONAME, memcpy) +MEMMOVE(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ +MEMMOVE(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ #elif defined(VGO_darwin) +MEMCPY(VG_Z_LIBC_SONAME, memcpy) MEMCPY(VG_Z_DYLD, memcpy) #endif /* icc9 blats these around all over the place. Not only in the main @@ -669,10 +730,10 @@ MEMCPY(NONE, _intel_fast_memcpy) #define MEMCMP(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + int VG_REPLACE_FUNCTION_EZU(2019,soname,fnname) \ ( const void *s1V, const void *s2V, SizeT n ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - ( const void *s1V, const void *s2V, SizeT n ) \ + int VG_REPLACE_FUNCTION_EZU(2019,soname,fnname) \ + ( const void *s1V, const void *s2V, SizeT n ) \ { \ int res; \ unsigned char a0; \ @@ -706,8 +767,10 @@ MEMCMP(VG_Z_DYLD, bcmp) /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. (minor variant of strcpy) */ #define STPCPY(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \ + char* VG_REPLACE_FUNCTION_EZU(2020,soname,fnname) \ + ( char* dst, const char* src ); \ + char* VG_REPLACE_FUNCTION_EZU(2020,soname,fnname) \ + ( char* dst, const char* src ) \ { \ const Char* src_orig = src; \ Char* dst_orig = dst; \ @@ -737,8 +800,10 @@ STPCPY(VG_Z_DYLD, stpcpy) #define MEMSET(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \ + void* VG_REPLACE_FUNCTION_EZU(2021,soname,fnname) \ + (void *s, Int c, SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(2021,soname,fnname) \ + (void *s, Int c, SizeT n) \ { \ Addr a = (Addr)s; \ UInt c4 = (c & 0xFF); \ @@ -759,27 +824,7 @@ MEMSET(VG_Z_DYLD, memset) #endif -#define MEMMOVE(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (void *dstV, const void *srcV, SizeT n); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (void *dstV, const void *srcV, SizeT n) \ - { \ - SizeT i; \ - Char* dst = (Char*)dstV; \ - Char* src = (Char*)srcV; \ - if (dst < src) { \ - for (i = 0; i < n; i++) \ - dst[i] = src[i]; \ - } \ - else \ - if (dst > src) { \ - for (i = 0; i < n; i++) \ - dst[n-i-1] = src[n-i-1]; \ - } \ - return dst; \ - } - +/* memmove -- use the MEMMOVE defn which also serves for memcpy. */ MEMMOVE(VG_Z_LIBC_SONAME, memmove) #if defined(VGO_darwin) MEMMOVE(VG_Z_DYLD, memmove) @@ -787,9 +832,9 @@ MEMMOVE(VG_Z_DYLD, memmove) #define BCOPY(soname, fnname) \ - void VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void VG_REPLACE_FUNCTION_EZU(2023,soname,fnname) \ (const void *srcV, void *dstV, SizeT n); \ - void VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void VG_REPLACE_FUNCTION_EZU(2023,soname,fnname) \ (const void *srcV, void *dstV, SizeT n) \ { \ SizeT i; \ @@ -815,9 +860,9 @@ BCOPY(VG_Z_DYLD, bcopy) /* glibc 2.5 variant of memmove which checks the dest is big enough. There is no specific part of glibc that this is copied from. */ #define GLIBC25___MEMMOVE_CHK(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2024,soname,fnname) \ (void *dstV, const void *srcV, SizeT n, SizeT destlen); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2024,soname,fnname) \ (void *dstV, const void *srcV, SizeT n, SizeT destlen) \ { \ SizeT i; \ @@ -849,8 +894,10 @@ GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk) /* Find the first occurrence of C in S or the final NUL byte. */ #define GLIBC232_STRCHRNUL(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \ + char* VG_REPLACE_FUNCTION_EZU(2025,soname,fnname) \ + (const char* s, int c_in); \ + char* VG_REPLACE_FUNCTION_EZU(2025,soname,fnname) \ + (const char* s, int c_in) \ { \ unsigned char c = (unsigned char) c_in; \ unsigned char* char_ptr = (unsigned char *)s; \ @@ -866,8 +913,10 @@ GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul) /* Find the first occurrence of C in S. */ #define GLIBC232_RAWMEMCHR(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \ + char* VG_REPLACE_FUNCTION_EZU(2026,soname,fnname) \ + (const char* s, int c_in); \ + char* VG_REPLACE_FUNCTION_EZU(2026,soname,fnname) \ + (const char* s, int c_in) \ { \ unsigned char c = (unsigned char) c_in; \ unsigned char* char_ptr = (unsigned char *)s; \ @@ -885,10 +934,10 @@ GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) /* glibc variant of strcpy that checks the dest is big enough. Copied from glibc-2.5/debug/test-strcpy_chk.c. */ #define GLIBC25___STRCPY_CHK(soname,fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (char* dst, const char* src, SizeT len); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (char* dst, const char* src, SizeT len) \ + char* VG_REPLACE_FUNCTION_EZU(2027,soname,fnname) \ + (char* dst, const char* src, SizeT len); \ + char* VG_REPLACE_FUNCTION_EZU(2027,soname,fnname) \ + (char* dst, const char* src, SizeT len) \ { \ char* ret = dst; \ if (! len) \ @@ -912,10 +961,10 @@ GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk) /* glibc variant of stpcpy that checks the dest is big enough. Copied from glibc-2.5/debug/test-stpcpy_chk.c. */ #define GLIBC25___STPCPY_CHK(soname,fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (char* dst, const char* src, SizeT len); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (char* dst, const char* src, SizeT len) \ + char* VG_REPLACE_FUNCTION_EZU(2028,soname,fnname) \ + (char* dst, const char* src, SizeT len); \ + char* VG_REPLACE_FUNCTION_EZU(2028,soname,fnname) \ + (char* dst, const char* src, SizeT len) \ { \ if (! len) \ goto badness; \ @@ -937,9 +986,9 @@ GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk) /* mempcpy */ #define GLIBC25_MEMPCPY(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2029,soname,fnname) \ ( void *dst, const void *src, SizeT len ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2029,soname,fnname) \ ( void *dst, const void *src, SizeT len ) \ { \ register char *d; \ @@ -975,9 +1024,9 @@ GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */ #define GLIBC26___MEMCPY_CHK(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2030,soname,fnname) \ (void* dst, const void* src, SizeT len, SizeT dstlen ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2030,soname,fnname) \ (void* dst, const void* src, SizeT len, SizeT dstlen ) \ { \ register char *d; \ @@ -1018,9 +1067,9 @@ GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk) #define STRSTR(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2031,soname,fnname) \ (void* haystack, void* needle); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2031,soname,fnname) \ (void* haystack, void* needle) \ { \ UChar* h = (UChar*)haystack; \ @@ -1060,9 +1109,9 @@ STRSTR(VG_Z_LIBC_SONAME, strstr) #define STRPBRK(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2032,soname,fnname) \ (void* sV, void* acceptV); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + void* VG_REPLACE_FUNCTION_EZU(2032,soname,fnname) \ (void* sV, void* acceptV) \ { \ UChar* s = (UChar*)sV; \ @@ -1097,9 +1146,9 @@ STRPBRK(VG_Z_LIBC_SONAME, strpbrk) #define STRCSPN(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(2033,soname,fnname) \ (void* sV, void* rejectV); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(2033,soname,fnname) \ (void* sV, void* rejectV) \ { \ UChar* s = (UChar*)sV; \ @@ -1134,34 +1183,43 @@ STRCSPN(VG_Z_LIBC_SONAME, strcspn) #endif -// And here's a validated strspn replacement, should it -// become necessary. -//UWord mystrspn( UChar* s, UChar* accept ) -//{ -// /* find the length of 'accept', not including terminating zero */ -// UWord nacc = 0; -// while (accept[nacc]) nacc++; -// if (nacc == 0) return 0; -// -// UWord len = 0; -// while (1) { -// UWord i; -// UChar sc = *s; -// if (sc == 0) -// break; -// for (i = 0; i < nacc; i++) { -// if (sc == accept[i]) -// break; -// } -// assert(i >= 0 && i <= nacc); -// if (i == nacc) -// break; -// s++; -// len++; -// } -// -// return len; -//} +#define STRSPN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(2034,soname,fnname) \ + (void* sV, void* acceptV); \ + SizeT VG_REPLACE_FUNCTION_EZU(2034,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 (nacc == 0) return 0; \ + \ + UWord len = 0; \ + while (1) { \ + UWord i; \ + UChar sc = *s; \ + if (sc == 0) \ + break; \ + for (i = 0; i < nacc; i++) { \ + if (sc == accept[i]) \ + break; \ + } \ + /* assert(i >= 0 && i <= nacc); */ \ + if (i == nacc) \ + break; \ + s++; \ + len++; \ + } \ + \ + return len; \ + } + +#if defined(VGO_linux) +STRSPN(VG_Z_LIBC_SONAME, strspn) +#endif /*------------------------------------------------------------*/ @@ -1170,6 +1228,10 @@ STRCSPN(VG_Z_LIBC_SONAME, strcspn) #if defined(VGO_linux) +/* If these wind up getting generated via a macro, so that multiple + versions of each function exist (as above), use the _EZU variants + to assign equivalance class tags. */ + /* putenv */ int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string); int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string)