On Wed, 2013-01-23 at 07:03 +0100, Jan Kratochvil wrote: > On Tue, 22 Jan 2013 22:03:24 +0100, Mark Wielaard wrote: > > I do wonder how realistic it is that we will ever encounter such a case > > though. > > I do not wonder, it is for example /usr/bin/fpc (from > fpc-2.6.0-3.fc18.x86_64).
Aha, thanks for that example. I guess it makes sense for static binaries. So lets support that too. I created a minimal testcase. How about the attached to support it? Thanks, Mark
>From cf875ef688c8f1d081a770e3df43e0668fa80c49 Mon Sep 17 00:00:00 2001 From: Mark Wielaard <[email protected]> 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 <[email protected]> --- libdwfl/ChangeLog | 12 ++++++++++++ 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(+), 16 deletions(-) create mode 100755 tests/testfilebasmin.bz2 diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 828db08..24d4ae5 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,15 @@ +2013-01-23 Mark Wielaard <[email protected]> + + * 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. + Substract one from aux_syments 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 <[email protected]> * 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 d2059ea..732b698 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 ffbe589..6ec11ff 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) { @@ -1077,6 +1085,10 @@ find_symtab (Dwfl_Module *mod) mod->aux_symdata = elf_getdata (aux_symscn, NULL); if (mod->aux_symdata == NULL) goto aux_cleanup; + + /* We will skip the auxiliary zero entry if there is another one. */ + if (mod->syments > 0 && mod->aux_syments > 0) + mod->aux_syments--; } } diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c index 3e4d9f6..07127b7 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 feb9f69..bc721c7 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2013-01-23 Mark Wielaard <[email protected]> + + * 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 <[email protected]> * Makefile.am (check_PROGRAMS): Add dwflsyms. diff --git a/tests/Makefile.am b/tests/Makefile.am index b46c4c2..f32ea24 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 570881a..56a7580 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 f14b305..bad31cf 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 <<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 index 0000000000000000000000000000000000000000..3843972037ca84dc9599f5dc25ad05e0f2278f43 GIT binary patch literal 1082 zcmV-A1jYM8T4*^jL0KkKS=jQ&IRF9VfB*mg-@X5@_22*Je}4D>|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<LNT3s<a4cUOpaMV{r-G!z+w|!8vB0a<YoE#v z&Uv1FRUYal>|-?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<hU-1HwP9pQ**~)mjMwrh;|VP0rrN4 z_c)H0bO8hAT@1lMaO((*%x^K=sZ_}Qui0`11PiQ+tq&O`3DM+5`mHd^m>>l$%zmIu zC9nb**KCAjP1duZ%tu-%MIbn=+FJ6WAWAu8(WoAOF?p$sNV6IOOrX*VPKt@Z1=qg` z18ayPYle(p>bL{IAOK3^IIQ8p0Iy<f`3pq3IWVO`UoxaxsBhdRKWEuNjKGg;MR}P1 z)t}2s)@Y0F3diYb=2LF+i(mAvk?o`M_-?lnU_oK_okv-fLdqp>T}^JKzl&0Hp$Ivc zJ_ND;r6QxOAtV73?e@Y*`|S~cAX0NxkFy5Y%a1-xXj@&`28P3iVXv&wM5QSP+Knp~ z4BO5CwD9VRY^<XR*i1_BfvcF%7Xx&Vt0xT)L}u2D8-}~{b+c&uXnC{OZLTe6U@eBA zYEL<a%!<`o*m3T4mMEc<wv$}=;g|qmm<?c1f<znwV27xmq3`&+k}1N3hR2pU$R!8e AVgLXD literal 0 HcmV?d00001 -- 1.7.1
_______________________________________________ elfutils-devel mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/elfutils-devel
