Don't instrument any code in ld.so.  Doing so merely generates a large
number of races which have to be expensively suppressed, so it's
better not to do so.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10676 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/glibc-2.34567-NPTL-helgrind.supp b/glibc-2.34567-NPTL-helgrind.supp
index 616309e..3703eff 100644
--- a/glibc-2.34567-NPTL-helgrind.supp
+++ b/glibc-2.34567-NPTL-helgrind.supp
@@ -24,11 +24,11 @@
 #   H fails to see glibc's internal locking/unlocking of FILE*s
 #   as required by POSIX.  A better solution is needed.
 
-{
-   helgrind-glibc2X-001
-   Helgrind:Race
-   obj:/lib*/ld-2.*so*
-}
+#{
+#   helgrind-glibc2X-001
+#   Helgrind:Race
+#   obj:/lib*/ld-2.*so*
+#}
 
 # helgrind-glibc2X-002 was merged into helgrind-glibc2X-001
 
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index a0a8840..d98b337 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -49,6 +49,9 @@
 #include "pub_tool_xarray.h"
 #include "pub_tool_stacktrace.h"
 #include "pub_tool_wordfm.h"
+#include "pub_tool_debuginfo.h" // VG_(find_seginfo), VG_(seginfo_soname)
+#include "pub_tool_redir.h"     // sonames for the dynamic linkers
+#include "pub_tool_vki.h"       // VKI_PAGE_SIZE
 
 #include "hg_basics.h"
 #include "hg_wordset.h"
@@ -3691,6 +3694,35 @@
 }
 
 
+/* Figure out if GA is a guest code address in the dynamic linker, and
+   if so return True.  Otherwise (and in case of any doubt) return
+   False.  (sidedly safe w/ False as the safe value) */
+static Bool is_in_dynamic_linker_shared_object( Addr64 ga )
+{
+   DebugInfo* dinfo;
+   const UChar* soname;
+   if (0) return False;
+
+   dinfo  = VG_(find_seginfo)( (Addr)ga );
+   if (!dinfo) return False;
+
+   soname = VG_(seginfo_soname)(dinfo);
+   tl_assert(soname);
+   if (0) VG_(printf)("%s\n", soname);
+
+#  if defined(VGO_linux)
+   if (VG_STREQ(soname, VG_U_LD_LINUX_SO_2))        return True;
+   if (VG_STREQ(soname, VG_U_LD_LINUX_X86_64_SO_2)) return True;
+   if (VG_STREQ(soname, VG_U_LD64_SO_1))            return True;
+   if (VG_STREQ(soname, VG_U_LD_SO_1))              return True;
+#  elif defined(VGO_darwin)
+   if (VG_STREQ(soname, VG_U_DYLD)) return True;
+#  else
+#    error "Unsupported OS"
+#  endif
+   return False;
+}
+
 static
 IRSB* hg_instrument ( VgCallbackClosure* closure,
                       IRSB* bbIn,
@@ -3702,12 +3734,18 @@
    IRSB*   bbOut;
    Addr64  cia; /* address of current insn */
    IRStmt* st;
+   Bool    inLDSO = False;
+   Addr64  inLDSOmask4K = 1; /* mismatches on first check */
 
    if (gWordTy != hWordTy) {
       /* We don't currently support this case. */
       VG_(tool_panic)("host/guest word size mismatch");
    }
 
+   if (VKI_PAGE_SIZE < 4096 || VG_(log2)(VKI_PAGE_SIZE) == -1) {
+      VG_(tool_panic)("implausible or too-small VKI_PAGE_SIZE");
+   }
+
    /* Set up BB */
    bbOut           = emptyIRSB();
    bbOut->tyenv    = deepCopyIRTypeEnv(bbIn->tyenv);
@@ -3745,6 +3783,20 @@
          case Ist_IMark:
             /* no mem refs, but note the insn address. */
             cia = st->Ist.IMark.addr;
+            /* Don't instrument the dynamic linker.  It generates a
+               lot of races which we just expensively suppress, so
+               it's pointless.
+
+               Avoid flooding is_in_dynamic_linker_shared_object with
+               requests by only checking at transitions between 4K
+               pages. */
+            if ((cia & ~(Addr64)0xFFF) != inLDSOmask4K) {
+               if (0) VG_(printf)("NEW %#lx\n", (Addr)cia);
+               inLDSOmask4K = cia & ~(Addr64)0xFFF;
+               inLDSO = is_in_dynamic_linker_shared_object(cia);
+            } else {
+               if (0) VG_(printf)("old %#lx\n", (Addr)cia);
+            }
             break;
 
          case Ist_MBE:
@@ -3769,14 +3821,16 @@
                tl_assert(!cas->dataHi);
             }
             /* Just be boring about it. */
-            instrument_mem_access(
-               bbOut,
-               cas->addr,
-               (isDCAS ? 2 : 1)
-                  * sizeofIRType(typeOfIRExpr(bbIn->tyenv, cas->dataLo)),
-               False/*!isStore*/,
-               sizeofIRType(hWordTy)
-            );
+            if (!inLDSO) {
+               instrument_mem_access(
+                  bbOut,
+                  cas->addr,
+                  (isDCAS ? 2 : 1)
+                     * sizeofIRType(typeOfIRExpr(bbIn->tyenv, cas->dataLo)),
+                  False/*!isStore*/,
+                  sizeofIRType(hWordTy)
+               );
+            }
             break;
          }
 
@@ -3784,13 +3838,15 @@
             /* It seems we pretend that store-conditionals don't
                exist, viz, just ignore them ... */
             if (st->Ist.Store.resSC == IRTemp_INVALID) {
-               instrument_mem_access( 
-                  bbOut, 
-                  st->Ist.Store.addr, 
-                  sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)),
-                  True/*isStore*/,
-                  sizeofIRType(hWordTy)
-               );
+               if (!inLDSO) {
+                  instrument_mem_access( 
+                     bbOut, 
+                     st->Ist.Store.addr, 
+                     sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)),
+                     True/*isStore*/,
+                     sizeofIRType(hWordTy)
+                  );
+               }
             }
             break;
 
@@ -3799,13 +3855,15 @@
                vanilla one or a load-linked. */
             IRExpr* data = st->Ist.WrTmp.data;
             if (data->tag == Iex_Load) {
-               instrument_mem_access(
-                  bbOut,
-                  data->Iex.Load.addr,
-                  sizeofIRType(data->Iex.Load.ty),
-                  False/*!isStore*/,
-                  sizeofIRType(hWordTy)
-               );
+               if (!inLDSO) {
+                  instrument_mem_access(
+                     bbOut,
+                     data->Iex.Load.addr,
+                     sizeofIRType(data->Iex.Load.ty),
+                     False/*!isStore*/,
+                     sizeofIRType(hWordTy)
+                  );
+               }
             }
             break;
          }
@@ -3820,16 +3878,20 @@
                tl_assert(d->mSize != 0);
                dataSize = d->mSize;
                if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
-                  instrument_mem_access( 
-                     bbOut, d->mAddr, dataSize, False/*!isStore*/,
-                     sizeofIRType(hWordTy)
-                  );
+                  if (!inLDSO) {
+                     instrument_mem_access( 
+                        bbOut, d->mAddr, dataSize, False/*!isStore*/,
+                        sizeofIRType(hWordTy)
+                     );
+                  }
                }
                if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
-                  instrument_mem_access( 
-                     bbOut, d->mAddr, dataSize, True/*isStore*/,
-                     sizeofIRType(hWordTy)
-                  );
+                  if (!inLDSO) {
+                     instrument_mem_access( 
+                        bbOut, d->mAddr, dataSize, True/*isStore*/,
+                        sizeofIRType(hWordTy)
+                     );
+                  }
                }
             } else {
                tl_assert(d->mAddr == NULL);
diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h
index 038c377..3d3b516 100644
--- a/include/pub_tool_redir.h
+++ b/include/pub_tool_redir.h
@@ -211,19 +211,31 @@
 #  error "Unknown platform"
 #endif
 
-/* --- Sonames for Linux ELF linkers. --- */
+/* --- Sonames for Linux ELF linkers, plus unencoded versions. --- */
 
 #if defined(VGO_linux)
+
 #define  VG_Z_LD_LINUX_SO_2         ldZhlinuxZdsoZd2           // ld-linux.so.2
+#define  VG_U_LD_LINUX_SO_2         "ld-linux.so.2"
+
 #define  VG_Z_LD_LINUX_X86_64_SO_2  ldZhlinuxZhx86Zh64ZdsoZd2  // ld-linux-x86-64.so.2
+#define  VG_U_LD_LINUX_X86_64_SO_2  "ld-linux-x86-64.so.2"
+
 #define  VG_Z_LD64_SO_1             ld64ZdsoZd1                // ld64.so.1
+#define  VG_U_LD64_SO_1             "ld64.so.1"
+
 #define  VG_Z_LD_SO_1               ldZdsoZd1                  // ld.so.1
+#define  VG_U_LD_SO_1               "ld.so.1"
+
 #endif
 
 /* --- Executable name for Darwin Mach-O linker. --- */
 
 #if defined(VGO_darwin)
+
 #define  VG_Z_DYLD               dyld                       // dyld
+#define  VG_U_DYLD               "dyld"
+
 #endif