diff options
author | Alan Modra <amodra@gmail.com> | 2011-08-17 00:39:41 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2011-08-17 00:39:41 +0000 |
commit | c77ec7261473e7a12a1af46c585caca4bb597b4f (patch) | |
tree | fe75ecc5e02d7b2bcd737b8ce8bccd8b14259809 /bfd/coffgen.c | |
parent | 142a8c5dcf3f3949d5d2228b894e169ffec28df4 (diff) | |
download | gdb-c77ec7261473e7a12a1af46c585caca4bb597b4f.zip gdb-c77ec7261473e7a12a1af46c585caca4bb597b4f.tar.gz gdb-c77ec7261473e7a12a1af46c585caca4bb597b4f.tar.bz2 |
PR ld/12762
bfd/
* bfd-in.h (struct bfd_section_already_linked): Forward declare.
(_bfd_handle_already_linked): Declare.
* coff-alpha.c (_bfd_ecoff_section_already_linked): Define as
_bfd_coff_section_already_linked.
* coff-mips.c (_bfd_ecoff_section_already_linked): Likewise.
* coffcode.h (coff_section_already_linked): Likewise.
* cofflink.c (coff_link_add_symbols): Revert 2011-07-09 changes.
* elf-bfd.h: Likewise.
* libbfd-in.h: Likewise.
* targets.c: Likewise.
* linker.c (bfd_section_already_linked): Likewise.
(bfd_section_already_linked_table_lookup): Likewise.
(bfd_section_already_linked_table_insert): Likewise.
(_bfd_generic_section_already_linked): Likewise. Call
_bfd_handle_already_linked.
(_bfd_handle_already_linked): New function, split out from..
* elflink.c (_bfd_elf_section_already_linked): ..here. Revert
2011-07-09 changes. Avoid unnecessary strcmp when matching
already_linked_list entries. Match plugin linkonce section.
(section_signature): Delete.
* coffgen.c (_bfd_coff_section_already_linked): New function.
* libcoff-in.h (_bfd_coff_section_already_linked): Declare.
* libbfd.h: Regenerate.
* libcoff.h: Regenerate.
* bfd-in2.h: Regenerate.
ld/
* ldlang.c (section_already_linked): Revert 2011-07-09 changes.
* plugin.c: Likewise.
(asymbol_from_plugin_symbol): Create linkonce section for syms
with comdat_key.
Diffstat (limited to 'bfd/coffgen.c')
-rw-r--r-- | bfd/coffgen.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/bfd/coffgen.c b/bfd/coffgen.c index b0c2c62..bbb0acc 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -2399,3 +2399,70 @@ bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec) else return NULL; } + +bfd_boolean +_bfd_coff_section_already_linked (bfd *abfd, + asection *sec, + struct bfd_link_info *info) +{ + flagword flags; + const char *name, *key; + struct bfd_section_already_linked *l; + struct bfd_section_already_linked_hash_entry *already_linked_list; + struct coff_comdat_info *s_comdat; + + flags = sec->flags; + if ((flags & SEC_LINK_ONCE) == 0) + return FALSE; + + /* The COFF backend linker doesn't support group sections. */ + if ((flags & SEC_GROUP) != 0) + return FALSE; + + name = bfd_get_section_name (abfd, sec); + s_comdat = bfd_coff_get_comdat_section (abfd, sec); + + if (s_comdat != NULL) + key = s_comdat->name; + else + { + if (CONST_STRNEQ (name, ".gnu.linkonce.") + && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL) + key++; + else + /* FIXME: gcc as of 2011-09 emits sections like .text$<key>, + .xdata$<key> and .pdata$<key> only the first of which has a + comdat key. Should these all match the LTO IR key? */ + key = name; + } + + already_linked_list = bfd_section_already_linked_table_lookup (key); + + for (l = already_linked_list->entry; l != NULL; l = l->next) + { + struct coff_comdat_info *l_comdat; + + l_comdat = bfd_coff_get_comdat_section (l->sec->owner, l->sec); + + /* The section names must match, and both sections must be + comdat and have the same comdat name, or both sections must + be non-comdat. LTO IR plugin sections are an exception. They + are always named .gnu.linkonce.t.<key> (<key> is some string) + and match any comdat section with comdat name of <key>, and + any linkonce section with the same suffix, ie. + .gnu.linkonce.*.<key>. */ + if (((s_comdat != NULL) == (l_comdat != NULL) + && strcmp (name, l->sec->name) == 0) + || (l->sec->owner->flags & BFD_PLUGIN) != 0) + { + /* The section has already been linked. See if we should + issue a warning. */ + return _bfd_handle_already_linked (sec, l, info); + } + } + + /* This is the first section with this name. Record it. */ + if (!bfd_section_already_linked_table_insert (already_linked_list, sec)) + info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return FALSE; +} |