]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdwfl: Support auxiliary symbol table only for getsym and addrsym.
authorMark Wielaard <mjw@redhat.com>
Wed, 23 Jan 2013 16:39:19 +0000 (17:39 +0100)
committerMark Wielaard <mjw@redhat.com>
Wed, 23 Jan 2013 18:44:23 +0000 (19:44 +0100)
Static binaries can have only an auxiliary symbol table and no dynsym
or symtab table.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
libdwfl/ChangeLog
libdwfl/dwfl_module_addrsym.c
libdwfl/dwfl_module_getdwarf.c
libdwfl/dwfl_module_getsym.c
tests/ChangeLog
tests/Makefile.am
tests/run-dwflsyms.sh
tests/run-readelf-s.sh
tests/testfilebasmin.bz2 [new file with mode: 0755]

index 828db083d25d5c2aee804a6b4d31dc003bc2b652..cf5b42e04b51821d8dd700e76f4b01cd4b9b2b72 100644 (file)
@@ -1,3 +1,16 @@
+2013-01-23  Mark Wielaard  <mjw@redhat.com>
+
+       * dwfl_module_getdwarf.c (find_aux_sym): Don't substract one
+       from aux_syments by default.
+       (find_symtab): Also succeed when only aux_symdata is found.
+       When no symtab is found always try to load auxiliary table.
+       (dwfl_module_getsymtab): Substract one from result when both
+       tables have symbols.
+       * dwfl_module_getsym.c (dwfl_module_getsym): Only skip auxiliary
+       zero entry when both tables have symbols.
+       * dwfl_module_addrsym.c (dwfl_module_addrsym): Only substract
+       one from first_global when both tables have symbols.
+
 2013-01-16  Mark Wielaard  <mjw@redhat.com>
 
        * libdwflP.h (struct Dwfl_Module): Add aux_sym, aux_symdata,
index d2059ea4bf0f93ba1b29382275beb89bead59c38..732b6983ae44ccb8014865609b2dc0de432fa133 100644 (file)
@@ -175,11 +175,17 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
 
   /* First go through global symbols.  mod->first_global and
      mod->aux_first_global are setup by dwfl_module_getsymtab to the
-     index of the first global symbol in the module's symbol table.  Both
-     are zero when unknown.  All symbols with local binding come first in
-     the symbol table, then all globals.  */
-  int first_global = mod->first_global + mod->aux_first_global - 1;
-  search_table (first_global < 0 ? 1 : first_global, syments);
+     index of the first global symbol in those symbol tables.  Both
+     are non-zero when the table exist, except when there is only a
+     dynsym table loaded through phdrs, then first_global is zero and
+     there will be no auxiliary table.  All symbols with local binding
+     come first in the symbol table, then all globals.  The zeroth,
+     null entry, in the auxiliary table is skipped if there is a main
+     table.  */
+  int first_global = mod->first_global + mod->aux_first_global;
+  if (mod->syments > 0 && mod->aux_syments > 0)
+    first_global--;
+  search_table (first_global == 0 ? 1 : first_global, syments);
 
   /* If we found nothing searching the global symbols, then try the locals.
      Unless we have a global sizeless symbol that matches exactly.  */
index ffbe5898120aa1336eea76369705188d0d71a7a4..d35c2660b032d2b1bf84c699b35293d9d0db310e 100644 (file)
@@ -909,7 +909,7 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
                        minisymtab = true;
                        *aux_symscn = scn;
                        *aux_strshndx = shdr->sh_link;
-                       mod->aux_syments = shdr->sh_size / shdr->sh_entsize - 1;
+                       mod->aux_syments = shdr->sh_size / shdr->sh_entsize;
                        mod->aux_first_global = shdr->sh_info;
                        if (*aux_xndxscn != NULL)
                          return;
@@ -949,7 +949,7 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
 static void
 find_symtab (Dwfl_Module *mod)
 {
-  if (mod->symdata != NULL     /* Already done.  */
+  if (mod->symdata != NULL || mod->aux_symdata != NULL /* Already done.  */
       || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure.  */
     return;
 
@@ -1001,16 +1001,23 @@ find_symtab (Dwfl_Module *mod)
          break;
 
        case DWFL_E_NO_SYMTAB:
+         /* There might be an auxiliary table.  */
+         find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx);
+
          if (symscn != NULL)
            {
              /* We still have the dynamic symbol table.  */
              mod->symerr = DWFL_E_NOERROR;
-
-             /* The dynsym table might be extended by an auxiliary table.  */
-             find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx);
              break;
            }
 
+         if (aux_symscn != NULL)
+           {
+             /* We still have the auxiliary symbol table.  */
+             mod->symerr = DWFL_E_NOERROR;
+             goto aux_cache;
+           }
+
          /* Last ditch, look for dynamic symbols without section headers.  */
          find_dynsym (mod);
          return;
@@ -1049,6 +1056,7 @@ find_symtab (Dwfl_Module *mod)
   /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym.  */
   if (aux_symscn != NULL)
     {
+  aux_cache:
       /* This does some sanity checks on the string table section.  */
       if (elf_strptr (mod->aux_sym.elf, aux_strshndx, 0) == NULL)
        {
@@ -1233,7 +1241,9 @@ dwfl_module_getsymtab (Dwfl_Module *mod)
 
   find_symtab (mod);
   if (mod->symerr == DWFL_E_NOERROR)
-    return mod->syments + mod->aux_syments;
+    /* We will skip the auxiliary zero entry if there is another one.  */
+    return (mod->syments + mod->aux_syments
+           - (mod->syments > 0 && mod->aux_syments > 0 ? 1 : 0));
 
   __libdwfl_seterrno (mod->symerr);
   return -1;
index 3e4d9f612d730a5c58a95104d4ddafcaccb67bf3..07127b78bdc1b81a24c43a199ee214d20a3c30f6 100644 (file)
@@ -48,6 +48,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
      And skip the auxiliary table zero undefined entry.  */
   GElf_Word shndx;
   int tndx = ndx;
+  int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
   struct dwfl_file *file;
   Elf_Data *symdata;
   Elf_Data *symxndxdata;
@@ -62,19 +63,19 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
       symxndxdata = mod->symxndxdata;
       symstrdata = mod->symstrdata;
     }
-  else if (ndx < mod->first_global + mod->aux_first_global - 1)
+  else if (ndx < mod->first_global + mod->aux_first_global - skip_aux_zero)
     {
       /* aux symbol table (locals).  */
-      tndx = ndx - mod->first_global + 1;
+      tndx = ndx - mod->first_global + skip_aux_zero;
       file = &mod->aux_sym;
       symdata = mod->aux_symdata;
       symxndxdata = mod->aux_symxndxdata;
       symstrdata = mod->aux_symstrdata;
     }
-  else if ((size_t) ndx < mod->syments + mod->aux_first_global - 1)
+  else if ((size_t) ndx < mod->syments + mod->aux_first_global - skip_aux_zero)
     {
       /* main symbol table (globals).  */
-      tndx = ndx - mod->aux_first_global + 1;
+      tndx = ndx - mod->aux_first_global + skip_aux_zero;
       file = mod->symfile;
       symdata = mod->symdata;
       symxndxdata = mod->symxndxdata;
@@ -83,7 +84,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
   else
     {
       /* aux symbol table (globals).  */
-      tndx = ndx - mod->syments + 1;
+      tndx = ndx - mod->syments + skip_aux_zero;
       file = &mod->aux_sym;
       symdata = mod->aux_symdata;
       symxndxdata = mod->aux_symxndxdata;
index feb9f69957e5cd1f6aade51c9dffbb40d59eeb39..bc721c70040301301abf92387b058a5dce378a17 100644 (file)
@@ -1,3 +1,10 @@
+2013-01-23  Mark Wielaard  <mjw@redhat.com>
+
+       * testfilebasmin.bz2: New testfile.
+       * Makefile.am (EXTRA_DIST): Add testfilebasmin.bz2.
+       * run-readelf-s.sh: Test testfilebasmin.
+       * run-dwflsyms.sh: Likewise.
+
 2013-01-16  Mark Wielaard  <mjw@redhat.com>
 
        * Makefile.am (check_PROGRAMS): Add dwflsyms.
index b46c4c23d32c5239dde8831f19fa41ebb7d735db..f32ea242d48b915ed199d5c1d4a73657a2f90d2d 100644 (file)
@@ -175,7 +175,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
             testfilegdbindex7.bz2 \
             run-readelf-s.sh testfilebazdbg.bz2 testfilebazdyn.bz2 \
             testfilebazmin.bz2 testfilebazdbg.debug.bz2 testfilebazmdb.bz2 \
-            testfilebaztab.bz2 \
+            testfilebaztab.bz2 testfilebasmin.bz2 \
             run-dwflsyms.sh \
             run-unstrip-n.sh testcore-rtlib.bz2 testcore-rtlib-ppc.bz2 \
             run-low_high_pc.sh testfile_low_high_pc.bz2 \
index 570881adeaf556f53b52f811db749066249cb5cd..56a75804dffad23aa95cad2d8cd7596a1e4e5806 100755 (executable)
@@ -25,6 +25,7 @@ testfiles testfilebazdbg testfilebazdbg.debug
 testfiles testfilebazdyn
 testfiles testfilebazmdb
 testfiles testfilebazmin
+testfiles testfilebasmin
 
 tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in dwflsyms.out
 
@@ -190,4 +191,16 @@ cat testfile.symtab.in \
 cat testfile.minsym.in \
   | testrun_compare ./dwflsyms -e testfilebazmin
 
+testrun_compare ./dwflsyms -e testfilebasmin <<\EOF
+   0: NOTYPE   LOCAL    (0) 0
+   1: FUNC     LOCAL   foo (18) 0x400168
+   2: SECTION  LOCAL    (0) 0x400120
+   3: SECTION  LOCAL    (0) 0x400144
+   4: SECTION  LOCAL    (0) 0x4001c0
+   5: SECTION  LOCAL    (0) 0x600258
+   6: FUNC     GLOBAL  _start (21) 0x4001a8
+   7: FUNC     GLOBAL  main (33) 0x400144
+   8: FUNC     GLOBAL  bar (44) 0x40017a
+EOF
+
 exit 0
index f14b3054e9a7b36c7989803b92466d246763e66a..bad31cf239594c6d8e8905f51ee888b9e9f94d85 100755 (executable)
 #
 # - testfilebazmin (dynsym + gnu_debugdata)
 # objcopy --remove-section=.gnu_debuglink baz testfilebazmin
+#
+#
+# Special auxiliary only, can happen with static binaries.
+# - start.c
+#
+# extern int main (int argc, char ** argv);
+# void _start (void) { for (;;) main (1, 0); }
+#
+# gcc -g -c start.c
+# gcc -static -nostdlib -o bas foo.o bar.o start.o
+#
+# eu-strip --remove-comment -f bas.debug bas
+# nm bas.debug --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > funcsyms
+# objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols=funcsyms bas.debug mini_debuginfo
+# rm -f mini_debuginfo.xz
+# xz mini_debuginfo
+# objcopy --add-section .gnu_debugdata=mini_debuginfo.xz bas
+# rm bas.debug
+# mv bas testfilebasmin
+
 
 testfiles testfilebaztab
 testfiles testfilebazdbg testfilebazdbg.debug
 testfiles testfilebazdyn
 testfiles testfilebazmdb
 testfiles testfilebazmin
+testfiles testfilebasmin
 
 tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in
 
@@ -253,4 +274,23 @@ cat testfile.dynsym.in \
 cat testfile.minsym.in \
   | testrun_compare ../src/readelf --elf-section -s testfilebazmin
 
+testrun_compare ../src/readelf -s testfilebasmin <<EOF
+EOF
+
+testrun_compare ../src/readelf --elf-section -s testfilebasmin <<\EOF
+
+Symbol table [ 6] '.symtab' contains 9 entries:
+ 6 local symbols  String table: [ 7] '.strtab'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000400168     18 FUNC    LOCAL  DEFAULT        2 foo
+    2: 0000000000400120      0 SECTION LOCAL  DEFAULT        1 
+    3: 0000000000400144      0 SECTION LOCAL  DEFAULT        2 
+    4: 00000000004001c0      0 SECTION LOCAL  DEFAULT        3 
+    5: 0000000000600258      0 SECTION LOCAL  DEFAULT        4 
+    6: 00000000004001a8     21 FUNC    GLOBAL DEFAULT        2 _start
+    7: 0000000000400144     33 FUNC    GLOBAL DEFAULT        2 main
+    8: 000000000040017a     44 FUNC    GLOBAL DEFAULT        2 bar
+EOF
+
 exit 0
diff --git a/tests/testfilebasmin.bz2 b/tests/testfilebasmin.bz2
new file mode 100755 (executable)
index 0000000..3843972
Binary files /dev/null and b/tests/testfilebasmin.bz2 differ