This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: IA64 unwind section references discarded section


On Thu, Mar 31, 2005 at 10:20:27PM -0800, H. J. Lu wrote:
> This is the same problem as
> 
> http://sourceware.org/ml/binutils/2004-08/msg00187.html
> http://sourceware.org/ml/binutils/2004-08/msg00190.html
> 
> But this time it is icc, which doesn't use gas. I would like to see a
> linker solution.
> 
> 

This is a linker patch. It creates a fake group section for a
linkonce text sections and its unwind sections. The fake group
section is removed before the output file is written.


H.J.
----
bfd/

2005-04-01  H.J. Lu  <hongjiu.lu@intel.com>

	* elf.c (bfd_elf_set_group_contents): Ignore linker created
	group section. 
	(assign_section_numbers): Remove the linker created group
	sections.

	* elfxx-ia64.c (elfNN_ia64_object_p): New.
	(elf_backend_object_p): Defined.

gas/

2005-04-01  H.J. Lu  <hongjiu.lu@intel.com>

	* config/tc-ia64.c (start_unwind_section): Undo the change
	of 2004-08-18.
	(generate_unwind_image, dot_endp): Likewise.

--- binutils/bfd/elf.c.unwind	2005-04-01 08:54:23.000000000 -0800
+++ binutils/bfd/elf.c	2005-04-01 15:29:01.966988213 -0800
@@ -2635,7 +2635,10 @@ bfd_elf_set_group_contents (bfd *abfd, a
   struct bfd_link_order *l;
   bfd_boolean gas;
 
+  /* Ignore linker created group section.  See elfNN_ia64_object_p in
+     elfxx-ia64.c.  */
   if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP
+      || (sec->flags & SEC_LINKER_CREATED) != 0
       || *failedptr)
     return;
 
@@ -2729,7 +2732,7 @@ static bfd_boolean
 assign_section_numbers (bfd *abfd)
 {
   struct elf_obj_tdata *t = elf_tdata (abfd);
-  asection *sec;
+  asection *sec, **prev_secp;
   unsigned int section_number, secn;
   Elf_Internal_Shdr **i_shdrp;
   bfd_size_type amt;
@@ -2739,17 +2742,37 @@ assign_section_numbers (bfd *abfd)
 
   _bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
 
-  /* Put SHT_GROUP sections first.  */
+  /* Put SHT_GROUP sections first and remove the linker created
+     SHT_GROUP sections.  */
+  prev_secp = &abfd->sections;
   for (sec = abfd->sections; sec; sec = sec->next)
     {
       d = elf_section_data (sec);
 
       if (d->this_hdr.sh_type == SHT_GROUP)
 	{
+	  if (sec->flags & SEC_LINKER_CREATED)
+	    break;
 	  if (section_number == SHN_LORESERVE)
 	    section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
 	  d->this_idx = section_number++;
 	}
+
+      prev_secp = &(*prev_secp)->next;
+    }
+
+   /* The linker created SHT_GROUP sections are always appended
+      at the end.  */
+  if (sec
+      && ((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED))
+	  == (SEC_GROUP | SEC_LINKER_CREATED)))
+    {
+      do
+	{
+	  bfd_section_list_remove (abfd, prev_secp);
+	  abfd->section_count--;
+	}
+      while (*prev_secp);
     }
 
   for (sec = abfd->sections; sec; sec = sec->next)
--- binutils/bfd/elfxx-ia64.c.unwind	2005-03-21 13:13:37.000000000 -0800
+++ binutils/bfd/elfxx-ia64.c	2005-04-01 15:02:55.334285508 -0800
@@ -4886,6 +4886,154 @@ static struct bfd_elf_special_section co
 };
 
 static bfd_boolean
+elfNN_ia64_object_p (bfd *abfd)
+{
+  asection *sec;
+  unsigned int num_group = 0;
+
+  if (abfd->flags & DYNAMIC)
+    return TRUE;
+
+  /* Count number of .gnu.linkonce.t.* sections which aren't in a
+     section group.  */
+  for (sec = abfd->sections; sec != NULL; sec = sec->next)
+    {
+      if (elf_sec_group (sec) == NULL
+	  && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE))
+	      == (SEC_LINK_ONCE | SEC_CODE))
+	  && strncmp (sec->name, ".gnu.linkonce.t.", 16) == 0)
+	num_group++;
+    }
+
+  if (num_group)
+    {
+      asection *group, *unwi, *unw;
+      flagword flags;
+      Elf_Internal_Shdr *shdr;
+      Elf_Internal_Shdr **shdrp, **old_shdrp;
+      Elf_Internal_Shdr **grp_shdrp, **old_grp_shdrp;
+      const char *name;
+      char *unwi_name, *unw_name;
+      bfd_size_type amt;
+      unsigned int shindex = elf_numsections (abfd);
+      unsigned int grpindex = elf_tdata (abfd)->num_group;
+      unsigned int num_sec = shindex + num_group;
+
+      if (num_sec > SHN_LORESERVE)
+	num_sec += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+
+      /* Allow a new ELF section table and copy the old one.  */
+      elf_numsections (abfd) = num_sec;
+      amt = sizeof (*shdrp) * num_sec;
+      old_shdrp = elf_elfsections (abfd);
+      elf_elfsections (abfd) = bfd_alloc (abfd, amt);
+      shdrp = elf_elfsections (abfd);
+      if (!shdrp)
+	return FALSE;
+      memcpy (shdrp, old_shdrp, shindex * sizeof (*shdrp));
+
+      /* Allow a new group section table and copy the old one.  */
+      elf_tdata (abfd)->num_group = grpindex + num_group;
+      amt = elf_tdata (abfd)->num_group * sizeof (*grp_shdrp);
+      old_grp_shdrp = elf_tdata (abfd)->group_sect_ptr;
+      elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt);
+      grp_shdrp = elf_tdata (abfd)->group_sect_ptr;
+      if (grp_shdrp == NULL)
+	return FALSE;
+      memcpy (grp_shdrp, old_grp_shdrp, grpindex * sizeof (*grp_shdrp));
+
+      /* Flags for fake group section.  */
+      flags = (SEC_LINKER_CREATED | SEC_GROUP | SEC_LINK_ONCE
+	       | SEC_EXCLUDE);
+
+      /* We add a fake section group for each linkonce text section and
+	 its unwind sections.  */
+      for (sec = abfd->sections; sec != NULL; sec = sec->next)
+	{
+	  if (elf_sec_group (sec) == NULL
+	      && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE))
+		  == (SEC_LINK_ONCE | SEC_CODE))
+	      && strncmp (sec->name, ".gnu.linkonce.t.", 16) == 0)
+	    {
+	      /* Fake a SHT_GROUP section.  */
+	      shdr = bfd_zalloc (abfd, sizeof (shdr));
+	      if (!shdr)
+		return FALSE;
+	      shdr->sh_type = SHT_GROUP;
+
+	      name = sec->name + 16;
+
+	      amt = strlen (name) + sizeof (".gnu.linkonce.ia64unwi.");
+	      unwi_name = bfd_alloc (abfd, amt);
+	      if (!unwi_name)
+		return FALSE;
+
+	      strcpy (stpcpy (unwi_name, ".gnu.linkonce.ia64unwi."),
+		      name);
+	      unwi = bfd_get_section_by_name (abfd, unwi_name);
+
+	      amt = strlen (name) + sizeof (".gnu.linkonce.ia64unw.");
+	      unw_name = bfd_alloc (abfd, amt);
+	      if (!unw_name)
+		return FALSE;
+
+	      strcpy (stpcpy (unw_name, ".gnu.linkonce.ia64unw."),
+		      name);
+	      unw = bfd_get_section_by_name (abfd, unw_name);
+
+	      /* We need to create a fake group section for it and its
+		 unwind sections.  */
+	      group = bfd_make_section_anyway (abfd, name);
+	      if (group == NULL
+		  || ! bfd_set_section_flags (abfd, group, flags))
+		return FALSE;
+
+	      elf_next_in_group (group) = sec;
+
+	      elf_group_name (sec) = name;
+	      elf_next_in_group (sec) = sec;
+	      elf_sec_group (sec) = group;
+
+	      if (unwi)
+		{
+		  elf_group_name (unwi) = name;
+		  elf_next_in_group (unwi) = sec;
+		  elf_next_in_group (sec) = unwi;
+		  elf_sec_group (unwi) = group;
+		}
+
+	      if (unw)
+		{
+		  elf_group_name (unw) = name;
+		  if (unwi)
+		    {
+		      elf_next_in_group (unw)
+			= elf_next_in_group (unwi);
+		      elf_next_in_group (unwi) = unw;
+		    }
+		  else
+		    {
+		      elf_next_in_group (unw) = sec;
+		      elf_next_in_group (sec) = unw;
+		    }
+		  elf_sec_group (unw) = group;
+		}
+
+	      shdr->bfd_section = group;
+	      elf_section_data (group)->this_hdr = *shdr;
+
+	      if (shindex == SHN_LORESERVE)
+		shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+	      elf_section_data (group)->this_idx = shindex++;
+	      shdrp [elf_section_data (group)->this_idx] = shdr;
+	      grp_shdrp [grpindex++] = shdr;
+	    }
+	}
+    }
+  return TRUE;
+}
+
+static bfd_boolean
 elfNN_ia64_hpux_vec (const bfd_target *vec)
 {
   extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
@@ -4968,6 +5116,9 @@ elfNN_hpux_backend_symbol_processing (bf
 #define bfd_elfNN_bfd_relax_section \
 	elfNN_ia64_relax_section
 
+#define elf_backend_object_p \
+	elfNN_ia64_object_p
+
 /* Stuff for the BFD linker: */
 #define bfd_elfNN_bfd_link_hash_table_create \
 	elfNN_ia64_hash_table_create
--- binutils/gas/config/tc-ia64.c.unwind	2005-03-28 14:54:17.000000000 -0800
+++ binutils/gas/config/tc-ia64.c	2005-04-01 12:41:26.792655189 -0800
@@ -3445,7 +3445,7 @@ static char *special_linkonce_name[] =
   };
 
 static void
-start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
+start_unwind_section (const segT text_seg, int sec_index)
 {
   /*
     Use a slightly ugly scheme to derive the unwind section names from
@@ -3507,8 +3507,6 @@ start_unwind_section (const segT text_se
       prefix = special_linkonce_name [sec_index - SPECIAL_SECTION_UNWIND];
       suffix += sizeof (".gnu.linkonce.t.") - 1;
     }
-  else if (linkonce_empty)
-    return;
 
   prefix_len = strlen (prefix);
   suffix_len = strlen (suffix);
@@ -3596,7 +3594,7 @@ generate_unwind_image (const segT text_s
       expressionS exp;
       bfd_reloc_code_real_type reloc;
 
-      start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 0);
+      start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO);
 
       /* Make sure the section has 4 byte alignment for ILP32 and
 	 8 byte alignment for LP64.  */
@@ -3637,8 +3635,6 @@ generate_unwind_image (const segT text_s
 	  unwind.personality_routine = 0;
 	}
     }
-  else
-    start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 1);
 
   free_saved_prologue_counts ();
   unwind.list = unwind.tail = unwind.current_entry = NULL;
@@ -4411,7 +4407,7 @@ dot_endp (dummy)
       subseg_set (md.last_text_seg, 0);
       proc_end = expr_build_dot ();
 
-      start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 0);
+      start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND);
 
       /* Make sure that section has 4 byte alignment for ILP32 and
          8 byte alignment for LP64.  */
@@ -4451,9 +4447,6 @@ dot_endp (dummy)
 			    bytes_per_address);
 
     }
-  else
-    start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 1);
-
   subseg_set (saved_seg, saved_subseg);
 
   if (unwind.proc_start)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]