aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2006-11-17 13:55:41 +0000
committerAlan Modra <amodra@gmail.com>2006-11-17 13:55:41 +0000
commitc2370991ed9651b03e1d801252630c18503ec623 (patch)
tree65d4cf1aafa9c69ca16f2ebfa9de9d1fcc695560
parent9daf3993283211fd4750be1ab6216caffee61c5c (diff)
downloadfsf-binutils-gdb-c2370991ed9651b03e1d801252630c18503ec623.zip
fsf-binutils-gdb-c2370991ed9651b03e1d801252630c18503ec623.tar.gz
fsf-binutils-gdb-c2370991ed9651b03e1d801252630c18503ec623.tar.bz2
* elflink.c (_bfd_elf_check_kept_section): Test for kept group
section. Save result of checks in kept_section. (_bfd_elf_section_already_linked): Tidy. Correct comments. Ignore all group member sections. Handle special matching of single-member groups against linkonce sections via their group section. When such a match is found, set kept_section to the group member section rather than to the group.
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/elflink.c84
2 files changed, 43 insertions, 51 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 490583f..50c9853 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2006-11-18 Alan Modra <amodra@bigpond.net.au>
+
+ * elflink.c (_bfd_elf_check_kept_section): Test for kept group
+ section. Save result of checks in kept_section.
+ (_bfd_elf_section_already_linked): Tidy. Correct comments.
+ Ignore all group member sections. Handle special matching of
+ single-member groups against linkonce sections via their group
+ section. When such a match is found, set kept_section to the
+ group member section rather than to the group.
+
2006-11-14 Phil Lello <phil.lello@homecall.co.uk>
* peXXigen.c: Updates for PE/COFF V8.0, and clarification
diff --git a/bfd/elflink.c b/bfd/elflink.c
index df7b899..b250758 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -7287,8 +7287,8 @@ match_group_member (asection *sec, asection *group,
}
/* Check if the kept section of a discarded section SEC can be used
- to replace it. Return the replacement if it is OK. Otherwise return
- NULL. */
+ to replace it. Return the replacement if it is OK. Otherwise return
+ NULL. */
asection *
_bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
@@ -7298,10 +7298,11 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
kept = sec->kept_section;
if (kept != NULL)
{
- if (elf_sec_group (sec) != NULL)
+ if ((kept->flags & SEC_GROUP) != 0)
kept = match_group_member (sec, kept, info);
if (kept != NULL && sec->size != kept->size)
kept = NULL;
+ sec->kept_section = kept;
}
return kept;
}
@@ -10316,33 +10317,21 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec,
const char *name, *p;
struct bfd_section_already_linked *l;
struct bfd_section_already_linked_hash_entry *already_linked_list;
- asection *group;
- /* A single member comdat group section may be discarded by a
- linkonce section. See below. */
if (sec->output_section == bfd_abs_section_ptr)
return;
flags = sec->flags;
- /* Check if it belongs to a section group. */
- group = elf_sec_group (sec);
-
- /* Return if it isn't a linkonce section nor a member of a group. A
- comdat group section also has SEC_LINK_ONCE set. */
- if ((flags & SEC_LINK_ONCE) == 0 && group == NULL)
+ /* 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;
- if (group)
- {
- /* If this is the member of a single member comdat group, check if
- the group should be discarded. */
- if (elf_next_in_group (sec) == sec
- && (group->flags & SEC_LINK_ONCE) != 0)
- sec = group;
- else
- 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
@@ -10373,11 +10362,8 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec,
for (l = already_linked_list->entry; l != NULL; l = l->next)
{
- /* We may have 3 different sections on the list: group section,
- comdat section and linkonce section. SEC may be a linkonce or
- group section. We match a group section with a group section,
- a linkonce section with a linkonce section, and ignore comdat
- section. */
+ /* 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, l->sec->name) == 0
&& bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
@@ -10465,32 +10451,28 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec,
}
}
- if (group)
+ /* A single member comdat group section may be discarded by a
+ linkonce section and vice versa. */
+
+ if ((flags & SEC_GROUP) != 0)
{
- /* If this is the member of a single member comdat group and the
- group hasn't be discarded, we check if it matches a linkonce
- section. We only record the discarded comdat group. Otherwise
- the undiscarded group will be discarded incorrectly later since
- itself has been recorded. */
- 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),
- info))
- {
- 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;
+ 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->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
- /* 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. */
+ /* 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)
{
@@ -10501,7 +10483,7 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec,
&& bfd_elf_match_symbols_in_sections (first, sec, info))
{
sec->output_section = bfd_abs_section_ptr;
- sec->kept_section = l->sec;
+ sec->kept_section = first;
break;
}
}