Another seemingly-small but critical change imported from 2.4.0-ppc:
don't read symbols from sections with w permissions.  For some reason
ppc-linux maps executables three times, not twice as on x86, and if
the w flag is ignored, we wind up reading debug info twice, getting
wrong redirections, and then it all goes to hell in a handbasket.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4139 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c
index e5fea33..7de7bdb 100644
--- a/coregrind/m_aspacemgr/aspacemgr.c
+++ b/coregrind/m_aspacemgr/aspacemgr.c
@@ -787,37 +787,58 @@
    /* If this mapping is of the beginning of a file, isn't part of
       Valgrind, is at least readable and seems to contain an object
       file, then try reading symbols from it.
+
+      Getting this heuristic right is critical.  On x86-linux,
+      objects are typically mapped twice:
+
+      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
+      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
+
+      whereas ppc32-linux mysteriously does this:
+
+      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
+      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
+      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
+
+      The third mapping should not be considered to have executable code in.
+      Therefore a test which works for both is: r and x and NOT w.  Reading
+      symbols from the rwx segment -- which overlaps the r-x segment in the
+      file -- causes the redirection mechanism to redirect to addresses in
+      that third segment, which is wrong and causes crashes.
    */
    if (s->seginfo == NULL
        && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
             || is_stage2
           )
        && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP
-   ) {
-      if (off == 0
-	  && s->fnIdx != -1
-	  && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
-	  && len >= VKI_PAGE_SIZE
-          && VG_(is_object_file)((void *)addr)
       ) {
+      if (off == 0
+         && s->fnIdx != -1
+         /* r, x are set */
+         && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
+         /* w is clear */
+         && (prot & VKI_PROT_WRITE) == 0
+         /* other checks .. */
+         && len >= VKI_PAGE_SIZE
+         && VG_(is_object_file)((void *)addr) ) {
          s->seginfo = VG_(read_seg_symbols)(s->addr, s->len, s->offset,
                                             s->filename);
-      } else if (flags & SF_MMAP) {
-#if 0
-	 const SegInfo *info;
-
-	 /* Otherwise see if an existing SegInfo applies to this Segment */
-	 for(info = VG_(next_seginfo)(NULL);
-	     info != NULL;
-	     info = VG_(next_seginfo)(info)) {
-	    if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
-            {
-	       s->seginfo = (SegInfo *)info;
-	       VG_(seginfo_incref)((SegInfo *)info);
-	    }
-	 }
-#endif
       }
+      //else 
+      //if (flags & SF_MMAP) {
+      //   const SegInfo *info;
+      //
+      //   /* Otherwise see if an existing SegInfo applies to this Segment */
+      //   for(info = VG_(next_seginfo)(NULL);
+      //      info != NULL;
+      //      info = VG_(next_seginfo)(info)) {
+      //      if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
+      //      {
+      //         s->seginfo = (SegInfo *)info;
+      //         VG_(seginfo_incref)((SegInfo *)info);
+      //      }
+      //   }
+      //}
    }
 
    /* clean up */