+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,
/* 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. */
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;
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;
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;
/* 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)
{
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;
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;
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;
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;
+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.
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 \
testfiles testfilebazdyn
testfiles testfilebazmdb
testfiles testfilebazmin
+testfiles testfilebasmin
tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in dwflsyms.out
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
#
# - 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
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