* elflink.c (struct already_linked_section): Removed.

(try_match_symbols_in_sections, already_linked): Removed.
	(_bfd_elf_section_already_linked): Skip ^\.gnu\.linkonce\.[^.]*\.
	prefix of section names when finding already_linked_table
	chain.  Compare section names.  Instead of calling already_linked,
	do it inline and only for sections in the same already_linked_list.
This commit is contained in:
Jakub Jelinek
2004-10-15 05:19:19 +00:00
parent 1c645fec9f
commit 6d2cd2108d
2 changed files with 46 additions and 83 deletions

View File

@ -1,3 +1,12 @@
2004-10-15 Jakub Jelinek <jakub@redhat.com>
* elflink.c (struct already_linked_section): Removed.
(try_match_symbols_in_sections, already_linked): Removed.
(_bfd_elf_section_already_linked): Skip ^\.gnu\.linkonce\.[^.]*\.
prefix of section names when finding already_linked_table
chain. Compare section names. Instead of calling already_linked,
do it inline and only for sections in the same already_linked_list.
2004-10-15 Alan Modra <amodra@bigpond.net.au> 2004-10-15 Alan Modra <amodra@bigpond.net.au>
* elf-eh-frame.c (_bfd_elf_eh_frame_section_offset): Add "info" * elf-eh-frame.c (_bfd_elf_eh_frame_section_offset): Add "info"

View File

@ -9268,88 +9268,11 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
return ret; return ret;
} }
struct already_linked_section
{
asection *sec;
asection *linked;
};
/* Check if the member of a single member comdat group matches a
linkonce section and vice versa. */
static bfd_boolean
try_match_symbols_in_sections
(struct bfd_section_already_linked_hash_entry *h, void *info)
{
struct bfd_section_already_linked *l;
struct already_linked_section *s
= (struct already_linked_section *) info;
if (elf_sec_group (s->sec) == NULL)
{
/* It is a linkonce section. Try to match it with the member of a
single member comdat group. */
for (l = h->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, s->sec))
{
s->linked = first;
return FALSE;
}
}
}
else
{
/* It is the member of a single member comdat group. Try to match
it with a linkonce section. */
for (l = h->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, s->sec))
{
s->linked = l->sec;
return FALSE;
}
}
return TRUE;
}
static bfd_boolean
already_linked (asection *sec, asection *group)
{
struct already_linked_section result;
result.sec = sec;
result.linked = NULL;
bfd_section_already_linked_table_traverse
(try_match_symbols_in_sections, &result);
if (result.linked)
{
sec->output_section = bfd_abs_section_ptr;
sec->kept_section = result.linked;
/* Also discard the group section. */
if (group)
group->output_section = bfd_abs_section_ptr;
return TRUE;
}
return FALSE;
}
void void
_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec) _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
{ {
flagword flags; flagword flags;
const char *name; const char *name, *p;
struct bfd_section_already_linked *l; struct bfd_section_already_linked *l;
struct bfd_section_already_linked_hash_entry *already_linked_list; struct bfd_section_already_linked_hash_entry *already_linked_list;
asection *group; asection *group;
@ -9399,7 +9322,13 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
name = bfd_get_section_name (abfd, sec); name = bfd_get_section_name (abfd, sec);
already_linked_list = bfd_section_already_linked_table_lookup (name); if (strncmp (name, ".gnu.linkonce.", sizeof (".gnu.linkonce.") - 1) == 0
&& (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) for (l = already_linked_list->entry; l != NULL; l = l->next)
{ {
@ -9409,10 +9338,11 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
a linkonce section with a linkonce section, and ignore comdat a linkonce section with a linkonce section, and ignore comdat
section. */ section. */
if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP) if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
&& strcmp (name, l->sec->name) == 0
&& bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL) && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
{ {
/* The section has already been linked. See if we should /* The section has already been linked. See if we should
issue a warning. */ issue a warning. */
switch (flags & SEC_LINK_DUPLICATES) switch (flags & SEC_LINK_DUPLICATES)
{ {
default: default:
@ -9501,15 +9431,39 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
section. We only record the discarded comdat group. Otherwise section. We only record the discarded comdat group. Otherwise
the undiscarded group will be discarded incorrectly later since the undiscarded group will be discarded incorrectly later since
itself has been recorded. */ itself has been recorded. */
if (! already_linked (elf_next_in_group (sec), group)) 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,
elf_next_in_group (sec)))
{
elf_next_in_group (sec)->output_section = bfd_abs_section_ptr;
elf_next_in_group (sec)->kept_section = l->sec;
group->output_section = bfd_abs_section_ptr;
break;
}
if (l == NULL)
return; return;
} }
else else
/* There is no direct match. But for linkonce section, we should /* There is no direct match. But for linkonce section, we should
check if there is a match with comdat group member. We always check if there is a match with comdat group member. We always
record the linkonce section, discarded or not. */ record the linkonce section, discarded or not. */
already_linked (sec, group); 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))
{
sec->output_section = bfd_abs_section_ptr;
sec->kept_section = l->sec;
break;
}
}
/* This is the first section with this name. Record it. */ /* This is the first section with this name. Record it. */
bfd_section_already_linked_table_insert (already_linked_list, sec); bfd_section_already_linked_table_insert (already_linked_list, sec);
} }