|
From: Jeremy F. <je...@go...> - 2005-02-04 00:26:59
|
CVS commit by fitzhardinge:
Split the redirection machinery out of vg_symtab2 into its own file,
in preparation for the wrapping machinery.
A vg_redir.c 1.1 [GPL (v2+)]
M +1 -0 Makefile.am 1.107
M +13 -0 core.h 1.78
M +18 -314 vg_symtab2.c 1.101
--- valgrind/coregrind/core.h #1.77:1.78
@@ -1075,4 +1075,5 @@ void VG_(parse_procselfmaps) (
typedef struct _Segment Segment;
+typedef struct _CodeRedirect CodeRedirect;
extern Bool VG_(is_object_file) ( const void *hdr );
@@ -1084,10 +1085,22 @@ extern void VG_(symtab_decref) ( SegIn
extern Bool VG_(get_fnname_nodemangle)( Addr a, Char* fnname, Int n_fnname );
+extern Addr VG_(reverse_search_one_symtab) ( const SegInfo* si, const Char* name );
+
/* Set up some default redirects */
extern void VG_(setup_code_redirect_table) ( void );
+extern Bool VG_(resolve_redir_allsegs)(CodeRedirect *redir);
+
+/* ---------------------------------------------------------------------
+ Exports of vg_redir.c
+ ------------------------------------------------------------------ */
/* Redirection machinery */
extern Addr VG_(code_redirect) ( Addr orig );
+extern void VG_(add_redirect_addr)(const Char *from_lib, const Char *from_sym,
+ Addr to_addr);
+extern void VG_(resolve_seg_redirs)(SegInfo *si);
+extern Bool VG_(resolve_redir)(CodeRedirect *redir, const SegInfo *si);
+
/* ---------------------------------------------------------------------
Exports of vg_main.c
--- valgrind/coregrind/vg_symtab2.c #1.100:1.101
@@ -35,4 +35,6 @@
#include <elf.h> /* ELF defns */
+static SegInfo* segInfo = NULL;
+
static Bool
intercept_demangle(const Char*, Char*, Int);
@@ -834,13 +836,9 @@ intercept_demangle(const Char* symbol, C
}
-// Forward declaration
-static void add_redirect_addr(const Char *from_lib, const Char *from_sym,
- Addr to_addr);
-
static
void handle_intercept( SegInfo* si, Char* symbol, Elf32_Sym* sym)
{
int len = VG_(strlen)(symbol) + 1 - VG_INTERCEPT_PREFIX_LEN;
- char *lib = VG_(malloc)(len);
+ char *lib = VG_(arena_malloc)(VG_AR_SYMTAB, len);
Char *func;
@@ -851,6 +849,17 @@ void handle_intercept( SegInfo* si, Char
*func = '\0';
- add_redirect_addr(lib, func+1, si->offset + sym->st_value);
- VG_(free)(lib);
+ VG_(add_redirect_addr)(lib, func+1, si->offset + sym->st_value);
+ VG_(arena_free)(VG_AR_SYMTAB, lib);
+}
+
+Bool VG_(resolve_redir_allsegs)(CodeRedirect *redir)
+{
+ SegInfo *si;
+
+ for(si = segInfo; si != NULL; si = si->next)
+ if (VG_(resolve_redir)(redir, si))
+ return True;
+
+ return False;
}
@@ -1537,8 +1546,4 @@ Bool vg_read_lib_symbols ( SegInfo* si )
disjoint address ranges.
*/
-static SegInfo* segInfo = NULL;
-
-static void resolve_seg_redirs(SegInfo *si);
-
SegInfo *VG_(read_seg_symbols) ( Segment *seg )
{
@@ -1596,5 +1601,5 @@ SegInfo *VG_(read_seg_symbols) ( Segment
/* do redirects */
- resolve_seg_redirs( si );
+ VG_(resolve_seg_redirs)( si );
}
VGP_POPCC(VgpReadSyms);
@@ -1695,6 +1700,5 @@ static Int search_one_symtab ( SegInfo*
scan of the table. Returns NULL if not found. */
-static Addr reverse_search_one_symtab ( const SegInfo* si,
- const Char* name )
+Addr VG_(reverse_search_one_symtab) ( const SegInfo* si, const Char* name )
{
UInt i;
@@ -2224,304 +2228,4 @@ void VG_(mini_stack_dump) ( Addr eips[],
/*------------------------------------------------------------*/
-/*--- General purpose redirection. ---*/
-/*------------------------------------------------------------*/
-
-/* Set to True for debug printing. */
-static const Bool verbose_redir = False;
-
-
-/* resolved redirections, indexed by from_addr */
-typedef struct _CodeRedirect {
- const Char *from_lib; /* library qualifier pattern */
- const Char *from_sym; /* symbol */
- Addr from_addr; /* old addr */
-
- const Char *to_lib; /* library qualifier pattern */
- const Char *to_sym; /* symbol */
- Addr to_addr; /* new addr */
-
- struct _CodeRedirect *next; /* next pointer on unresolved list */
-} CodeRedirect;
-
-static Int addrcmp(const void *ap, const void *bp)
-{
- Addr a = *(Addr *)ap;
- Addr b = *(Addr *)bp;
- Int ret;
-
- if (a == b)
- ret = 0;
- else
- ret = (a < b) ? -1 : 1;
-
- return ret;
-}
-
-static Char *straddr(void *p)
-{
- static Char buf[16];
-
- VG_(sprintf)(buf, "%p", *(Addr *)p);
-
- return buf;
-}
-
-static SkipList sk_resolved_redir = SKIPLIST_INIT(CodeRedirect, from_addr,
- addrcmp, straddr, VG_AR_SYMTAB);
-static CodeRedirect *unresolved_redir = NULL;
-
-static Bool match_lib(const Char *pattern, const SegInfo *si)
-{
- /* pattern == NULL matches everything, otherwise use globbing
-
- If the pattern starts with:
- file:, then match filename
- soname:, then match soname
- something else, match filename
- */
- const Char *name = si->filename;
-
- if (pattern == NULL)
- return True;
-
- if (VG_(strncmp)(pattern, "file:", 5) == 0) {
- pattern += 5;
- name = si->filename;
- }
- if (VG_(strncmp)(pattern, "soname:", 7) == 0) {
- pattern += 7;
- name = si->soname;
- }
-
- if (name == NULL)
- return False;
-
- return VG_(string_match)(pattern, name);
-}
-
-/* Resolve a redir using si if possible, and add it to the resolved
- list */
-static Bool resolve_redir(CodeRedirect *redir, const SegInfo *si)
-{
- Bool resolved;
-
- vg_assert(si != NULL);
- vg_assert(si->seg != NULL);
-
- /* no redirection from Valgrind segments */
- if (si->seg->flags & SF_VALGRIND)
- return False;
-
- resolved = (redir->from_addr != 0) && (redir->to_addr != 0);
-
- if (0 && verbose_redir)
- VG_(printf)(" consider FROM binding %s:%s -> %s:%s in %s(%s)\n",
- redir->from_lib, redir->from_sym,
- redir->to_lib, redir->to_sym,
- si->filename, si->soname);
-
- vg_assert(!resolved);
-
- if (redir->from_addr == 0) {
- vg_assert(redir->from_sym != NULL);
-
- if (match_lib(redir->from_lib, si)) {
- redir->from_addr = reverse_search_one_symtab(si, redir->from_sym);
- if (verbose_redir && redir->from_addr != 0)
- VG_(printf)(" bind FROM: %p = %s:%s\n",
- redir->from_addr,redir->from_lib, redir->from_sym );
- }
- }
-
- if (redir->to_addr == 0) {
- vg_assert(redir->to_sym != NULL);
-
- if (match_lib(redir->to_lib, si)) {
- redir->to_addr = reverse_search_one_symtab(si, redir->to_sym);
- if (verbose_redir && redir->to_addr != 0)
- VG_(printf)(" bind TO: %p = %s:%s\n",
- redir->to_addr,redir->to_lib, redir->to_sym );
-
- }
- }
-
- resolved = (redir->from_addr != 0) && (redir->to_addr != 0);
-
- if (0 && verbose_redir)
- VG_(printf)("resolve_redir: %s:%s from=%p %s:%s to=%p\n",
- redir->from_lib, redir->from_sym, redir->from_addr,
- redir->to_lib, redir->to_sym, redir->to_addr);
-
- if (resolved) {
- if (VG_(clo_verbosity) > 2 || verbose_redir) {
- VG_(message)(Vg_DebugMsg, " redir resolved (%s:%s=%p -> ",
- redir->from_lib, redir->from_sym, redir->from_addr);
- VG_(message)(Vg_DebugMsg, " %s:%s=%p)",
- redir->to_lib, redir->to_sym, redir->to_addr);
- }
-
- if (VG_(search_transtab)(redir->from_addr) != 0) {
- /* For some given (from, to) redir, the "from" function got
- called before the .so containing "to" became available. We
- know this because there is already a translation for the
- entry point of the original "from". So the redirect will
- never actually take effect unless that translation is
- discarded.
-
- Note, we only really need to discard the first bb of the
- old entry point, and so we avoid the problem of having to
- figure out how big that bb was -- since it is at least 1
- byte of original code, we can just pass 1 as the original
- size to invalidate_translations() and it will indeed get
- rid of the translation.
-
- Note, this is potentially expensive -- discarding
- translations causes complete unchaining.
- */
- if (VG_(clo_verbosity) > 2) {
- 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 );
- }
- VG_(invalidate_translations)(redir->from_addr, 1, True);
- }
-
- {
- CodeRedirect *r = VG_(SkipList_Find_Exact)(&sk_resolved_redir, &redir->from_addr);
-
- if (r == NULL)
- VG_(SkipList_Insert)(&sk_resolved_redir, redir);
- else if (verbose_redir)
- VG_(message)(Vg_DebugMsg, " redir %s:%s:%p->%s:%s:%p duplicated\n",
- redir->from_lib, redir->from_sym, redir->from_addr,
- redir->to_lib, redir->to_sym, redir->to_addr);
- }
- }
-
- return resolved;
-}
-
-/* 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.
- */
-static void resolve_seg_redirs(SegInfo *si)
-{
- CodeRedirect **prevp = &unresolved_redir;
- CodeRedirect *redir, *next;
-
- if (verbose_redir)
- VG_(printf)("Considering redirs to/from %s(soname=%s)\n",
- si->filename, si->soname);
-
- /* visit each unresolved redir - if it becomes resolved, then
- remove it from the unresolved list */
- for(redir = unresolved_redir; redir != NULL; redir = next) {
- next = redir->next;
-
- if (resolve_redir(redir, si)) {
- *prevp = next;
- redir->next = NULL;
- } else
- prevp = &redir->next;
- }
-}
-
-static Bool resolve_redir_allsegs(CodeRedirect *redir)
-{
- SegInfo *si;
-
- for(si = segInfo; si != NULL; si = si->next)
- if (resolve_redir(redir, si))
- return True;
-
- return False;
-}
-
-/* Redirect a lib/symbol reference to a function at lib/symbol */
-static void add_redirect_sym(const Char *from_lib, const Char *from_sym,
- const Char *to_lib, const Char *to_sym)
-{
- CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
-
- 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_lib = VG_(arena_strdup)(VG_AR_SYMTAB, to_lib);
- redir->to_sym = VG_(arena_strdup)(VG_AR_SYMTAB, to_sym);
- redir->to_addr = 0;
-
- if (VG_(clo_verbosity) >= 2)
- VG_(message)(Vg_UserMsg,
- "REDIRECT %s(%s) to %s(%s)",
- from_lib, from_sym, to_lib, to_sym);
-
- if (!resolve_redir_allsegs(redir)) {
- /* can't resolve immediately; add to list */
- redir->next = unresolved_redir;
- unresolved_redir = redir;
- }
-}
-
-/* Redirect a lib/symbol reference to a function at lib/symbol */
-static void add_redirect_addr(const Char *from_lib, const Char *from_sym,
- Addr to_addr)
-{
- CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
-
- 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_lib = NULL;
- redir->to_sym = NULL;
- redir->to_addr = to_addr;
-
- if (!resolve_redir_allsegs(redir)) {
- /* can't resolve immediately; add to list */
- redir->next = unresolved_redir;
- unresolved_redir = redir;
- }
-}
-
-Addr VG_(code_redirect)(Addr a)
-{
- CodeRedirect *r = VG_(SkipList_Find_Exact)(&sk_resolved_redir, &a);
-
- if (r == NULL)
- return a;
-
- vg_assert(r->to_addr != 0);
-
- return r->to_addr;
-}
-
-void VG_(setup_code_redirect_table) ( void )
-{
- /* Redirect _dl_sysinfo_int80, which is glibc's default system call
- routine, to the routine in our trampoline page so that the
- special sysinfo unwind hack in vg_execontext.c will kick in.
- */
- add_redirect_addr("soname:ld-linux.so.2", "_dl_sysinfo_int80",
- VG_(client_trampoline_code)+VG_(tramp_syscall_offset));
-
- /* Overenthusiastic use of PLT bypassing by the glibc people also
- means we need to patch the following functions to our own
- implementations of said, in mac_replace_strmem.c.
- */
- add_redirect_sym("soname:libc.so.6", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
- add_redirect_sym("soname:libc.so.6", "strnlen",
- "*vgpreload_memcheck.so*", "strnlen");
- add_redirect_sym("soname:ld-linux.so.2", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
- add_redirect_sym("soname:ld-linux.so.2", "strchr",
- "*vgpreload_memcheck.so*", "strchr");
-}
-
-/*------------------------------------------------------------*/
/*--- SegInfo accessor functions ---*/
/*------------------------------------------------------------*/
--- valgrind/coregrind/Makefile.am #1.106:1.107
@@ -66,4 +66,5 @@
vg_signals.c \
vg_symtab2.c \
+ vg_redir.c \
vg_dwarf.c \
vg_stabs.c \
|