summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2013-01-23 17:39:19 +0100
committerMark Wielaard <[email protected]>2013-01-23 19:44:23 +0100
commit697bdca1d7d70ebdcae90759dd885258400e1951 (patch)
tree04f0b8cf278ee5d97a58f3416c8da7e41899999c
parent9a91fb2279fc9365b44f4526623ff0851c84f23d (diff)
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]>
-rw-r--r--libdwfl/ChangeLog13
-rw-r--r--libdwfl/dwfl_module_addrsym.c16
-rw-r--r--libdwfl/dwfl_module_getdwarf.c22
-rw-r--r--libdwfl/dwfl_module_getsym.c11
-rw-r--r--tests/ChangeLog7
-rw-r--r--tests/Makefile.am2
-rwxr-xr-xtests/run-dwflsyms.sh13
-rwxr-xr-xtests/run-readelf-s.sh40
-rwxr-xr-xtests/testfilebasmin.bz2bin0 -> 1082 bytes
9 files changed, 107 insertions, 17 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 828db083..cf5b42e0 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,16 @@
+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.
+ (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 <[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 d2059ea4..732b6983 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 ffbe5898..d35c2660 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 3e4d9f61..07127b78 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 feb9f699..bc721c70 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 b46c4c23..f32ea242 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 570881ad..56a75804 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 f14b3054..bad31cf2 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 00000000..38439720
--- /dev/null
+++ b/tests/testfilebasmin.bz2
Binary files differ