The FDE initial_location is printed as start address with format_dwarf_addr.
Which does the right thing for .debug_frame addresses, but in .eh_frame
this is encoded as DW_EH_PE_pcrel and so needs to be adjusted before
formatting.

Signed-off-by: Mark Wielaard <[email protected]>
---
 src/ChangeLog |    5 +++++
 src/readelf.c |   16 +++++++++++++++-
 2 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 547605d..7aadcf4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,10 @@
 2012-12-21  Mark Wielaard  <[email protected]>
 
+       * readelf.c (print_debug_frame_section): Adjust FDE start address
+       if pcrel before feeding it to format_dwarf_addr.
+
+2012-12-21  Mark Wielaard  <[email protected]>
+
        * addr2line (main): Call dwfl_end.
 
 2012-12-11  Roland McGrath  <[email protected]>
diff --git a/src/readelf.c b/src/readelf.c
index 7f6f31c..434ec68 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4710,6 +4710,10 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl 
*ebl, GElf_Ehdr *ehdr,
   (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
   const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
 
+  /* Needed if we find pc relative addresses.  */
+  GElf_Addr bias;
+  dwfl_module_getelf (dwflmod, &bias);
+
   Elf_Data *data = elf_rawdata (scn, NULL);
 
   if (unlikely (data == NULL))
@@ -4956,8 +4960,18 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl 
*ebl, GElf_Ehdr *ehdr,
          Dwarf_Word address_range
            = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
 
+         /* pcrel for an FDE address really means data relative. */
+         Dwarf_Addr pc_start = initial_location;
+         if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
+           pc_start += ((uint64_t) shdr->sh_addr
+                        + (base - (const unsigned char *) data->d_buf))
+                        - bias;
+         pc_start &= (ptr_size == 4
+                      ? UINT64_C (0xffffffff)
+                      : UINT64_C (0xffffffffffffffff));
+
          char *a = format_dwarf_addr (dwflmod, cie->address_size,
-                                      initial_location);
+                                      pc_start);
          printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
                  "   CIE_pointer:              %" PRIu64 "\n"
                  "   initial_location:         %s",
-- 
1.7.1

_______________________________________________
elfutils-devel mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/elfutils-devel

Reply via email to