summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2013-11-18 14:29:35 -0800
committerJosh Stone <jistone@redhat.com>2013-11-18 14:29:35 -0800
commitdb35c87a85aa651b8ea3ed19689c53cefc28e313 (patch)
treee880f0849642b2772ba4837f6df36d5ebb232026
parent68ce4fc85bbf95441e96fedd76c8bd78f76d8da2 (diff)
downloadelfutils-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/ChangeLog5
-rw-r--r--libdwfl/dwfl_module_getdwarf.c45
-rw-r--r--tests/ChangeLog7
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/run-dwflsyms.sh10
-rwxr-xr-xtests/testfilebazdbg_plr.bz2bin0 -> 2241 bytes
-rwxr-xr-xtests/testfilebazmin_plr.bz2bin0 -> 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
new file mode 100755
index 00000000..1bc43dd2
--- /dev/null
+++ b/tests/testfilebazdbg_plr.bz2
Binary files differ
diff --git a/tests/testfilebazmin_plr.bz2 b/tests/testfilebazmin_plr.bz2
new file mode 100755
index 00000000..e4fcf85d
--- /dev/null
+++ b/tests/testfilebazmin_plr.bz2
Binary files differ