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 <mjw@redhat.com>
This commit is contained in:
Mark Wielaard
2013-01-23 17:39:19 +01:00
parent 9a91fb2279
commit 697bdca1d7
9 changed files with 107 additions and 17 deletions
+13
View 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,
+11 -5
View 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. */
+16 -6
View 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;
+6 -5
View 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;
+7
View 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.
+1 -1
View 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 \
+13
View File
@@ -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
+40
View File
@@ -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
BIN
View File
Binary file not shown.