Change the criteria by which translations are discarded in the presence of
redirections.  Patch from Tom Hughes.  This fixes #109401.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4230 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 253f278..4981160 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -117,7 +117,7 @@
    unresolved_redirs = redir;
 }
 
-static void add_redir_to_resolved_list(CodeRedirect *redir)
+static void add_redir_to_resolved_list(CodeRedirect *redir, Bool need_discard)
 {
    vg_assert(redir->from_addr);
 
@@ -131,13 +131,11 @@
 
       vg_assert(redir->to_addr != 0);
 
-      if (VG_(search_transtab)(NULL, (Addr64)redir->from_addr, False)) {
+      if (need_discard) {
          /* 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.  
+            loaded before the .so containing "to" became available so
+            we need to discard any existing translations involving
+            the "from" function.
 
             Note, we only really need to discard the first bb of the
             old entry point, and so we avoid the problem of having to
@@ -149,7 +147,7 @@
             Note, this is potentially expensive -- discarding
             translations causes complete unchaining.  
          */
-         TRACE_REDIR("Discarding translation due to redirect of already called function" );
+         TRACE_REDIR("Discarding translation due to redirect of already loaded 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);
@@ -240,7 +238,7 @@
       if (resolve_redir_with_seginfo(redir, si)) {
 	 *prevp = next;
 	 redir->next = NULL;
-         add_redir_to_resolved_list(redir);
+         add_redir_to_resolved_list(redir, False);
       } else
 	 prevp = &redir->next;
    }
@@ -268,7 +266,7 @@
    TRACE_REDIR("REDIRECT addr to addr: %p to %p", from_addr, to_addr);
 
    // This redirection is already resolved, put it straight in the list.
-   add_redir_to_resolved_list(redir);
+   add_redir_to_resolved_list(redir, True);
 }
 
 /* Redirect a lib/symbol reference to a function at addr */
@@ -294,7 +292,7 @@
    // function is loaded after the replacee).  Then add it to the
    // appropriate list.
    if (resolve_redir_with_existing_seginfos(redir)) {
-      add_redir_to_resolved_list(redir);
+      add_redir_to_resolved_list(redir, True);
    } else {
       add_redir_to_unresolved_list(redir);
    }
@@ -318,7 +316,7 @@
    // 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);
+      add_redir_to_resolved_list(redir, True);
    } else {
       add_redir_to_unresolved_list(redir);
    }