PATCH: Fix SHF_LINK_ORDER and SHT_IA_64_UNWIND handling

H. J. Lu hjl@lucon.org
Sat Jul 24 20:19:00 GMT 2004


On Sat, Jul 24, 2004 at 12:20:40AM -0700, H. J. Lu wrote:
> On Fri, Jul 23, 2004 at 06:00:46PM -0700, Jim Wilson wrote:
> > On Thu, 2004-07-22 at 10:12, H. J. Lu wrote:
> > > The current linker/assembler don't handle SHF_LINK_ORDER right. Linker
> > > never tries to preserve it at all. IA64 uses section name for
> > > SHT_IA_64_UNWIND, which has SHF_LINK_ORDER. It doesn't work with
> > > multiple text sections with the same same.
> > 
> > In general, I think this is an improvement.  Saving a pointer to the
> > text section in the assembler is much better than trying to deduce it in
> > the linker from section names.
> > 
> > However, I have a number of questions that came up while looking at this
> > patch.
> > 1) The gABI says that SHF_LINK_ORDER causes sh_info to be set.  But you
> > are setting sh_link.  This seems wrong.
> 
> Yes, it is confusing. The gABI says different things in different
> places. I am trying to get a clarification on that.

The gABI does say sh_link, not sh_info. But HPUX uses sh_info. We only
need to set sh_info for IA64.

> 
> > 2) Despite the comments in the code, I can't find anyplace in the IA-64
> > psABI or the IA-64 SCRA that clearly says we have to set SHF_LINK_ORDER
> > and/or sh_link.  The psABI just refers to the SCRA, and the SCRA says
> > nothing about section header contents.  My copies are up to date
> > according to the Intel developer web site.  Can you point to anywhere
> > where this is documented?
> 
> The psABI only says .IA64.unwind section has SHF_LINK_ORDER and nothing
> more. I will ask. I think it makes senses to have it linked to the
> corresponding text section.
> 
> > 3) The comments imply that HPUX got it wrong by setting sh_info, but
> > HPUX seems to be the right one, as it agrees with the gABI.  It looks
> > like we got it wrong when we thought sh_link had to be set at all.  We
> > can probably drop all this stuff about sh_link and HPUX, and just set
> > sh_info as the gABI says to.
> 
> And fix the the gABI.
> 
> > 4) The ia64_elf_section_change_hook patch looks wrong.  You are
> > unconditionally setting elf_linked_to_section, which might overwrite a
> > previous value set by start_unwind_section.  Why do you need this?  If
> > it is needed, then it should be somehow conditional on it not already
> > being set, such as the byteorder setting is already done.
> 
> For SHT_IA_64_UNWIND section, ia64_elf_section_change_hook is always
> called before link-to section is set in start_unwind_section. It is
> needed by the testcase:
> 
>         .section .IA_64.unwind, "ao", "unwind"
> 	data8 1234
> 
> I added this testcase. Now I am not sure if we should support it at
> all.

I updated my patch to see if elf_linked_to_section has been set before
setting it to text_section.

> 
> > 5) For the elf.c change, I haven't tried to figure out if it is right
> > except as mentioned above that setting sh_link is wrong, as it should be
> > setting sh_info.  If "if" part looks fine.  The "else" part is using bfd
> > stuff that I am unfamiliar with.  I would need some kind of testcase to
> > be able to figure out what it is doing.
> 
> It is for "ld -r". Try
> 
> # ld -r -o foo.o x.o x.o
> # readelf -gS foo.o
> 
> Watch for sh_link of SHT_IA_64_UNWIND sections. It isn't set without
> my patch.
> 


H.J.
-------------- next part --------------
bfd/

2004-07-22  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (bfd_elf_section_data): Add a pointer for the
	linked-to section.
	(elf_linked_to_section): New.

	* elf.c (assign_section_numbers): Set up sh_link for
	SHF_LINK_ORDER.

	* elfxx-ia64.c (elfNN_ia64_final_write_processing): Set sh_info
	to sh_link for SHT_IA_64_UNWIND sections.

gas/

2004-07-22  H.J. Lu  <hongjiu.lu@intel.com>

	* config/tc-ia64.c (start_unwind_section): Set the linked-to
	section.
	(ia64_elf_section_change_hook): Set the linked-to section for
	SHT_IA_64_UNWIND.

--- binutils/bfd/elf-bfd.h.order	2004-07-22 12:21:57.000000000 -0700
+++ binutils/bfd/elf-bfd.h	2004-07-22 12:21:57.000000000 -0700
@@ -1038,6 +1038,9 @@ struct bfd_elf_section_data
      no dynamic symbol for this section.  */
   int dynindx;
 
+  /* A pointer to the linked-to section for SHF_LINK_ORDER.  */
+  asection *linked_to;
+
   /* Used by the backend linker to store the symbol hash table entries
      associated with relocs against global symbols.  */
   struct elf_link_hash_entry **rel_hashes;
@@ -1075,6 +1078,7 @@ struct bfd_elf_section_data
 };
 
 #define elf_section_data(sec)  ((struct bfd_elf_section_data*)sec->used_by_bfd)
+#define elf_linked_to_section(sec) (elf_section_data(sec)->linked_to)
 #define elf_section_type(sec)  (elf_section_data(sec)->this_hdr.sh_type)
 #define elf_section_flags(sec) (elf_section_data(sec)->this_hdr.sh_flags)
 #define elf_group_name(sec)    (elf_section_data(sec)->group.name)
--- binutils/bfd/elf.c.order	2004-07-22 12:21:57.000000000 -0700
+++ binutils/bfd/elf.c	2004-07-22 12:21:57.000000000 -0700
@@ -2832,6 +2832,7 @@ assign_section_numbers (bfd *abfd)
       i_shdrp[t->strtab_section] = &t->strtab_hdr;
       t->symtab_hdr.sh_link = t->strtab_section;
     }
+
   for (sec = abfd->sections; sec; sec = sec->next)
     {
       struct bfd_elf_section_data *d = elf_section_data (sec);
@@ -2860,6 +2861,40 @@ assign_section_numbers (bfd *abfd)
 	  d->rel_hdr2->sh_info = d->this_idx;
 	}
 
+      /* We need to set up sh_link for SHF_LINK_ORDER.  */
+      if ((d->this_hdr.sh_flags & SHF_LINK_ORDER) != 0)
+	{
+	  s = elf_linked_to_section (sec);
+	  if (s)
+	    d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+	  else
+	    {
+	      struct bfd_link_order *p;
+
+	      /* Find out what the corresponding section in output
+		 is.  */
+	      for (p = sec->link_order_head; p != NULL; p = p->next)
+		{
+		  s = p->u.indirect.section;
+		  if (p->type == bfd_indirect_link_order
+		      && (bfd_get_flavour (s->owner)
+			  == bfd_target_elf_flavour))
+		    {
+		      Elf_Internal_Shdr ** const elf_shdrp
+			= elf_elfsections (s->owner);
+		      int elfsec
+			= _bfd_elf_section_from_bfd_section (s->owner, s);
+		      elfsec = elf_shdrp[elfsec]->sh_link;
+		      BFD_ASSERT (elfsec != 0);
+		      s = elf_shdrp[elfsec]->bfd_section->output_section;
+		      BFD_ASSERT (s != NULL);
+		      d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+		      break;
+		    }
+		}
+	    }
+	}
+
       switch (d->this_hdr.sh_type)
 	{
 	case SHT_REL:
--- binutils/bfd/elfxx-ia64.c.order	2004-07-22 12:21:57.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c	2004-07-22 12:21:57.000000000 -0700
@@ -1375,9 +1375,7 @@ elfNN_ia64_final_write_processing (abfd,
      bfd_boolean linker ATTRIBUTE_UNUSED;
 {
   Elf_Internal_Shdr *hdr;
-  const char *sname;
-  asection *text_sect, *s;
-  size_t len;
+  asection *s;
 
   for (s = abfd->sections; s; s = s->next)
     {
@@ -1385,64 +1383,11 @@ elfNN_ia64_final_write_processing (abfd,
       switch (hdr->sh_type)
 	{
 	case SHT_IA_64_UNWIND:
-	  /* See comments in gas/config/tc-ia64.c:dot_endp on why we
-	     have to do this.  */
-	  sname = bfd_get_section_name (abfd, s);
-	  len = sizeof (ELF_STRING_ia64_unwind) - 1;
-	  if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)
-	    {
-	      sname += len;
-
-	      if (sname[0] == '\0')
-		/* .IA_64.unwind -> .text */
-		text_sect = bfd_get_section_by_name (abfd, ".text");
-	      else
-		/* .IA_64.unwindFOO -> FOO */
-		text_sect = bfd_get_section_by_name (abfd, sname);
-	    }
-	  else if (sname
-		   && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,
-		       strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)
-	    {
-	      /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
-	      size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
-	      char *once_name = bfd_malloc (len2 + strlen (sname + len) + 1);
-
-	      if (once_name != NULL)
-		{
-		  memcpy (once_name, ".gnu.linkonce.t.", len2);
-		  strcpy (once_name + len2, sname + len);
-		  text_sect = bfd_get_section_by_name (abfd, once_name);
-		  free (once_name);
-		}
-	      else
-		/* Should only happen if we run out of memory, in
-		   which case we're probably toast anyway.  Try to
-		   cope by finding the section the slow way.  */
-		for (text_sect = abfd->sections;
-		     text_sect != NULL;
-		     text_sect = text_sect->next)
-		  {
-		    if (strncmp (bfd_section_name (abfd, text_sect),
-				 ".gnu.linkonce.t.", len2) == 0
-			&& strcmp (bfd_section_name (abfd, text_sect) + len2,
-				   sname + len) == 0)
-		      break;
-		  }
-	    }
-	  else
-	    /* last resort: fall back on .text */
-	    text_sect = bfd_get_section_by_name (abfd, ".text");
-
-	  if (text_sect)
-	    {
-	      /* The IA-64 processor-specific ABI requires setting
-		 sh_link to the unwind section, whereas HP-UX requires
-		 sh_info to do so.  For maximum compatibility, we'll
-		 set both for now... */
-	      hdr->sh_link = elf_section_data (text_sect)->this_idx;
-	      hdr->sh_info = elf_section_data (text_sect)->this_idx;
-	    }
+	  /* The IA-64 processor-specific ABI requires setting sh_link
+	     to the unwind section, whereas HP-UX requires sh_info to
+	     do so.  For maximum compatibility, we'll set both for
+	     now... */
+	  hdr->sh_info = hdr->sh_link;
 	  break;
 	}
     }
--- binutils/gas/config/tc-ia64.c.order	2004-07-11 08:57:28.000000000 -0700
+++ binutils/gas/config/tc-ia64.c	2004-07-24 13:13:48.000000000 -0700
@@ -3403,6 +3403,8 @@ start_unwind_section (const segT text_se
       bfd_set_section_flags (stdoutput, now_seg,
 			     SEC_LOAD | SEC_ALLOC | SEC_READONLY);
     }
+
+  elf_linked_to_section (now_seg) = text_seg;
 }
 
 static void
@@ -11022,6 +11024,9 @@ ia64_float_to_chars_littleendian (char *
 void
 ia64_elf_section_change_hook  (void)
 {
+  if (elf_section_type (now_seg) == SHT_IA_64_UNWIND
+      && elf_linked_to_section (now_seg) == NULL)
+    elf_linked_to_section (now_seg) = text_section;
   dot_byteorder (-1);
 }
 


More information about the Binutils mailing list