PATCH: Reject sh_link pointing to discarded section

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


On Fri, Apr 01, 2005 at 10:46:59AM +0930, Alan Modra wrote:
> On Thu, Mar 31, 2005 at 04:29:06PM -0800, H. J. Lu wrote:
> > 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.
> 
> OK.
> 

I'd like to check in this patch instead. _bfd_elf_check_kept_section
will make sure we use the same criteria when choosing the kept section.


H.J.
----
2005-03-31  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (_bfd_elf_check_kept_section): New.

	* elf.c (assign_section_numbers): When sh_link points to a
	discarded section, call _bfd_elf_check_kept_section to see if
	the kept section can be used. Otherwise reject sh_link
	pointing to discarded section.

	* elflink.c (_bfd_elf_check_kept_section): New.
	(elf_link_input_bfd): Use it.

--- bfd/elf-bfd.h.index	2005-03-21 09:13:21.000000000 -0800
+++ bfd/elf-bfd.h	2005-03-31 17:56:19.827159793 -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_check_kept_section
+  (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 17:56:57.753261934 -0800
@@ -2927,7 +2927,25 @@ 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 = _bfd_elf_check_kept_section (s);
+			       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 18:03:07.006468952 -0800
@@ -6779,6 +6779,26 @@ match_group_member (asection *sec, asect
   return NULL;
 }
 
+/* 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. */
+
+asection *
+_bfd_elf_check_kept_section (asection *sec)
+{
+  asection *kept;
+
+  kept = sec->kept_section;
+  if (kept != NULL)
+    {
+      if (elf_sec_group (sec) != NULL)
+	kept = match_group_member (sec, kept);
+      if (kept != NULL && sec->size != kept->size)
+	kept = NULL;
+    }
+  return kept;
+}
+
 /* Link an input file into the linker output file.  This function
    handles all the sections and relocations of the input file at once.
    This is so that we only have to read the local symbols once, and
@@ -7094,8 +7114,6 @@ elf_link_input_bfd (struct elf_final_lin
 		     discarded section.  */
 		  if ((sec = *ps) != NULL && elf_discarded_section (sec))
 		    {
-		      asection *kept;
-
 		      BFD_ASSERT (r_symndx != 0);
 		      if (action & COMPLAIN)
 			{
@@ -7116,13 +7134,12 @@ elf_link_input_bfd (struct elf_final_lin
 			 is that we warn in non-debug sections, and
 			 debug sections tend to come after other
 			 sections.  */
-		      kept = sec->kept_section;
-		      if (kept != NULL && (action & PRETEND))
+		      if (action & PRETEND)
 			{
-			  if (elf_sec_group (sec) != NULL)
-			    kept = match_group_member (sec, kept);
-			  if (kept != NULL
-			      && sec->size == kept->size)
+			  asection *kept;
+
+			  kept = _bfd_elf_check_kept_section (sec);
+			  if (kept != NULL)
 			    {
 			      *ps = kept;
 			      continue;



More information about the Binutils mailing list