From: Mark Wielaard Date: Wed, 23 Jan 2013 16:39:19 +0000 (+0100) Subject: libdwfl: Support auxiliary symbol table only for getsym and addrsym. X-Git-Tag: elfutils-0.156~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=697bdca1d7d70ebdcae90759dd885258400e1951;p=thirdparty%2Felfutils.git libdwfl: Support auxiliary symbol table only for getsym and addrsym. Static binaries can have only an auxiliary symbol table and no dynsym or symtab table. Signed-off-by: Mark Wielaard --- diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 828db083d..cf5b42e04 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,16 @@ +2013-01-23 Mark Wielaard + + * 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 * libdwflP.h (struct Dwfl_Module): Add aux_sym, aux_symdata, diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c index d2059ea4b..732b6983a 100644 --- a/libdwfl/dwfl_module_addrsym.c +++ b/libdwfl/dwfl_module_addrsym.c @@ -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. */ diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index ffbe58981..d35c2660b 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -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; diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c index 3e4d9f612..07127b78b 100644 --- a/libdwfl/dwfl_module_getsym.c +++ b/libdwfl/dwfl_module_getsym.c @@ -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; diff --git a/tests/ChangeLog b/tests/ChangeLog index feb9f6995..bc721c700 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2013-01-23 Mark Wielaard + + * 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 * Makefile.am (check_PROGRAMS): Add dwflsyms. diff --git a/tests/Makefile.am b/tests/Makefile.am index b46c4c23d..f32ea242d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 \ diff --git a/tests/run-dwflsyms.sh b/tests/run-dwflsyms.sh index 570881ade..56a75804d 100755 --- a/tests/run-dwflsyms.sh +++ b/tests/run-dwflsyms.sh @@ -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 diff --git a/tests/run-readelf-s.sh b/tests/run-readelf-s.sh index f14b3054e..bad31cf23 100755 --- a/tests/run-readelf-s.sh +++ b/tests/run-readelf-s.sh @@ -74,12 +74,33 @@ # # - 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 <