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:
Alan Modra 2011-07-09 06:20:52 +00:00
parent beabb2c68f
commit 0c51100021
14 changed files with 406 additions and 174 deletions

View File

@ -1,3 +1,32 @@
2011-07-09 Alan Modra <amodra@gmail.com>
PR ld/12942
* 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.
2011-07-09 H.J. Lu <hongjiu.lu@intel.com>
PR ld/12942
* 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.
2011-07-06 Tristan Gingold <gingold@adacore.com>
* mach-o.h: Move loader related definitions to

View File

@ -5726,6 +5726,7 @@ enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
/* Forward declaration. */
typedef struct bfd_link_info _bfd_link_info;
struct already_linked;
typedef struct bfd_target
{
@ -6051,7 +6052,7 @@ typedef struct bfd_target
/* Check if SEC has been already linked during a reloceatable or
final link. */
void (*_section_already_linked) (bfd *, struct bfd_section *,
void (*_section_already_linked) (bfd *, struct already_linked *,
struct bfd_link_info *);
/* Define a common symbol. */
@ -6121,11 +6122,12 @@ 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, asection *sec,
void bfd_section_already_linked (bfd *abfd,
struct already_linked *data,
struct bfd_link_info *info);
#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))
bfd_boolean bfd_generic_define_common_symbol
(bfd *output_bfd, struct bfd_link_info *info,

View File

@ -392,7 +392,11 @@ coff_link_add_symbols (bfd *abfd,
section = coff_section_from_bfd_index (abfd, sym.n_scnum);
if (! obj_pe (abfd))
value -= section->vma;
break;
/* Treat a symbol from a discarded section as undefined. */
if (bfd_is_abs_section (section)
|| !bfd_is_abs_section (section->output_section))
break;
/* Fall thru */
case COFF_SYMBOL_UNDEFINED:
flags = 0;

View File

@ -1793,7 +1793,7 @@ extern bfd_boolean _bfd_elf_match_sections_by_type
extern bfd_boolean bfd_elf_is_group_section
(bfd *, const struct bfd_section *);
extern void _bfd_elf_section_already_linked
(bfd *, struct bfd_section *, struct bfd_link_info *);
(bfd *, struct already_linked *, struct bfd_link_info *);
extern void bfd_elf_set_group_contents
(bfd *, asection *, void *);
extern asection *_bfd_elf_check_kept_section

View File

@ -3900,7 +3900,7 @@ error_free_dyn:
sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (sec == NULL)
sec = bfd_abs_section_ptr;
else if (sec->kept_section)
else if (elf_discarded_section (sec))
{
/* Symbols from discarded section are undefined. We keep
its visibility. */
@ -12438,63 +12438,100 @@ section_signature (asection *sec)
}
void
_bfd_elf_section_already_linked (bfd *abfd, asection *sec,
_bfd_elf_section_already_linked (bfd *abfd,
struct already_linked *linked,
struct bfd_link_info *info)
{
flagword flags;
const char *name, *p;
struct bfd_section_already_linked *l;
struct bfd_section_already_linked_hash_entry *already_linked_list;
asection *sec, *l_sec;
if (sec->output_section == bfd_abs_section_ptr)
return;
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;
/* 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;
/* 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.
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.
Also, not merging link once sections in a relocatable link
causes trouble for MIPS ELF, which relies on link once semantics
to handle the .reginfo section correctly. */
name = section_signature (sec);
if (CONST_STRNEQ (name, ".gnu.linkonce.")
&& (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
p++;
p = name = linked->comdat_key;
if (name)
{
sec = NULL;
flags = SEC_GROUP | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
}
else
p = name;
{
sec = linked->u.sec;
if (sec->output_section == bfd_abs_section_ptr)
return;
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;
/* 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;
/* 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.
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.
Also, not merging link once sections in a relocatable link
causes trouble for MIPS ELF, which relies on link once semantics
to handle the .reginfo section correctly. */
name = section_signature (sec);
if (CONST_STRNEQ (name, ".gnu.linkonce.")
&& ((p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.'))
!= NULL))
p++;
else
p = name;
}
already_linked_list = bfd_section_already_linked_table_lookup (p);
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;
if (l_name)
{
l_sec = NULL;
l_owner = l->linked.u.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->sec->flags & SEC_GROUP)
&& strcmp (name, section_signature (l->sec)) == 0
&& bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
if ((flags & SEC_GROUP) == (l_flags & SEC_GROUP)
&& strcmp (name, l_name) == 0
&& !l_coff_comdat_sec)
{
/* The section has already been linked. See if we should
issue a warning. */
@ -12504,6 +12541,18 @@ _bfd_elf_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:
@ -12513,14 +12562,20 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec,
break;
case SEC_LINK_DUPLICATES_SAME_SIZE:
if (sec->size != l->sec->size)
if (!sec || !l_sec)
abort ();
if (sec->size != l_sec->size)
(*_bfd_error_handler)
(_("%B: duplicate section `%A' has different size"),
abfd, sec);
break;
case SEC_LINK_DUPLICATES_SAME_CONTENTS:
if (sec->size != l->sec->size)
if (!sec || !l_sec)
abort ();
if (sec->size != l_sec->size)
(*_bfd_error_handler)
(_("%B: duplicate section `%A' has different size"),
abfd, sec);
@ -12532,11 +12587,11 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec,
(*_bfd_error_handler)
(_("%B: warning: could not read contents of section `%A'"),
abfd, sec);
else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
else if (!bfd_malloc_and_get_section (l_sec->owner, l_sec,
&l_sec_contents))
(*_bfd_error_handler)
(_("%B: warning: could not read contents of section `%A'"),
l->sec->owner, l->sec);
l_sec->owner, l_sec);
else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
(*_bfd_error_handler)
(_("%B: warning: duplicate section `%A' has different contents"),
@ -12550,28 +12605,31 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *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 (flags & SEC_GROUP)
if (sec)
{
asection *first = elf_next_in_group (sec);
asection *s = first;
/* 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;
while (s != NULL)
if (flags & SEC_GROUP)
{
s->output_section = bfd_abs_section_ptr;
/* Record which group discards it. */
s->kept_section = l->sec;
s = elf_next_in_group (s);
/* These lists are circular. */
if (s == first)
break;
asection *first = elf_next_in_group (sec);
asection *s = first;
while (s != NULL)
{
s->output_section = bfd_abs_section_ptr;
/* Record which group discards it. */
s->kept_section = l_sec;
s = elf_next_in_group (s);
/* These lists are circular. */
if (s == first)
break;
}
}
}
@ -12579,67 +12637,100 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec,
}
}
/* A single member comdat group section may be discarded by a
linkonce section and vice versa. */
if ((flags & SEC_GROUP) != 0)
if (sec)
{
asection *first = elf_next_in_group (sec);
/* A single member comdat group section may be discarded by a
linkonce section and vice versa. */
if (first != NULL && elf_next_in_group (first) == first)
/* Check this single member group against linkonce sections. */
if ((flags & SEC_GROUP) != 0)
{
asection *first = elf_next_in_group (sec);
if (first != NULL && elf_next_in_group (first) == first)
/* Check this single member group against linkonce sections. */
for (l = already_linked_list->entry; l != NULL; l = l->next)
{
if (l->linked.comdat_key == NULL)
{
l_sec = l->linked.u.sec;
if ((l_sec->flags & SEC_GROUP) == 0
&& bfd_coff_get_comdat_section (l_sec->owner,
l_sec) == NULL
&& bfd_elf_match_symbols_in_sections (l_sec,
first,
info))
{
first->output_section = bfd_abs_section_ptr;
first->kept_section = l_sec;
sec->output_section = bfd_abs_section_ptr;
break;
}
}
}
}
else
/* Check this linkonce section against single member groups. */
for (l = already_linked_list->entry; l != NULL; l = l->next)
if ((l->sec->flags & SEC_GROUP) == 0
&& bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL
&& bfd_elf_match_symbols_in_sections (l->sec, first, info))
{
first->output_section = bfd_abs_section_ptr;
first->kept_section = l->sec;
sec->output_section = bfd_abs_section_ptr;
break;
}
{
if (l->linked.comdat_key == NULL)
{
l_sec = l->linked.u.sec;
if (l_sec->flags & SEC_GROUP)
{
asection *first = elf_next_in_group (l_sec);
if (first != NULL
&& elf_next_in_group (first) == first
&& bfd_elf_match_symbols_in_sections (first,
sec,
info))
{
sec->output_section = bfd_abs_section_ptr;
sec->kept_section = first;
break;
}
}
}
}
/* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
referencing its discarded `.gnu.linkonce.t.F' counterpart -
g++-3.4 specific as g++-4.x is using COMDAT groups (without the
`.gnu.linkonce' prefix) instead. `.gnu.linkonce.r.*' were the
`.rodata' part of its matching `.gnu.linkonce.t.*'. If
`.gnu.linkonce.r.F' is not discarded but its `.gnu.linkonce.t.F'
is discarded means we chose one-only `.gnu.linkonce.t.F' section
from a different bfd not requiring any `.gnu.linkonce.r.F'.
Thus `.gnu.linkonce.r.F' should be discarded. The reverse order
cannot happen as there is never a bfd with only the
`.gnu.linkonce.r.F' section. The order of sections in a bfd
does not matter as here were are looking only for cross-bfd
sections. */
if ((flags & SEC_GROUP) == 0
&& CONST_STRNEQ (name, ".gnu.linkonce.r."))
for (l = already_linked_list->entry; l != NULL; l = l->next)
{
if (l->linked.comdat_key == NULL)
{
l_sec = l->linked.u.sec;
if ((l_sec->flags & SEC_GROUP) == 0
&& CONST_STRNEQ (l_sec->name, ".gnu.linkonce.t."))
{
if (abfd != l_sec->owner)
sec->output_section = bfd_abs_section_ptr;
break;
}
}
}
}
else
/* Check this linkonce section against single member groups. */
for (l = already_linked_list->entry; l != NULL; l = l->next)
if (l->sec->flags & SEC_GROUP)
{
asection *first = elf_next_in_group (l->sec);
if (first != NULL
&& elf_next_in_group (first) == first
&& bfd_elf_match_symbols_in_sections (first, sec, info))
{
sec->output_section = bfd_abs_section_ptr;
sec->kept_section = first;
break;
}
}
/* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
referencing its discarded `.gnu.linkonce.t.F' counterpart - g++-3.4
specific as g++-4.x is using COMDAT groups (without the `.gnu.linkonce'
prefix) instead. `.gnu.linkonce.r.*' were the `.rodata' part of its
matching `.gnu.linkonce.t.*'. If `.gnu.linkonce.r.F' is not discarded
but its `.gnu.linkonce.t.F' is discarded means we chose one-only
`.gnu.linkonce.t.F' section from a different bfd not requiring any
`.gnu.linkonce.r.F'. Thus `.gnu.linkonce.r.F' should be discarded.
The reverse order cannot happen as there is never a bfd with only the
`.gnu.linkonce.r.F' section. The order of sections in a bfd does not
matter as here were are looking only for cross-bfd sections. */
if ((flags & SEC_GROUP) == 0 && CONST_STRNEQ (name, ".gnu.linkonce.r."))
for (l = already_linked_list->entry; l != NULL; l = l->next)
if ((l->sec->flags & SEC_GROUP) == 0
&& CONST_STRNEQ (l->sec->name, ".gnu.linkonce.t."))
{
if (abfd != l->sec->owner)
sec->output_section = bfd_abs_section_ptr;
break;
}
/* 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"));
}

View File

@ -478,7 +478,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 bfd_section *, struct bfd_link_info *)) bfd_void)
((void (*) (bfd *, struct already_linked*, \
struct bfd_link_info *)) bfd_void)
#define _bfd_nolink_bfd_define_common_symbol \
((bfd_boolean (*) (bfd *, struct bfd_link_info *, \
struct bfd_link_hash_entry *)) bfd_false)
@ -599,7 +600,7 @@ extern bfd_boolean _bfd_generic_link_split_section
(bfd *, struct bfd_section *);
extern void _bfd_generic_section_already_linked
(bfd *, struct bfd_section *, struct bfd_link_info *);
(bfd *, struct already_linked *, struct bfd_link_info *);
/* Generic reloc_link_order processing routine. */
extern bfd_boolean _bfd_generic_reloc_link_order
@ -791,16 +792,26 @@ struct bfd_section_already_linked_hash_entry
struct bfd_section_already_linked *entry;
};
struct already_linked
{
const char *comdat_key;
union
{
asection *sec;
bfd *abfd;
} u;
};
struct bfd_section_already_linked
{
struct bfd_section_already_linked *next;
asection *sec;
struct already_linked linked;
};
extern struct bfd_section_already_linked_hash_entry *
bfd_section_already_linked_table_lookup (const char *);
extern bfd_boolean bfd_section_already_linked_table_insert
(struct bfd_section_already_linked_hash_entry *, asection *);
(struct bfd_section_already_linked_hash_entry *, struct already_linked *);
extern void bfd_section_already_linked_table_traverse
(bfd_boolean (*) (struct bfd_section_already_linked_hash_entry *,
void *), void *);

View File

@ -483,7 +483,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 bfd_section *, struct bfd_link_info *)) bfd_void)
((void (*) (bfd *, struct already_linked*, \
struct bfd_link_info *)) bfd_void)
#define _bfd_nolink_bfd_define_common_symbol \
((bfd_boolean (*) (bfd *, struct bfd_link_info *, \
struct bfd_link_hash_entry *)) bfd_false)
@ -604,7 +605,7 @@ extern bfd_boolean _bfd_generic_link_split_section
(bfd *, struct bfd_section *);
extern void _bfd_generic_section_already_linked
(bfd *, struct bfd_section *, struct bfd_link_info *);
(bfd *, struct already_linked *, struct bfd_link_info *);
/* Generic reloc_link_order processing routine. */
extern bfd_boolean _bfd_generic_reloc_link_order
@ -796,16 +797,26 @@ struct bfd_section_already_linked_hash_entry
struct bfd_section_already_linked *entry;
};
struct already_linked
{
const char *comdat_key;
union
{
asection *sec;
bfd *abfd;
} u;
};
struct bfd_section_already_linked
{
struct bfd_section_already_linked *next;
asection *sec;
struct already_linked linked;
};
extern struct bfd_section_already_linked_hash_entry *
bfd_section_already_linked_table_lookup (const char *);
extern bfd_boolean bfd_section_already_linked_table_insert
(struct bfd_section_already_linked_hash_entry *, asection *);
(struct bfd_section_already_linked_hash_entry *, struct already_linked *);
extern void bfd_section_already_linked_table_traverse
(bfd_boolean (*) (struct bfd_section_already_linked_hash_entry *,
void *), void *);

View File

@ -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"));
}

View File

@ -176,6 +176,7 @@ DESCRIPTION
.
.{* Forward declaration. *}
.typedef struct bfd_link_info _bfd_link_info;
.struct already_linked;
.
.typedef struct bfd_target
.{
@ -503,7 +504,7 @@ BFD_JUMP_TABLE macros.
.
. {* Check if SEC has been already linked during a reloceatable or
. final link. *}
. void (*_section_already_linked) (bfd *, struct bfd_section *,
. void (*_section_already_linked) (bfd *, struct already_linked *,
. struct bfd_link_info *);
.
. {* Define a common symbol. *}

View File

@ -1,3 +1,8 @@
2011-07-09 H.J. Lu <hongjiu.lu@intel.com>
PR ld/12942
* bfdlink.h (bfd_link_info): Add loading_lto_outputs.
2011-07-01 Joel Brobecker <brobecker@adacore.com>
* filenames.h (HAVE_CASE_INSENSITIVE_FILE_SYSTEM): Define

View File

@ -357,6 +357,9 @@ struct bfd_link_info
linker created sections, TRUE if it should be omitted. */
unsigned int no_ld_generated_unwind_info: 1;
/* TRUE if we are loading LTO outputs. */
unsigned int loading_lto_outputs: 1;
/* Non-NULL if .note.gnu.build-id section should be created. */
char *emit_note_gnu_build_id;

View File

@ -1,3 +1,13 @@
2011-07-09 H.J. Lu <hongjiu.lu@intel.com>
PR ld/12942
* 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.
2011-06-20 H.J. Lu <hongjiu.lu@intel.com>
* configure.tgt: Revert x32 change.

View File

@ -2237,7 +2237,12 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
}
if (!(abfd->flags & DYNAMIC))
bfd_section_already_linked (abfd, sec, &link_info);
{
struct already_linked linked;
linked.comdat_key = NULL;
linked.u.sec = sec;
bfd_section_already_linked (abfd, &linked, &link_info);
}
}
/* The wild routines.
@ -6544,6 +6549,7 @@ lang_process (void)
einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
plugin_error_plugin ());
/* Open any newly added files, updating the file chains. */
link_info.loading_lto_outputs = TRUE;
open_input_bfds (added.head, OPEN_BFD_NORMAL);
/* Restore the global list pointer now they have all been added. */
lang_list_remove_tail (stat_ptr, &added);

View File

@ -32,6 +32,7 @@
#include "plugin.h"
#include "plugin-api.h"
#include "elf-bfd.h"
#include "libbfd.h"
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
#include <windows.h>
#endif
@ -385,7 +386,16 @@ add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
for (n = 0; n < nsyms; n++)
{
enum ld_plugin_status rv;
asymbol *bfdsym = bfd_make_empty_symbol (abfd);
asymbol *bfdsym;
if (syms[n].comdat_key)
{
struct already_linked linked;
linked.comdat_key = xstrdup (syms[n].comdat_key);
linked.u.abfd = abfd;
bfd_section_already_linked (abfd, &linked, &link_info);
}
bfdsym = bfd_make_empty_symbol (abfd);
symptrs[n] = bfdsym;
rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
if (rv != LDPS_OK)