resolve_redir(): when a redirect is resolved, if the source has
already been translated, discard that translation. Otherwise the
redirect will never take effect.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2141 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_symtab2.c b/coregrind/vg_symtab2.c
index 025650c..bb0c847 100644
--- a/coregrind/vg_symtab2.c
+++ b/coregrind/vg_symtab2.c
@@ -2045,9 +2045,33 @@
redir->to_lib, redir->to_sym, redir->to_addr);
}
- if (VG_(search_transtab)(redir->from_addr) != 0)
- VG_(message)(Vg_DebugMsg, "!!!! adding redirect to already called function %s (%p -> %p)!!!",
- redir->from_sym, redir->from_addr, 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);
+ }
VG_(SkipList_Insert)(&sk_resolved_redir, redir);
}