From: Nicholas Nethercote Date: Sun, 26 Jun 2005 04:49:25 +0000 (+0000) Subject: Cleaned up m_redir.c: renamed some variables and functions, added some X-Git-Tag: svn/VALGRIND_3_0_0~290 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c8f13ea9d32692724d80022e4a73daf66f3fad82;p=thirdparty%2Fvalgrind.git 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 --- diff --git a/coregrind/m_debuginfo/symtab.c b/coregrind/m_debuginfo/symtab.c index 379a5e8cd8..9a516b4544 100644 --- a/coregrind/m_debuginfo/symtab.c +++ b/coregrind/m_debuginfo/symtab.c @@ -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); diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index 78e29eeef1..0f66a57832 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 @@ struct _CodeRedirect { const Char *from_sym; /* symbol */ Addr from_addr; /* old addr */ - /* used for redirection */ - Addr to_addr; /* new addr */ - - /* used for wrapping */ - const FuncWrapper *wrapper; + Addr to_addr; /* used for redirection -- new addr */ + const FuncWrapper *wrapper; /* used for wrapping */ - 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); - - 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); - } + r = VG_(SkipList_Find_Exact)(&sk_resolved_redirs, &redir->from_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; } + + TRACE_REDIR(" Finished resolving"); } -static void add_redirect_X_to_addr( - const Char *from_lib, const Char *from_sym, Addr from_addr, Addr to_addr -) +/* 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 ) { - CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir); + CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs); - redir->type = R_REDIRECT; + vg_assert(0 != from_addr && 0 != to_addr); - 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->type = R_REDIRECT; + + redir->from_lib = NULL; + redir->from_sym = NULL; redir->from_addr = from_addr; - vg_assert(0 != to_addr); - redir->to_addr = to_addr; - redir->wrapper = 0; + 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); + TRACE_REDIR("REDIRECT addr to addr: %p to %p", 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; - } + // 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) +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); -} + CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs); -/* 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) -{ - add_redirect_X_to_addr(NULL, NULL, from_addr, to_addr); + 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; diff --git a/coregrind/pub_core_redir.h b/coregrind/pub_core_redir.h index 06f69b542c..37435887d5 100644 --- a/coregrind/pub_core_redir.h +++ b/coregrind/pub_core_redir.h @@ -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); //--------------------------------------------------------------------