Extend the behavioural-equivalence-class mechanism for redirection

functions to include the ability to give a priority to each function,
as well as a tag indicating its behavioural class.  Add logic in
m_redir.c to resolve conflicting redirections with the same eclass but
different priorities by preferring the redirection with the higher
priority.  Use all of the above in mc_replace_strmem.c, to cause a
conflict between redirections for "memcpy" and "memcpy@GLIBC_2.2.5" to
be resolved in favour of the latter (the non-overlap-checking
version).

This is all related to the massive swamp that is #275284.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11991
This commit is contained in:
Julian Seward 2011-08-18 13:09:55 +00:00
parent 3cc26a2ef6
commit e1567da7c5
7 changed files with 316 additions and 246 deletions

View File

@ -100,7 +100,7 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
interested in that). */
if (do_z_demangling) {
if (VG_(maybe_Z_demangle)( orig, NULL,0,/*soname*/
z_demangled, N_ZBUF, NULL, NULL )) {
z_demangled, N_ZBUF, NULL, NULL, NULL )) {
orig = z_demangled;
}
}
@ -147,7 +147,8 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym,
/*OUT*/HChar* so, Int soLen,
/*OUT*/HChar* fn, Int fnLen,
/*OUT*/Bool* isWrap,
/*OUT*/Int* eclassTag )
/*OUT*/Int* eclassTag,
/*OUT*/Int* eclassPrio )
{
# define EMITSO(ch) \
do { \
@ -181,24 +182,28 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym,
valid = sym[0] == '_'
&& sym[1] == 'v'
&& sym[2] == 'g'
&& (sym[3] == 'r' || sym[3] == 'w' || sym[3] == 'n')
&& (sym[3] == 'r' || sym[3] == 'w')
&& VG_(isdigit)(sym[4])
&& VG_(isdigit)(sym[5])
&& VG_(isdigit)(sym[6])
&& VG_(isdigit)(sym[7])
&& sym[8] == 'Z'
&& (sym[9] == 'Z' || sym[9] == 'U')
&& sym[10] == '_';
if (valid && sym[3] == 'n') {
/* for _vgn (notify-on-load symbols), the equivalence class has
no meaning; hence ensure it is the default 0000 value. */
if (sym[4] != '0' || sym[5] != '0' || sym[6] != '0' || sym[7] != '0')
valid = False;
&& VG_(isdigit)(sym[8])
&& sym[9] == 'Z'
&& (sym[10] == 'Z' || sym[10] == 'U')
&& sym[11] == '_';
if (valid
&& sym[4] == '0' && sym[5] == '0' && sym[6] == '0' && sym[7] == '0'
&& sym[8] != '0') {
/* If the eclass tag is 0000 (meaning "no eclass"), the priority
must be 0 too. */
valid = False;
}
if (!valid)
return False;
fn_is_encoded = sym[9] == 'Z';
fn_is_encoded = sym[10] == 'Z';
if (isWrap)
*isWrap = sym[3] == 'w';
@ -211,21 +216,26 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym,
vg_assert(*eclassTag >= 0 && *eclassTag <= 9999);
}
if (eclassPrio) {
*eclassPrio = ((Int)sym[8]) - '0';
vg_assert(*eclassPrio >= 0 && *eclassPrio <= 9);
}
/* Now check the soname prefix isn't "VG_Z_", as described in
pub_tool_redir.h. */
is_VG_Z_prefixed =
sym[11] == 'V' &&
sym[12] == 'G' &&
sym[13] == '_' &&
sym[14] == 'Z' &&
sym[15] == '_';
sym[12] == 'V' &&
sym[13] == 'G' &&
sym[14] == '_' &&
sym[15] == 'Z' &&
sym[16] == '_';
if (is_VG_Z_prefixed) {
vg_assert2(0, "symbol with a 'VG_Z_' prefix: %s.\n"
"see pub_tool_redir.h for an explanation.", sym);
}
/* Now scan the Z-encoded soname. */
i = 11;
i = 12;
while (True) {
if (sym[i] == '_')

View File

@ -233,6 +233,9 @@ typedef
Int becTag; /* 0 through 9999. Behavioural equivalance class tag.
If two wrappers have the same (non-zero) tag, they
are promising that they behave identically. */
Int becPrio; /* 0 through 9. Behavioural equivalence class prio.
Used to choose between competing wrappers with
the same (non-zero) tag. */
const HChar** mandatory; /* non-NULL ==> abort V and print the
strings if from_sopatt is loaded but
from_fnpatt cannot be found */
@ -278,6 +281,7 @@ typedef
TopSpec* parent_spec; /* the TopSpec which supplied the Spec */
TopSpec* parent_sym; /* the TopSpec which supplied the symbol */
Int becTag; /* behavioural eclass tag for ::to_addr */
Int becPrio; /* and its priority */
Bool isWrap; /* wrap or replacement? */
Bool isIFunc; /* indirect function? */
}
@ -371,7 +375,7 @@ static void free_symname_array ( UChar** names, UChar** twoslots )
void VG_(redir_notify_new_DebugInfo)( DebugInfo* newdi )
{
Bool ok, isWrap;
Int i, nsyms, becTag;
Int i, nsyms, becTag, becPrio;
Spec* specList;
Spec* spec;
TopSpec* ts;
@ -416,7 +420,7 @@ void VG_(redir_notify_new_DebugInfo)( DebugInfo* newdi )
ok = VG_(maybe_Z_demangle)( *names,
demangled_sopatt, N_DEMANGLED,
demangled_fnpatt, N_DEMANGLED,
&isWrap, &becTag );
&isWrap, &becTag, &becPrio );
/* ignore data symbols */
if (!isText)
continue;
@ -442,6 +446,7 @@ void VG_(redir_notify_new_DebugInfo)( DebugInfo* newdi )
spec->to_addr = sym_addr;
spec->isWrap = isWrap;
spec->becTag = becTag;
spec->becPrio = becPrio;
/* check we're not adding manifestly stupid destinations */
vg_assert(is_plausible_guest_addr(sym_addr));
spec->next = specList;
@ -465,7 +470,7 @@ void VG_(redir_notify_new_DebugInfo)( DebugInfo* newdi )
ok = isText
&& VG_(maybe_Z_demangle)(
*names, demangled_sopatt, N_DEMANGLED,
demangled_fnpatt, N_DEMANGLED, &isWrap, NULL );
demangled_fnpatt, N_DEMANGLED, &isWrap, NULL, NULL );
if (!ok)
/* not a redirect. Ignore. */
continue;
@ -640,6 +645,7 @@ void generate_and_add_actives (
act.parent_spec = parent_spec;
act.parent_sym = parent_sym;
act.becTag = sp->becTag;
act.becPrio = sp->becPrio;
act.isWrap = sp->isWrap;
act.isIFunc = isIFunc;
sp->done = True;
@ -707,8 +713,9 @@ void generate_and_add_actives (
conflicting bindings. */
static void maybe_add_active ( Active act )
{
HChar* what = NULL;
Active* old = NULL;
HChar* what = NULL;
Active* old = NULL;
Bool add_act = False;
/* Complain and ignore manifestly bogus 'from' addresses.
@ -744,26 +751,63 @@ static void maybe_add_active ( Active act )
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. */
vg_assert(old->becTag >= 0 && old->becTag <= 9999);
vg_assert(old->becPrio >= 0 && old->becPrio <= 9);
vg_assert(act.becTag >= 0 && act.becTag <= 9999);
vg_assert(act.becPrio >= 0 && act.becPrio <= 9);
if (old->becTag == 0)
vg_assert(old->becPrio == 0);
if (act.becTag == 0)
vg_assert(act.becPrio == 0);
if (old->becTag == 0 || act.becTag == 0 || old->becTag != act.becTag) {
/* We can't show that they are equivalent. Complain and
ignore. */
what = "new redirection conflicts with existing -- ignoring it";
goto bad;
}
/* They have the same eclass tag. Use the priorities to
resolve the ambiguity. */
if (act.becPrio <= old->becPrio) {
/* The new one doesn't have a higher priority, so just
ignore it. */
if (VG_(clo_verbosity) > 2) {
VG_(message)(Vg_UserMsg, "Ignoring duplicate redirection:\n");
VG_(message)(Vg_UserMsg, "Ignoring %s redirection:\n",
act.becPrio < old->becPrio ? "lower priority"
: "duplicate");
show_active( " old: ", old);
show_active( " new: ", &act);
}
} else {
what = "new redirection conflicts with existing -- ignoring it";
goto bad;
/* The tricky case. The new one has a higher priority, so
we need to get the old one out of the OSet and install
this one in its place. */
if (VG_(clo_verbosity) > 1) {
VG_(message)(Vg_UserMsg,
"Preferring higher priority redirection:\n");
show_active( " old: ", old);
show_active( " new: ", &act);
}
add_act = True;
void* oldNd = VG_(OSetGen_Remove)( activeSet, &act.from_addr );
vg_assert(oldNd == old);
VG_(OSetGen_FreeNode)( activeSet, old );
old = NULL;
}
} else {
/* This appears to be a duplicate of an existing binding.
Safe(ish) -- ignore. */
/* XXXXXXXXXXX COMPLAIN if new and old parents differ */
}
} else {
/* There's no previous binding for this from_addr, so we must
add 'act' to the active set. */
add_act = True;
}
/* So, finally, actually add it. */
if (add_act) {
Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active));
vg_assert(a);
*a = act;
@ -786,6 +830,7 @@ static void maybe_add_active ( Active act )
bad:
vg_assert(what);
vg_assert(!add_act);
if (VG_(clo_verbosity) > 1) {
VG_(message)(Vg_UserMsg, "WARNING: %s\n", what);
if (old) {
@ -936,6 +981,7 @@ static void add_hardwired_active ( Addr from, Addr to )
act.parent_spec = NULL;
act.parent_sym = NULL;
act.becTag = 0; /* "not equivalent to any other fn" */
act.becPrio = 0; /* mandatory when becTag == 0 */
act.isWrap = False;
act.isIFunc = False;
maybe_add_active( act );
@ -1248,7 +1294,8 @@ void handle_maybe_load_notifier( const UChar* soname,
if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0)
VG_(client___libc_freeres_wrapper) = addr;
else if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0)
else
if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0)
iFuncWrapper = addr;
else
vg_assert2(0, "unrecognised load notification function: %s", symbol);
@ -1381,11 +1428,11 @@ static void handle_require_text_symbols ( DebugInfo* di )
static void show_spec ( HChar* left, Spec* spec )
{
VG_(message)( Vg_DebugMsg,
"%s%25s %30s %s-> (%04d) 0x%08llx\n",
"%s%25s %30s %s-> (%04d.%d) 0x%08llx\n",
left,
spec->from_sopatt, spec->from_fnpatt,
spec->isWrap ? "W" : "R",
spec->becTag,
spec->becTag, spec->becPrio,
(ULong)spec->to_addr );
}
@ -1400,11 +1447,12 @@ static void show_active ( HChar* left, Active* act )
ok = VG_(get_fnname_w_offset)(act->to_addr, name2, 64);
if (!ok) VG_(strcpy)(name2, "???");
VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> (%04d) 0x%08llx %s\n",
VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> (%04d.%d) 0x%08llx %s\n",
left,
(ULong)act->from_addr, name1,
act->isWrap ? "W" : "R",
act->becTag, (ULong)act->to_addr, name2 );
act->becTag, act->becPrio,
(ULong)act->to_addr, name2 );
}
static void show_redir_state ( HChar* who )

View File

@ -73,28 +73,28 @@
/* 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
10010 ALLOC_or_NULL
10020 ZONEALLOC_or_NULL
10030 ALLOC_or_BOMB
10040 ZONEFREE
10050 FREE
10060 ZONECALLOC
10070 CALLOC
10080 ZONEREALLOC
10090 REALLOC
10100 ZONEMEMALIGN
10110 MEMALIGN
10120 VALLOC
10130 ZONEVALLOC
10140 MALLOPT
10150 MALLOC_TRIM
10160 POSIX_MEMALIGN
10170 MALLOC_USABLE_SIZE
10180 PANIC
10190 MALLOC_STATS
10200 MALLINFO
10210 DEFAULT_ZONE
10220 ZONE_CHECK
*/
/* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style
@ -198,8 +198,8 @@ static void init(void);
*/
#define ALLOC_or_NULL(soname, fnname, vg_replacement) \
\
void* VG_REPLACE_FUNCTION_EZU(1001,soname,fnname) (SizeT n); \
void* VG_REPLACE_FUNCTION_EZU(1001,soname,fnname) (SizeT n) \
void* VG_REPLACE_FUNCTION_EZU(10010,soname,fnname) (SizeT n); \
void* VG_REPLACE_FUNCTION_EZU(10010,soname,fnname) (SizeT n) \
{ \
void* v; \
\
@ -213,8 +213,8 @@ static void init(void);
#define ZONEALLOC_or_NULL(soname, fnname, vg_replacement) \
\
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* VG_REPLACE_FUNCTION_EZU(10020,soname,fnname) (void *zone, SizeT n); \
void* VG_REPLACE_FUNCTION_EZU(10020,soname,fnname) (void *zone, SizeT n) \
{ \
void* v; \
\
@ -233,8 +233,8 @@ static void init(void);
*/
#define ALLOC_or_BOMB(soname, fnname, vg_replacement) \
\
void* VG_REPLACE_FUNCTION_EZU(1003,soname,fnname) (SizeT n); \
void* VG_REPLACE_FUNCTION_EZU(1003,soname,fnname) (SizeT n) \
void* VG_REPLACE_FUNCTION_EZU(10030,soname,fnname) (SizeT n); \
void* VG_REPLACE_FUNCTION_EZU(10030,soname,fnname) (SizeT n) \
{ \
void* v; \
\
@ -342,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_EZU(1004,soname,fnname) (void *zone, void *p); \
void VG_REPLACE_FUNCTION_EZU(1004,soname,fnname) (void *zone, void *p) \
void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p); \
void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p) \
{ \
if (!init_done) init(); \
MALLOC_TRACE(#vg_replacement "(%p, %p)\n", zone, p ); \
@ -354,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_EZU(1005,soname,fnname) (void *p); \
void VG_REPLACE_FUNCTION_EZU(1005,soname,fnname) (void *p) \
void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p); \
void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p) \
{ \
if (!init_done) init(); \
MALLOC_TRACE(#vg_replacement "(%p)\n", p ); \
@ -417,9 +417,9 @@ FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
#define ZONECALLOC(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1006,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10060,soname,fnname) \
( void *zone, SizeT nmemb, SizeT size ); \
void* VG_REPLACE_FUNCTION_EZU(1006,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10060,soname,fnname) \
( void *zone, SizeT nmemb, SizeT size ) \
{ \
void* v; \
@ -434,9 +434,9 @@ FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
#define CALLOC(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1007,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10070,soname,fnname) \
( SizeT nmemb, SizeT size ); \
void* VG_REPLACE_FUNCTION_EZU(1007,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10070,soname,fnname) \
( SizeT nmemb, SizeT size ) \
{ \
void* v; \
@ -469,9 +469,9 @@ ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc);
#define ZONEREALLOC(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1008,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10080,soname,fnname) \
( void *zone, void* ptrV, SizeT new_size ); \
void* VG_REPLACE_FUNCTION_EZU(1008,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10080,soname,fnname) \
( void *zone, void* ptrV, SizeT new_size ) \
{ \
void* v; \
@ -482,10 +482,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. GrP fixme use zonemalloc instead? */ \
return VG_REPLACE_FUNCTION_EZU(1001,VG_Z_LIBC_SONAME,malloc) \
return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \
(new_size); \
if (new_size <= 0) { \
VG_REPLACE_FUNCTION_EZU(1005,VG_Z_LIBC_SONAME,free)(ptrV); \
VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
MALLOC_TRACE(" = 0\n"); \
return NULL; \
} \
@ -496,9 +496,9 @@ ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc);
#define REALLOC(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1009,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10090,soname,fnname) \
( void* ptrV, SizeT new_size );\
void* VG_REPLACE_FUNCTION_EZU(1009,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10090,soname,fnname) \
( void* ptrV, SizeT new_size ) \
{ \
void* v; \
@ -509,10 +509,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_EZU(1001,VG_Z_LIBC_SONAME,malloc) \
return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \
(new_size); \
if (new_size <= 0) { \
VG_REPLACE_FUNCTION_EZU(1005,VG_Z_LIBC_SONAME,free)(ptrV); \
VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
MALLOC_TRACE(" = 0\n"); \
return NULL; \
} \
@ -531,9 +531,9 @@ ZONEREALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc);
#define ZONEMEMALIGN(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1010,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10100,soname,fnname) \
( void *zone, SizeT alignment, SizeT n ); \
void* VG_REPLACE_FUNCTION_EZU(1010,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10100,soname,fnname) \
( void *zone, SizeT alignment, SizeT n ) \
{ \
void* v; \
@ -556,9 +556,9 @@ ZONEREALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc);
#define MEMALIGN(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1011,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10110,soname,fnname) \
( SizeT alignment, SizeT n ); \
void* VG_REPLACE_FUNCTION_EZU(1011,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10110,soname,fnname) \
( SizeT alignment, SizeT n ) \
{ \
void* v; \
@ -589,27 +589,27 @@ ZONEMEMALIGN(VG_Z_LIBC_SONAME, malloc_zone_memalign);
#define VALLOC(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1012,soname,fnname) ( SizeT size ); \
void* VG_REPLACE_FUNCTION_EZU(1012,soname,fnname) ( SizeT size ) \
void* VG_REPLACE_FUNCTION_EZU(10120,soname,fnname) ( SizeT size ); \
void* VG_REPLACE_FUNCTION_EZU(10120,soname,fnname) ( SizeT size ) \
{ \
static int pszB = 0; \
if (pszB == 0) \
pszB = my_getpagesize(); \
return VG_REPLACE_FUNCTION_EZU(1011,VG_Z_LIBC_SONAME,memalign) \
return VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
((SizeT)pszB, size); \
}
#define ZONEVALLOC(soname, fnname) \
\
void* VG_REPLACE_FUNCTION_EZU(1013,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10130,soname,fnname) \
( void *zone, SizeT size ); \
void* VG_REPLACE_FUNCTION_EZU(1013,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(10130,soname,fnname) \
( void *zone, SizeT size ) \
{ \
static int pszB = 0; \
if (pszB == 0) \
pszB = my_getpagesize(); \
return VG_REPLACE_FUNCTION_EZU(1011,VG_Z_LIBC_SONAME,memalign) \
return VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
((SizeT)pszB, size); \
}
@ -625,8 +625,8 @@ ZONEVALLOC(VG_Z_LIBC_SONAME, malloc_zone_valloc);
#define MALLOPT(soname, fnname) \
\
int VG_REPLACE_FUNCTION_EZU(1014,soname,fnname) ( int cmd, int value ); \
int VG_REPLACE_FUNCTION_EZU(1014,soname,fnname) ( int cmd, int value ) \
int VG_REPLACE_FUNCTION_EZU(10140,soname,fnname) ( int cmd, int value ); \
int VG_REPLACE_FUNCTION_EZU(10140,soname,fnname) ( int cmd, int value ) \
{ \
/* In glibc-2.2.4, 1 denotes a successful return value for \
mallopt */ \
@ -661,8 +661,8 @@ MALLOPT(VG_Z_LIBC_SONAME, mallopt);
// For simplicity, we always return 0.
#define MALLOC_TRIM(soname, fnname) \
\
int VG_REPLACE_FUNCTION_EZU(1015,soname,fnname) ( SizeT pad ); \
int VG_REPLACE_FUNCTION_EZU(1015,soname,fnname) ( SizeT pad ) \
int VG_REPLACE_FUNCTION_EZU(10150,soname,fnname) ( SizeT pad ); \
int VG_REPLACE_FUNCTION_EZU(10150,soname,fnname) ( SizeT pad ) \
{ \
/* 0 denotes that malloc_trim() either wasn't able \
to do anything, or was not implemented */ \
@ -676,9 +676,9 @@ MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim);
#define POSIX_MEMALIGN(soname, fnname) \
\
int VG_REPLACE_FUNCTION_EZU(1016,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(10160,soname,fnname) \
( void **memptr, SizeT alignment, SizeT size ); \
int VG_REPLACE_FUNCTION_EZU(1016,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(10160,soname,fnname) \
( void **memptr, SizeT alignment, SizeT size ) \
{ \
void *mem; \
@ -689,7 +689,7 @@ MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim);
|| (alignment & (alignment - 1)) != 0) \
return VKI_EINVAL; \
\
mem = VG_REPLACE_FUNCTION_EZU(1011,VG_Z_LIBC_SONAME,memalign) \
mem = VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
(alignment, size); \
\
if (mem != NULL) { \
@ -707,8 +707,8 @@ POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
#define MALLOC_USABLE_SIZE(soname, fnname) \
\
SizeT VG_REPLACE_FUNCTION_EZU(1017,soname,fnname) ( void* p ); \
SizeT VG_REPLACE_FUNCTION_EZU(1017,soname,fnname) ( void* p ) \
SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ); \
SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ) \
{ \
SizeT pszB; \
\
@ -740,8 +740,8 @@ static void panic(const char *str)
#define PANIC(soname, fnname) \
\
void VG_REPLACE_FUNCTION_EZU(1018,soname,fnname) ( void ); \
void VG_REPLACE_FUNCTION_EZU(1018,soname,fnname) ( void ) \
void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void ); \
void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void ) \
{ \
panic(#fnname); \
}
@ -752,8 +752,8 @@ PANIC(VG_Z_LIBC_SONAME, malloc_set_state);
#define MALLOC_STATS(soname, fnname) \
\
void VG_REPLACE_FUNCTION_EZU(1019,soname,fnname) ( void ); \
void VG_REPLACE_FUNCTION_EZU(1019,soname,fnname) ( void ) \
void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void ); \
void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void ) \
{ \
/* Valgrind's malloc_stats implementation does nothing. */ \
}
@ -768,8 +768,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_EZU(1020,soname,fnname) ( void ); \
struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(1020,soname,fnname) ( void ) \
struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ); \
struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ) \
{ \
static struct vg_mallinfo mi; \
if (!init_done) init(); \
@ -787,11 +787,11 @@ static vki_malloc_zone_t vg_default_zone = {
NULL, // reserved
NULL, // reserved
NULL, // GrP fixme malloc_size
(void*)VG_REPLACE_FUNCTION_EZU(1002,VG_Z_LIBC_SONAME,malloc_zone_malloc),
(void*)VG_REPLACE_FUNCTION_EZU(1006,VG_Z_LIBC_SONAME,malloc_zone_calloc),
(void*)VG_REPLACE_FUNCTION_EZU(1013,VG_Z_LIBC_SONAME,malloc_zone_valloc),
(void*)VG_REPLACE_FUNCTION_EZU(1004,VG_Z_LIBC_SONAME,malloc_zone_free),
(void*)VG_REPLACE_FUNCTION_EZU(1008,VG_Z_LIBC_SONAME,malloc_zone_realloc),
(void*)VG_REPLACE_FUNCTION_EZU(10020,VG_Z_LIBC_SONAME,malloc_zone_malloc),
(void*)VG_REPLACE_FUNCTION_EZU(10060,VG_Z_LIBC_SONAME,malloc_zone_calloc),
(void*)VG_REPLACE_FUNCTION_EZU(10130,VG_Z_LIBC_SONAME,malloc_zone_valloc),
(void*)VG_REPLACE_FUNCTION_EZU(10040,VG_Z_LIBC_SONAME,malloc_zone_free),
(void*)VG_REPLACE_FUNCTION_EZU(10080,VG_Z_LIBC_SONAME,malloc_zone_realloc),
NULL, // GrP fixme destroy
"ValgrindMallocZone",
NULL, // batch_malloc
@ -806,8 +806,8 @@ static vki_malloc_zone_t vg_default_zone = {
#define DEFAULT_ZONE(soname, fnname) \
\
void *VG_REPLACE_FUNCTION_EZU(1021,soname,fnname) ( void ); \
void *VG_REPLACE_FUNCTION_EZU(1021,soname,fnname) ( void ) \
void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ); \
void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ) \
{ \
return &vg_default_zone; \
}
@ -820,8 +820,8 @@ 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_EZU(1022,soname,fnname)(void* zone); \
int VG_REPLACE_FUNCTION_EZU(1022,soname,fnname)(void* zone) \
int VG_REPLACE_FUNCTION_EZU(10220,soname,fnname)(void* zone); \
int VG_REPLACE_FUNCTION_EZU(10220,soname,fnname)(void* zone) \
{ \
return 1; \
}

View File

@ -60,7 +60,8 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym,
/*OUT*/HChar* so, Int soLen,
/*OUT*/HChar* fn, Int fnLen,
/*OUT*/Bool* isWrap,
/*OUT*/Int* eclassTag );
/*OUT*/Int* eclassTag,
/*OUT*/Int* eclassPrio );
#endif // __PUB_CORE_DEMANGLE_H

View File

@ -51,24 +51,31 @@
sure you use the VG_REPLACE_FN_ macros and not the VG_WRAP_FN_
macros.
Finally there is the concept of behavioural equivalence tags. A
tag is a 4-digit decimal number (0001 to 9999) encoded in the name.
If two replacement functions have the same tag then the redirect
mechanism will assume that they have identical behaviour. If, when
processing redirections at library load time, the set of available
specifications yields more than one replacement or wrapper function
for a given address, the system will try to resolve the situation
by examining the tags on the replacements/wrappers. In particular,
if all of them have the same tag, then they are all claiming to
behave identically, so any of them may be chosen to be the actual
redirection target. Of course if not all of them have the same tag
then the redirection is ambiguous and the system will have to stop.
Finally there is the concept of prioritised behavioural equivalence
tags. A tag is a 5-digit decimal number (00000 to 99999) encoded
in the name. The top 4 digits are the equivalence class number,
and the last digit is a priority.
The tag is mandatory and must comprise 4 decimal digits. The tag
0000 is special and means "does not have behaviour identical to any
When processing redirections at library load time, if the set of
available specifications yields more than one replacement or
wrapper function for a given address, the system will try to
resolve the situation by examining the tags on the
replacements/wrappers.
If two replacement/wrapper functions have the same tag and
priority, then the redirection machinery will assume they have
identical behaviour and can choose between them arbitrarily. If
they have the same tag but different priorities, then the one with
higher priority will be chosen. If neither case holds, then the
redirection is ambiguous and the system will ignore one of them
arbitrarily, but print a warning when running at -v or above.
The tag is mandatory and must comprise 5 decimal digits. The tag
00000 is special and means "does not have behaviour identical to any
other replacement/wrapper function". Hence if you wish to write a
wrap/replacement function that is not subject to the above
resolution rules, use 0000 for the tag.
resolution rules, use 00000 for the tag. Tags 00001 through 00009
may not be used for any purpose.
Replacement
@ -83,12 +90,12 @@
zEncodedSoname should be a Z-encoded soname (see below for
Z-encoding details) and fnname should be an unencoded fn name. A
default-safe equivalence tag of 0000 is assumed (see comments
default-safe equivalence tag of 00000 is assumed (see comments
above). The resulting name is
_vgr0000ZU_zEncodedSoname_fnname
_vgr00000ZU_zEncodedSoname_fnname
The "_vgr0000ZU_" is a prefix that gets discarded upon decoding.
The "_vgr00000ZU_" is a prefix that gets discarded upon decoding.
It identifies this function as a replacement and specifies its
equivalence tag.
@ -104,7 +111,7 @@
Z-encoded. This can sometimes be necessary. In this case the
resulting function name is
_vgr0000ZZ_zEncodedSoname_zEncodedFnname
_vgr00000ZZ_zEncodedSoname_zEncodedFnname
When it sees this either such name, the core's symbol-table reading
machinery and redirection machinery first Z-decode the soname and
@ -138,12 +145,12 @@
To write function names which explicitly state the equivalence class
tag, use
VG_REPLACE_FUNCTION_EZU(4-digit-tag,zEncodedSoname,fnname)
VG_REPLACE_FUNCTION_EZU(5-digit-tag,zEncodedSoname,fnname)
or
VG_REPLACE_FUNCTION_EZZ(4-digit-tag,zEncodedSoname,zEncodedFnname)
VG_REPLACE_FUNCTION_EZZ(5-digit-tag,zEncodedSoname,zEncodedFnname)
As per comments above, the tag must be a 4 digit decimal number,
padded with leading zeroes, in the range 0001 to 9999 inclusive.
As per comments above, the tag must be a 5 digit decimal number,
padded with leading zeroes, in the range 00010 to 99999 inclusive.
Wrapping
@ -206,16 +213,16 @@
/* Convenience macros defined in terms of the above 4. */
#define VG_REPLACE_FUNCTION_ZU(_soname,_fnname) \
VG_CONCAT6(_vgr,0000,ZU_,_soname,_,_fnname)
VG_CONCAT6(_vgr,00000,ZU_,_soname,_,_fnname)
#define VG_REPLACE_FUNCTION_ZZ(_soname,_fnname) \
VG_CONCAT6(_vgr,0000,ZZ_,_soname,_,_fnname)
VG_CONCAT6(_vgr,00000,ZZ_,_soname,_,_fnname)
#define VG_WRAP_FUNCTION_ZU(_soname,_fnname) \
VG_CONCAT6(_vgw,0000,ZU_,_soname,_,_fnname)
VG_CONCAT6(_vgw,00000,ZU_,_soname,_,_fnname)
#define VG_WRAP_FUNCTION_ZZ(_soname,_fnname) \
VG_CONCAT6(_vgw,0000,ZZ_,_soname,_,_fnname)
VG_CONCAT6(_vgw,00000,ZZ_,_soname,_,_fnname)
/* --------- Some handy Z-encoded names. --------- */

View File

@ -689,10 +689,10 @@ typedef
#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
VG_CONCAT4(_vgw0000ZU_,soname,_,fnname)
VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
VG_CONCAT4(_vgw0000ZZ_,soname,_,fnname)
VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
/* Use this macro from within a wrapper function to collect the
context (address and possibly other info) of the original function.

View File

@ -53,43 +53,46 @@
THEY RUN ON THE SIMD CPU!
------------------------------------------------------------------ */
/* Assignment of behavioural equivalence class tags: 2NNN is intended
/* Assignment of behavioural equivalence class tags: 2NNNP 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
20010 STRRCHR
20020 STRCHR
20030 STRCAT
20040 STRNCAT
20050 STRLCAT
20060 STRNLEN
20070 STRLEN
20080 STRCPY
20090 STRNCPY
20100 STRLCPY
20110 STRNCMP
20120 STRCASECMP
20130 STRNCASECMP
20140 STRCASECMP_L
20150 STRNCASECMP_L
20160 STRCMP
20170 MEMCHR
20180 MEMCPY if there's a conflict between memcpy and
20181 MEMMOVE memmove, prefer memmove
20190 MEMCMP
20200 STPCPY
20210 MEMSET
2022P unused (was previously MEMMOVE)
20230 BCOPY
20240 GLIBC25___MEMMOVE_CHK
20250 GLIBC232_STRCHRNUL
20260 GLIBC232_RAWMEMCHR
20270 GLIBC25___STRCPY_CHK
20280 GLIBC25___STPCPY_CHK
20290 GLIBC25_MEMPCPY
20300 GLIBC26___MEMCPY_CHK
20310 STRSTR
20320 STRPBRK
20330 STRCSPN
20340 STRSPN
*/
@ -152,8 +155,8 @@ static inline void my_exit ( int x )
#define STRRCHR(soname, fnname) \
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 ) \
char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \
char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \
{ \
UChar ch = (UChar)((UInt)c); \
UChar* p = (UChar*)s; \
@ -178,8 +181,8 @@ STRRCHR(VG_Z_DYLD, rindex)
#define STRCHR(soname, fnname) \
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 ) \
char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \
char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \
{ \
UChar ch = (UChar)((UInt)c); \
UChar* p = (UChar*)s; \
@ -206,9 +209,9 @@ STRCHR(VG_Z_DYLD, index)
#define STRCAT(soname, fnname) \
char* VG_REPLACE_FUNCTION_EZU(2003,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
( char* dst, const char* src ); \
char* VG_REPLACE_FUNCTION_EZU(2003,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \
( char* dst, const char* src ) \
{ \
const Char* src_orig = src; \
@ -234,9 +237,9 @@ STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
#endif
#define STRNCAT(soname, fnname) \
char* VG_REPLACE_FUNCTION_EZU(2004,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
( char* dst, const char* src, SizeT n ); \
char* VG_REPLACE_FUNCTION_EZU(2004,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \
( char* dst, const char* src, SizeT n ) \
{ \
const Char* src_orig = src; \
@ -270,9 +273,9 @@ STRNCAT(VG_Z_DYLD, strncat)
Truncation occurred if retval >= n.
*/
#define STRLCAT(soname, fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(2005,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
( char* dst, const char* src, SizeT n ); \
SizeT VG_REPLACE_FUNCTION_EZU(2005,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \
( char* dst, const char* src, SizeT n ) \
{ \
const Char* src_orig = src; \
@ -307,9 +310,9 @@ STRLCAT(VG_Z_DYLD, strlcat)
#define STRNLEN(soname, fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(2006,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
( const char* str, SizeT n ); \
SizeT VG_REPLACE_FUNCTION_EZU(2006,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \
( const char* str, SizeT n ) \
{ \
SizeT i = 0; \
@ -328,9 +331,9 @@ 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_EZU(2007,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
( const char* str ); \
SizeT VG_REPLACE_FUNCTION_EZU(2007,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \
( const char* str ) \
{ \
SizeT i = 0; \
@ -345,9 +348,9 @@ STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
#define STRCPY(soname, fnname) \
char* VG_REPLACE_FUNCTION_EZU(2008,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
( char* dst, const char* src ); \
char* VG_REPLACE_FUNCTION_EZU(2008,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \
( char* dst, const char* src ) \
{ \
const Char* src_orig = src; \
@ -376,9 +379,9 @@ STRCPY(VG_Z_DYLD, strcpy)
#define STRNCPY(soname, fnname) \
char* VG_REPLACE_FUNCTION_EZU(2009,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
( char* dst, const char* src, SizeT n ); \
char* VG_REPLACE_FUNCTION_EZU(2009,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \
( char* dst, const char* src, SizeT n ) \
{ \
const Char* src_orig = src; \
@ -406,9 +409,9 @@ 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_EZU(2010,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
( char* dst, const char* src, SizeT n ); \
SizeT VG_REPLACE_FUNCTION_EZU(2010,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \
( char* dst, const char* src, SizeT n ) \
{ \
const char* src_orig = src; \
@ -435,9 +438,9 @@ STRLCPY(VG_Z_DYLD, strlcpy)
#define STRNCMP(soname, fnname) \
int VG_REPLACE_FUNCTION_EZU(2011,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
( const char* s1, const char* s2, SizeT nmax ); \
int VG_REPLACE_FUNCTION_EZU(2011,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \
( const char* s1, const char* s2, SizeT nmax ) \
{ \
SizeT n = 0; \
@ -463,9 +466,9 @@ STRNCMP(VG_Z_DYLD, strncmp)
#define STRCASECMP(soname, fnname) \
int VG_REPLACE_FUNCTION_EZU(2012,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
( const char* s1, const char* s2 ); \
int VG_REPLACE_FUNCTION_EZU(2012,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \
( const char* s1, const char* s2 ) \
{ \
extern int tolower(int); \
@ -492,9 +495,9 @@ STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
#define STRNCASECMP(soname, fnname) \
int VG_REPLACE_FUNCTION_EZU(2013,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
( const char* s1, const char* s2, SizeT nmax ); \
int VG_REPLACE_FUNCTION_EZU(2013,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \
( const char* s1, const char* s2, SizeT nmax ) \
{ \
extern int tolower(int); \
@ -525,9 +528,9 @@ STRNCASECMP(VG_Z_DYLD, strncasecmp)
#define STRCASECMP_L(soname, fnname) \
int VG_REPLACE_FUNCTION_EZU(2014,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
( const char* s1, const char* s2, void* locale ); \
int VG_REPLACE_FUNCTION_EZU(2014,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \
( const char* s1, const char* s2, void* locale ) \
{ \
extern int tolower_l(int, void*) __attribute__((weak)); \
@ -553,9 +556,9 @@ STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l)
#define STRNCASECMP_L(soname, fnname) \
int VG_REPLACE_FUNCTION_EZU(2015,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
( const char* s1, const char* s2, SizeT nmax, void* locale ); \
int VG_REPLACE_FUNCTION_EZU(2015,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \
( const char* s1, const char* s2, SizeT nmax, void* locale ) \
{ \
extern int tolower_l(int, void*) __attribute__((weak)); \
@ -584,9 +587,9 @@ STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
#define STRCMP(soname, fnname) \
int VG_REPLACE_FUNCTION_EZU(2016,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
( const char* s1, const char* s2 ); \
int VG_REPLACE_FUNCTION_EZU(2016,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \
( const char* s1, const char* s2 ) \
{ \
register unsigned char c1; \
@ -612,9 +615,9 @@ STRCMP(VG_Z_LD64_SO_1, strcmp)
#define MEMCHR(soname, fnname) \
void* VG_REPLACE_FUNCTION_EZU(2017,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
(const void *s, int c, SizeT n); \
void* VG_REPLACE_FUNCTION_EZU(2017,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \
(const void *s, int c, SizeT n) \
{ \
SizeT i; \
@ -705,16 +708,17 @@ MEMCHR(VG_Z_DYLD, memchr)
}
#define MEMMOVE(soname, fnname) \
MEMMOVE_OR_MEMCPY(2018, soname, fnname, 0)
MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0)
#define MEMCPY(soname, fnname) \
MEMMOVE_OR_MEMCPY(2022, soname, fnname, 1)
MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1)
#if defined(VGO_linux)
/* For older memcpy we have to use memmove-like semantics and skip the
overlap check; sigh; see #275284. */
MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */
MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */
MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */
MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
#elif defined(VGO_darwin)
@ -733,9 +737,9 @@ MEMCPY(NONE, ZuintelZufastZumemcpy)
#define MEMCMP(soname, fnname) \
int VG_REPLACE_FUNCTION_EZU(2019,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
( const void *s1V, const void *s2V, SizeT n ); \
int VG_REPLACE_FUNCTION_EZU(2019,soname,fnname) \
int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \
( const void *s1V, const void *s2V, SizeT n ) \
{ \
int res; \
@ -770,9 +774,9 @@ 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_EZU(2020,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
( char* dst, const char* src ); \
char* VG_REPLACE_FUNCTION_EZU(2020,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \
( char* dst, const char* src ) \
{ \
const Char* src_orig = src; \
@ -803,9 +807,9 @@ STPCPY(VG_Z_DYLD, stpcpy)
#define MEMSET(soname, fnname) \
void* VG_REPLACE_FUNCTION_EZU(2021,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
(void *s, Int c, SizeT n); \
void* VG_REPLACE_FUNCTION_EZU(2021,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \
(void *s, Int c, SizeT n) \
{ \
Addr a = (Addr)s; \
@ -827,7 +831,7 @@ MEMSET(VG_Z_DYLD, memset)
#endif
/* memmove -- use the MEMMOVE defn which also serves for memcpy. */
/* memmove -- use the MEMMOVE defn above. */
MEMMOVE(VG_Z_LIBC_SONAME, memmove)
#if defined(VGO_darwin)
MEMMOVE(VG_Z_DYLD, memmove)
@ -835,9 +839,9 @@ MEMMOVE(VG_Z_DYLD, memmove)
#define BCOPY(soname, fnname) \
void VG_REPLACE_FUNCTION_EZU(2023,soname,fnname) \
void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
(const void *srcV, void *dstV, SizeT n); \
void VG_REPLACE_FUNCTION_EZU(2023,soname,fnname) \
void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \
(const void *srcV, void *dstV, SizeT n) \
{ \
SizeT i; \
@ -863,9 +867,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_EZU(2024,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
(void *dstV, const void *srcV, SizeT n, SizeT destlen); \
void* VG_REPLACE_FUNCTION_EZU(2024,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \
(void *dstV, const void *srcV, SizeT n, SizeT destlen) \
{ \
SizeT i; \
@ -897,9 +901,9 @@ 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_EZU(2025,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
(const char* s, int c_in); \
char* VG_REPLACE_FUNCTION_EZU(2025,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \
(const char* s, int c_in) \
{ \
unsigned char c = (unsigned char) c_in; \
@ -916,9 +920,9 @@ GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
/* Find the first occurrence of C in S. */
#define GLIBC232_RAWMEMCHR(soname, fnname) \
char* VG_REPLACE_FUNCTION_EZU(2026,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
(const char* s, int c_in); \
char* VG_REPLACE_FUNCTION_EZU(2026,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \
(const char* s, int c_in) \
{ \
unsigned char c = (unsigned char) c_in; \
@ -937,9 +941,9 @@ 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_EZU(2027,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
(char* dst, const char* src, SizeT len); \
char* VG_REPLACE_FUNCTION_EZU(2027,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \
(char* dst, const char* src, SizeT len) \
{ \
char* ret = dst; \
@ -964,9 +968,9 @@ 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_EZU(2028,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
(char* dst, const char* src, SizeT len); \
char* VG_REPLACE_FUNCTION_EZU(2028,soname,fnname) \
char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \
(char* dst, const char* src, SizeT len) \
{ \
if (! len) \
@ -989,9 +993,9 @@ GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk)
/* mempcpy */
#define GLIBC25_MEMPCPY(soname, fnname) \
void* VG_REPLACE_FUNCTION_EZU(2029,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
( void *dst, const void *src, SizeT len ); \
void* VG_REPLACE_FUNCTION_EZU(2029,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \
( void *dst, const void *src, SizeT len ) \
{ \
register char *d; \
@ -1027,9 +1031,9 @@ GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */
#define GLIBC26___MEMCPY_CHK(soname, fnname) \
void* VG_REPLACE_FUNCTION_EZU(2030,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
(void* dst, const void* src, SizeT len, SizeT dstlen ); \
void* VG_REPLACE_FUNCTION_EZU(2030,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \
(void* dst, const void* src, SizeT len, SizeT dstlen ) \
{ \
register char *d; \
@ -1070,9 +1074,9 @@ GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk)
#define STRSTR(soname, fnname) \
void* VG_REPLACE_FUNCTION_EZU(2031,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
(void* haystack, void* needle); \
void* VG_REPLACE_FUNCTION_EZU(2031,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \
(void* haystack, void* needle) \
{ \
UChar* h = (UChar*)haystack; \
@ -1112,9 +1116,9 @@ STRSTR(VG_Z_LIBC_SONAME, strstr)
#define STRPBRK(soname, fnname) \
void* VG_REPLACE_FUNCTION_EZU(2032,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
(void* sV, void* acceptV); \
void* VG_REPLACE_FUNCTION_EZU(2032,soname,fnname) \
void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \
(void* sV, void* acceptV) \
{ \
UChar* s = (UChar*)sV; \
@ -1149,9 +1153,9 @@ STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
#define STRCSPN(soname, fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(2033,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
(void* sV, void* rejectV); \
SizeT VG_REPLACE_FUNCTION_EZU(2033,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \
(void* sV, void* rejectV) \
{ \
UChar* s = (UChar*)sV; \
@ -1187,9 +1191,9 @@ STRCSPN(VG_Z_LIBC_SONAME, strcspn)
#define STRSPN(soname, fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(2034,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
(void* sV, void* acceptV); \
SizeT VG_REPLACE_FUNCTION_EZU(2034,soname,fnname) \
SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \
(void* sV, void* acceptV) \
{ \
UChar* s = (UChar*)sV; \