Remove .eh_frame zero terminators
authorAlan Modra <amodra@gmail.com>
Thu, 31 Aug 2017 10:09:14 +0000 (19:39 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 31 Aug 2017 10:10:35 +0000 (19:40 +0930)
The machinery to do this was there, but not enabled if the terminator
was the only thing in the section.

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.

bfd/ChangeLog
bfd/elf-eh-frame.c
bfd/elflink.c
ld/ChangeLog
ld/testsuite/ld-elf/eh3.d
ld/testsuite/ld-elf/eh4.d

index edc447e..08dfa79 100644 (file)
@@ -1,5 +1,14 @@
 2017-08-31  Alan Modra  <amodra@gmail.com>
 
+       * 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.
+
+2017-08-31  Alan Modra  <amodra@gmail.com>
+
        PR 21441
        PR 22048
        * elflink.c (bfd_elf_discard_info): Don't pad embedded zero
index 7e0d63f..f0ede2d 100644 (file)
@@ -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++;
index f6f57fa..6008915 100644 (file)
@@ -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);
index 1dcb981..670f356 100644 (file)
@@ -1,3 +1,8 @@
+2017-08-31  Alan Modra  <amodra@gmail.com>
+
+       * testsuite/ld-elf/eh3.d: Update.
+       * testsuite/ld-elf/eh4.d: Update.
+
 2017-08-30  Maciej W. Rozycki  <macro@imgtec.com>
 
        * testsuite/ld-elf/orphan-11.ld: Also discard `.MIPS.options'
index 3811341..6ac584a 100644 (file)
@@ -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
index b5eec2f..6c1cb32 100644 (file)
@@ -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