[PATCH] readelf: Adjust initial FDE address if pcrel before printing.

Mark Wielaard mjw at redhat.com
Fri Dec 21 21:18:07 UTC 2012


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 <mjw at redhat.com>
---
 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  <mjw at redhat.com>
 
+	* readelf.c (print_debug_frame_section): Adjust FDE start address
+	if pcrel before feeding it to format_dwarf_addr.
+
+2012-12-21  Mark Wielaard  <mjw at redhat.com>
+
 	* addr2line (main): Call dwfl_end.
 
 2012-12-11  Roland McGrath  <roland at hack.frob.com>
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



More information about the elfutils-devel mailing list