This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Remove .eh_frame zero terminators


The machinery to do this was there, but not enabled if the terminator
was the only thing in the section.

We should have seen quite a lot of exception handling failures due to
ld's nasty LTO support.  It has the habit of adding object files
extracted from archives after crtend.o, the file that has the
.eh_frame terminator.  The saving grace is that with --eh-frame-hdr
there doesn't need to be a scan of section contents (which would
terminate on hitting the terminator) for an FDE covering a given
address.

bfd/
	* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Don't exit early
	for a section containing just a terminator.  Allow multiple
	terminators at end of section.
	* elflink.c (bfd_elf_discard_info): Iterate over .eh_frame
	sections when not adding alignment.  Assert on terminator in
	the middle of FDEs.
ld/
	* testsuite/ld-elf/eh3.d: Update.
	* testsuite/ld-elf/eh4.d: Update.

diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 7e0d63f..f0ede2d 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -619,15 +619,6 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
 
   REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf));
 
-  if (sec->size >= 4
-      && bfd_get_32 (abfd, ehbuf) == 0
-      && cookie->rel == cookie->relend)
-    {
-      /* Empty .eh_frame section.  */
-      free (ehbuf);
-      return;
-    }
-
   /* If .eh_frame section size doesn't fit into int, we cannot handle
      it (it would need to use 64-bit .eh_frame format anyway).  */
   REQUIRE (sec->size == (unsigned int) sec->size);
@@ -669,8 +660,11 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
   REQUIRE (sec_info);
 
   /* We need to have a "struct cie" for each CIE in this section.  */
-  local_cies = (struct cie *) bfd_zmalloc (num_cies * sizeof (*local_cies));
-  REQUIRE (local_cies);
+  if (num_cies)
+    {
+      local_cies = (struct cie *) bfd_zmalloc (num_cies * sizeof (*local_cies));
+      REQUIRE (local_cies);
+    }
 
   /* FIXME: octets_per_byte.  */
 #define ENSURE_NO_RELOCS(buf)				\
@@ -724,7 +718,9 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
       if (hdr_length == 0)
 	{
 	  /* A zero-length CIE should only be found at the end of
-	     the section.  */
+	     the section, but allow multiple terminators.  */
+	  while (skip_bytes (&buf, ehbuf + sec->size, 4))
+	    REQUIRE (bfd_get_32 (abfd, buf - 4) == 0);
 	  REQUIRE ((bfd_size_type) (buf - ehbuf) == sec->size);
 	  ENSURE_NO_RELOCS (buf);
 	  sec_info->count++;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index f6f57fa..6008915 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -13862,39 +13862,36 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
 
 	  fini_reloc_cookie_for_section (&cookie, i);
 	}
+
       eh_alignment = 1 << o->alignment_power;
-      if (eh_alignment > 4)
-	{
-	  /* Skip over zero terminator, and prevent empty sections
-	     from adding alignment padding at the end.  */
-	  for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)
-	    if (i->size == 0)
-	      i->flags |= SEC_EXCLUDE;
-	    else if (i->size > 4)
-	      break;
-	  /* The last non-empty eh_frame section doesn't need padding.  */
-	  if (i != NULL)
-	    i = i->map_tail.s;
-	  /* Any prior sections must pad the last FDE out to the
-	     output section alignment.  Otherwise we might have zero
-	     padding between sections, which would be seen as a
-	     terminator.  If there is a terminator in the middle of
-	     FDEs, don't increase its size as that will write bogus
-	     data of whatever was after the terminator in the input
-	     file, to the output file.  */
-	  for (; i != NULL; i = i->map_tail.s)
-	    if (i->size != 4)
+      /* Skip over zero terminator, and prevent empty sections from
+	 adding alignment padding at the end.  */
+      for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)
+	if (i->size == 0)
+	  i->flags |= SEC_EXCLUDE;
+	else if (i->size > 4)
+	  break;
+      /* The last non-empty eh_frame section doesn't need padding.  */
+      if (i != NULL)
+	i = i->map_tail.s;
+      /* Any prior sections must pad the last FDE out to the output
+	 section alignment.  Otherwise we might have zero padding
+	 between sections, which would be seen as a terminator.  */
+      for (; i != NULL; i = i->map_tail.s)
+	if (i->size == 4)
+	  /* All but the last zero terminator should have been removed.  */
+	  BFD_FAIL ();
+	else
+	  {
+	    bfd_size_type size
+	      = (i->size + eh_alignment - 1) & -eh_alignment;
+	    if (i->size != size)
 	      {
-		bfd_size_type size
-		  = (i->size + eh_alignment - 1) & -eh_alignment;
-		if (i->size != size)
-		  {
-		    i->size = size;
-		    changed = 1;
-		    eh_changed = 1;
-		  }
+		i->size = size;
+		changed = 1;
+		eh_changed = 1;
 	      }
-	}
+	  }
       if (eh_changed)
 	elf_link_hash_traverse (elf_hash_table (info),
 				_bfd_elf_adjust_eh_frame_global_symbol, NULL);
diff --git a/ld/testsuite/ld-elf/eh3.d b/ld/testsuite/ld-elf/eh3.d
index 3811341..6ac584a 100644
--- a/ld/testsuite/ld-elf/eh3.d
+++ b/ld/testsuite/ld-elf/eh3.d
@@ -23,20 +23,12 @@ Contents of the .eh_frame section:
   DW_CFA_nop
   DW_CFA_nop
 
-0+0018 0+0024 0+001c FDE cie=0+0000 pc=0+400078\.\.0+400090
+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: 8 to 0+400088
   DW_CFA_def_cfa_register: r6 \(rbp\)
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
 
-0+0040 ZERO terminator
+0+0038 ZERO terminator
 #pass
diff --git a/ld/testsuite/ld-elf/eh4.d b/ld/testsuite/ld-elf/eh4.d
index b5eec2f..6c1cb32 100644
--- a/ld/testsuite/ld-elf/eh4.d
+++ b/ld/testsuite/ld-elf/eh4.d
@@ -28,14 +28,12 @@ Contents of the .eh_frame section:
   DW_CFA_set_loc: 0+0417
   DW_CFA_def_cfa_offset: 80
 
-0+0048 0+0024 0+004c FDE cie=0+0000 pc=[0-9a-f]+\.\.[0-9a-f]+
+0+0048 0+002[04] 0+004c FDE cie=0+0000 pc=[0-9a-f]+\.\.[0-9a-f]+
   DW_CFA_def_cfa_offset: 16
   DW_CFA_advance_loc: [0-9a-f]+ to [0-9a-f]+
   DW_CFA_def_cfa_offset: 24
   DW_CFA_advance_loc: [0-9a-f]+ to [0-9a-f]+
   DW_CFA_def_cfa_expression \(DW_OP_breg7 \(rsp\): 8; DW_OP_breg16 \(rip\): 0;.*
-  DW_CFA_nop
 #...
-
 [0-9a-f]+ ZERO terminator
 #pass

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]