diff options
-rw-r--r-- | bfd/ChangeLog | 24 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 2 | ||||
-rw-r--r-- | bfd/elf-eh-frame.c | 47 | ||||
-rw-r--r-- | bfd/elf32-i386.c | 45 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 3 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 2 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 38 | ||||
-rw-r--r-- | bfd/elflink.c | 24 |
8 files changed, 114 insertions, 71 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 35bbb31..2165cd8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,27 @@ +2012-05-25 Alan Modra <amodra@gmail.com> + + PR ld/13909 + * elf-eh-frame.c (_bfd_elf_eh_frame_present): New function. + (_bfd_elf_maybe_strip_eh_frame_hdr): Use it here. + * elf-bfd.h (_bfd_elf_eh_frame_present): Declare. + * elflink.c (bfd_elf_size_dynamic_sections): Let the backend + size dynamic sections before stripping eh_frame_hdr. + (bfd_elf_gc_sections): Handle multiple .eh_frame sections. + * elf32-ppc.c (ppc_elf_size_dynamic_sections): Drop glink_eh_frame + if no other .eh_frame sections exist. + * elf64-ppc.c (ppc64_elf_size_stubs): Likewise. + * elf32-i386.c (elf_i386_create_dynamic_sections): Don't size + or alloc plt_eh_frame here.. + (elf_i386_size_dynamic_sections): ..do it here instead. Don't + specially keep sgotplt, iplt, tgotplt, sdynbss for symbols. + (elf_i386_finish_dynamic_sections): Check plt_eh_frame->contents + before writing plt offset. + * elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Don't size + or alloc plt_eh_frame here.. + (elf_x86_64_size_dynamic_sections): ..do it here instead. + (elf_x86_64_finish_dynamic_sections): Check plt_eh_frame->contents + before writing plt offset. + 2012-05-24 Alan Modra <amodra@gmail.com> PR ld/14158 diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index b07d8c4..5426c93 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1950,6 +1950,8 @@ extern bfd_boolean _bfd_elf_write_section_eh_frame (bfd *, struct bfd_link_info *, asection *, bfd_byte *); extern bfd_boolean _bfd_elf_write_section_eh_frame_hdr (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_eh_frame_present + (struct bfd_link_info *); extern bfd_boolean _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *); diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 685540c..a75d806 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -1247,6 +1247,26 @@ _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) return TRUE; } +/* Return true if there is at least one non-empty .eh_frame section in + input files. Can only be called after ld has mapped input to + output sections, and before sections are stripped. */ +bfd_boolean +_bfd_elf_eh_frame_present (struct bfd_link_info *info) +{ + asection *eh = bfd_get_section_by_name (info->output_bfd, ".eh_frame"); + + if (eh == NULL) + return FALSE; + + /* Count only sections which have at least a single CIE or FDE. + There cannot be any CIE or FDE <= 8 bytes. */ + for (eh = eh->map_head.s; eh != NULL; eh = eh->map_head.s) + if (eh->size > 8) + return TRUE; + + return FALSE; +} + /* This function is called from size_dynamic_sections. It needs to decide whether .eh_frame_hdr should be output or not, because when the dynamic symbol table has been sized it is too late @@ -1255,8 +1275,6 @@ _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) bfd_boolean _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info) { - asection *o; - bfd *abfd; struct elf_link_hash_table *htab; struct eh_frame_hdr_info *hdr_info; @@ -1265,28 +1283,9 @@ _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info) if (hdr_info->hdr_sec == NULL) return TRUE; - if (bfd_is_abs_section (hdr_info->hdr_sec->output_section)) - { - hdr_info->hdr_sec = NULL; - return TRUE; - } - - abfd = NULL; - if (info->eh_frame_hdr) - for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next) - { - /* Count only sections which have at least a single CIE or FDE. - There cannot be any CIE or FDE <= 8 bytes. */ - o = bfd_get_section_by_name (abfd, ".eh_frame"); - while (o != NULL - && (o->size <= 8 - || bfd_is_abs_section (o->output_section))) - o = bfd_get_next_section_by_name (o); - if (o != NULL) - break; - } - - if (abfd == NULL) + if (bfd_is_abs_section (hdr_info->hdr_sec->output_section) + || !info->eh_frame_hdr + || !_bfd_elf_eh_frame_present (info)) { hdr_info->hdr_sec->flags |= SEC_EXCLUDE; hdr_info->hdr_sec = NULL; diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 84299ce..7b33d77 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1027,12 +1027,6 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) if (htab->plt_eh_frame == NULL || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2)) return FALSE; - - htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt); - htab->plt_eh_frame->contents - = bfd_alloc (dynobj, htab->plt_eh_frame->size); - memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt, - sizeof (elf_i386_eh_frame_plt)); } return TRUE; @@ -2726,7 +2720,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) FALSE, FALSE, FALSE); /* Don't allocate .got.plt section if there are no GOT nor PLT - entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */ + entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */ if ((got == NULL || !got->ref_regular_nonweak) && (htab->elf.sgotplt->size @@ -2742,6 +2736,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) htab->elf.sgotplt->size = 0; } + + if (htab->plt_eh_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && !bfd_is_abs_section (htab->elf.splt->output_section) + && _bfd_elf_eh_frame_present (info)) + htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt); + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; @@ -2753,11 +2755,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) continue; if (s == htab->elf.splt - || s == htab->elf.sgot - || s == htab->elf.sgotplt - || s == htab->elf.iplt - || s == htab->elf.igotplt - || s == htab->sdynbss) + || s == htab->elf.sgot) { /* Strip this section if we don't need it; see the comment below. */ @@ -2768,6 +2766,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) if (htab->elf.hplt != NULL) strip_section = FALSE; } + else if (s == htab->elf.sgotplt + || s == htab->elf.iplt + || s == htab->elf.igotplt + || s == htab->plt_eh_frame + || s == htab->sdynbss) + { + /* Strip these too. */ + } else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) { if (s->size != 0 @@ -2815,11 +2821,13 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) } if (htab->plt_eh_frame != NULL - && htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && (htab->elf.splt->flags & SEC_EXCLUDE) == 0) - bfd_put_32 (dynobj, htab->elf.splt->size, - htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + && htab->plt_eh_frame->contents != NULL) + { + memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt, + sizeof (elf_i386_eh_frame_plt)); + bfd_put_32 (dynobj, htab->elf.splt->size, + htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + } if (htab->elf.dynamic_sections_created) { @@ -4840,7 +4848,8 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, } /* Adjust .eh_frame for .plt section. */ - if (htab->plt_eh_frame != NULL) + if (htab->plt_eh_frame != NULL + && htab->plt_eh_frame->contents != NULL) { if (htab->elf.splt != NULL && htab->elf.splt->size != 0 diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 9665d39..98f1aa8 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -6244,7 +6244,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->glink != NULL && htab->glink->size != 0 && htab->glink_eh_frame != NULL - && !bfd_is_abs_section (htab->glink_eh_frame->output_section)) + && !bfd_is_abs_section (htab->glink_eh_frame->output_section) + && _bfd_elf_eh_frame_present (info)) { s = htab->glink_eh_frame; s->size = sizeof (glink_eh_frame_cie) + 20; diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index df1db6d..79f551d 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -11662,7 +11662,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, if (htab->glink_eh_frame != NULL && !bfd_is_abs_section (htab->glink_eh_frame->output_section) - && (htab->glink_eh_frame->flags & SEC_EXCLUDE) == 0) + && htab->glink_eh_frame->output_section->size != 0) { size_t size = 0, align; diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 1f490d4..abd8d60 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -982,8 +982,6 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj, && htab->plt_eh_frame == NULL && htab->elf.splt != NULL) { - const struct elf_x86_64_backend_data *const abed - = get_elf_x86_64_backend_data (dynobj); flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags; htab->plt_eh_frame = bfd_make_section_anyway_with_flags (dynobj, ".eh_frame", @@ -993,12 +991,6 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj, if (htab->plt_eh_frame == NULL || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3)) return FALSE; - - htab->plt_eh_frame->size = abed->eh_frame_plt_size; - htab->plt_eh_frame->contents - = bfd_alloc (dynobj, htab->plt_eh_frame->size); - memcpy (htab->plt_eh_frame->contents, - abed->eh_frame_plt, abed->eh_frame_plt_size); } return TRUE; } @@ -2797,6 +2789,17 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, htab->elf.sgotplt->size = 0; } + if (htab->plt_eh_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && !bfd_is_abs_section (htab->elf.splt->output_section) + && _bfd_elf_eh_frame_present (info)) + { + const struct elf_x86_64_backend_data *arch_data + = (const struct elf_x86_64_backend_data *) bed->arch_data; + htab->plt_eh_frame->size = arch_data->eh_frame_plt_size; + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; @@ -2810,6 +2813,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, || s == htab->elf.sgotplt || s == htab->elf.iplt || s == htab->elf.igotplt + || s == htab->plt_eh_frame || s == htab->sdynbss) { /* Strip this section if we don't need it; see the @@ -2861,11 +2865,16 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, } if (htab->plt_eh_frame != NULL - && htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && (htab->elf.splt->flags & SEC_EXCLUDE) == 0) - bfd_put_32 (dynobj, htab->elf.splt->size, - htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + && htab->plt_eh_frame->contents != NULL) + { + const struct elf_x86_64_backend_data *arch_data + = (const struct elf_x86_64_backend_data *) bed->arch_data; + + memcpy (htab->plt_eh_frame->contents, + arch_data->eh_frame_plt, htab->plt_eh_frame->size); + bfd_put_32 (dynobj, htab->elf.splt->size, + htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + } if (htab->elf.dynamic_sections_created) { @@ -4725,7 +4734,8 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, } /* Adjust .eh_frame for .plt section. */ - if (htab->plt_eh_frame != NULL) + if (htab->plt_eh_frame != NULL + && htab->plt_eh_frame->contents != NULL) { if (htab->elf.splt != NULL && htab->elf.splt->size != 0 diff --git a/bfd/elflink.c b/bfd/elflink.c index 7722fb5..7f35e7f 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -5584,17 +5584,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, && ! (*bed->elf_backend_always_size_sections) (output_bfd, info)) return FALSE; - if (! _bfd_elf_maybe_strip_eh_frame_hdr (info)) - return FALSE; - dynobj = elf_hash_table (info)->dynobj; - /* If there were no dynamic objects in the link, there is nothing to - do here. */ - if (dynobj == NULL) - return TRUE; - - if (elf_hash_table (info)->dynamic_sections_created) + if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created) { struct elf_info_failed eif; struct elf_link_hash_entry *h; @@ -5897,11 +5889,15 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* The backend must work out the sizes of all the other dynamic sections. */ - if (bed->elf_backend_size_dynamic_sections + if (dynobj != NULL + && bed->elf_backend_size_dynamic_sections != NULL && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) return FALSE; - if (elf_hash_table (info)->dynamic_sections_created) + if (! _bfd_elf_maybe_strip_eh_frame_hdr (info)) + return FALSE; + + if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created) { unsigned long section_sym_count; struct bfd_elf_version_tree *verdefs; @@ -12002,12 +11998,14 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) struct elf_reloc_cookie cookie; sec = bfd_get_section_by_name (sub, ".eh_frame"); - if (sec && init_reloc_cookie_for_section (&cookie, info, sec)) + while (sec && init_reloc_cookie_for_section (&cookie, info, sec)) { _bfd_elf_parse_eh_frame (sub, info, sec, &cookie); - if (elf_section_data (sec)->sec_info) + if (elf_section_data (sec)->sec_info + && (sec->flags & SEC_LINKER_CREATED) == 0) elf_eh_frame_section (sub) = sec; fini_reloc_cookie_for_section (&cookie, sec); + sec = bfd_get_next_section_by_name (sec); } } _bfd_elf_end_eh_frame_parsing (info); |