diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 13 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 4 | ||||
-rw-r--r-- | bfd/elf-eh-frame.c | 24 |
3 files changed, 35 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e4445dc..dd59324 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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 diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index dc343ec..b2feee3 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 b32add3..331570a 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 |