diff options
author | Josh Stone <jistone@redhat.com> | 2013-11-18 14:29:35 -0800 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2013-11-18 14:29:35 -0800 |
commit | db35c87a85aa651b8ea3ed19689c53cefc28e313 (patch) | |
tree | e880f0849642b2772ba4837f6df36d5ebb232026 | |
parent | 68ce4fc85bbf95441e96fedd76c8bd78f76d8da2 (diff) | |
download | elfutils-db35c87a85aa651b8ea3ed19689c53cefc28e313.tar.gz |
libdwfl: Fix and test aux_sym address_sync with relocated ELF
The aux_sym address_sync already worked with a full prelink, which has
.gnu.prelink_undo, but it failed on plain relocations with prelink -r.
Now it uses the difference in ehdr.e_entry as a first offset guess, and
the tests confirm this seems to work fine.
Signed-off-by: Josh Stone <jistone@redhat.com>
-rw-r--r-- | libdwfl/ChangeLog | 5 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getdwarf.c | 45 | ||||
-rw-r--r-- | tests/ChangeLog | 7 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rwxr-xr-x | tests/run-dwflsyms.sh | 10 | ||||
-rwxr-xr-x | tests/testfilebazdbg_plr.bz2 | bin | 0 -> 2241 bytes | |||
-rwxr-xr-x | tests/testfilebazmin_plr.bz2 | bin | 0 -> 3337 bytes |
7 files changed, 54 insertions, 14 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 99013805..ca328ded 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2013-11-18 Josh Stone <jistone@redhat.com> + + * dwfl_module_getdwarf.c (find_aux_address_sync): New function. + (find_aux_sym): Use it. + 2013-11-14 Jan Kratochvil <jan.kratochvil@redhat.com> Code cleanup: Remove const in prototype diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 7a65ec3b..dd76f257 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -816,6 +816,33 @@ find_dynsym (Dwfl_Module *mod) } } + +#if USE_LZMA +/* Try to find the offset between the main file and .gnu_debugdata. */ +static bool +find_aux_address_sync (Dwfl_Module *mod) +{ + /* Don't trust the phdrs in the minisymtab elf file to be setup correctly. + The address_sync is equal to the main file it is embedded in at first. */ + mod->aux_sym.address_sync = mod->main.address_sync; + + /* Adjust address_sync for the difference in entry addresses, attempting to + account for ELF relocation changes after aux was split. */ + GElf_Ehdr ehdr_main, ehdr_aux; + if (unlikely (gelf_getehdr (mod->main.elf, &ehdr_main) == NULL) + || unlikely (gelf_getehdr (mod->aux_sym.elf, &ehdr_aux) == NULL)) + return false; + mod->aux_sym.address_sync += ehdr_aux.e_entry - ehdr_main.e_entry; + + /* The shdrs are setup OK to make find_prelink_address_sync () do the right + thing, which is possibly more reliable, but it needs .gnu.prelink_undo. */ + if (mod->aux_sym.address_sync != 0) + return find_prelink_address_sync (mod, &mod->aux_sym) == DWFL_E_NOERROR; + + return true; +} +#endif + /* Try to find the auxiliary symbol table embedded in the main elf file section .gnu_debugdata. Only matters if the symbol information comes from the main file dynsym. No harm done if not found. */ @@ -879,21 +906,11 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)), mod->aux_sym.elf->flags |= ELF_F_MALLOCED; if (open_elf (mod, &mod->aux_sym) != DWFL_E_NOERROR) return; - /* Don't trust the phdrs in the minisymtab elf file to be - setup correctly. The address_sync is equal to the main - file it is embedded in at first. The shdrs are setup - OK to make find_prelink_address_sync () do the right - thing if necessary though. */ - mod->aux_sym.address_sync = mod->main.address_sync; - if (mod->aux_sym.address_sync != 0) + if (! find_aux_address_sync (mod)) { - error = find_prelink_address_sync (mod, &mod->aux_sym); - if (error != DWFL_E_NOERROR) - { - elf_end (mod->aux_sym.elf); - mod->aux_sym.elf = NULL; - return; - } + elf_end (mod->aux_sym.elf); + mod->aux_sym.elf = NULL; + return; } /* So far, so good. Get minisymtab table data and cache it. */ diff --git a/tests/ChangeLog b/tests/ChangeLog index 9461287a..9a8ac613 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2013-11-18 Josh Stone <jistone@redhat.com> + + * testfilebazdbg_plr.bz2: New testfile. + * testfilebazmin_plr.bz2: Likewise. + * Makefile.am (EXTRA_DIST): Add the above files. + * run-dwflsyms.sh: Add prelink -r tests. + 2013-11-15 Mark Wielaard <mjw@redhat.com> * testfilebazmdb.bz2: Regenerated. diff --git a/tests/Makefile.am b/tests/Makefile.am index e9cf950c..4f8e9e49 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -190,6 +190,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfilebazmin.bz2 testfilebazdbg.debug.bz2 testfilebazmdb.bz2 \ testfilebaztab.bz2 testfilebasmin.bz2 \ testfilebazdbg_pl.bz2 testfilebazmin_pl.bz2 \ + testfilebazdbg_plr.bz2 testfilebazmin_plr.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 a425277c..2adec5a3 100755 --- a/tests/run-dwflsyms.sh +++ b/tests/run-dwflsyms.sh @@ -19,14 +19,18 @@ # Tests dwfl_module_{addrsym,getsym,relocate_address} # See run-readelf-s.sh for how to generate test binaries. +# In addition, *_pl files were created from their base file +# with prelink -N, and *_plr with prelink -r 0x4200000000. testfiles testfilebaztab testfiles testfilebazdbg testfilebazdbg.debug testfiles testfilebazdbg_pl +testfiles testfilebazdbg_plr testfiles testfilebazdyn testfiles testfilebazmdb testfiles testfilebazmin testfiles testfilebazmin_pl +testfiles testfilebazmin_plr testfiles testfilebasmin tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in dwflsyms.out @@ -328,6 +332,9 @@ cat testfile.symtab.in \ cat testfile.symtab_pl.in \ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg_pl +sed s/0x3000/0x4200/g testfile.symtab_pl.in \ + | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg_plr + cat testfile.dynsym.in \ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdyn @@ -340,6 +347,9 @@ cat testfile.minsym.in \ cat testfile.minsym_pl.in \ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin_pl +sed s/0x3000/0x4200/g testfile.minsym_pl.in \ + | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin_plr + testrun_compare ${abs_builddir}/dwflsyms -e testfilebasmin <<\EOF 0: NOTYPE LOCAL (0) 0 1: FUNC LOCAL foo (18) 0x400168, rel: 0x400168 diff --git a/tests/testfilebazdbg_plr.bz2 b/tests/testfilebazdbg_plr.bz2 Binary files differnew file mode 100755 index 00000000..1bc43dd2 --- /dev/null +++ b/tests/testfilebazdbg_plr.bz2 diff --git a/tests/testfilebazmin_plr.bz2 b/tests/testfilebazmin_plr.bz2 Binary files differnew file mode 100755 index 00000000..e4fcf85d --- /dev/null +++ b/tests/testfilebazmin_plr.bz2 |