Discard zero address range eh_frame FDEs

Alan Modra amodra@gmail.com
Sat Oct 4 13:25:00 GMT 2014


Zero address range FDEs are useless because they can't match any
address.  In fact, worse than useless because the .eh_frame_hdr lookup
table matching addresses to FDEs does not contain information about
the FDE range.  The table is sorted by address;  Range is inferred by
the address delta from one entry to the next.  So if a zero address
range FDE is followed by a normal non-zero range FDE for the same
address, everything is good.  The zero address range FDE will be seen
as having zero range, and the normal FDE an address range up to the
next FDE.  However, the qsort could just as easily sort the FDEs in
the other order, in which case the normal FDE would be seen to have a
zero range.

bfd/
	PR 17447
	* elf-bfd.h (struct eh_cie_fde): Comment re NULL u.fde.cie_inf.
	* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Mark zero address
	range FDEs for discarding.
	(vma_compare): Sort on range after address.
	(_bfd_elf_gc_mark_fdes): Test for NULL u.fde.cie_inf.
	(_bfd_elf_discard_section_eh_frame): Likewise.  Write "FDE" in
	error message rather than "fde".
	(_bfd_elf_write_section_eh_frame_hdr): Write "PC" and "FDE" in
	error message.
ld/testsuite/
	* ld-elf/eh1.s: Don't create FDEs with zero address ranges.
	* ld-elf/eh3.s: Likewise.
	* ld-elf/eh1.d, * ld-elf/eh2.d, * ld-elf/eh3.d: Adjust.
	* ld-mips-elf/eh-frame1-n32.d: Warning match update.
	* ld-mips-elf/eh-frame1-n64.d: Likewise.
	* ld-mips-elf/eh-frame2-n32.d: Likewise.
	* ld-mips-elf/eh-frame2-n64.d: Likewise.

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index dc343ec..b2feee3 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -280,7 +280,9 @@ struct eh_cie_fde
 
 	 If REMOVED == 0, this is the CIE that we have chosen to use for
 	 the output FDE.  The CIE's REMOVED field is also 0, but the CIE
-	 might belong to a different .eh_frame input section from the FDE.  */
+	 might belong to a different .eh_frame input section from the FDE.
+
+	 May be NULL to signify that the FDE should be discarded.  */
       struct eh_cie_fde *cie_inf;
       struct eh_cie_fde *next_for_section;
     } fde;
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index b32add3..331570a 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -808,6 +808,16 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
 	  length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size);
 	  REQUIRE (skip_bytes (&buf, end, 2 * length));
 
+	  SKIP_RELOCS (buf - length);
+	  if (!GET_RELOC (buf - length)
+	      && read_value (abfd, buf - length, length, FALSE) == 0)
+	    {
+	      (*info->callbacks->minfo)
+		(_("discarding zero address range FDE in %B(%A).\n"),
+		 abfd, sec);
+	      this_inf->u.fde.cie_inf = NULL;
+	    }
+
 	  /* Skip the augmentation size, if present.  */
 	  if (cie->augmentation[0] == 'z')
 	    REQUIRE (read_uleb128 (&buf, end, &length));
@@ -959,7 +969,7 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_info *info, asection *sec,
       /* At this stage, all cie_inf fields point to local CIEs, so we
 	 can use the same cookie to refer to them.  */
       cie = fde->u.fde.cie_inf;
-      if (!cie->u.cie.gc_mark)
+      if (cie != NULL && !cie->u.cie.gc_mark)
 	{
 	  cie->u.cie.gc_mark = 1;
 	  if (!mark_entry (info, eh_frame, cie, gc_mark_hook, cookie))
@@ -1137,7 +1147,7 @@ _bfd_elf_discard_section_eh_frame
       /* There should only be one zero terminator, on the last input
 	 file supplying .eh_frame (crtend.o).  Remove any others.  */
       ent->removed = sec->map_head.s != NULL;
-    else if (!ent->cie)
+    else if (!ent->cie && ent->u.fde.cie_inf != NULL)
       {
 	bfd_boolean keep;
 	if ((sec->flags & SEC_LINKER_CREATED) != 0 && cookie->rels == NULL)
@@ -1170,7 +1180,7 @@ _bfd_elf_discard_section_eh_frame
 		   since it is affected by runtime relocations.  */
 		hdr_info->table = FALSE;
 		(*info->callbacks->einfo)
-		  (_("%P: fde encoding in %B(%A) prevents .eh_frame_hdr"
+		  (_("%P: FDE encoding in %B(%A) prevents .eh_frame_hdr"
 		     " table being created.\n"), abfd, sec);
 	      }
 	    ent->removed = 0;
@@ -1725,6 +1735,10 @@ vma_compare (const void *a, const void *b)
     return 1;
   if (p->initial_loc < q->initial_loc)
     return -1;
+  if (p->range > q->range)
+    return 1;
+  if (p->range < q->range)
+    return -1;
   return 0;
 }
 
@@ -1821,7 +1835,7 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
 		  && (hdr_info->array[i].initial_loc
 		      != sec->output_section->vma + val))
 		(*info->callbacks->einfo)
-		  (_("%X%P: .eh_frame_hdr table[%u] pc overflow.\n"), i);
+		  (_("%X%P: .eh_frame_hdr table[%u] PC overflow.\n"), i);
 	      bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
 
 	      val = hdr_info->array[i].fde - sec->output_section->vma;
@@ -1830,7 +1844,7 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
 		  && (hdr_info->array[i].fde
 		      != sec->output_section->vma + val))
 		(*info->callbacks->einfo)
-		  (_("%X%P: .eh_frame_hdr table[%u] fde overflow.\n"), i);
+		  (_("%X%P: .eh_frame_hdr table[%u] FDE overflow.\n"), i);
 	      bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
 
 	      if (i != 0
diff --git a/ld/testsuite/ld-elf/eh1.d b/ld/testsuite/ld-elf/eh1.d
index bdf84cc..f6841dc 100644
--- a/ld/testsuite/ld-elf/eh1.d
+++ b/ld/testsuite/ld-elf/eh1.d
@@ -23,11 +23,11 @@ Contents of the .eh_frame section:
   DW_CFA_nop
   DW_CFA_nop
 
-0+0018 0+001c 0+001c FDE cie=0+0000 pc=0+400078..0+400078
-  DW_CFA_advance_loc: 0 to 0+400078
+0+0018 0+001c 0+001c FDE cie=0+0000 pc=0+400078\.\.0+400090
+  DW_CFA_advance_loc: 8 to 0+400080
   DW_CFA_def_cfa_offset: 16
   DW_CFA_offset: r6 \(rbp\) at cfa-16
-  DW_CFA_advance_loc: 0 to 0+400078
+  DW_CFA_advance_loc: 8 to 0+400088
   DW_CFA_def_cfa_register: r6 \(rbp\)
 
 0+0038 ZERO terminator
diff --git a/ld/testsuite/ld-elf/eh1.s b/ld/testsuite/ld-elf/eh1.s
index a605209..73d715f 100644
--- a/ld/testsuite/ld-elf/eh1.s
+++ b/ld/testsuite/ld-elf/eh1.s
@@ -3,8 +3,11 @@
 	.type	_start, %function
 _start:
 .LFB2:
+	.space	8
 .LCFI0:
+	.space	8
 .LCFI1:
+	.space	8
 .LFE2:
 	.size	_start, .-_start
 	.section	.eh_frame,"a",%progbits
diff --git a/ld/testsuite/ld-elf/eh2.d b/ld/testsuite/ld-elf/eh2.d
index 65ad448..cb75a2d 100644
--- a/ld/testsuite/ld-elf/eh2.d
+++ b/ld/testsuite/ld-elf/eh2.d
@@ -23,11 +23,11 @@ Contents of the .eh_frame section:
   DW_CFA_nop
   DW_CFA_nop
 
-0+0018 0+001c 0+001c FDE cie=0+0000 pc=0+400078..0+400078
-  DW_CFA_advance_loc: 0 to 0+400078
+0+0018 0+001c 0+001c FDE cie=0+0000 pc=0+400078\.\.0+400090
+  DW_CFA_advance_loc: 8 to 0+400080
   DW_CFA_def_cfa_offset: 16
   DW_CFA_offset: r6 \(rbp\) at cfa-16
-  DW_CFA_advance_loc: 0 to 0+400078
+  DW_CFA_advance_loc: 8 to 0+400088
   DW_CFA_def_cfa_register: r6 \(rbp\)
 
 0+0038 ZERO terminator
diff --git a/ld/testsuite/ld-elf/eh3.d b/ld/testsuite/ld-elf/eh3.d
index 2d322dd..6ac584a 100644
--- a/ld/testsuite/ld-elf/eh3.d
+++ b/ld/testsuite/ld-elf/eh3.d
@@ -23,11 +23,11 @@ Contents of the .eh_frame section:
   DW_CFA_nop
   DW_CFA_nop
 
-0+0018 0+001c 0+001c FDE cie=0+0000 pc=0+400078..0+400078
-  DW_CFA_advance_loc: 0 to 0+400078
+0+0018 0+001c 0+001c FDE cie=0+0000 pc=0+400078\.\.0+400090
+  DW_CFA_advance_loc: 8 to 0+400080
   DW_CFA_def_cfa_offset: 16
   DW_CFA_offset: r6 \(rbp\) at cfa-16
-  DW_CFA_advance_loc: 0 to 0+400078
+  DW_CFA_advance_loc: 8 to 0+400088
   DW_CFA_def_cfa_register: r6 \(rbp\)
 
 0+0038 ZERO terminator
diff --git a/ld/testsuite/ld-elf/eh3.s b/ld/testsuite/ld-elf/eh3.s
index 24bd90d..e293c38 100644
--- a/ld/testsuite/ld-elf/eh3.s
+++ b/ld/testsuite/ld-elf/eh3.s
@@ -3,8 +3,11 @@
 	.type	_start, %function
 _start:
 .LFB2:
+	.space	8
 .LCFI0:
+	.space	8
 .LCFI1:
+	.space	8
 .LFE2:
 	.size	_start, .-_start
 	.section	.eh_frame,"a",%progbits
diff --git a/ld/testsuite/ld-mips-elf/eh-frame1-n32.d b/ld/testsuite/ld-mips-elf/eh-frame1-n32.d
index 0542ebd..eafd022 100644
--- a/ld/testsuite/ld-mips-elf/eh-frame1-n32.d
+++ b/ld/testsuite/ld-mips-elf/eh-frame1-n32.d
@@ -4,7 +4,7 @@
 #as: -march=from-abi -EB -n32 --defsym alignment=2 --defsym fill=0x40
 #readelf: --relocs -wf
 #ld: -shared -melf32btsmipn32 -Teh-frame1.ld
-#warning: fde encoding in.*prevents \.eh_frame_hdr table being created.
+#warning: FDE encoding in.*prevents \.eh_frame_hdr table being created.
 
 Relocation section '\.rel\.dyn' .*:
  *Offset .*
diff --git a/ld/testsuite/ld-mips-elf/eh-frame1-n64.d b/ld/testsuite/ld-mips-elf/eh-frame1-n64.d
index 2a7aa30..cdc43bc 100644
--- a/ld/testsuite/ld-mips-elf/eh-frame1-n64.d
+++ b/ld/testsuite/ld-mips-elf/eh-frame1-n64.d
@@ -4,7 +4,7 @@
 #as: -march=from-abi -EB -64 --defsym alignment=3 --defsym fill=0x40
 #readelf: --relocs -wf
 #ld: -shared -melf64btsmip -Teh-frame1.ld
-#warning: fde encoding in.*prevents \.eh_frame_hdr table being created.
+#warning: FDE encoding in.*prevents \.eh_frame_hdr table being created.
 
 Relocation section '\.rel\.dyn' .*:
  *Offset .*
diff --git a/ld/testsuite/ld-mips-elf/eh-frame2-n32.d b/ld/testsuite/ld-mips-elf/eh-frame2-n32.d
index cda4409..528be87 100644
--- a/ld/testsuite/ld-mips-elf/eh-frame2-n32.d
+++ b/ld/testsuite/ld-mips-elf/eh-frame2-n32.d
@@ -4,7 +4,7 @@
 #as: -march=from-abi -EB -n32 --defsym alignment=2 --defsym fill=0
 #readelf: --relocs -wf
 #ld: -shared -melf32btsmipn32 -Teh-frame1.ld
-#warning: fde encoding in.*prevents \.eh_frame_hdr table being created.
+#warning: FDE encoding in.*prevents \.eh_frame_hdr table being created.
 
 Relocation section '\.rel\.dyn' .*:
  *Offset .*
diff --git a/ld/testsuite/ld-mips-elf/eh-frame2-n64.d b/ld/testsuite/ld-mips-elf/eh-frame2-n64.d
index 05ba94f..add403e 100644
--- a/ld/testsuite/ld-mips-elf/eh-frame2-n64.d
+++ b/ld/testsuite/ld-mips-elf/eh-frame2-n64.d
@@ -4,7 +4,7 @@
 #as: -march=from-abi -EB -64 --defsym alignment=3 --defsym fill=0
 #readelf: --relocs -wf
 #ld: -shared -melf64btsmip -Teh-frame1.ld
-#warning: fde encoding in.*prevents \.eh_frame_hdr table being created.
+#warning: FDE encoding in.*prevents \.eh_frame_hdr table being created.
 
 Relocation section '\.rel\.dyn' .*:
  *Offset .*

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list