libdwfl: Fix and test aux_sym address_sync with relocated ELF
authorJosh Stone <jistone@redhat.com>
Mon, 18 Nov 2013 22:29:35 +0000 (14:29 -0800)
committerJosh Stone <jistone@redhat.com>
Mon, 18 Nov 2013 22:29:35 +0000 (14:29 -0800)
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>
libdwfl/ChangeLog
libdwfl/dwfl_module_getdwarf.c
tests/ChangeLog
tests/Makefile.am
tests/run-dwflsyms.sh
tests/testfilebazdbg_plr.bz2 [new file with mode: 0755]
tests/testfilebazmin_plr.bz2 [new file with mode: 0755]

index 9901380..ca328de 100644 (file)
@@ -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
index 7a65ec3..dd76f25 100644 (file)
@@ -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. */
index 9461287..9a8ac61 100644 (file)
@@ -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.
index e9cf950..4f8e9e4 100644 (file)
@@ -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 \
index a425277..2adec5a 100755 (executable)
 
 # 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 (executable)
index 0000000..1bc43dd
Binary files /dev/null and b/tests/testfilebazdbg_plr.bz2 differ
diff --git a/tests/testfilebazmin_plr.bz2 b/tests/testfilebazmin_plr.bz2
new file mode 100755 (executable)
index 0000000..e4fcf85
Binary files /dev/null and b/tests/testfilebazmin_plr.bz2 differ