summaryrefslogtreecommitdiff
path: root/bfd/linker.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2011-08-17 00:39:41 +0000
committerAlan Modra <amodra@gmail.com>2011-08-17 00:39:41 +0000
commitc77ec7261473e7a12a1af46c585caca4bb597b4f (patch)
treefe75ecc5e02d7b2bcd737b8ce8bccd8b14259809 /bfd/linker.c
parent142a8c5dcf3f3949d5d2228b894e169ffec28df4 (diff)
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/linker.c')
-rw-r--r--bfd/linker.c250
1 files changed, 114 insertions, 136 deletions
diff --git a/bfd/linker.c b/bfd/linker.c
index b3ccefd6e1..e44386232d 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -2889,15 +2889,15 @@ FUNCTION
SYNOPSIS
bfd_boolean bfd_section_already_linked (bfd *abfd,
- struct already_linked *data,
+ asection *sec,
struct bfd_link_info *info);
DESCRIPTION
Check if @var{data} has been already linked during a reloceatable
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))
+.#define bfd_section_already_linked(abfd, sec, info) \
+. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
.
*/
@@ -2940,7 +2940,7 @@ bfd_section_already_linked_table_lookup (const char *name)
bfd_boolean
bfd_section_already_linked_table_insert
(struct bfd_section_already_linked_hash_entry *already_linked_list,
- struct already_linked *data)
+ asection *sec)
{
struct bfd_section_already_linked *l;
@@ -2950,7 +2950,7 @@ bfd_section_already_linked_table_insert
bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
if (l == NULL)
return FALSE;
- l->linked = *data;
+ l->sec = sec;
l->next = already_linked_list->entry;
already_linked_list->entry = l;
return TRUE;
@@ -2988,159 +2988,137 @@ bfd_section_already_linked_table_free (void)
bfd_hash_table_free (&_bfd_section_already_linked_table);
}
-/* This is used on non-ELF inputs. */
+/* Report warnings as appropriate for duplicate section SEC.
+ Return FALSE if we decide to keep SEC after all. */
bfd_boolean
-_bfd_generic_section_already_linked (bfd *abfd,
- struct already_linked *linked,
- struct bfd_link_info *info)
+_bfd_handle_already_linked (asection *sec,
+ struct bfd_section_already_linked *l,
+ struct bfd_link_info *info)
{
- flagword flags;
- const char *name;
- struct bfd_section_already_linked *l;
- struct bfd_section_already_linked_hash_entry *already_linked_list;
- struct coff_comdat_info *s_comdat;
- asection *sec;
-
- name = linked->comdat_key;
- if (name)
- {
- sec = NULL;
- flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
- s_comdat = NULL;
- }
- else
+ switch (sec->flags & SEC_LINK_DUPLICATES)
{
- sec = linked->u.sec;
- flags = sec->flags;
- if ((flags & SEC_LINK_ONCE) == 0)
- return FALSE;
+ default:
+ abort ();
- s_comdat = bfd_coff_get_comdat_section (abfd, sec);
+ case SEC_LINK_DUPLICATES_DISCARD:
+ /* If we found an LTO IR match for this comdat group on
+ the first pass, replace it with the LTO output on the
+ second pass. We can't simply choose real object
+ files over IR because the first pass may contain a
+ mix of LTO and normal objects and we must keep the
+ first match, be it IR or real. */
+ if (info->loading_lto_outputs
+ && (l->sec->owner->flags & BFD_PLUGIN) != 0)
+ {
+ l->sec = sec;
+ return FALSE;
+ }
+ break;
- /* FIXME: When doing a relocatable link, we may have trouble
- copying relocations in other sections that refer to local symbols
- in the section being discarded. Those relocations will have to
- be converted somehow; as of this writing I'm not sure that any of
- the backends handle that correctly.
+ case SEC_LINK_DUPLICATES_ONE_ONLY:
+ info->callbacks->einfo
+ (_("%B: ignoring duplicate section `%A'\n"),
+ sec->owner, sec);
+ break;
- It is tempting to instead not discard link once sections when
- doing a relocatable link (technically, they should be discarded
- whenever we are building constructors). However, that fails,
- because the linker winds up combining all the link once sections
- into a single large link once section, which defeats the purpose
- of having link once sections in the first place. */
+ case SEC_LINK_DUPLICATES_SAME_SIZE:
+ if ((l->sec->owner->flags & BFD_PLUGIN) != 0)
+ ;
+ else if (sec->size != l->sec->size)
+ info->callbacks->einfo
+ (_("%B: duplicate section `%A' has different size\n"),
+ sec->owner, sec);
+ break;
- name = bfd_get_section_name (abfd, sec);
+ case SEC_LINK_DUPLICATES_SAME_CONTENTS:
+ if ((l->sec->owner->flags & BFD_PLUGIN) != 0)
+ ;
+ else if (sec->size != l->sec->size)
+ info->callbacks->einfo
+ (_("%B: duplicate section `%A' has different size\n"),
+ sec->owner, sec);
+ else if (sec->size != 0)
+ {
+ bfd_byte *sec_contents, *l_sec_contents = NULL;
+
+ if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents))
+ info->callbacks->einfo
+ (_("%B: could not read contents of section `%A'\n"),
+ sec->owner, sec);
+ else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
+ &l_sec_contents))
+ info->callbacks->einfo
+ (_("%B: could not read contents of section `%A'\n"),
+ l->sec->owner, l->sec);
+ else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
+ info->callbacks->einfo
+ (_("%B: duplicate section `%A' has different contents\n"),
+ sec->owner, sec);
+
+ if (sec_contents)
+ free (sec_contents);
+ if (l_sec_contents)
+ free (l_sec_contents);
+ }
+ break;
}
- already_linked_list = bfd_section_already_linked_table_lookup (name);
+ /* Set the output_section field so that lang_add_section
+ does not create a lang_input_section structure for this
+ section. Since there might be a symbol in the section
+ being discarded, we must retain a pointer to the section
+ which we are really going to use. */
+ sec->output_section = bfd_abs_section_ptr;
+ sec->kept_section = l->sec;
+ return TRUE;
+}
- for (l = already_linked_list->entry; l != NULL; l = l->next)
- {
- bfd_boolean skip = FALSE;
- bfd *l_owner;
- flagword l_flags;
- struct coff_comdat_info *l_comdat;
- asection *l_sec;
+/* This is used on non-ELF inputs. */
- if (l->linked.comdat_key)
- {
- l_sec = NULL;
- l_owner = l->linked.u.abfd;
- l_comdat = NULL;
- l_flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
- }
- else
- {
- l_sec = l->linked.u.sec;
- l_owner = l_sec->owner;
- l_flags = l_sec->flags;
- l_comdat = bfd_coff_get_comdat_section (l_sec->owner, l_sec);
- }
+bfd_boolean
+_bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec,
+ struct bfd_link_info *info)
+{
+ const char *name;
+ struct bfd_section_already_linked *l;
+ struct bfd_section_already_linked_hash_entry *already_linked_list;
- /* We may have 3 different sections on the list: group section,
- comdat section and linkonce section. SEC may be a linkonce or
- comdat section. We always ignore group section. For non-COFF
- inputs, we also ignore comdat section.
+ if ((sec->flags & SEC_LINK_ONCE) == 0)
+ return FALSE;
- FIXME: Is that safe to match a linkonce section with a comdat
- section for COFF inputs? */
- if ((l_flags & SEC_GROUP) != 0)
- skip = TRUE;
- else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
- {
- if (s_comdat != NULL
- && l_comdat != NULL
- && strcmp (s_comdat->name, l_comdat->name) != 0)
- skip = TRUE;
- }
- else if (l_comdat != NULL)
- skip = TRUE;
+ /* The generic linker doesn't handle section groups. */
+ if ((sec->flags & SEC_GROUP) != 0)
+ return FALSE;
- if (!skip)
- {
- /* The section has already been linked. See if we should
- issue a warning. */
- switch (flags & SEC_LINK_DUPLICATES)
- {
- default:
- abort ();
-
- case SEC_LINK_DUPLICATES_DISCARD:
- /* If we found an LTO IR match for this comdat group on
- the first pass, replace it with the LTO output on the
- second pass. We can't simply choose real object
- files over IR because the first pass may contain a
- mix of LTO and normal objects and we must keep the
- first match, be it IR or real. */
- if (info->loading_lto_outputs
- && (l_owner->flags & BFD_PLUGIN) != 0)
- {
- l->linked = *linked;
- return FALSE;
- }
- break;
+ /* FIXME: When doing a relocatable link, we may have trouble
+ copying relocations in other sections that refer to local symbols
+ in the section being discarded. Those relocations will have to
+ be converted somehow; as of this writing I'm not sure that any of
+ the backends handle that correctly.
- case SEC_LINK_DUPLICATES_ONE_ONLY:
- (*_bfd_error_handler)
- (_("%B: warning: ignoring duplicate section `%A'\n"),
- abfd, sec);
- break;
+ It is tempting to instead not discard link once sections when
+ doing a relocatable link (technically, they should be discarded
+ whenever we are building constructors). However, that fails,
+ because the linker winds up combining all the link once sections
+ into a single large link once section, which defeats the purpose
+ of having link once sections in the first place. */
- case SEC_LINK_DUPLICATES_SAME_CONTENTS:
- /* FIXME: We should really dig out the contents of both
- sections and memcmp them. The COFF/PE spec says that
- the Microsoft linker does not implement this
- correctly, so I'm not going to bother doing it
- either. */
- /* Fall through. */
- case SEC_LINK_DUPLICATES_SAME_SIZE:
- if (sec->size != l_sec->size)
- (*_bfd_error_handler)
- (_("%B: warning: duplicate section `%A' has different size\n"),
- abfd, sec);
- break;
- }
+ name = bfd_get_section_name (abfd, sec);
- if (sec)
- {
- /* Set the output_section field so that lang_add_section
- does not create a lang_input_section structure for this
- section. Since there might be a symbol in the section
- being discarded, we must retain a pointer to the section
- which we are really going to use. */
- sec->output_section = bfd_abs_section_ptr;
- sec->kept_section = l_sec;
- }
+ already_linked_list = bfd_section_already_linked_table_lookup (name);
- return TRUE;
- }
+ l = already_linked_list->entry;
+ if (l != NULL)
+ {
+ /* 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,
- linked))
+ if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
return FALSE;
}