From 43e1669b2d187f4b2e4ecdf98a5aac8e9fb10bfd Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 5 Aug 2011 03:17:12 +0000 Subject: [PATCH] PR ld/12762 bfd/ * elflink.c (_bfd_elf_section_already_linked): Return matched status. Remove COFF comdat section handling. * linker.c (_bfd_generic_section_already_linked): Return matched status. Don't set SEC_GROUP in l_flags for plugin entries. (bfd_section_already_linked): Update prototype. * targets.c (_section_already_linked): Likewise. * elf-bfd.h (_bfd_elf_section_already_linked): Likewise. * libbfd-in.h (_bfd_generic_section_already_linked): Likewise. (_bfd_nolink_section_already_linked): Update. * libbfd.h: Regenerate. * bfd-in2.h: Regenerate. ld/ * plugin.c (add_symbols): Exclude comdat_key symbols from symbol table if already seen. --- bfd/ChangeLog | 15 +++++++++++++++ bfd/bfd-in2.h | 6 +++--- bfd/elf-bfd.h | 2 +- bfd/elflink.c | 29 ++++++++++++++++------------- bfd/libbfd-in.h | 6 +++--- bfd/libbfd.h | 6 +++--- bfd/linker.c | 23 +++++++++++------------ bfd/targets.c | 4 ++-- ld/ChangeLog | 6 ++++++ ld/plugin.c | 12 +++++++----- 10 files changed, 67 insertions(+), 42 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f6ccd5452d..82defd9ff1 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2011-08-05 Alan Modra + + PR ld/12762 + * elflink.c (_bfd_elf_section_already_linked): Return matched + status. Remove COFF comdat section handling. + * linker.c (_bfd_generic_section_already_linked): Return matched + status. Don't set SEC_GROUP in l_flags for plugin entries. + (bfd_section_already_linked): Update prototype. + * targets.c (_section_already_linked): Likewise. + * elf-bfd.h (_bfd_elf_section_already_linked): Likewise. + * libbfd-in.h (_bfd_generic_section_already_linked): Likewise. + (_bfd_nolink_section_already_linked): Update. + * libbfd.h: Regenerate. + * bfd-in2.h: Regenerate. + 2011-08-05 Alan Modra * elf32-ppc.c: Include dwarf2.h. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index ac8145d776..af13ca4ada 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6107,8 +6107,8 @@ typedef struct bfd_target /* Check if SEC has been already linked during a reloceatable or final link. */ - void (*_section_already_linked) (bfd *, struct already_linked *, - struct bfd_link_info *); + bfd_boolean (*_section_already_linked) (bfd *, struct already_linked *, + struct bfd_link_info *); /* Define a common symbol. */ bfd_boolean (*_bfd_define_common_symbol) (bfd *, struct bfd_link_info *, @@ -6177,7 +6177,7 @@ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); #define bfd_link_split_section(abfd, sec) \ BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) -void bfd_section_already_linked (bfd *abfd, +bfd_boolean bfd_section_already_linked (bfd *abfd, struct already_linked *data, struct bfd_link_info *info); diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index e6ea5805ef..2c80f67be7 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1802,7 +1802,7 @@ extern bfd_boolean _bfd_elf_match_sections_by_type extern bfd_boolean bfd_elf_is_group_section (bfd *, const struct bfd_section *); struct already_linked; -extern void _bfd_elf_section_already_linked +extern bfd_boolean _bfd_elf_section_already_linked (bfd *, struct already_linked *, struct bfd_link_info *); extern void bfd_elf_set_group_contents (bfd *, asection *, void *); diff --git a/bfd/elflink.c b/bfd/elflink.c index 2e592f5e0f..53765b626d 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12515,7 +12515,7 @@ section_signature (asection *sec) return sec->name; } -void +bfd_boolean _bfd_elf_section_already_linked (bfd *abfd, struct already_linked *linked, struct bfd_link_info *info) @@ -12525,6 +12525,7 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section_already_linked *l; struct bfd_section_already_linked_hash_entry *already_linked_list; asection *sec, *l_sec; + bfd_boolean matched; p = name = linked->comdat_key; if (name) @@ -12536,20 +12537,20 @@ _bfd_elf_section_already_linked (bfd *abfd, { sec = linked->u.sec; if (sec->output_section == bfd_abs_section_ptr) - return; + return FALSE; flags = sec->flags; /* Return if it isn't a linkonce section. A comdat group section also has SEC_LINK_ONCE set. */ if ((flags & SEC_LINK_ONCE) == 0) - return; + return FALSE; /* Don't put group member sections on our list of already linked sections. They are handled as a group via their group section. */ if (elf_sec_group (sec) != NULL) - return; + return FALSE; /* FIXME: When doing a relocatable link, we may have trouble copying relocations in other sections that refer to local symbols @@ -12582,7 +12583,6 @@ _bfd_elf_section_already_linked (bfd *abfd, for (l = already_linked_list->entry; l != NULL; l = l->next) { - bfd_boolean l_coff_comdat_sec; flagword l_flags; bfd *l_owner; const char *l_name = l->linked.comdat_key; @@ -12593,23 +12593,19 @@ _bfd_elf_section_already_linked (bfd *abfd, l_flags = (SEC_GROUP | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD); - l_coff_comdat_sec = FALSE; } else { l_sec = l->linked.u.sec; l_owner = l_sec->owner; l_flags = l_sec->flags; - l_coff_comdat_sec - = !!bfd_coff_get_comdat_section (l_sec->owner, l_sec); l_name = section_signature (l_sec); } /* We may have 2 different types of sections on the list: group sections and linkonce sections. Match like sections. */ if ((flags & SEC_GROUP) == (l_flags & SEC_GROUP) - && strcmp (name, l_name) == 0 - && !l_coff_comdat_sec) + && strcmp (name, l_name) == 0) { /* The section has already been linked. See if we should issue a warning. */ @@ -12629,7 +12625,7 @@ _bfd_elf_section_already_linked (bfd *abfd, && (l_owner->flags & BFD_PLUGIN) != 0) { l->linked = *linked; - return; + return FALSE; } break; @@ -12711,10 +12707,11 @@ _bfd_elf_section_already_linked (bfd *abfd, } } - return; + return TRUE; } } + matched = FALSE; if (sec) { /* A single member comdat group section may be discarded by a @@ -12742,6 +12739,7 @@ _bfd_elf_section_already_linked (bfd *abfd, first->output_section = bfd_abs_section_ptr; first->kept_section = l_sec; sec->output_section = bfd_abs_section_ptr; + matched = TRUE; break; } } @@ -12767,6 +12765,7 @@ _bfd_elf_section_already_linked (bfd *abfd, { sec->output_section = bfd_abs_section_ptr; sec->kept_section = first; + matched = TRUE; break; } } @@ -12799,7 +12798,10 @@ _bfd_elf_section_already_linked (bfd *abfd, && CONST_STRNEQ (l_sec->name, ".gnu.linkonce.t.")) { if (abfd != l_sec->owner) - sec->output_section = bfd_abs_section_ptr; + { + sec->output_section = bfd_abs_section_ptr; + matched = TRUE; + } break; } } @@ -12810,6 +12812,7 @@ _bfd_elf_section_already_linked (bfd *abfd, if (! bfd_section_already_linked_table_insert (already_linked_list, linked)) info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return matched; } bfd_boolean diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 0c98b47cbc..db39f3cfc6 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -481,8 +481,8 @@ extern bfd_boolean _bfd_generic_set_section_contents #define _bfd_nolink_bfd_link_split_section \ ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ - ((void (*) (bfd *, struct already_linked*, \ - struct bfd_link_info *)) bfd_void) + ((bfd_boolean (*) (bfd *, struct already_linked*, \ + struct bfd_link_info *)) bfd_false) #define _bfd_nolink_bfd_define_common_symbol \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, \ struct bfd_link_hash_entry *)) bfd_false) @@ -602,7 +602,7 @@ extern bfd_boolean _bfd_generic_final_link extern bfd_boolean _bfd_generic_link_split_section (bfd *, struct bfd_section *); -extern void _bfd_generic_section_already_linked +extern bfd_boolean _bfd_generic_section_already_linked (bfd *, struct already_linked *, struct bfd_link_info *); /* Generic reloc_link_order processing routine. */ diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 33069b0d0c..71188dcc1e 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -486,8 +486,8 @@ extern bfd_boolean _bfd_generic_set_section_contents #define _bfd_nolink_bfd_link_split_section \ ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ - ((void (*) (bfd *, struct already_linked*, \ - struct bfd_link_info *)) bfd_void) + ((bfd_boolean (*) (bfd *, struct already_linked*, \ + struct bfd_link_info *)) bfd_false) #define _bfd_nolink_bfd_define_common_symbol \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, \ struct bfd_link_hash_entry *)) bfd_false) @@ -607,7 +607,7 @@ extern bfd_boolean _bfd_generic_final_link extern bfd_boolean _bfd_generic_link_split_section (bfd *, struct bfd_section *); -extern void _bfd_generic_section_already_linked +extern bfd_boolean _bfd_generic_section_already_linked (bfd *, struct already_linked *, struct bfd_link_info *); /* Generic reloc_link_order processing routine. */ diff --git a/bfd/linker.c b/bfd/linker.c index 8700c05a59..b3ccefd6e1 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -2888,13 +2888,13 @@ FUNCTION bfd_section_already_linked SYNOPSIS - void bfd_section_already_linked (bfd *abfd, - struct already_linked *data, - struct bfd_link_info *info); + bfd_boolean bfd_section_already_linked (bfd *abfd, + struct already_linked *data, + struct bfd_link_info *info); DESCRIPTION Check if @var{data} has been already linked during a reloceatable - or final link. + or final link. Return TRUE if it has. .#define bfd_section_already_linked(abfd, data, info) \ . BFD_SEND (abfd, _section_already_linked, (abfd, data, info)) @@ -2990,7 +2990,7 @@ bfd_section_already_linked_table_free (void) /* This is used on non-ELF inputs. */ -void +bfd_boolean _bfd_generic_section_already_linked (bfd *abfd, struct already_linked *linked, struct bfd_link_info *info) @@ -3006,7 +3006,7 @@ _bfd_generic_section_already_linked (bfd *abfd, if (name) { sec = NULL; - flags = SEC_GROUP | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD; + flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD; s_comdat = NULL; } else @@ -3014,7 +3014,7 @@ _bfd_generic_section_already_linked (bfd *abfd, sec = linked->u.sec; flags = sec->flags; if ((flags & SEC_LINK_ONCE) == 0) - return; + return FALSE; s_comdat = bfd_coff_get_comdat_section (abfd, sec); @@ -3049,9 +3049,7 @@ _bfd_generic_section_already_linked (bfd *abfd, l_sec = NULL; l_owner = l->linked.u.abfd; l_comdat = NULL; - l_flags = (SEC_GROUP - | SEC_LINK_ONCE - | SEC_LINK_DUPLICATES_DISCARD); + l_flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD; } else { @@ -3100,7 +3098,7 @@ _bfd_generic_section_already_linked (bfd *abfd, && (l_owner->flags & BFD_PLUGIN) != 0) { l->linked = *linked; - return; + return FALSE; } break; @@ -3136,7 +3134,7 @@ _bfd_generic_section_already_linked (bfd *abfd, sec->kept_section = l_sec; } - return; + return TRUE; } } @@ -3144,6 +3142,7 @@ _bfd_generic_section_already_linked (bfd *abfd, if (! bfd_section_already_linked_table_insert (already_linked_list, linked)) info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return FALSE; } /* Convert symbols in excluded output sections to use a kept section. */ diff --git a/bfd/targets.c b/bfd/targets.c index c34ce69072..3dfa145b45 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -512,8 +512,8 @@ BFD_JUMP_TABLE macros. . . {* Check if SEC has been already linked during a reloceatable or . final link. *} -. void (*_section_already_linked) (bfd *, struct already_linked *, -. struct bfd_link_info *); +. bfd_boolean (*_section_already_linked) (bfd *, struct already_linked *, +. struct bfd_link_info *); . . {* Define a common symbol. *} . bfd_boolean (*_bfd_define_common_symbol) (bfd *, struct bfd_link_info *, diff --git a/ld/ChangeLog b/ld/ChangeLog index 2b217b5532..bb23c7a65e 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,9 @@ +2011-08-05 Alan Modra + + PR ld/12762 + * plugin.c (add_symbols): Exclude comdat_key symbols from symbol + table if already seen. + 2011-08-04 H.J. Lu * ldmain.c (main): Replace remove_output with ld_cleanup in diff --git a/ld/plugin.c b/ld/plugin.c index 0a0ee0c0d3..5ba1fca845 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -380,10 +380,11 @@ add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms) { asymbol **symptrs; bfd *abfd = handle; - int n; + int n, k; + ASSERT (called_plugin); symptrs = xmalloc (nsyms * sizeof *symptrs); - for (n = 0; n < nsyms; n++) + for (n = 0, k = 0; n < nsyms; n++) { enum ld_plugin_status rv; asymbol *bfdsym; @@ -393,15 +394,16 @@ add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms) struct already_linked linked; linked.comdat_key = xstrdup (syms[n].comdat_key); linked.u.abfd = abfd; - bfd_section_already_linked (abfd, &linked, &link_info); + if (bfd_section_already_linked (abfd, &linked, &link_info)) + continue; } bfdsym = bfd_make_empty_symbol (abfd); - symptrs[n] = bfdsym; + symptrs[k++] = bfdsym; rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n); if (rv != LDPS_OK) return rv; } - bfd_set_symtab (abfd, symptrs, nsyms); + bfd_set_symtab (abfd, symptrs, k); return LDPS_OK; } -- 2.34.1