Discard zero address range eh_frame FDEs
authorAlan Modra <amodra@gmail.com>
Sat, 4 Oct 2014 06:23:58 +0000 (15:53 +0930)
committerAlan Modra <amodra@gmail.com>
Sat, 4 Oct 2014 13:19:32 +0000 (22:49 +0930)
These 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.  However, the qsort could just as easily sort the
FDEs in the other order, in which case the normal FDE would
effectively 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.

13 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf-eh-frame.c
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/eh1.d
ld/testsuite/ld-elf/eh1.s
ld/testsuite/ld-elf/eh2.d
ld/testsuite/ld-elf/eh3.d
ld/testsuite/ld-elf/eh3.s
ld/testsuite/ld-mips-elf/eh-frame1-n32.d
ld/testsuite/ld-mips-elf/eh-frame1-n64.d
ld/testsuite/ld-mips-elf/eh-frame2-n32.d
ld/testsuite/ld-mips-elf/eh-frame2-n64.d

index e4445dcbb27414257630531435dca0d19c7602da..dd59324f64e493d0920287f64ec4945a88dd4f0e 100644 (file)
@@ -1,3 +1,16 @@
+2014-10-04  Alan Modra  <amodra@gmail.com>
+
+       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.
+
 2014-09-29  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/17440
index dc343ece475d11e1256cf8d7ce37254bd30f9c8a..b2feee3b147a82abb20cdd70fed23802369d0869 100644 (file)
@@ -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;
index b32add34a36c1a6753d812fc1f625afbea0bb684..331570a0f963f38097842b53cfcae71a4ee2e2b2 100644 (file)
@@ -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
index a03dd719beb15ec24468566260f60a75217f1d57..fd0c8baa460e32a765351c5293d30f33709d6442 100644 (file)
@@ -1,3 +1,13 @@
+2014-10-04  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2014-09-22  Alan Modra  <amodra@gmail.com>
 
        * ld-plugin/lto.exp: Use both --print-file-name and --print-prog-name
 
 2014-06-09  Ryan Mansfield  <rmansfield@qnx.com>
 
-        * config/default.exp (GASP): Remove.
+       * config/default.exp (GASP): Remove.
 
 2014-06-03  Alan Modra  <amodra@gmail.com>
 
index bdf84cc2b8e2bdd4058eb652a61371c716e7ead9..f6841dc71979bd13419e3e738af9d62a66bba8c8 100644 (file)
@@ -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
index a605209680845e8a54a2ff1875c69742a7edb17e..73d715f35371febd401e0f6ac58307098906e4d4 100644 (file)
@@ -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
index 65ad44805cce352d3d53deaacccc0e14e1c3f340..cb75a2da6420313e595a3461fefb1a9dbd2d3968 100644 (file)
@@ -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
index 2d322dddd3812bb6a5fc98c7f91c7b940c72fd21..6ac584a622290688df0a434a10425e4a2940e32c 100644 (file)
@@ -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
index 24bd90d241322d2a73cb5d2908564aa9e2401139..e293c38679953564d7fe6e458fda506a53963b40 100644 (file)
@@ -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
index 0542ebd6978e6ebd0c46d5250759a2092ced3283..eafd022816df8e7a51c8eace468e8c09e5b9259f 100644 (file)
@@ -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 .*
index 2a7aa305b4e79ff44f08f2d70b95849270cc7b32..cdc43bcf6845cc67c00af06121470891bc201105 100644 (file)
@@ -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 .*
index cda44097f7b2147667eb0029be627946b1a9db84..528be8753773dff602dd9fa0cb8b34107fb6d986 100644 (file)
@@ -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 .*
index 05ba94f1eb6a17151d7980b6f21f873fe2a3b6b2..add403e4e4acb4f0a9cf29eaa2e90fece6c91e3f 100644 (file)
@@ -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 .*