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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 78e29ee..0f66a57 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -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 @@
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 @@
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 @@
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);
+ CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs);
- if (0)
- VG_(printf)("adding wrapper for %s:%s -> (%p,%p)\n",
- from_lib, from_sym, wrapper->before, wrapper->after);
-
- redir->type = R_WRAPPER;
-
+ 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 @@
{
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;