|
From: Jeremy F. <je...@go...> - 2005-02-04 01:08:47
|
CVS commit by fitzhardinge:
Hook into the existing redirection machinery to allow wrapped
functions to be requested symbolically.
M +18 -19 vg_main.c 1.244
M +152 -51 vg_redir.c 1.3
M +9 -1 vg_transtab.c 1.40
--- valgrind/coregrind/vg_redir.c #1.2:1.3
@@ -40,15 +40,37 @@
static const Bool verbose_redir = False;
+/*
+ wraps and redirections, indexed by from_addr
-/* resolved redirections, indexed by from_addr */
+ Redirection and wrapping are two distinct mechanisms which Valgrind
+ can use to change the client's control flow.
+
+ Redirection intercepts a call to a client function, and re-points it
+ to a new piece of code (presumably functionally equivalent). The
+ original code is never run.
+
+ Wrapping does call the client's original code, but calls "before"
+ and "after" functions which can inspect (and perhaps modify) the
+ function's arguments and return value.
+ */
struct _CodeRedirect {
+ enum redir_type {
+ R_REDIRECT, /* plain redirection */
+ R_WRAPPER, /* wrap with valgrind-internal code */
+ R_CLIENT_WRAPPER, /* wrap with client-side code */
+ } type;
+
const Char *from_lib; /* library qualifier pattern */
const Char *from_sym; /* symbol */
Addr from_addr; /* old addr */
+ /* used for redirection */
const Char *to_lib; /* library qualifier pattern */
const Char *to_sym; /* symbol */
Addr to_addr; /* new addr */
+ /* used for wrapping */
+ const FuncWrapper *wrapper;
+
CodeRedirect *next; /* next pointer on unresolved list */
};
@@ -110,4 +132,17 @@ static Bool match_lib(const Char *patter
}
+static inline Bool from_resolved(const CodeRedirect *redir)
+{
+ return redir->from_addr != 0;
+}
+
+static inline Bool to_resolved(const CodeRedirect *redir)
+{
+ if (redir->type == R_REDIRECT)
+ return redir->to_addr != 0;
+ vg_assert(redir->wrapper != NULL);
+ return True;
+}
+
/* Resolve a redir using si if possible, and add it to the resolved
list */
@@ -123,5 +158,5 @@ Bool VG_(resolve_redir)(CodeRedirect *re
return False;
- resolved = (redir->from_addr != 0) && (redir->to_addr != 0);
+ resolved = from_resolved(redir) && to_resolved(redir);
if (0 && verbose_redir)
@@ -133,5 +168,5 @@ Bool VG_(resolve_redir)(CodeRedirect *re
vg_assert(!resolved);
- if (redir->from_addr == 0) {
+ if (!from_resolved(redir)) {
vg_assert(redir->from_sym != NULL);
@@ -144,5 +179,6 @@ Bool VG_(resolve_redir)(CodeRedirect *re
}
- if (redir->to_addr == 0) {
+ if (!to_resolved(redir)) {
+ vg_assert(redir->type == R_REDIRECT);
vg_assert(redir->to_sym != NULL);
@@ -156,5 +192,5 @@ Bool VG_(resolve_redir)(CodeRedirect *re
}
- resolved = (redir->from_addr != 0) && (redir->to_addr != 0);
+ resolved = from_resolved(redir) && to_resolved(redir);
if (0 && verbose_redir)
@@ -164,4 +200,6 @@ Bool VG_(resolve_redir)(CodeRedirect *re
if (resolved) {
+ switch(redir->type) {
+ case R_REDIRECT:
if (VG_(clo_verbosity) > 2 || verbose_redir) {
VG_(message)(Vg_DebugMsg, " redir resolved (%s:%s=%p -> ",
@@ -204,5 +242,7 @@ Bool VG_(resolve_redir)(CodeRedirect *re
if (r == NULL)
VG_(SkipList_Insert)(&sk_resolved_redir, redir);
- else if (verbose_redir)
+ else {
+ /* XXX leak redir */
+ 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,
@@ -210,4 +250,21 @@ Bool VG_(resolve_redir)(CodeRedirect *re
}
}
+ break;
+
+ case R_WRAPPER:
+ if (VG_(clo_verbosity) > 2 || verbose_redir) {
+ VG_(message)(Vg_DebugMsg, " redir resolved (%s:%s=%p -> wrapper)",
+ redir->from_lib, redir->from_sym, redir->from_addr);
+ }
+
+ /* XXX redir leaked */
+ VG_(wrap_function)(redir->from_addr, redir->wrapper);
+ break;
+
+ case R_CLIENT_WRAPPER:
+ VG_(core_panic)("not implemented");
+ break;
+ }
+ }
return resolved;
@@ -246,4 +303,6 @@ static void add_redirect_sym(const Char
CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
+ 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);
@@ -259,6 +318,8 @@ static void add_redirect_sym(const Char
from_lib, from_sym, to_lib, to_sym);
+ /* Check against all existing segments to see if this redirection
+ can be resolved immediately */
if (!VG_(resolve_redir_allsegs)(redir)) {
- /* can't resolve immediately; add to list */
+ /* nope, add to list */
redir->next = unresolved_redir;
unresolved_redir = redir;
@@ -266,5 +327,5 @@ static void add_redirect_sym(const Char
}
-/* Redirect a lib/symbol reference to a function at lib/symbol */
+/* Redirect a lib/symbol reference to a function at addr */
void VG_(add_redirect_addr)(const Char *from_lib, const Char *from_sym,
Addr to_addr)
@@ -272,4 +333,6 @@ void VG_(add_redirect_addr)(const Char *
CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
+ 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);
@@ -280,6 +343,8 @@ void VG_(add_redirect_addr)(const Char *
redir->to_addr = to_addr;
+ /* Check against all existing segments to see if this redirection
+ can be resolved immediately */
if (!VG_(resolve_redir_allsegs)(redir)) {
- /* can't resolve immediately; add to list */
+ /* nope, add to list */
redir->next = unresolved_redir;
unresolved_redir = redir;
@@ -287,4 +352,36 @@ void VG_(add_redirect_addr)(const Char *
}
+void 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;
+
+ 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 = 0;
+
+ redir->wrapper = wrapper;
+
+ /* Check against all existing segments to see if this redirection
+ can be resolved immediately */
+ if (!VG_(resolve_redir_allsegs)(redir)) {
+ /* nope, add to list */
+ redir->next = unresolved_redir;
+ unresolved_redir = redir;
+ }
+}
+
+ /* If address 'a' is being redirected, return the redirected-to
+ address. */
Addr VG_(code_redirect)(Addr a)
{
@@ -444,4 +541,5 @@ void VG_(wrap_after)(ThreadState *tst)
struct call_instance *call = find_call(EIP, ESP, tst->tid);
+ VG_(printf)("wrap_after(%p,%p,%d) -> %p\n", EIP, ESP, tst->tid, call);
if (call != NULL) {
if (call->wrapper->after)
@@ -476,4 +574,7 @@ void VG_(wrap_function)(Addr eip, const
struct wrapped_function *func;
+ if (0)
+ VG_(printf)("wrapping %p with (%p,%p)\n", eip, wrapper->before, wrapper->after);
+
func = VG_(SkipList_Find_Exact)(&wrapped_functions, &eip);
--- valgrind/coregrind/vg_main.c #1.243:1.244
@@ -2548,4 +2548,22 @@ int main(int argc, char **argv, char **e
//--------------------------------------------------------------
+ // Allow GDB attach
+ // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
+ //--------------------------------------------------------------
+ /* Hook to delay things long enough so we can get the pid and
+ attach GDB in another shell. */
+ if (VG_(clo_wait_for_gdb)) {
+ VG_(printf)("pid=%d\n", VG_(getpid)());
+ /* do "jump *$eip" to skip this in gdb */
+ VG_(do_syscall)(__NR_pause);
+ }
+
+ //--------------------------------------------------------------
+ // Read debug info to find glibc entry points to intercept
+ // p: parse_procselfmaps? [XXX for debug info?]
+ //--------------------------------------------------------------
+ VG_(setup_code_redirect_table)();
+
+ //--------------------------------------------------------------
// Build segment map (all segments)
// p: shadow/redzone segments
@@ -2577,16 +2595,4 @@ int main(int argc, char **argv, char **e
//--------------------------------------------------------------
- // Allow GDB attach
- // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
- //--------------------------------------------------------------
- /* Hook to delay things long enough so we can get the pid and
- attach GDB in another shell. */
- if (VG_(clo_wait_for_gdb)) {
- VG_(printf)("pid=%d\n", VG_(getpid)());
- /* do "jump *$eip" to skip this in gdb */
- VG_(do_syscall)(__NR_pause);
- }
-
- //--------------------------------------------------------------
// Search for file descriptors that are inherited from our parent
// p: process_cmd_line_options [for VG_(clo_track_fds)]
@@ -2641,11 +2647,4 @@ int main(int argc, char **argv, char **e
//--------------------------------------------------------------
- // Read debug info to find glibc entry points to intercept
- // p: parse_procselfmaps? [XXX for debug info?]
- // p: init_tt_tc? [XXX ???]
- //--------------------------------------------------------------
- VG_(setup_code_redirect_table)();
-
- //--------------------------------------------------------------
// Verbosity message
// p: end_rdtsc_calibration [so startup message is printed first]
--- valgrind/coregrind/vg_transtab.c #1.39:1.40
@@ -618,4 +618,8 @@ Addr VG_(search_transtab) ( Addr origina
{
TTEntry* tte;
+
+ if (vg_tt == NULL)
+ return 0;
+
VGP_PUSHCC(VgpSlowFindT);
tte = search_tt ( original_addr );
@@ -647,4 +651,8 @@ void VG_(invalidate_translations) ( Addr
Int i, j;
TCEntry* tce;
+
+ if (vg_tt == NULL)
+ return;
+
# ifdef DEBUG_TRANSTAB
VG_(sanity_check_tt_tc)();
@@ -670,5 +678,5 @@ void VG_(invalidate_translations) ( Addr
tce->orig_addr = VG_TTE_DELETED;
- if (unchain_blocks) {
+ if (VG_(clo_chain_bb) && unchain_blocks) {
/* make sure no other blocks chain to the one we just discarded */
for(j = 0; j < VG_TC_N_SECTORS; j++) {
|