mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-01 11:59:27 +08:00
PR ld/12942
bfd/ * elflink.c (elf_link_add_object_symbols): Use elf_discarded_section rather than kept_section to determine whether a symbol is from a discarded section. * cofflink.c (coff_link_add_symbols): Make symbols from discarded sections appear undefined. * elf-bfd.h (_bfd_elf_section_already_linked): Replace "asection *" with "struct already_linked *". * libbfd-in.h (_bfd_nolink_section_already_linked): Likewise. (_bfd_generic_section_already_linked): Likewise. (bfd_section_already_linked_table_insert): Likewise. (struct already_linked): New. (struct bfd_section_already_linked): Use it. * elflink.c (_bfd_elf_section_already_linked): Replace. "asection *" with "struct already_linked *". Replace the plugin dummy with the LTO output. * linker.c (_bfd_generic_section_already_linked): Likewise. * targets.c (struct already_linked): Add forward declaration. (bfd_target): Replace "struct bfd_section *" with "struct already_linked *" in _section_already_linked. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. include/ * bfdlink.h (bfd_link_info): Add loading_lto_outputs. ld/ * ldlang.c (section_already_linked): Pass "struct already_linked *" to bfd_section_already_linked. (lang_process): Set link_info.loading_lto_outputs before loading LTO outputs. * plugin.c: Include "libbfd.h". (add_symbols): Call bfd_section_already_linked with comdat_key.
This commit is contained in:
121
bfd/linker.c
121
bfd/linker.c
@ -2888,15 +2888,16 @@ FUNCTION
|
||||
bfd_section_already_linked
|
||||
|
||||
SYNOPSIS
|
||||
void bfd_section_already_linked (bfd *abfd, asection *sec,
|
||||
void bfd_section_already_linked (bfd *abfd,
|
||||
struct already_linked *data,
|
||||
struct bfd_link_info *info);
|
||||
|
||||
DESCRIPTION
|
||||
Check if @var{sec} has been already linked during a reloceatable
|
||||
Check if @var{data} has been already linked during a reloceatable
|
||||
or final link.
|
||||
|
||||
.#define bfd_section_already_linked(abfd, sec, info) \
|
||||
. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
|
||||
.#define bfd_section_already_linked(abfd, data, info) \
|
||||
. BFD_SEND (abfd, _section_already_linked, (abfd, data, info))
|
||||
.
|
||||
|
||||
*/
|
||||
@ -2939,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,
|
||||
asection *sec)
|
||||
struct already_linked *data)
|
||||
{
|
||||
struct bfd_section_already_linked *l;
|
||||
|
||||
@ -2949,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->sec = sec;
|
||||
l->linked = *data;
|
||||
l->next = already_linked_list->entry;
|
||||
already_linked_list->entry = l;
|
||||
return TRUE;
|
||||
@ -2990,42 +2991,74 @@ bfd_section_already_linked_table_free (void)
|
||||
/* This is used on non-ELF inputs. */
|
||||
|
||||
void
|
||||
_bfd_generic_section_already_linked (bfd *abfd, asection *sec,
|
||||
_bfd_generic_section_already_linked (bfd *abfd,
|
||||
struct already_linked *linked,
|
||||
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;
|
||||
|
||||
flags = sec->flags;
|
||||
if ((flags & SEC_LINK_ONCE) == 0)
|
||||
return;
|
||||
name = linked->comdat_key;
|
||||
if (name)
|
||||
{
|
||||
sec = NULL;
|
||||
flags = SEC_GROUP | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
|
||||
s_comdat = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = linked->u.sec;
|
||||
flags = sec->flags;
|
||||
if ((flags & SEC_LINK_ONCE) == 0)
|
||||
return;
|
||||
|
||||
/* 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.
|
||||
s_comdat = bfd_coff_get_comdat_section (abfd, sec);
|
||||
|
||||
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. */
|
||||
/* 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.
|
||||
|
||||
name = bfd_get_section_name (abfd, sec);
|
||||
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. */
|
||||
|
||||
name = bfd_get_section_name (abfd, sec);
|
||||
}
|
||||
|
||||
already_linked_list = bfd_section_already_linked_table_lookup (name);
|
||||
|
||||
for (l = already_linked_list->entry; l != NULL; l = l->next)
|
||||
{
|
||||
bfd_boolean skip = FALSE;
|
||||
struct coff_comdat_info *s_comdat
|
||||
= bfd_coff_get_comdat_section (abfd, sec);
|
||||
struct coff_comdat_info *l_comdat
|
||||
= bfd_coff_get_comdat_section (l->sec->owner, l->sec);
|
||||
bfd *l_owner;
|
||||
flagword l_flags;
|
||||
struct coff_comdat_info *l_comdat;
|
||||
asection *l_sec;
|
||||
|
||||
if (l->linked.comdat_key)
|
||||
{
|
||||
l_sec = NULL;
|
||||
l_owner = l->linked.u.abfd;
|
||||
l_comdat = NULL;
|
||||
l_flags = (SEC_GROUP
|
||||
| SEC_LINK_ONCE
|
||||
| SEC_LINK_DUPLICATES_DISCARD);
|
||||
}
|
||||
else
|
||||
{
|
||||
l_sec = l->linked.u.sec;
|
||||
l_owner = l_sec->owner;
|
||||
l_comdat = bfd_coff_get_comdat_section (l_sec->owner, l_sec);
|
||||
}
|
||||
|
||||
/* We may have 3 different sections on the list: group section,
|
||||
comdat section and linkonce section. SEC may be a linkonce or
|
||||
@ -3034,7 +3067,7 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec,
|
||||
|
||||
FIXME: Is that safe to match a linkonce section with a comdat
|
||||
section for COFF inputs? */
|
||||
if ((l->sec->flags & SEC_GROUP) != 0)
|
||||
if ((l_flags & SEC_GROUP) != 0)
|
||||
skip = TRUE;
|
||||
else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
|
||||
{
|
||||
@ -3056,6 +3089,18 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec,
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEC_LINK_DUPLICATES_ONE_ONLY:
|
||||
@ -3072,27 +3117,31 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec,
|
||||
either. */
|
||||
/* Fall through. */
|
||||
case SEC_LINK_DUPLICATES_SAME_SIZE:
|
||||
if (sec->size != l->sec->size)
|
||||
if (sec->size != l_sec->size)
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: warning: duplicate section `%A' has different size\n"),
|
||||
abfd, sec);
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the first section with this name. Record it. */
|
||||
if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
|
||||
if (! bfd_section_already_linked_table_insert (already_linked_list,
|
||||
linked))
|
||||
info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user