This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
PATCH: Reject sh_link pointing to discarded section
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Thu, 31 Mar 2005 16:29:06 -0800
- Subject: PATCH: Reject sh_link pointing to discarded section
I got 2 ia64 .o files with the same linkonce text section, one with
unwind section and the other without. I think the one without unwind
section is bad. When linker sees the one without unwind section first,
the linkonce text section in the other one will be discarded. But
its unwind section still points to the discarded section and linker
will crash when trying to set sh_link. This patch will try to use the
kept section if they have the same size, otherwise, reject it.
H.J.
----
2005-03-31 H.J. Lu <hongjiu.lu@intel.com>
* elf-bfd.h (_bfd_elf_match_group_member): New.
* elf.c (assign_section_numbers): Use the kept section when
sh_link points to a discarded section if the kept section has
the same size as the discarded one. Otherwise reject sh_link
pointing to discarded section.
* elflink.c (match_group_member): Renamed it to ...
(_bfd_elf_match_group_member): This.
--- bfd/elf-bfd.h.index 2005-03-21 09:13:21.000000000 -0800
+++ bfd/elf-bfd.h 2005-03-31 16:17:21.753551817 -0800
@@ -1441,6 +1441,8 @@ extern void _bfd_elf_section_already_lin
(bfd *, struct bfd_section *);
extern void bfd_elf_set_group_contents
(bfd *, asection *, void *);
+extern asection *_bfd_elf_match_group_member
+ (asection *, asection *);
extern void _bfd_elf_link_just_syms
(asection *, struct bfd_link_info *);
extern bfd_boolean _bfd_elf_copy_private_header_data
--- bfd/elf.c.index 2005-03-31 11:14:58.000000000 -0800
+++ bfd/elf.c 2005-03-31 16:28:07.611123238 -0800
@@ -2927,7 +2927,35 @@ assign_section_numbers (bfd *abfd)
}
else
{
- s = elf_shdrp[elfsec]->bfd_section->output_section;
+ s = elf_shdrp[elfsec]->bfd_section;
+ if (elf_discarded_section (s))
+ {
+ asection *kept;
+ (*_bfd_error_handler)
+ (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
+ abfd, d->this_hdr.bfd_section,
+ s, s->owner);
+ /* Point to the kept section if it has
+ the same size as the discarded
+ one. */
+ kept = s->kept_section;
+ if (kept)
+ {
+ if (elf_sec_group (s) != NULL)
+ kept = _bfd_elf_match_group_member (s, kept);
+ if (kept != NULL
+ && s->size == kept->size)
+ s = kept;
+ else
+ kept = NULL;
+ }
+ if (kept == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ }
+ s = s->output_section;
BFD_ASSERT (s != NULL);
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
}
--- bfd/elflink.c.index 2005-03-31 11:14:58.000000000 -0800
+++ bfd/elflink.c 2005-03-31 16:17:52.208617787 -0800
@@ -6761,8 +6761,8 @@ elf_action_discarded (asection *sec)
/* Find a match between a section and a member of a section group. */
-static asection *
-match_group_member (asection *sec, asection *group)
+asection *
+_bfd_elf_match_group_member (asection *sec, asection *group)
{
asection *first = elf_next_in_group (group);
asection *s = first;
@@ -7120,7 +7120,7 @@ elf_link_input_bfd (struct elf_final_lin
if (kept != NULL && (action & PRETEND))
{
if (elf_sec_group (sec) != NULL)
- kept = match_group_member (sec, kept);
+ kept = _bfd_elf_match_group_member (sec, kept);
if (kept != NULL
&& sec->size == kept->size)
{