From c2aaac080c05369f6fb7009d85dcf9bb98a914e6 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 4 Oct 2014 15:53:58 +0930 Subject: [PATCH] Discard zero address range eh_frame FDEs 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. --- bfd/ChangeLog | 13 +++++++++++++ bfd/elf-bfd.h | 4 +++- bfd/elf-eh-frame.c | 24 +++++++++++++++++++----- ld/testsuite/ChangeLog | 12 +++++++++++- ld/testsuite/ld-elf/eh1.d | 6 +++--- ld/testsuite/ld-elf/eh1.s | 3 +++ ld/testsuite/ld-elf/eh2.d | 6 +++--- ld/testsuite/ld-elf/eh3.d | 6 +++--- ld/testsuite/ld-elf/eh3.s | 3 +++ ld/testsuite/ld-mips-elf/eh-frame1-n32.d | 2 +- ld/testsuite/ld-mips-elf/eh-frame1-n64.d | 2 +- ld/testsuite/ld-mips-elf/eh-frame2-n32.d | 2 +- ld/testsuite/ld-mips-elf/eh-frame2-n64.d | 2 +- 13 files changed, 65 insertions(+), 20 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e4445dcbb27..dd59324f64e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2014-10-04 Alan Modra + + 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 PR ld/17440 diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index dc343ece475..b2feee3b147 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 b32add34a36..331570a0f96 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/ChangeLog b/ld/testsuite/ChangeLog index a03dd719beb..fd0c8baa460 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2014-10-04 Alan Modra + + * 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 * ld-plugin/lto.exp: Use both --print-file-name and --print-prog-name @@ -534,7 +544,7 @@ 2014-06-09 Ryan Mansfield - * config/default.exp (GASP): Remove. + * config/default.exp (GASP): Remove. 2014-06-03 Alan Modra diff --git a/ld/testsuite/ld-elf/eh1.d b/ld/testsuite/ld-elf/eh1.d index bdf84cc2b8e..f6841dc7197 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 a6052096808..73d715f3537 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 65ad44805cc..cb75a2da642 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 2d322dddd38..6ac584a6222 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 24bd90d2413..e293c386799 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 0542ebd6978..eafd022816d 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 2a7aa305b4e..cdc43bcf684 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 cda44097f7b..528be875377 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 05ba94f1eb6..add403e4e4a 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 .*