mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 10:05:29 +00:00
Cleaned up m_redir.c: renamed some variables and functions, added some
comments, neatened the debugging output, avoided unexpected side-effects in functions, tweaked code to make it clearer. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4028
This commit is contained in:
parent
cc404a9c03
commit
c8f13ea9d3
@ -1650,7 +1650,7 @@ SegInfo *VG_(read_seg_symbols) ( Addr seg_addr, SizeT seg_len,
|
||||
canonicaliseCfiSI ( si );
|
||||
|
||||
/* do redirects */
|
||||
VG_(resolve_seg_redirs)( si );
|
||||
VG_(resolve_existing_redirs_with_seginfo)( si );
|
||||
}
|
||||
VGP_POPCC(VgpReadSyms);
|
||||
|
||||
|
||||
@ -46,6 +46,9 @@
|
||||
/*--- General purpose redirection. ---*/
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
#define TRACE_REDIR(format, args...) \
|
||||
if (VG_(clo_trace_redir)) { VG_(message)(Vg_DebugMsg, format, ## args); }
|
||||
|
||||
/*
|
||||
wraps and redirections, indexed by from_addr
|
||||
|
||||
@ -71,29 +74,24 @@ struct _CodeRedirect {
|
||||
const Char *from_sym; /* symbol */
|
||||
Addr from_addr; /* old addr */
|
||||
|
||||
/* used for redirection */
|
||||
Addr to_addr; /* new addr */
|
||||
Addr to_addr; /* used for redirection -- new addr */
|
||||
const FuncWrapper *wrapper; /* used for wrapping */
|
||||
|
||||
/* used for wrapping */
|
||||
const FuncWrapper *wrapper;
|
||||
|
||||
CodeRedirect *next; /* next pointer on unresolved list */
|
||||
CodeRedirect *next; /* next pointer on unresolved list */
|
||||
};
|
||||
|
||||
static Char *straddr(void *p)
|
||||
{
|
||||
static Char buf[16];
|
||||
|
||||
VG_(sprintf)(buf, "%p", *(Addr *)p);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static SkipList sk_resolved_redir =
|
||||
static SkipList sk_resolved_redirs =
|
||||
VG_SKIPLIST_INIT(CodeRedirect, from_addr, VG_(cmp_Addr),
|
||||
straddr, VG_AR_SYMTAB);
|
||||
|
||||
static CodeRedirect *unresolved_redir = NULL;
|
||||
static CodeRedirect *unresolved_redirs = NULL;
|
||||
|
||||
static Bool soname_matches(const Char *pattern, const Char* soname)
|
||||
{
|
||||
@ -107,25 +105,31 @@ static Bool soname_matches(const Char *pattern, const Char* soname)
|
||||
return VG_(string_match)(pattern + 7, soname);
|
||||
}
|
||||
|
||||
static inline Bool from_resolved(const CodeRedirect *redir)
|
||||
Bool VG_(is_resolved)(const CodeRedirect *redir)
|
||||
{
|
||||
return redir->from_addr != 0;
|
||||
}
|
||||
|
||||
Bool VG_(is_resolved)(const CodeRedirect *redir)
|
||||
// Prepends redir to the unresolved list.
|
||||
static void add_redir_to_unresolved_list(CodeRedirect *redir)
|
||||
{
|
||||
return from_resolved(redir);
|
||||
redir->next = unresolved_redirs;
|
||||
unresolved_redirs = redir;
|
||||
}
|
||||
|
||||
static void add_resolved(CodeRedirect *redir)
|
||||
static void add_redir_to_resolved_list(CodeRedirect *redir)
|
||||
{
|
||||
switch(redir->type) {
|
||||
case R_REDIRECT:
|
||||
if (VG_(clo_trace_redir)) {
|
||||
VG_(message)(Vg_DebugMsg, " redir resolved (%s:%s=%p -> ",
|
||||
redir->from_lib, redir->from_sym, redir->from_addr);
|
||||
VG_(message)(Vg_DebugMsg, " %p)", redir->to_addr);
|
||||
}
|
||||
vg_assert(redir->from_addr);
|
||||
|
||||
switch (redir->type) {
|
||||
case R_REDIRECT: {
|
||||
CodeRedirect* r;
|
||||
|
||||
TRACE_REDIR(" redir resolved (%s:%s=%p -> %p)",
|
||||
redir->from_lib, redir->from_sym, redir->from_addr,
|
||||
redir->to_addr);
|
||||
|
||||
vg_assert(redir->to_addr != 0);
|
||||
|
||||
if (VG_(search_transtab)(NULL, (Addr64)redir->from_addr, False)) {
|
||||
/* For some given (from, to) redir, the "from" function got
|
||||
@ -145,191 +149,173 @@ static void add_resolved(CodeRedirect *redir)
|
||||
Note, this is potentially expensive -- discarding
|
||||
translations causes complete unchaining.
|
||||
*/
|
||||
if (VG_(clo_verbosity) > 2 && VG_(clo_trace_redir)) {
|
||||
VG_(message)(Vg_UserMsg,
|
||||
"Discarding translation due to redirect of already called function" );
|
||||
VG_(message)(Vg_UserMsg,
|
||||
" %s (%p -> %p)",
|
||||
redir->from_sym, redir->from_addr, redir->to_addr );
|
||||
}
|
||||
TRACE_REDIR("Discarding translation due to redirect of already called function" );
|
||||
TRACE_REDIR(" %s:%s(%p) -> %p)", redir->from_lib, redir->from_sym,
|
||||
redir->from_addr, redir->to_addr );
|
||||
VG_(discard_translations)((Addr64)redir->from_addr, 1);
|
||||
}
|
||||
|
||||
{
|
||||
CodeRedirect *r = VG_(SkipList_Find_Exact)(&sk_resolved_redir, &redir->from_addr);
|
||||
r = VG_(SkipList_Find_Exact)(&sk_resolved_redirs, &redir->from_addr);
|
||||
|
||||
if (r == NULL)
|
||||
VG_(SkipList_Insert)(&sk_resolved_redir, redir);
|
||||
else {
|
||||
/* XXX leak redir */
|
||||
if (VG_(clo_trace_redir))
|
||||
VG_(message)(Vg_DebugMsg, " redir %s:%s:%p->%p duplicated\n",
|
||||
redir->from_lib, redir->from_sym, redir->from_addr,
|
||||
redir->to_addr);
|
||||
}
|
||||
if (r == NULL) {
|
||||
VG_(SkipList_Insert)(&sk_resolved_redirs, redir);
|
||||
} else {
|
||||
/* XXX leak redir */
|
||||
TRACE_REDIR(" redir %s:%s:%p->%p duplicated\n",
|
||||
redir->from_lib, redir->from_sym, redir->from_addr,
|
||||
redir->to_addr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case R_WRAPPER:
|
||||
if (VG_(clo_trace_redir)) {
|
||||
VG_(message)(Vg_DebugMsg, " wrapper resolved (%s:%s=%p -> wrapper)",
|
||||
redir->from_lib, redir->from_sym, redir->from_addr);
|
||||
}
|
||||
TRACE_REDIR(" wrapper resolved (%s:%s=%p -> wrapper)",
|
||||
redir->from_lib, redir->from_sym, redir->from_addr);
|
||||
|
||||
vg_assert(redir->wrapper);
|
||||
|
||||
/* XXX redir leaked */
|
||||
//VG_(wrap_function)(redir->from_addr, redir->wrapper);
|
||||
break;
|
||||
|
||||
case R_CLIENT_WRAPPER:
|
||||
vg_assert(redir->wrapper);
|
||||
VG_(core_panic)("not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolve a redir using si if possible, and add it to the resolved
|
||||
list */
|
||||
static Bool resolve_redir(CodeRedirect *redir, const SegInfo *si)
|
||||
// Resolve a redir using si if possible. Returns True if it succeeded.
|
||||
static Bool resolve_redir_with_seginfo(CodeRedirect *redir, const SegInfo *si)
|
||||
{
|
||||
Bool resolved;
|
||||
Bool ok;
|
||||
|
||||
vg_assert(si != NULL);
|
||||
vg_assert(redir->from_addr == 0 );
|
||||
vg_assert(redir->from_sym != NULL);
|
||||
|
||||
resolved = from_resolved(redir);
|
||||
vg_assert(!resolved);
|
||||
vg_assert(redir->from_sym != NULL);
|
||||
|
||||
if (soname_matches(redir->from_lib, VG_(seginfo_soname)(si))) {
|
||||
// Resolved if the soname matches and we find the symbol.
|
||||
ok = soname_matches(redir->from_lib, VG_(seginfo_soname)(si));
|
||||
if (ok) {
|
||||
redir->from_addr = VG_(reverse_search_one_symtab)(si, redir->from_sym);
|
||||
if (VG_(clo_trace_redir) && redir->from_addr != 0)
|
||||
VG_(printf)(" bind FROM: %p = %s:%s\n",
|
||||
redir->from_addr,redir->from_lib, redir->from_sym );
|
||||
ok = ( redir->from_addr == 0 ? False : True );
|
||||
}
|
||||
|
||||
resolved = from_resolved(redir);
|
||||
|
||||
if (0 && VG_(clo_trace_redir))
|
||||
VG_(printf)("resolve_redir: %s:%s from=%p to=%p\n",
|
||||
redir->from_lib, redir->from_sym, redir->from_addr,
|
||||
redir->to_addr);
|
||||
|
||||
if (resolved) add_resolved(redir);
|
||||
|
||||
return resolved;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static Bool resolve_redir_allsegs(CodeRedirect *redir)
|
||||
// Resolve a redir using any SegInfo if possible.
|
||||
static Bool resolve_redir_with_existing_seginfos(CodeRedirect *redir)
|
||||
{
|
||||
const SegInfo *si;
|
||||
|
||||
for(si = VG_(next_seginfo)(NULL);
|
||||
si != NULL;
|
||||
si = VG_(next_seginfo)(si))
|
||||
for (si = VG_(next_seginfo)(NULL);
|
||||
si != NULL;
|
||||
si = VG_(next_seginfo)(si))
|
||||
{
|
||||
if (resolve_redir(redir, si))
|
||||
if (resolve_redir_with_seginfo(redir, si))
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Go through the complete redir list, resolving as much as possible with this SegInfo.
|
||||
|
||||
This should be called when a new SegInfo symtab is loaded.
|
||||
*/
|
||||
void VG_(resolve_seg_redirs)(SegInfo *si)
|
||||
// Resolve as many unresolved redirs as possible with this SegInfo. This
|
||||
// should be called when a new SegInfo symtab is loaded.
|
||||
void VG_(resolve_existing_redirs_with_seginfo)(SegInfo *si)
|
||||
{
|
||||
CodeRedirect **prevp = &unresolved_redir;
|
||||
CodeRedirect **prevp = &unresolved_redirs;
|
||||
CodeRedirect *redir, *next;
|
||||
|
||||
if (VG_(clo_trace_redir))
|
||||
VG_(printf)("Considering redirs to/from %s(soname=%s)\n",
|
||||
VG_(seginfo_filename)(si), VG_(seginfo_soname)(si));
|
||||
TRACE_REDIR("Just loaded %s (soname=%s),",
|
||||
VG_(seginfo_filename)(si), VG_(seginfo_soname)(si));
|
||||
TRACE_REDIR(" resolving any unresolved redirs with it");
|
||||
|
||||
/* visit each unresolved redir - if it becomes resolved, then
|
||||
remove it from the unresolved list */
|
||||
for(redir = unresolved_redir; redir != NULL; redir = next) {
|
||||
// Visit each unresolved redir - if it becomes resolved, then
|
||||
// move it from the unresolved list to the resolved list.
|
||||
for (redir = unresolved_redirs; redir != NULL; redir = next) {
|
||||
next = redir->next;
|
||||
|
||||
if (resolve_redir(redir, si)) {
|
||||
if (resolve_redir_with_seginfo(redir, si)) {
|
||||
*prevp = next;
|
||||
redir->next = NULL;
|
||||
add_redir_to_resolved_list(redir);
|
||||
} else
|
||||
prevp = &redir->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void add_redirect_X_to_addr(
|
||||
const Char *from_lib, const Char *from_sym, Addr from_addr, Addr to_addr
|
||||
)
|
||||
{
|
||||
CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
|
||||
|
||||
redir->type = R_REDIRECT;
|
||||
|
||||
if (from_lib) redir->from_lib = VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
|
||||
else redir->from_lib = NULL;
|
||||
if (from_sym) redir->from_sym = VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
|
||||
else redir->from_sym = NULL;
|
||||
|
||||
redir->from_addr = from_addr;
|
||||
|
||||
vg_assert(0 != to_addr);
|
||||
redir->to_addr = to_addr;
|
||||
redir->wrapper = 0;
|
||||
|
||||
if (VG_(clo_verbosity) >= 2 && VG_(clo_trace_redir))
|
||||
VG_(message)(Vg_UserMsg,
|
||||
"REDIRECT %s:%s(%p) to %p",
|
||||
from_lib, from_sym, from_addr, to_addr);
|
||||
|
||||
/* Check against all existing segments to see if this redirection
|
||||
can be resolved immediately */
|
||||
if (VG_(is_resolved)(redir)) {
|
||||
add_resolved(redir);
|
||||
}
|
||||
else if (!resolve_redir_allsegs(redir)) {
|
||||
/* nope, add to list */
|
||||
redir->next = unresolved_redir;
|
||||
unresolved_redir = redir;
|
||||
}
|
||||
}
|
||||
|
||||
/* Redirect a lib/symbol reference to a function at addr */
|
||||
static void add_redirect_sym_to_addr(const Char *from_lib, const Char *from_sym,
|
||||
Addr to_addr)
|
||||
{
|
||||
add_redirect_X_to_addr(from_lib, from_sym, 0, to_addr);
|
||||
TRACE_REDIR(" Finished resolving");
|
||||
}
|
||||
|
||||
/* Redirect a function at from_addr to a function at to_addr */
|
||||
__attribute__((unused)) // It is used, but not on all platforms...
|
||||
static void add_redirect_addr_to_addr(Addr from_addr, Addr to_addr)
|
||||
static void add_redirect_addr_to_addr( Addr from_addr, Addr to_addr )
|
||||
{
|
||||
add_redirect_X_to_addr(NULL, NULL, from_addr, to_addr);
|
||||
CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs);
|
||||
|
||||
vg_assert(0 != from_addr && 0 != to_addr);
|
||||
|
||||
redir->type = R_REDIRECT;
|
||||
|
||||
redir->from_lib = NULL;
|
||||
redir->from_sym = NULL;
|
||||
redir->from_addr = from_addr;
|
||||
|
||||
redir->to_addr = to_addr;
|
||||
redir->wrapper = 0;
|
||||
|
||||
TRACE_REDIR("REDIRECT addr to addr: %p to %p", from_addr, to_addr);
|
||||
|
||||
// This redirection is already resolved, put it straight in the list.
|
||||
add_redir_to_resolved_list(redir);
|
||||
}
|
||||
|
||||
/* Redirect a lib/symbol reference to a function at addr */
|
||||
static void add_redirect_sym_to_addr(
|
||||
const Char *from_lib, const Char *from_sym, Addr to_addr
|
||||
)
|
||||
{
|
||||
CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs);
|
||||
|
||||
vg_assert(from_lib && from_sym && 0 != to_addr);
|
||||
|
||||
redir->type = R_REDIRECT;
|
||||
redir->from_lib = VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
|
||||
redir->from_sym = VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
|
||||
redir->from_addr = 0;
|
||||
redir->to_addr = to_addr;
|
||||
redir->wrapper = 0;
|
||||
|
||||
TRACE_REDIR("REDIR sym to addr: %s:%s to %p", from_lib, from_sym, to_addr);
|
||||
|
||||
// Check against all existing segments to see if this redirection
|
||||
// can be resolved immediately. Then add it to the appropriate list.
|
||||
if (resolve_redir_with_existing_seginfos(redir)) {
|
||||
add_redir_to_resolved_list(redir);
|
||||
} else {
|
||||
add_redir_to_unresolved_list(redir);
|
||||
}
|
||||
}
|
||||
|
||||
CodeRedirect *VG_(add_wrapper)(const Char *from_lib, const Char *from_sym,
|
||||
const FuncWrapper *wrapper)
|
||||
{
|
||||
CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
|
||||
|
||||
if (0)
|
||||
VG_(printf)("adding wrapper for %s:%s -> (%p,%p)\n",
|
||||
from_lib, from_sym, wrapper->before, wrapper->after);
|
||||
|
||||
redir->type = R_WRAPPER;
|
||||
CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs);
|
||||
|
||||
redir->type = R_WRAPPER;
|
||||
redir->from_lib = VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
|
||||
redir->from_sym = VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
|
||||
redir->from_addr = 0;
|
||||
redir->to_addr = 0;
|
||||
redir->wrapper = wrapper;
|
||||
|
||||
/* Check against all existing segments to see if this redirection
|
||||
can be resolved immediately */
|
||||
if (!resolve_redir_allsegs(redir)) {
|
||||
/* nope, add to list */
|
||||
redir->next = unresolved_redir;
|
||||
unresolved_redir = redir;
|
||||
TRACE_REDIR("REDIR sym to wrapper: %s:%s to (%p,%p)",
|
||||
from_lib, from_sym, wrapper->before, wrapper->after);
|
||||
|
||||
// Check against all existing segments to see if this redirection
|
||||
// can be resolved immediately. Then add it to the appropriate list.
|
||||
if (resolve_redir_with_existing_seginfos(redir)) {
|
||||
add_redir_to_resolved_list(redir);
|
||||
} else {
|
||||
add_redir_to_unresolved_list(redir);
|
||||
}
|
||||
|
||||
return redir;
|
||||
@ -341,7 +327,7 @@ Addr VG_(code_redirect)(Addr a)
|
||||
{
|
||||
CodeRedirect* r;
|
||||
|
||||
r = VG_(SkipList_Find_Exact)(&sk_resolved_redir, &a);
|
||||
r = VG_(SkipList_Find_Exact)(&sk_resolved_redirs, &a);
|
||||
if (r == NULL)
|
||||
return a;
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ extern Addr VG_(code_redirect) ( Addr orig );
|
||||
/* Set up some default redirects */
|
||||
extern void VG_(setup_code_redirect_table) ( void );
|
||||
|
||||
extern void VG_(resolve_seg_redirs)(SegInfo *si);
|
||||
extern void VG_(resolve_existing_redirs_with_seginfo)(SegInfo *si);
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user