|
From: <sv...@va...> - 2005-05-29 17:01:51
|
Author: njn
Date: 2005-05-29 18:01:48 +0100 (Sun, 29 May 2005)
New Revision: 3808
Added:
trunk/coregrind/m_redir.c
Removed:
trunk/coregrind/amd64-linux/core_platform.c
trunk/coregrind/vg_redir.c
trunk/coregrind/x86-linux/core_platform.c
Modified:
trunk/coregrind/Makefile.am
trunk/coregrind/amd64-linux/Makefile.am
trunk/coregrind/arm-linux/Makefile.am
trunk/coregrind/core.h
trunk/coregrind/m_translate.c
trunk/coregrind/vg_main.c
trunk/coregrind/vg_symtab2.c
trunk/coregrind/x86-linux/Makefile.am
Log:
Modularised m_redir. As a side-effect, managed to remove
$PLATFORM/core_platform.c and $PLATFORM/libplatform.a, hooray.
Modified: trunk/coregrind/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/Makefile.am 2005-05-29 16:23:17 UTC (rev 3807)
+++ trunk/coregrind/Makefile.am 2005-05-29 17:01:48 UTC (rev 3808)
@@ -45,6 +45,7 @@
pub_core_hashtable.h \
pub_core_mallocfree.h \
pub_core_options.h \
+ pub_core_redir.h \
pub_core_replacemalloc.h\
pub_core_sigframe.h \
pub_core_skiplist.h \
@@ -79,6 +80,7 @@
m_hashtable.c \
m_mallocfree.c \
m_options.c \
+ m_redir.c \
m_skiplist.c \
m_stacktrace.c \
m_tooliface.c \
@@ -95,19 +97,16 @@
vg_symtab2.c \
vg_threadmodel.c \
vg_pthreadmodel.c \
- vg_redir.c \
vg_dwarf.c \
vg_stabs.c \
vg_symtypes.c
=20
-## libplatform.a must be before libarch.a and libos.a, it seems.
stage2_extra=3D \
m_dispatch/libdispatch.a \
m_demangle/libdemangle.a \
m_aspacemgr/libaspacemgr.a \
m_sigframe/libsigframe.a \
m_syscalls/libsyscalls.a \
- ${VG_PLATFORM}/libplatform.a \
${VG_ARCH}/libarch.a \
${VG_OS}/libos.a \
@VEX_DIR@/libvex.a
Modified: trunk/coregrind/amd64-linux/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/amd64-linux/Makefile.am 2005-05-29 16:23:17 UTC (rev =
3807)
+++ trunk/coregrind/amd64-linux/Makefile.am 2005-05-29 17:01:48 UTC (rev =
3808)
@@ -4,9 +4,3 @@
noinst_HEADERS =3D \
core_platform.h \
vki_unistd.h
-
-noinst_LIBRARIES =3D libplatform.a
-
-
-libplatform_a_SOURCES =3D \
- core_platform.c
Deleted: trunk/coregrind/amd64-linux/core_platform.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/amd64-linux/core_platform.c 2005-05-29 16:23:17 UTC (=
rev 3807)
+++ trunk/coregrind/amd64-linux/core_platform.c 2005-05-29 17:01:48 UTC (=
rev 3808)
@@ -1,10 +0,0 @@
-#include "core.h"
-
-void VGP_(setup_redirects)(void)
-{
- /* Redirect vsyscalls to local versions */
- VG_(add_redirect_addr_to_addr)(0xFFFFFFFFFF600000ULL,
- VG_(client_trampoline_code)+VG_(tramp_=
gettimeofday_offset));
- VG_(add_redirect_addr_to_addr)(0xFFFFFFFFFF600400ULL,
- VG_(client_trampoline_code)+VG_(tramp_=
time_offset));
-}
Modified: trunk/coregrind/arm-linux/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/arm-linux/Makefile.am 2005-05-29 16:23:17 UTC (rev 38=
07)
+++ trunk/coregrind/arm-linux/Makefile.am 2005-05-29 17:01:48 UTC (rev 38=
08)
@@ -4,8 +4,3 @@
noinst_HEADERS =3D \
core_platform.h \
vki_unistd.h
-
-noinst_LIBRARIES =3D libplatform.a
-
-libplatform_a_SOURCES =3D
-
Modified: trunk/coregrind/core.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/core.h 2005-05-29 16:23:17 UTC (rev 3807)
+++ trunk/coregrind/core.h 2005-05-29 17:01:48 UTC (rev 3808)
@@ -489,45 +489,6 @@
=20
=20
/* ---------------------------------------------------------------------
- Exports of vg_redir.c
- ------------------------------------------------------------------ */
-
-/* Redirection machinery */
-extern Addr VG_(code_redirect) ( Addr orig );
-
-/* Set up some default redirects */
-extern void VG_(setup_code_redirect_table) ( void );
-
-extern void VG_(add_redirect_sym_to_addr)(const Char *from_lib,
- const Char *from_sym,
- Addr to_addr);
-extern void VG_(add_redirect_addr_to_addr)(Addr from_addr, Addr to_addr)=
;
-extern void VG_(resolve_seg_redirs)(SegInfo *si);
-
-/* Wrapping machinery */
-enum return_type {
- RT_RETURN,
- RT_LONGJMP,
- RT_EXIT,
-};
-
-typedef struct _FuncWrapper FuncWrapper;
-struct _FuncWrapper {
- void *(*before)(va_list args);
- void (*after) (void *nonce, enum return_type, Word retval);
-};
-
-extern void VG_(wrap_function)(Addr eip, const FuncWrapper *wrapper);
-extern const FuncWrapper *VG_(is_wrapped)(Addr eip);
-extern Bool VG_(is_wrapper_return)(Addr eip);
-
-/* Primary interface for adding wrappers for client-side functions. */
-extern CodeRedirect *VG_(add_wrapper)(const Char *from_lib, const Char *=
from_sym,
- const FuncWrapper *wrapper);
-
-extern Bool VG_(is_resolved)(const CodeRedirect *redir);
-
-/* ---------------------------------------------------------------------
Exports of vg_main.c
------------------------------------------------------------------ */
=20
@@ -688,13 +649,6 @@
extern Bool VGA_(client_requests)(ThreadId tid, UWord *args);
=20
=20
-// ---------------------------------------------------------------------
-// Platform-specific things defined in eg. x86/*.c
-// ---------------------------------------------------------------------
-
-// Do any platform specific redirects.
-extern void VGP_(setup_redirects)(void);
-
///* -------------------------------------------------------------------=
--
// Thread modelling
// ------------------------------------------------------------------ =
*/
Copied: trunk/coregrind/m_redir.c (from rev 3807, trunk/coregrind/vg_redi=
r.c)
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_redir.c 2005-05-29 16:23:17 UTC (rev 3807)
+++ trunk/coregrind/m_redir.c 2005-05-29 17:01:48 UTC (rev 3808)
@@ -0,0 +1,726 @@
+/*--------------------------------------------------------------------*/
+/*--- Management of function redirection and wrapping. ---*/
+/*--- vg_redir.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, an extensible x86 protected-mode
+ emulator for monitoring program execution on x86-Unixes.
+
+ Copyright (C) 2000-2005 Julian Seward=20
+ js...@ac...
+ Copyright (C) 2003-2005 Jeremy Fitzhardinge
+ je...@go...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+#include "core.h"
+#include "vg_symtab2.h"
+
+#include "pub_core_aspacemgr.h"
+#include "pub_core_skiplist.h"
+#include "pub_core_options.h"
+#include "pub_core_redir.h"
+#include "pub_core_transtab.h"
+
+/*------------------------------------------------------------*/
+/*--- General purpose redirection. ---*/
+/*------------------------------------------------------------*/
+
+/*
+ wraps and 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;
+ =20
+ 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 */
+};
+
+static Char *straddr(void *p)
+{
+ static Char buf[16];
+
+ VG_(sprintf)(buf, "%p", *(Addr *)p);
+
+ return buf;
+}
+
+static SkipList sk_resolved_redir =3D VG_SKIPLIST_INIT(CodeRedirect, fro=
m_addr,=20
+ VG_(cmp_Addr), straddr, VG_AR_SYMTAB);
+static CodeRedirect *unresolved_redir =3D NULL;
+
+static Bool match_lib(const Char *pattern, const SegInfo *si)
+{
+ /* pattern =3D=3D 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 =3D si->filename;
+
+ if (pattern =3D=3D NULL)
+ return True;
+
+ if (VG_(strncmp)(pattern, "file:", 5) =3D=3D 0) {
+ pattern +=3D 5;
+ name =3D si->filename;
+ }
+ if (VG_(strncmp)(pattern, "soname:", 7) =3D=3D 0) {
+ pattern +=3D 7;
+ name =3D si->soname;
+ }
+
+ if (name =3D=3D NULL)
+ return False;
+ =20
+ return VG_(string_match)(pattern, name);
+}
+
+static inline Bool from_resolved(const CodeRedirect *redir)
+{
+ return redir->from_addr !=3D 0;
+}
+
+static inline Bool to_resolved(const CodeRedirect *redir)
+{
+ if (redir->type =3D=3D R_REDIRECT)
+ return redir->to_addr !=3D 0;
+ vg_assert(redir->wrapper !=3D NULL);
+ return True;
+}
+
+Bool VG_(is_resolved)(const CodeRedirect *redir)
+{
+ return from_resolved(redir) && to_resolved(redir);
+}
+
+static void add_resolved(CodeRedirect *redir)
+{
+ switch(redir->type) {
+ case R_REDIRECT:
+ if (VG_(clo_trace_redir)) {
+ VG_(message)(Vg_DebugMsg, " redir resolved (%s:%s=3D%p -> ",
+ redir->from_lib, redir->from_sym, redir->from_addr=
);
+ VG_(message)(Vg_DebugMsg, " %s:%s=3D%p)",
+ redir->to_lib, redir->to_sym, redir->to_addr);
+ }
+
+ if (VG_(search_transtab)(NULL, (Addr64)redir->from_addr, False)) {
+ /* 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. =20
+
+ 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.=20
+
+ Note, this is potentially expensive -- discarding
+ translations causes complete unchaining. =20
+ */
+ if (VG_(clo_verbosity) > 2 && VG_(clo_trace_redir)) {
+ VG_(message)(Vg_UserMsg, =20
+ "Discarding translation due to redirect of alre=
ady called function" );
+ VG_(message)(Vg_UserMsg,
+ " %s (%p -> %p)",
+ redir->from_sym, redir->from_addr, redir->to_ad=
dr );
+ }
+ VG_(discard_translations)((Addr64)redir->from_addr, 1);
+ }
+
+ {
+ CodeRedirect *r =3D VG_(SkipList_Find_Exact)(&sk_resolved_redir=
, &redir->from_addr);
+
+ if (r =3D=3D 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->%s:%s:%p dup=
licated\n",
+ redir->from_lib, redir->from_sym, redir->fro=
m_addr,
+ redir->to_lib, redir->to_sym, redir->to_addr=
);
+ }
+ }
+ break;
+
+ case R_WRAPPER:
+ if (VG_(clo_trace_redir)) {
+ VG_(message)(Vg_DebugMsg, " wrapper resolved (%s:%s=3D%p -> wr=
apper)",
+ 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;
+ }
+}
+
+/* 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 !=3D NULL);
+ vg_assert(si->seg !=3D NULL);
+
+ /* no redirection from Valgrind segments */
+ if (si->seg->flags & SF_VALGRIND)
+ return False;
+
+ resolved =3D VG_(is_resolved)(redir);
+
+ if (0 && VG_(clo_trace_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 (!from_resolved(redir)) {
+ vg_assert(redir->from_sym !=3D NULL);
+
+ if (match_lib(redir->from_lib, si)) {
+ redir->from_addr =3D VG_(reverse_search_one_symtab)(si, redir->from_sy=
m);
+ if (VG_(clo_trace_redir) && redir->from_addr !=3D 0)
+ VG_(printf)(" bind FROM: %p =3D %s:%s\n",=20
+ redir->from_addr,redir->from_lib, redir->from_sy=
m );
+ }
+ }
+
+ if (!to_resolved(redir)) {
+ vg_assert(redir->type =3D=3D R_REDIRECT);
+ vg_assert(redir->to_sym !=3D NULL);
+
+ if (match_lib(redir->to_lib, si)) {
+ redir->to_addr =3D VG_(reverse_search_one_symtab)(si, redir->to_sym);
+ if (VG_(clo_trace_redir) && redir->to_addr !=3D 0)
+ VG_(printf)(" bind TO: %p =3D %s:%s\n",=20
+ redir->to_addr,redir->to_lib, redir->to_sym );
+
+ }
+ }
+
+ resolved =3D from_resolved(redir) && to_resolved(redir);
+
+ if (0 && VG_(clo_trace_redir))
+ VG_(printf)("resolve_redir: %s:%s from=3D%p %s:%s to=3D%p\n",
+ redir->from_lib, redir->from_sym, redir->from_addr,=20
+ redir->to_lib, redir->to_sym, redir->to_addr);
+
+ if (resolved) add_resolved(redir);
+
+ return resolved;
+}
+
+static Bool resolve_redir_allsegs(CodeRedirect *redir)
+{
+ const SegInfo *si;
+
+ for(si =3D VG_(next_seginfo)(NULL);=20
+ si !=3D NULL;=20
+ si =3D VG_(next_seginfo)(si))
+ {
+ if (resolve_redir(redir, si))
+ return True;
+ }
+ return False;
+}
+
+/* Go through the complete redir list, resolving as much as possible wit=
h this SegInfo.
+
+ This should be called when a new SegInfo symtab is loaded.
+ */
+void VG_(resolve_seg_redirs)(SegInfo *si)
+{
+ CodeRedirect **prevp =3D &unresolved_redir;
+ CodeRedirect *redir, *next;
+
+ if (VG_(clo_trace_redir))
+ VG_(printf)("Considering redirs to/from %s(soname=3D%s)\n",
+ si->filename, si->soname);
+
+ /* visit each unresolved redir - if it becomes resolved, then
+ remove it from the unresolved list */
+ for(redir =3D unresolved_redir; redir !=3D NULL; redir =3D next) {
+ next =3D redir->next;
+
+ if (resolve_redir(redir, si)) {
+ *prevp =3D next;
+ redir->next =3D NULL;
+ } else
+ prevp =3D &redir->next;
+ }
+}
+
+/* Redirect a lib/symbol reference to a function at lib/symbol */
+static void add_redirect_sym_to_sym(const Char *from_lib, const Char *fr=
om_sym,
+ const Char *to_lib, const Char *to_sym)
+{
+ CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
+
+ redir->type =3D R_REDIRECT;
+
+ redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
+ redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
+ redir->from_addr =3D 0;
+
+ redir->to_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, to_lib);
+ redir->to_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, to_sym);
+ redir->to_addr =3D 0;
+
+ if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
+ VG_(message)(Vg_UserMsg,=20
+ "REDIRECT %s(%s) to %s(%s)",
+ from_lib, from_sym, to_lib, to_sym);
+
+ /* 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 =3D unresolved_redir;
+ unresolved_redir =3D redir;
+ }
+}
+
+/* Redirect a lib/symbol reference to a function at addr */
+void VG_(add_redirect_sym_to_addr)(const Char *from_lib, const Char *fro=
m_sym,
+ Addr to_addr)
+{
+ CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
+
+ redir->type =3D R_REDIRECT;
+
+ redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
+ redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
+ redir->from_addr =3D 0;
+
+ redir->to_lib =3D NULL;
+ redir->to_sym =3D NULL;
+ redir->to_addr =3D to_addr;
+
+ if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
+ VG_(message)(Vg_UserMsg,=20
+ "REDIRECT %s(%s) to %p",
+ from_lib, from_sym, to_addr);
+
+ /* 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 =3D unresolved_redir;
+ unresolved_redir =3D redir;
+ }
+}
+
+/* Redirect a function at from_addr to a function at to_addr */
+void VG_(add_redirect_addr_to_addr)(Addr from_addr, Addr to_addr)
+{
+ CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
+
+ redir->type =3D R_REDIRECT;
+
+ redir->from_lib =3D NULL;
+ redir->from_sym =3D NULL;
+ redir->from_addr =3D from_addr;
+
+ redir->to_lib =3D NULL;
+ redir->to_sym =3D NULL;
+ redir->to_addr =3D to_addr;
+
+ if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
+ VG_(message)(Vg_UserMsg,=20
+ "REDIRECT %p to %p",
+ from_addr, to_addr);
+
+ add_resolved(redir);
+}
+
+CodeRedirect *VG_(add_wrapper)(const Char *from_lib, const Char *from_sy=
m,
+ const FuncWrapper *wrapper)
+{
+ CodeRedirect *redir =3D 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 =3D R_WRAPPER;
+
+ redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
+ redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
+ redir->from_addr =3D 0;
+
+ redir->to_lib =3D NULL;
+ redir->to_sym =3D NULL;
+ redir->to_addr =3D 0;
+
+ redir->wrapper =3D wrapper;
+ =20
+ /* 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 =3D unresolved_redir;
+ unresolved_redir =3D redir;
+ }
+
+ return redir;
+}
+
+/* If address 'a' is being redirected, return the redirected-to
+ address. */
+Addr VG_(code_redirect)(Addr a)
+{
+ CodeRedirect* r;
+
+ r =3D VG_(SkipList_Find_Exact)(&sk_resolved_redir, &a);
+ if (r =3D=3D NULL)
+ return a;
+
+ vg_assert(r->to_addr !=3D 0);
+
+ return r->to_addr;
+}
+
+void VG_(setup_code_redirect_table) ( void )
+{
+ /* 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_to_sym("soname:libc.so.6", "stpcpy",
+ "*vgpreload_memcheck.so*", "stpcpy");
+
+ add_redirect_sym_to_sym("soname:ld-linux.so.2", "strlen",
+ "*vgpreload_memcheck.so*", "strlen");
+ add_redirect_sym_to_sym("soname:libc.so.6", "strlen",
+ "*vgpreload_memcheck.so*", "strlen");
+
+ add_redirect_sym_to_sym("soname:libc.so.6", "strnlen",
+ "*vgpreload_memcheck.so*", "strnlen");
+
+ add_redirect_sym_to_sym("soname:ld-linux.so.2", "stpcpy",
+ "*vgpreload_memcheck.so*", "stpcpy");
+ add_redirect_sym_to_sym("soname:libc.so.6", "stpcpy",
+ "*vgpreload_memcheck.so*", "stpcpy");
+
+ add_redirect_sym_to_sym("soname:libc.so.6", "strchr",
+ "*vgpreload_memcheck.so*", "strchr");
+ add_redirect_sym_to_sym("soname:ld-linux.so.2", "strchr",
+ "*vgpreload_memcheck.so*", "strchr");
+
+ /* apparently index is the same thing as strchr */
+ add_redirect_sym_to_sym("soname:ld-linux.so.2", "index",
+ "*vgpreload_memcheck.so*", "strchr");
+
+ add_redirect_sym_to_sym("soname:libc.so.6", "strchrnul",
+ "*vgpreload_memcheck.so*", "glibc232_strchrnu=
l");
+
+ add_redirect_sym_to_sym("soname:libc.so.6", "rawmemchr",
+ "*vgpreload_memcheck.so*", "glibc232_rawmemch=
r");
+
+ /* amd64-linux (glibc 2.3.3, SuSE 9.2) */
+ /* apparently index is the same thing as strchr */
+ add_redirect_sym_to_sym("soname:libc.so.6", "index",
+ "*vgpreload_memcheck.so*", "strchr");
+ add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "index",
+ "*vgpreload_memcheck.so*", "strchr");
+
+ add_redirect_sym_to_sym("soname:libc.so.6", "strcpy",
+ "*vgpreload_memcheck.so*", "strcpy");
+
+ add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "strcmp",
+ "*vgpreload_memcheck.so*", "strcmp");
+ add_redirect_sym_to_sym("soname:libc.so.6", "strcmp",
+ "*vgpreload_memcheck.so*", "strcmp");
+
+ add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "strlen",
+ "*vgpreload_memcheck.so*", "strlen");
+
+#if defined(VGP_x86_linux)
+ /* 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 m_stacktrace.c will kick in. */
+ VG_(add_redirect_sym_to_addr)("soname:ld-linux.so.2", "_dl_sysinfo_in=
t80",
+ VG_(client_trampoline_code)+VG_(tramp_s=
yscall_offset));
+#elif defined(VGP_amd64_linux)
+ /* Redirect vsyscalls to local versions */
+ VG_(add_redirect_addr_to_addr)(0xFFFFFFFFFF600000ULL,
+ VG_(client_trampoline_code)+VG_(tramp_=
gettimeofday_offset));
+ VG_(add_redirect_addr_to_addr)(0xFFFFFFFFFF600400ULL,
+ VG_(client_trampoline_code)+VG_(tramp_=
time_offset));
+#else
+# error Unknown platform
+#endif
+}
+
+//:: /*------------------------------------------------------------*/
+//:: /*--- General function wrapping. ---*/
+//:: /*------------------------------------------------------------*/
+//::=20
+//:: /*=20
+//:: TODO:
+//:: - hook into the symtab machinery
+//:: - client-side wrappers?
+//:: - better interfaces for before() functions to get to arguments
+//:: - handle munmap of code (dlclose())
+//:: - handle thread exit
+//:: - handle longjmp
+//:: */
+//:: struct callkey {
+//:: ThreadId tid; /* calling thread */
+//:: Addr esp; /* address of args on stack */
+//:: Addr eip; /* return address */
+//:: };
+//::=20
+//:: struct call_instance {
+//:: struct callkey key;
+//::=20
+//:: const FuncWrapper *wrapper;
+//:: void *nonce;
+//:: };
+//::=20
+//:: static inline Addr addrcmp(Addr a, Addr b)
+//:: {
+//:: if (a < b)
+//:: return -1;
+//:: else if (a > b)
+//:: return 1;
+//:: else=20
+//:: return 0;
+//:: }
+//::=20
+//:: static inline Int cmp(UInt a, UInt b)
+//:: {
+//:: if (a < b)
+//:: return -1;
+//:: else if (a > b)
+//:: return 1;
+//:: else=20
+//:: return 0;
+//:: }
+//::=20
+//:: static Int keycmp(const void *pa, const void *pb)
+//:: {
+//:: const struct callkey *a =3D (const struct callkey *)pa;
+//:: const struct callkey *b =3D (const struct callkey *)pb;
+//:: Int ret;
+//::=20
+//:: if ((ret =3D cmp(a->tid, b->tid)))
+//:: return ret;
+//::=20
+//:: if ((ret =3D addrcmp(a->esp, b->esp)))
+//:: return ret;
+//::=20
+//:: return addrcmp(a->eip, b->eip);
+//:: }
+//::=20
+//:: /* List of wrapped call invocations which are currently active */
+//:: static SkipList wrapped_frames =3D VG_SKIPLIST_INIT(struct call_ins=
tance, key, keycmp,=20
+//:: NULL, VG_AR_SYMTAB);
+//::=20
+//:: static struct call_instance *find_call(Addr retaddr, Addr argsp, Th=
readId tid)
+//:: {
+//:: struct callkey key =3D { tid, argsp, retaddr };
+//::=20
+//:: return VG_(SkipList_Find_Exact)(&wrapped_frames, &key);
+//:: }
+//::=20
+//:: static void wrapper_return(Addr retaddr);
+//::=20
+//:: /* Called from generated code via helper */
+//:: void VG_(wrap_before)(ThreadState *tst, const FuncWrapper *wrapper)
+//:: {
+//:: Addr retaddr =3D VGA_RETADDR(tst->arch);
+//:: Addr argp =3D (Addr)&VGA_FUNC_ARG(tst->arch, 0);
+//:: void *nonce =3D NULL;
+//:: Bool mf =3D VG_(my_fault);
+//:: VG_(my_fault) =3D True;
+//::=20
+//:: if (wrapper->before) {
+//:: va_list args =3D VGA_VA_LIST(tst->arch);
+//:: nonce =3D (*wrapper->before)(args);
+//:: }
+//::=20
+//:: if (wrapper->after) {
+//:: /* If there's an after function, make sure it gets called */
+//:: struct call_instance *call;
+//::=20
+//:: call =3D find_call(retaddr, argp, tst->tid);
+//::=20
+//:: if (call !=3D NULL) {
+//:: /* Found a stale outstanding call; clean it up and recycle
+//:: the structure */
+//:: if (call->wrapper->after)
+//:: (*call->wrapper->after)(call->nonce, RT_LONGJMP, 0);
+//:: } else {
+//:: call =3D VG_(SkipNode_Alloc)(&wrapped_frames);
+//:: =20
+//:: call->key.tid =3D tst->tid;
+//:: call->key.esp =3D argp;
+//:: call->key.eip =3D retaddr;
+//::=20
+//:: VG_(SkipList_Insert)(&wrapped_frames, call);
+//::=20
+//:: wrapper_return(retaddr);
+//:: }
+//::=20
+//:: call->wrapper =3D wrapper;
+//:: call->nonce =3D nonce;
+//:: } else=20
+//:: vg_assert(nonce =3D=3D NULL);
+//::=20
+//:: VG_(my_fault) =3D mf;
+//:: }
+//::=20
+//:: /* Called from generated code via helper */
+//:: void VG_(wrap_after)(ThreadState *tst)
+//:: {
+//:: Addr EIP =3D VGA_INSTR_PTR(tst->arch); /* instruction after call=
*/
+//:: Addr ESP =3D VGA_STACK_PTR(tst->arch); /* pointer to args */
+//:: Word ret =3D VGA_RETVAL(tst->arch); /* return value */
+//:: struct call_instance *call;
+//:: Bool mf =3D VG_(my_fault);
+//::=20
+//:: VG_(my_fault) =3D True;
+//:: call =3D find_call(EIP, ESP, tst->tid);
+//::=20
+//:: if (0)
+//:: VG_(printf)("wrap_after(%p,%p,%d) -> %p\n", EIP, ESP, tst->ti=
d, call);
+//::=20
+//:: if (call !=3D NULL) {
+//:: if (call->wrapper->after)
+//:: (*call->wrapper->after)(call->nonce, RT_RETURN, ret);
+//::=20
+//:: VG_(SkipList_Remove)(&wrapped_frames, &call->key);
+//:: VG_(SkipNode_Free)(&wrapped_frames, call);
+//:: }
+//:: VG_(my_fault) =3D mf;
+//:: }
+//::=20
+//::=20
+//:: struct wrapped_function {
+//:: Addr eip; /* eip of function entrypoint */
+//:: const FuncWrapper *wrapper;
+//:: };
+//::=20
+//:: struct wrapper_return {
+//:: Addr eip; /* return address */
+//:: };
+//::=20
+//:: /* A mapping from eip of wrapped function entrypoints to actual wra=
ppers */
+//:: static SkipList wrapped_functions =3D VG_SKIPLIST_INIT(struct wrapp=
ed_function, eip, VG_(cmp_Addr),
+//:: NULL, VG_AR_SYMTAB);
+//::=20
+//:: /* A set of EIPs which are return addresses for wrapped functions *=
/
+//:: static SkipList wrapper_returns =3D VG_SKIPLIST_INIT(struct wrapper=
_return, eip, VG_(cmp_Addr),
+//:: NULL, VG_AR_SYMTAB);
+//::=20
+//:: /* Wrap function starting at eip */
+//:: void VG_(wrap_function)(Addr eip, const FuncWrapper *wrapper)
+//:: {
+//:: struct wrapped_function *func;
+//::=20
+//:: if (0)
+//:: VG_(printf)("wrapping %p with (%p,%p)\n", eip, wrapper->befor=
e, wrapper->after);
+//::=20
+//:: func =3D VG_(SkipList_Find_Exact)(&wrapped_functions, &eip);
+//::=20
+//:: if (func =3D=3D NULL) {
+//:: func =3D VG_(SkipNode_Alloc)(&wrapped_functions);
+//:: VG_(invalidate_translations)(eip, 1, True);
+//::=20
+//:: func->eip =3D eip;
+//:: VG_(SkipList_Insert)(&wrapped_functions, func);
+//:: }
+//::=20
+//:: func->wrapper =3D wrapper;
+//:: }
+//::=20
+//:: const FuncWrapper *VG_(is_wrapped)(Addr eip)
+//:: {
+//:: struct wrapped_function *func =3D VG_(SkipList_Find_Exact)(&wrap=
ped_functions, &eip);
+//::=20
+//:: if (func)
+//:: return func->wrapper;
+//:: return NULL;
+//:: }
+//::=20
+//:: Bool VG_(is_wrapper_return)(Addr eip)
+//:: {
+//:: struct wrapper_return *ret =3D VG_(SkipList_Find_Exact)(&wrapper=
_returns, &eip);
+//::=20
+//:: return ret !=3D NULL;
+//:: }
+//::=20
+//:: /* Mark eip as being the return address of a wrapper, so that the
+//:: codegen will generate the appropriate call. */
+//:: void wrapper_return(Addr eip)
+//:: {
+//:: struct wrapper_return *ret;
+//::=20
+//:: if (VG_(is_wrapper_return)(eip))
+//:: return;
+//::=20
+//:: VG_(invalidate_translations)(eip, 1, True);
+//::=20
+//:: ret =3D VG_(SkipNode_Alloc)(&wrapper_returns);
+//:: ret->eip =3D eip;
+//::=20
+//:: VG_(SkipList_Insert)(&wrapper_returns, ret);
+//:: }
Modified: trunk/coregrind/m_translate.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_translate.c 2005-05-29 16:23:17 UTC (rev 3807)
+++ trunk/coregrind/m_translate.c 2005-05-29 17:01:48 UTC (rev 3808)
@@ -32,6 +32,7 @@
#include "core.h"
#include "pub_core_aspacemgr.h"
#include "pub_core_options.h"
+#include "pub_core_redir.h"
#include "pub_core_tooliface.h"
#include "pub_core_translate.h"
#include "pub_core_transtab.h"
Modified: trunk/coregrind/vg_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_main.c 2005-05-29 16:23:17 UTC (rev 3807)
+++ trunk/coregrind/vg_main.c 2005-05-29 17:01:48 UTC (rev 3808)
@@ -37,6 +37,7 @@
#include "pub_core_errormgr.h"
#include "pub_core_execontext.h"
#include "pub_core_options.h"
+#include "pub_core_redir.h"
#include "pub_core_syscalls.h"
#include "pub_core_tooliface.h"
#include "pub_core_transtab.h"
@@ -2794,7 +2795,6 @@
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Initialise redirects\n");
VG_(setup_code_redirect_table)();
- VGP_(setup_redirects)();
=20
//--------------------------------------------------------------
// Verbosity message
Deleted: trunk/coregrind/vg_redir.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_redir.c 2005-05-29 16:23:17 UTC (rev 3807)
+++ trunk/coregrind/vg_redir.c 2005-05-29 17:01:48 UTC (rev 3808)
@@ -1,710 +0,0 @@
-/*--------------------------------------------------------------------*/
-/*--- Management of function redirection and wrapping. ---*/
-/*--- vg_redir.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
- This file is part of Valgrind, an extensible x86 protected-mode
- emulator for monitoring program execution on x86-Unixes.
-
- Copyright (C) 2000-2005 Julian Seward=20
- js...@ac...
- Copyright (C) 2003-2005 Jeremy Fitzhardinge
- je...@go...
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-#include "core.h"
-#include "vg_symtab2.h"
-
-#include "pub_core_aspacemgr.h"
-#include "pub_core_skiplist.h"
-#include "pub_core_options.h"
-#include "pub_core_transtab.h"
-
-/*------------------------------------------------------------*/
-/*--- General purpose redirection. ---*/
-/*------------------------------------------------------------*/
-
-/*
- wraps and 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;
- =20
- 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 */
-};
-
-static Char *straddr(void *p)
-{
- static Char buf[16];
-
- VG_(sprintf)(buf, "%p", *(Addr *)p);
-
- return buf;
-}
-
-static SkipList sk_resolved_redir =3D VG_SKIPLIST_INIT(CodeRedirect, fro=
m_addr,=20
- VG_(cmp_Addr), straddr, VG_AR_SYMTAB);
-static CodeRedirect *unresolved_redir =3D NULL;
-
-static Bool match_lib(const Char *pattern, const SegInfo *si)
-{
- /* pattern =3D=3D 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 =3D si->filename;
-
- if (pattern =3D=3D NULL)
- return True;
-
- if (VG_(strncmp)(pattern, "file:", 5) =3D=3D 0) {
- pattern +=3D 5;
- name =3D si->filename;
- }
- if (VG_(strncmp)(pattern, "soname:", 7) =3D=3D 0) {
- pattern +=3D 7;
- name =3D si->soname;
- }
-
- if (name =3D=3D NULL)
- return False;
- =20
- return VG_(string_match)(pattern, name);
-}
-
-static inline Bool from_resolved(const CodeRedirect *redir)
-{
- return redir->from_addr !=3D 0;
-}
-
-static inline Bool to_resolved(const CodeRedirect *redir)
-{
- if (redir->type =3D=3D R_REDIRECT)
- return redir->to_addr !=3D 0;
- vg_assert(redir->wrapper !=3D NULL);
- return True;
-}
-
-Bool VG_(is_resolved)(const CodeRedirect *redir)
-{
- return from_resolved(redir) && to_resolved(redir);
-}
-
-static void add_resolved(CodeRedirect *redir)
-{
- switch(redir->type) {
- case R_REDIRECT:
- if (VG_(clo_trace_redir)) {
- VG_(message)(Vg_DebugMsg, " redir resolved (%s:%s=3D%p -> ",
- redir->from_lib, redir->from_sym, redir->from_addr=
);
- VG_(message)(Vg_DebugMsg, " %s:%s=3D%p)",
- redir->to_lib, redir->to_sym, redir->to_addr);
- }
-
- if (VG_(search_transtab)(NULL, (Addr64)redir->from_addr, False)) {
- /* 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. =20
-
- 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.=20
-
- Note, this is potentially expensive -- discarding
- translations causes complete unchaining. =20
- */
- if (VG_(clo_verbosity) > 2 && VG_(clo_trace_redir)) {
- VG_(message)(Vg_UserMsg, =20
- "Discarding translation due to redirect of alre=
ady called function" );
- VG_(message)(Vg_UserMsg,
- " %s (%p -> %p)",
- redir->from_sym, redir->from_addr, redir->to_ad=
dr );
- }
- VG_(discard_translations)((Addr64)redir->from_addr, 1);
- }
-
- {
- CodeRedirect *r =3D VG_(SkipList_Find_Exact)(&sk_resolved_redir=
, &redir->from_addr);
-
- if (r =3D=3D 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->%s:%s:%p dup=
licated\n",
- redir->from_lib, redir->from_sym, redir->fro=
m_addr,
- redir->to_lib, redir->to_sym, redir->to_addr=
);
- }
- }
- break;
-
- case R_WRAPPER:
- if (VG_(clo_trace_redir)) {
- VG_(message)(Vg_DebugMsg, " wrapper resolved (%s:%s=3D%p -> wr=
apper)",
- 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;
- }
-}
-
-/* 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 !=3D NULL);
- vg_assert(si->seg !=3D NULL);
-
- /* no redirection from Valgrind segments */
- if (si->seg->flags & SF_VALGRIND)
- return False;
-
- resolved =3D VG_(is_resolved)(redir);
-
- if (0 && VG_(clo_trace_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 (!from_resolved(redir)) {
- vg_assert(redir->from_sym !=3D NULL);
-
- if (match_lib(redir->from_lib, si)) {
- redir->from_addr =3D VG_(reverse_search_one_symtab)(si, redir->from_sy=
m);
- if (VG_(clo_trace_redir) && redir->from_addr !=3D 0)
- VG_(printf)(" bind FROM: %p =3D %s:%s\n",=20
- redir->from_addr,redir->from_lib, redir->from_sy=
m );
- }
- }
-
- if (!to_resolved(redir)) {
- vg_assert(redir->type =3D=3D R_REDIRECT);
- vg_assert(redir->to_sym !=3D NULL);
-
- if (match_lib(redir->to_lib, si)) {
- redir->to_addr =3D VG_(reverse_search_one_symtab)(si, redir->to_sym);
- if (VG_(clo_trace_redir) && redir->to_addr !=3D 0)
- VG_(printf)(" bind TO: %p =3D %s:%s\n",=20
- redir->to_addr,redir->to_lib, redir->to_sym );
-
- }
- }
-
- resolved =3D from_resolved(redir) && to_resolved(redir);
-
- if (0 && VG_(clo_trace_redir))
- VG_(printf)("resolve_redir: %s:%s from=3D%p %s:%s to=3D%p\n",
- redir->from_lib, redir->from_sym, redir->from_addr,=20
- redir->to_lib, redir->to_sym, redir->to_addr);
-
- if (resolved) add_resolved(redir);
-
- return resolved;
-}
-
-static Bool resolve_redir_allsegs(CodeRedirect *redir)
-{
- const SegInfo *si;
-
- for(si =3D VG_(next_seginfo)(NULL);=20
- si !=3D NULL;=20
- si =3D VG_(next_seginfo)(si))
- {
- if (resolve_redir(redir, si))
- return True;
- }
- return False;
-}
-
-/* Go through the complete redir list, resolving as much as possible wit=
h this SegInfo.
-
- This should be called when a new SegInfo symtab is loaded.
- */
-void VG_(resolve_seg_redirs)(SegInfo *si)
-{
- CodeRedirect **prevp =3D &unresolved_redir;
- CodeRedirect *redir, *next;
-
- if (VG_(clo_trace_redir))
- VG_(printf)("Considering redirs to/from %s(soname=3D%s)\n",
- si->filename, si->soname);
-
- /* visit each unresolved redir - if it becomes resolved, then
- remove it from the unresolved list */
- for(redir =3D unresolved_redir; redir !=3D NULL; redir =3D next) {
- next =3D redir->next;
-
- if (resolve_redir(redir, si)) {
- *prevp =3D next;
- redir->next =3D NULL;
- } else
- prevp =3D &redir->next;
- }
-}
-
-/* Redirect a lib/symbol reference to a function at lib/symbol */
-static void add_redirect_sym_to_sym(const Char *from_lib, const Char *fr=
om_sym,
- const Char *to_lib, const Char *to_sym)
-{
- CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
-
- redir->type =3D R_REDIRECT;
-
- redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
- redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
- redir->from_addr =3D 0;
-
- redir->to_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, to_lib);
- redir->to_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, to_sym);
- redir->to_addr =3D 0;
-
- if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
- VG_(message)(Vg_UserMsg,=20
- "REDIRECT %s(%s) to %s(%s)",
- from_lib, from_sym, to_lib, to_sym);
-
- /* 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 =3D unresolved_redir;
- unresolved_redir =3D redir;
- }
-}
-
-/* Redirect a lib/symbol reference to a function at addr */
-void VG_(add_redirect_sym_to_addr)(const Char *from_lib, const Char *fro=
m_sym,
- Addr to_addr)
-{
- CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
-
- redir->type =3D R_REDIRECT;
-
- redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
- redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
- redir->from_addr =3D 0;
-
- redir->to_lib =3D NULL;
- redir->to_sym =3D NULL;
- redir->to_addr =3D to_addr;
-
- if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
- VG_(message)(Vg_UserMsg,=20
- "REDIRECT %s(%s) to %p",
- from_lib, from_sym, to_addr);
-
- /* 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 =3D unresolved_redir;
- unresolved_redir =3D redir;
- }
-}
-
-/* Redirect a function at from_addr to a function at to_addr */
-void VG_(add_redirect_addr_to_addr)(Addr from_addr, Addr to_addr)
-{
- CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
-
- redir->type =3D R_REDIRECT;
-
- redir->from_lib =3D NULL;
- redir->from_sym =3D NULL;
- redir->from_addr =3D from_addr;
-
- redir->to_lib =3D NULL;
- redir->to_sym =3D NULL;
- redir->to_addr =3D to_addr;
-
- if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
- VG_(message)(Vg_UserMsg,=20
- "REDIRECT %p to %p",
- from_addr, to_addr);
-
- add_resolved(redir);
-}
-
-CodeRedirect *VG_(add_wrapper)(const Char *from_lib, const Char *from_sy=
m,
- const FuncWrapper *wrapper)
-{
- CodeRedirect *redir =3D 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 =3D R_WRAPPER;
-
- redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
- redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
- redir->from_addr =3D 0;
-
- redir->to_lib =3D NULL;
- redir->to_sym =3D NULL;
- redir->to_addr =3D 0;
-
- redir->wrapper =3D wrapper;
- =20
- /* 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 =3D unresolved_redir;
- unresolved_redir =3D redir;
- }
-
- return redir;
-}
-
-/* If address 'a' is being redirected, return the redirected-to
- address. */
-Addr VG_(code_redirect)(Addr a)
-{
- CodeRedirect* r;
-
- r =3D VG_(SkipList_Find_Exact)(&sk_resolved_redir, &a);
- if (r =3D=3D NULL)
- return a;
-
- vg_assert(r->to_addr !=3D 0);
-
- return r->to_addr;
-}
-
-void VG_(setup_code_redirect_table) ( void )
-{
- /* 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_to_sym("soname:libc.so.6", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
-
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "strlen",
- "*vgpreload_memcheck.so*", "strlen");
- add_redirect_sym_to_sym("soname:libc.so.6", "strlen",
- "*vgpreload_memcheck.so*", "strlen");
-
- add_redirect_sym_to_sym("soname:libc.so.6", "strnlen",
- "*vgpreload_memcheck.so*", "strnlen");
-
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
- add_redirect_sym_to_sym("soname:libc.so.6", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
-
- add_redirect_sym_to_sym("soname:libc.so.6", "strchr",
- "*vgpreload_memcheck.so*", "strchr");
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "strchr",
- "*vgpreload_memcheck.so*", "strchr");
-
- /* apparently index is the same thing as strchr */
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "index",
- "*vgpreload_memcheck.so*", "strchr");
-
- add_redirect_sym_to_sym("soname:libc.so.6", "strchrnul",
- "*vgpreload_memcheck.so*", "glibc232_strchrnu=
l");
-
- add_redirect_sym_to_sym("soname:libc.so.6", "rawmemchr",
- "*vgpreload_memcheck.so*", "glibc232_rawmemch=
r");
-
- /* amd64-linux (glibc 2.3.3, SuSE 9.2) */
- /* apparently index is the same thing as strchr */
- add_redirect_sym_to_sym("soname:libc.so.6", "index",
- "*vgpreload_memcheck.so*", "strchr");
- add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "index",
- "*vgpreload_memcheck.so*", "strchr");
-
- add_redirect_sym_to_sym("soname:libc.so.6", "strcpy",
- "*vgpreload_memcheck.so*", "strcpy");
-
- add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "strcmp",
- "*vgpreload_memcheck.so*", "strcmp");
- add_redirect_sym_to_sym("soname:libc.so.6", "strcmp",
- "*vgpreload_memcheck.so*", "strcmp");
-
- add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "strlen",
- "*vgpreload_memcheck.so*", "strlen");
-}
-
-
-//:: /*------------------------------------------------------------*/
-//:: /*--- General function wrapping. ---*/
-//:: /*------------------------------------------------------------*/
-//::=20
-//:: /*=20
-//:: TODO:
-//:: - hook into the symtab machinery
-//:: - client-side wrappers?
-//:: - better interfaces for before() functions to get to arguments
-//:: - handle munmap of code (dlclose())
-//:: - handle thread exit
-//:: - handle longjmp
-//:: */
-//:: struct callkey {
-//:: ThreadId tid; /* calling thread */
-//:: Addr esp; /* address of args on stack */
-//:: Addr eip; /* return address */
-//:: };
-//::=20
-//:: struct call_instance {
-//:: struct callkey key;
-//::=20
-//:: const FuncWrapper *wrapper;
-//:: void *nonce;
-//:: };
-//::=20
-//:: static inline Addr addrcmp(Addr a, Addr b)
-//:: {
-//:: if (a < b)
-//:: return -1;
-//:: else if (a > b)
-//:: return 1;
-//:: else=20
-//:: return 0;
-//:: }
-//::=20
-//:: static inline Int cmp(UInt a, UInt b)
-//:: {
-//:: if (a < b)
-//:: return -1;
-//:: else if (a > b)
-//:: return 1;
-//:: else=20
-//:: return 0;
-//:: }
-//::=20
-//:: static Int keycmp(const void *pa, const void *pb)
-//:: {
-//:: const struct callkey *a =3D (const struct callkey *)pa;
-//:: const struct callkey *b =3D (const struct callkey *)pb;
-//:: Int ret;
-//::=20
-//:: if ((ret =3D cmp(a->tid, b->tid)))
-//:: return ret;
-//::=20
-//:: if ((ret =3D addrcmp(a->esp, b->esp)))
-//:: return ret;
-//::=20
-//:: return addrcmp(a->eip, b->eip);
-//:: }
-//::=20
-//:: /* List of wrapped call invocations which are currently active */
-//:: static SkipList wrapped_frames =3D VG_SKIPLIST_INIT(struct call_ins=
tance, key, keycmp,=20
-//:: NULL, VG_AR_SYMTAB);
-//::=20
-//:: static struct call_instance *find_call(Addr retaddr, Addr argsp, Th=
readId tid)
-//:: {
-//:: struct callkey key =3D { tid, argsp, retaddr };
-//::=20
-//:: return VG_(SkipList_Find_Exact)(&wrapped_frames, &key);
-//:: }
-//::=20
-//:: static void wrapper_return(Addr retaddr);
-//::=20
-//:: /* Called from generated code via helper */
-//:: void VG_(wrap_before)(ThreadState *tst, const FuncWrapper *wrapper)
-//:: {
-//:: Addr retaddr =3D VGA_RETADDR(tst->arch);
-//:: Addr argp =3D (Addr)&VGA_FUNC_ARG(tst->arch, 0);
-//:: void *nonce =3D NULL;
-//:: Bool mf =3D VG_(my_fault);
-//:: VG_(my_fault) =3D True;
-//::=20
-//:: if (wrapper->before) {
-//:: va_list args =3D VGA_VA_LIST(tst->arch);
-//:: nonce =3D (*wrapper->before)(args);
-//:: }
-//::=20
-//:: if (wrapper->after) {
-//:: /* If there's an after function, make sure it gets called */
-//:: struct call_instance *call;
-//::=20
-//:: call =3D find_call(retaddr, argp, tst->tid);
-//::=20
-//:: if (call !=3D NULL) {
-//:: /* Found a stale outstanding call; clean it up and recycle
-//:: the structure */
-//:: if (call->wrapper->after)
-//:: (*call->wrapper->after)(call->nonce, RT_LONGJMP, 0);
-//:: } else {
-//:: call =3D VG_(SkipNode_Alloc)(&wrapped_frames);
-//:: =20
-//:: call->key.tid =3D tst->tid;
-//:: call->key.esp =3D argp;
-//:: call->key.eip =3D retaddr;
-//::=20
-//:: VG_(SkipList_Insert)(&wrapped_frames, call);
-//::=20
-//:: wrapper_return(retaddr);
-//:: }
-//::=20
-//:: call->wrapper =3D wrapper;
-//:: call->nonce =3D nonce;
-//:: } else=20
-//:: vg_assert(nonce =3D=3D NULL);
-//::=20
-//:: VG_(my_fault) =3D mf;
-//:: }
-//::=20
-//:: /* Called from generated code via helper */
-//:: void VG_(wrap_after)(ThreadState *tst)
-//:: {
-//:: Addr EIP =3D VGA_INSTR_PTR(tst->arch); /* instruction after call=
*/
-//:: Addr ESP =3D VGA_STACK_PTR(tst->arch); /* pointer to args */
-//:: Word ret =3D VGA_RETVAL(tst->arch); /* return value */
-//:: struct call_instance *call;
-//:: Bool mf =3D VG_(my_fault);
-//::=20
-//:: VG_(my_fault) =3D True;
-//:: call =3D find_call(EIP, ESP, tst->tid);
-//::=20
-//:: if (0)
-//:: VG_(printf)("wrap_after(%p,%p,%d) -> %p\n", EIP, ESP, tst->ti=
d, call);
-//::=20
-//:: if (call !=3D NULL) {
-//:: if (call->wrapper->after)
-//:: (*call->wrapper->after)(call->nonce, RT_RETURN, ret);
-//::=20
-//:: VG_(SkipList_Remove)(&wrapped_frames, &call->key);
-//:: VG_(SkipNode_Free)(&wrapped_frames, call);
-//:: }
-//:: VG_(my_fault) =3D mf;
-//:: }
-//::=20
-//::=20
-//:: struct wrapped_function {
-//:: Addr eip; /* eip of function entrypoint */
-//:: const FuncWrapper *wrapper;
-//:: };
-//::=20
-//:: struct wrapper_return {
-//:: Addr eip; /* return address */
-//:: };
-//::=20
-//:: /* A mapping from eip of wrapped function entrypoints to actual wra=
ppers */
-//:: static SkipList wrapped_functions =3D VG_SKIPLIST_INIT(struct wrapp=
ed_function, eip, VG_(cmp_Addr),
-//:: NULL, VG_AR_SYMTAB);
-//::=20
-//:: /* A set of EIPs which are return addresses for wrapped functions *=
/
-//:: static SkipList wrapper_returns =3D VG_SKIPLIST_INIT(struct wrapper=
_return, eip, VG_(cmp_Addr),
-//:: NULL, VG_AR_SYMTAB);
-//::=20
-//:: /* Wrap function starting at eip */
-//:: void VG_(wrap_function)(Addr eip, const FuncWrapper *wrapper)
-//:: {
-//:: struct wrapped_function *func;
-//::=20
-//:: if (0)
-//:: VG_(printf)("wrapping %p with (%p,%p)\n", eip, wrapper->befor=
e, wrapper->after);
-//::=20
-//:: func =3D VG_(SkipList_Find_Exact)(&wrapped_functions, &eip);
-//::=20
-//:: if (func =3D=3D NULL) {
-//:: func =3D VG_(SkipNode_Alloc)(&wrapped_functions);
-//:: VG_(invalidate_translations)(eip, 1, True);
-//::=20
-//:: func->eip =3D eip;
-//:: VG_(SkipList_Insert)(&wrapped_functions, func);
-//:: }
-//::=20
-//:: func->wrapper =3D wrapper;
-//:: }
-//::=20
-//:: const FuncWrapper *VG_(is_wrapped)(Addr eip)
-//:: {
-//:: struct wrapped_function *func =3D VG_(SkipList_Find_Exact)(&wrap=
ped_functions, &eip);
-//::=20
-//:: if (func)
-//:: return func->wrapper;
-//:: return NULL;
-//:: }
-//::=20
-//:: Bool VG_(is_wrapper_return)(Addr eip)
-//:: {
-//:: struct wrapper_return *ret =3D VG_(SkipList_Find_Exact)(&wrapper=
_returns, &eip);
-//::=20
-//:: return ret !=3D NULL;
-//:: }
-//::=20
-//:: /* Mark eip as being the return address of a wrapper, so that the
-//:: codegen will generate the appropriate call. */
-//:: void wrapper_return(Addr eip)
-//:: {
-//:: struct wrapper_return *ret;
-//::=20
-//:: if (VG_(is_wrapper_return)(eip))
-//:: return;
-//::=20
-//:: VG_(invalidate_translations)(eip, 1, True);
-//::=20
-//:: ret =3D VG_(SkipNode_Alloc)(&wrapper_returns);
-//:: ret->eip =3D eip;
-//::=20
-//:: VG_(SkipList_Insert)(&wrapper_returns, ret);
-//:: }
Modified: trunk/coregrind/vg_symtab2.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_symtab2.c 2005-05-29 16:23:17 UTC (rev 3807)
+++ trunk/coregrind/vg_symtab2.c 2005-05-29 17:01:48 UTC (rev 3808)
@@ -36,6 +36,7 @@
#include "pub_core_aspacemgr.h"
#include "pub_core_demangle.h"
#include "pub_core_options.h"
+#include "pub_core_redir.h"
#include "pub_core_tooliface.h"
=20
#include <elf.h> /* ELF defns */
Modified: trunk/coregrind/x86-linux/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/x86-linux/Makefile.am 2005-05-29 16:23:17 UTC (rev 38=
07)
+++ trunk/coregrind/x86-linux/Makefile.am 2005-05-29 17:01:48 UTC (rev 38=
08)
@@ -4,9 +4,3 @@
noinst_HEADERS =3D \
core_platform.h \
vki_unistd.h
-
-noinst_LIBRARIES =3D libplatform.a
-
-
-libplatform_a_SOURCES =3D \
- core_platform.c
Deleted: trunk/coregrind/x86-linux/core_platform.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/x86-linux/core_platform.c 2005-05-29 16:23:17 UTC (re=
v 3807)
+++ trunk/coregrind/x86-linux/core_platform.c 2005-05-29 17:01:48 UTC (re=
v 3808)
@@ -1,11 +0,0 @@
-#include "core.h"
-
-void VGP_(setup_redirects)(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.
- */
- VG_(add_redirect_sym_to_addr)("soname:ld-linux.so.2", "_dl_sysinfo_in=
t80",
- VG_(client_trampoline_code)+VG_(tramp_s=
yscall_offset));
-}
|