Merge patch from Josef Weidendorfer <Josef.Weidendorfer@gmx.de>:

Read symbols from both "symtab" and "dynsym" sections, rather than
merely from the one that comes last in the file.

MERGE TO STABLE


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1562 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_symtab2.c b/coregrind/vg_symtab2.c
index 71f0201..b11b1c2 100644
--- a/coregrind/vg_symtab2.c
+++ b/coregrind/vg_symtab2.c
@@ -1534,8 +1534,12 @@
    {
       UChar*     o_strtab    = NULL;
       Elf32_Sym* o_symtab    = NULL;
+      UChar*     o_dynstr    = NULL;
+      Elf32_Sym* o_dynsym    = NULL;
       UInt       o_strtab_sz = 0;
       UInt       o_symtab_sz = 0;
+      UInt       o_dynstr_sz = 0;
+      UInt       o_dynsym_sz = 0;
 
       UChar*     o_got = NULL;
       UChar*     o_plt = NULL;
@@ -1548,24 +1552,18 @@
       /* find the .stabstr and .stab sections */
       for (i = 0; i < ehdr->e_shnum; i++) {
 
-         /* As a fallback position, we look first for the dynamic
-            symbols of a library to increase the chances that we can
-            say something helpful even if the standard and debug
-            symbols are missing. */
-
          if (0 == VG_(strcmp)(".dynsym",sh_strtab + shdr[i].sh_name)) {
-            o_symtab    = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
-            o_symtab_sz = shdr[i].sh_size;
-            vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
+            o_dynsym    = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
+            o_dynsym_sz = shdr[i].sh_size;
+            vg_assert((o_dynsym_sz % sizeof(Elf32_Sym)) == 0);
             /* check image overrun here */
          }
          if (0 == VG_(strcmp)(".dynstr",sh_strtab + shdr[i].sh_name)) {
-            o_strtab    = (UChar*)(oimage + shdr[i].sh_offset);
-            o_strtab_sz = shdr[i].sh_size;
+            o_dynstr    = (UChar*)(oimage + shdr[i].sh_offset);
+            o_dynstr_sz = shdr[i].sh_size;
             /* check image overrun here */
          }
  
-         /* now look for the main symbol and string tables. */
          if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) {
             o_symtab    = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
             o_symtab_sz = shdr[i].sh_size;
@@ -1609,13 +1607,40 @@
 
       if (o_strtab == NULL || o_symtab == NULL) {
          vg_symerr("   object doesn't have a symbol table");
-      } else {
+      }
+      if (o_dynstr == NULL || o_dynsym == NULL) {
+         vg_symerr("   object doesn't have a dynamic symbol table");
+      }
+
+      while (True) {
+	 if (o_strtab == NULL || o_symtab == NULL) {
+
+	    o_strtab    = o_dynstr;
+	    o_symtab    = o_dynsym;
+	    o_strtab_sz = o_dynstr_sz;
+	    o_symtab_sz = o_dynsym_sz;
+
+	    if (o_strtab == NULL || o_symtab == NULL) break;
+
+	    o_dynstr = NULL;
+	    o_dynsym = NULL;
+
+	    if (VG_(clo_trace_symtab))
+	       VG_(printf)("Reading dynamic symbol table (%d entries)\n",
+			    o_symtab_sz/sizeof(Elf32_Sym) );
+	 }
+	 else if (VG_(clo_trace_symtab)) {
+	      
+	    VG_(printf)("Reading symbol table (%d entries)\n",
+			o_symtab_sz/sizeof(Elf32_Sym) );
+	 }
+
          /* Perhaps should start at i = 1; ELF docs suggest that entry
             0 always denotes `unknown symbol'. */
          for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){
 #           if 1
 	    if (VG_(clo_trace_symtab)) {
-	       VG_(printf)("raw symbol: ");
+	       VG_(printf)("raw symbol [%d]: ", i);
 	       switch (ELF32_ST_BIND(o_symtab[i].st_info)) {
                case STB_LOCAL:  VG_(printf)("LOC "); break;
                case STB_GLOBAL: VG_(printf)("GLO "); break;
@@ -1746,6 +1771,9 @@
                addSym ( si, &sym );
 	    }
          }
+	 /* If there's dynamic symbol info, force reading in next loop */
+	 o_strtab    = NULL;
+	 o_symtab    = NULL;
       }
    }