aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elflink.c120
2 files changed, 46 insertions, 83 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 06c75be..c757205 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
* elf-eh-frame.c (_bfd_elf_eh_frame_section_offset): Add "info"
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 0687eca..75b8c96 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -9268,88 +9268,11 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
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
_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
{
flagword flags;
- const char *name;
+ const char *name, *p;
struct bfd_section_already_linked *l;
struct bfd_section_already_linked_hash_entry *already_linked_list;
asection *group;
@@ -9399,7 +9322,13 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * 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)
{
@@ -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
section. */
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)
{
/* The section has already been linked. See if we should
- issue a warning. */
+ issue a warning. */
switch (flags & SEC_LINK_DUPLICATES)
{
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
the undiscarded group will be discarded incorrectly later since
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;
}
else
/* There is no direct match. But for linkonce section, we should
check if there is a match with comdat group member. We always
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. */
bfd_section_already_linked_table_insert (already_linked_list, sec);
}