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.
This commit is contained in:
Alan Modra 2014-10-04 15:53:58 +09:30
parent 0661ae8e4d
commit c2aaac080c
13 changed files with 65 additions and 20 deletions

View 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

View 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;

View 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

View 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
@ -534,7 +544,7 @@
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>

View 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

View 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

View 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

View 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

View 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

View 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 .*

View 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 .*

View 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 .*

View 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 .*