The problem with linkonce sections in ELF

Ian Lance Taylor ian@zembu.com
Mon Feb 7 18:12:00 GMT 2000


   Date: Mon, 7 Feb 2000 18:06:39 -0800
   From: "H . J . Lu" <hjl@lucon.org>

   On Mon, Feb 07, 2000 at 08:54:50PM -0500, Ian Lance Taylor wrote:
   > 
   > Yes, you're right, there are problems with my patch.  It seems to
   > confuse the linker.
   > 
   > This needs to be redone somehow.  I don't know when I will have the
   > time.
   > 
   > Do you see what I think is wrong with your patch?

   I didn't study it further. I trust your judgement. If you can
   remind me what is wrong in my patch, I may be able to figure
   something out between yours and mine.

_bfd_strip_section_from_output should not strip the section if it has
another input section.

The existing code checks the link_orders to see if there is a
link_order.  However, this is wrong.  At the time the function is
called, the link_orders have not been set up.  In fact, at the time
the code is called, the link order can not be set up.

Your patch stuffed in a link order, because that is what the existing
code was looking for.  However, there shouldn't be a link order at
that point.  Putting one in doesn't make sense.

I tried a different mechanism to detect whether there was another
input section for the output section.  But I got it wrong.

But, actually, now I see that I made a simple mistake.  Instead of my
earlier patch, try this one.

Ian

Index: section.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/section.c,v
retrieving revision 1.10
diff -u -r1.10 section.c
--- section.c	2000/01/13 22:10:36	1.10
+++ section.c	2000/02/08 02:11:56
@@ -1100,20 +1100,28 @@
 
 SYNOPSIS
 	void _bfd_strip_section_from_output
-	(asection *section);
+	(struct bfd_link_info *info, asection *section);
 
 DESCRIPTION
-	Remove @var{section} from the output.  If the output section becomes
-	empty, remove it from the output bfd.
+	Remove @var{section} from the output.  If the output section
+	becomes empty, remove it from the output bfd.  @var{info} may
+	be NULL; if it is not, it is used to decide whether the output
+	section is empty.
 */
 void
-_bfd_strip_section_from_output (s)
+_bfd_strip_section_from_output (info, s)
+     struct bfd_link_info *info;
      asection *s;
 {
   asection **spp, *os;
   struct bfd_link_order *p, *pp;
+  boolean keep_os;
 
-  /* Excise the input section from the link order.  */
+  /* Excise the input section from the link order.
+
+     FIXME: For all calls that I can see to this function, the link
+     orders have not yet been set up.  So why are we checking them? --
+     Ian */
   os = s->output_section;
   for (p = os->link_order_head, pp = NULL; p != NULL; pp = p, p = p->next)
     if (p->type == bfd_indirect_link_order
@@ -1128,10 +1136,30 @@
 	break;
       }
 
+  keep_os = os->link_order_head != NULL;
+
+  if (! keep_os && info != NULL)
+    {
+      bfd *abfd;
+      for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+	{
+	  asection *is;
+	  for (is = abfd->sections; is != NULL; is = is->next)
+	    {
+	      if (is != s && is->output_section == os)
+		break;
+	    }
+	  if (is != NULL)
+	    break;
+	}
+      if (abfd != NULL)
+	keep_os = true;
+    }
+
   /* If the output section is empty, remove it too.  Careful about sections
      that have been discarded in the link script -- they are mapped to 
      bfd_abs_section, which has no owner.  */
-  if (!os->link_order_head && os->owner)
+  if (!keep_os && os->owner != NULL)
     {
       for (spp = &os->owner->sections; *spp; spp = &(*spp)->next)
 	if (*spp == os)


More information about the Binutils mailing list