PATCH: Reject sh_link pointing to discarded section

H. J. Lu hjl@lucon.org
Fri Apr 1 00:30:00 GMT 2005


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)
 			    {



More information about the Binutils mailing list