From 697bdca1d7d70ebdcae90759dd885258400e1951 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 23 Jan 2013 17:39:19 +0100 Subject: [PATCH] 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 --- libdwfl/ChangeLog | 13 +++++++++++ libdwfl/dwfl_module_addrsym.c | 16 ++++++++----- libdwfl/dwfl_module_getdwarf.c | 22 +++++++++++++----- libdwfl/dwfl_module_getsym.c | 11 ++++----- tests/ChangeLog | 7 ++++++ tests/Makefile.am | 2 +- tests/run-dwflsyms.sh | 13 +++++++++++ tests/run-readelf-s.sh | 40 +++++++++++++++++++++++++++++++++ tests/testfilebasmin.bz2 | Bin 0 -> 1082 bytes 9 files changed, 107 insertions(+), 17 deletions(-) create mode 100755 tests/testfilebasmin.bz2 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 <|M%bjf9>DZXV?7x z?YGnI|Np=OyaGAKD2ftjJw_CI4H-iLqfHtO6KOIHsLdKpF&?3fObq~!NuwjuHlS!| z(@X*~X!SPL8$x;`LkW`&OaV07pQ>zXg-FzGO&Sdv27mzafB*mh0ib9A00000&;S4i zjQ{`u0000Q211oG8z{uk14pO;000Jn05kwJ0004?000000MGyifCE4P007fb36#Xz z6wn$pdY-0+Kn6etng9lYp!El+G7UXLKmY-wKmY&%>Hq)+fB+2xMN`W|n6h(h0~K>X zNiGMW@`8zhT$zR$Q^rgd*$`Z9m`lJJN=B=@R>H_>9>04+P)<)iw#_)u2`;4s1XYxQ z9}uz#GXx+X1|SKtrWQgv?lFfA-#;|A8=J{3XaGtQh!I5)Bl3a?6Xg&~nIr&_0YN-M z2ayzjC$F}srzs+e!yXn@>tVwlyr78b$dn2c5^Fk{+Y`YQg%HUSX{A@nB68N^(p5O{ zATe4f8YA~bIz=l1QLZImYyc?26z@xQYCg<>;Xs7H%T~Z`Yys-)sW&t6S0bDA(8051 zAxTc5gaV@;>$5PfN%(W-xY*dt^eR|-?hMa&2c&|6INhjMZdSYzW_oGylL|KPlLLCtlmn3I}kT{@N8z&DxV z8}UGx_G!iDpv9&XK%>W>Mxc+9_~Qgw*R(uQwnt7D416J#3P`L`2oU1Pis9c|I#>hK z?s4BbkO1?8vo0@ius^RN{Lz2t6qp0av4o-S&4C1!`*&7ss|9DSfooz`AWAX=$)x}c zNO3X5&J6`os40YoapOF1d?dPonFJ<`x(98R>l$%zmIu zC9nb**KCAjP1duZ%tu-%MIbn=+FJ6WAWAu8(WoAOF?p$sNV6IOOrX*VPKt@Z1=qg` z18ayPYle(p>bL{IAOK3^IIQ8p0IyT}^JKzl&0Hp$Ivc zJ_ND;r6QxOAtV73?e@Y*`|S~cAX0NxkFy5Y%a1-xXj@&`28P3iVXv&wM5QSP+Knp~ z4BO5CwD9VRY^