This is the mail archive of the binutils@sourceware.org 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]

Re: FRV and Blackfin PT_GNU_STACK


On Tue, Jun 20, 2006 at 04:45:08PM +0800, Jie Zhang wrote:
> On Tue, 2006-06-20 at 01:29 +0930, Alan Modra wrote:
> > When testing SIZEOF_HEADERS relaxation, I noticed that a fix in
> > http://sources.redhat.com/ml/binutils/2006-05/msg00318.html for PT_NOTE
> > p_memsz broke PT_GNU_STACK p_memsz for frv and bfin.  To get this field
> > set, these ports create an output .stack section with the desired stack
> > size (and alignment) and tack it on to the PT_GNU_STACK header using
> > elf_backend_modify_segment_map.  It's very much a hack, since you're not
> > supposed to create sections like this in the output bfd.  One
> > consequence is that the .stack section header doesn't get its type
> > correct (you'd expect NOBITS) or size set (which is fortunate in a way,
> > because otherwise you'd end up with a large useless PROGBITS section in
> > the object file).
> > 
> > The question I have is this:  Do you want a .stack section in the output
> > file?  Or should this section really be attached as an input section
> > that extends the .bss output section?  Or do without the section
> > entirely and just magically tweak PT_GNU_STACK?
> > 
> >From the code of binfmt_elf_fdpic.c in linux kernel, it seems the .stack
> section is not needed. The kernel gets the stack size for the FDPIC ELF
> application is from p_memsz of the PT_GNU_STACK segment.
> 
> I'm not sure if my thought is right on why a .stack section is used
> here, since I'm not the original writer of the code. The .stack section
> is used to help set the PT_GNU_STACK segment size, since segment size is
> calculated by sum up the size of all the sections of it. If we want to
> eliminate the use of the section entirely, where can we magically tweak
> PT_GNU_STACK? Is there is already a hook we can use or we need add one?

Thanks for the feedback.  Like you, I think the .stack section is only
there to set PT_GNU_STACK p_memsz and p_palign.

This is how I think FRV and Blackfin should set PT_GNU_STACK.  No
messing around with a bogus .stack section.  The new hook also allows me
to modify ia64 segments, so the final backend_modify_segment_map call
isn't needed.

	* elf-bfd.h (struct elf_backend_data): Add
	elf_backend_modify_program_headers.
	* elfxx-target.h (elf_backend_modify_program_headers): Define.
	(elfNN_bed): Init new field.
	* elf.c (elf_modify_segment_map): Remove comment.
	(assign_file_positions_for_load_sections): Only call
	elf_modify_segment_map for objcopy/strip.
	(assign_file_positions_except_relocs): Call
	elf_backend_modify_program_headers.
	* elf32-frv.c (elf32_frvfdpic_always_size_sections): Don't make
	.stack section.
	(elf32_frvfdpic_modify_segment_map): Delete.
	(elf32_frvfdpic_modify_program_headers): New.
	(elf_backend_modify_segment_map): Don't define.
	(elf_backend_modify_program_headers): Define.
	* elf32-bfin.c (elf32_bfinfdpic_always_size_sections): Don't make
	.stack section.
	(elf32_bfinfdpic_modify_segment_map): Delete.
	(elf32_bfinfdpic_modify_program_headers): New.
	(elf_backend_modify_segment_map): Don't define.
	(elf_backend_modify_program_headers): Define.
	* elfxx-ia64.c (elfNN_ia64_modify_program_headers): New function.
	Split out from..
	(elfNN_ia64_modify_segment_map): ..here.
	(elf_backend_modify_program_headers): Define.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.209
diff -u -p -r1.209 elf-bfd.h
--- bfd/elf-bfd.h	20 Jun 2006 02:22:13 -0000	1.209
+++ bfd/elf-bfd.h	20 Jun 2006 03:47:47 -0000
@@ -836,6 +836,11 @@ struct elf_backend_data
   bfd_boolean (*elf_backend_modify_segment_map)
     (bfd *, struct bfd_link_info *);
 
+  /* This function is called to modify program headers just before
+     they are written.  */
+  bfd_boolean (*elf_backend_modify_program_headers)
+    (bfd *, struct bfd_link_info *);
+
   /* This function is called during section garbage collection to
      mark sections that define global symbols.  */
   bfd_boolean (*gc_mark_dynamic_ref)
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.95
diff -u -p -r1.95 elfxx-target.h
--- bfd/elfxx-target.h	30 May 2006 16:45:31 -0000	1.95
+++ bfd/elfxx-target.h	20 Jun 2006 03:48:02 -0000
@@ -402,6 +402,9 @@
 #ifndef elf_backend_modify_segment_map
 #define elf_backend_modify_segment_map	0
 #endif
+#ifndef elf_backend_modify_program_headers
+#define elf_backend_modify_program_headers	0
+#endif
 #ifndef elf_backend_ecoff_debug_swap
 #define elf_backend_ecoff_debug_swap	0
 #endif
@@ -603,6 +606,7 @@ static struct elf_backend_data elfNN_bed
   elf_backend_final_write_processing,
   elf_backend_additional_program_headers,
   elf_backend_modify_segment_map,
+  elf_backend_modify_program_headers,
   elf_backend_gc_mark_dynamic_ref,
   elf_backend_gc_mark_hook,
   elf_backend_gc_sweep_hook,
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.344
diff -u -p -r1.344 elf.c
--- bfd/elf.c	20 Jun 2006 02:22:13 -0000	1.344
+++ bfd/elf.c	20 Jun 2006 03:47:52 -0000
@@ -3733,8 +3733,6 @@ elf_modify_segment_map (bfd *abfd, struc
 	m->count = new_count;
     }
 
-  /* Yes, we call elf_backend_modify_segment_map at least two times
-     for the linker.  The final time the link_orders are available.  */
   bed = get_elf_backend_data (abfd);
   if (bed->elf_backend_modify_segment_map != NULL)
     {
@@ -4216,7 +4214,8 @@ assign_file_positions_for_load_sections 
   unsigned int alloc;
   unsigned int i;
 
-  if (!elf_modify_segment_map (abfd, link_info))
+  if (link_info == NULL
+      && !elf_modify_segment_map (abfd, link_info))
     return FALSE;
 
   alloc = 0;
@@ -4822,6 +4821,12 @@ assign_file_positions_except_relocs (bfd
       if (!assign_file_positions_for_non_load_sections (abfd, link_info))
 	return FALSE;
 
+      if (bed->elf_backend_modify_program_headers != NULL)
+	{
+	  if (!(*bed->elf_backend_modify_program_headers) (abfd, link_info))
+	    return FALSE;
+	}
+
       /* Write out the program headers.  */
       alloc = tdata->program_header_size / bed->s->sizeof_phdr;
       if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
Index: bfd/elf32-frv.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-frv.c,v
retrieving revision 1.47
diff -u -p -r1.47 elf32-frv.c
--- bfd/elf32-frv.c	20 Jun 2006 02:22:13 -0000	1.47
+++ bfd/elf32-frv.c	20 Jun 2006 03:47:58 -0000
@@ -5603,7 +5603,6 @@ elf32_frvfdpic_always_size_sections (bfd
   if (!info->relocatable)
     {
       struct elf_link_hash_entry *h;
-      asection *sec;
 
       /* Force a PT_GNU_STACK segment to be created.  */
       if (! elf_tdata (output_bfd)->stack_flags)
@@ -5630,13 +5629,6 @@ elf32_frvfdpic_always_size_sections (bfd
 	  h->type = STT_OBJECT;
 	  /* This one must NOT be hidden.  */
 	}
-
-      /* Create a stack section, and set its alignment.  */
-      sec = bfd_make_section (output_bfd, ".stack");
-
-      if (sec == NULL
-	  || ! bfd_set_section_alignment (output_bfd, sec, 3))
-	return FALSE;
     }
 
   return TRUE;
@@ -5718,51 +5710,45 @@ elf32_frvfdpic_relax_section (bfd *abfd 
 }
 
 static bfd_boolean
-elf32_frvfdpic_modify_segment_map (bfd *output_bfd,
-				   struct bfd_link_info *info)
+elf32_frvfdpic_modify_program_headers (bfd *output_bfd,
+				       struct bfd_link_info *info)
 {
+  struct elf_obj_tdata *tdata = elf_tdata (output_bfd);
   struct elf_segment_map *m;
+  Elf_Internal_Phdr *p;
 
   /* objcopy and strip preserve what's already there using
      elf32_frvfdpic_copy_private_bfd_data ().  */
   if (! info)
     return TRUE;
 
-  for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
+  for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
     if (m->p_type == PT_GNU_STACK)
       break;
 
   if (m)
     {
-      asection *sec = bfd_get_section_by_name (output_bfd, ".stack");
       struct elf_link_hash_entry *h;
 
-      if (sec)
+      /* Obtain the pointer to the __stacksize symbol.  */
+      h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
+				FALSE, FALSE, FALSE);
+      if (h)
 	{
-	  /* Obtain the pointer to the __stacksize symbol.  */
-	  h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
-				    FALSE, FALSE, FALSE);
 	  while (h->root.type == bfd_link_hash_indirect
 		 || h->root.type == bfd_link_hash_warning)
-	    h = (struct elf_link_hash_entry *)h->root.u.i.link;
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 	  BFD_ASSERT (h->root.type == bfd_link_hash_defined);
+	}
 
-	  /* Set the section size from the symbol value.  We
-	     intentionally ignore the symbol section.  */
-	  if (h->root.type == bfd_link_hash_defined)
-	    sec->size = h->root.u.def.value;
-	  else
-	    sec->size = DEFAULT_STACK_SIZE;
+      /* Set the header p_memsz from the symbol value.  We
+	 intentionally ignore the symbol section.  */
+      if (h && h->root.type == bfd_link_hash_defined)
+	p->p_memsz = h->root.u.def.value;
+      else
+	p->p_memsz = DEFAULT_STACK_SIZE;
 
-	  /* Add the stack section to the PT_GNU_STACK segment,
-	     such that its size and alignment requirements make it
-	     to the segment.  */
-	  if (m->count == 0)
-	    {
-	      m->sections[m->count] = sec;
-	      m->count++;
-	    }
-	}
+      p->p_align = 8;
     }
 
   return TRUE;
@@ -6973,9 +6959,9 @@ elf32_frv_grok_psinfo (bfd *abfd, Elf_In
 #undef elf_backend_always_size_sections
 #define elf_backend_always_size_sections \
 		elf32_frvfdpic_always_size_sections
-#undef elf_backend_modify_segment_map
-#define elf_backend_modify_segment_map \
-		elf32_frvfdpic_modify_segment_map
+#undef elf_backend_modify_program_headers
+#define elf_backend_modify_program_headers \
+		elf32_frvfdpic_modify_program_headers
 #undef bfd_elf32_bfd_copy_private_bfd_data
 #define bfd_elf32_bfd_copy_private_bfd_data \
 		elf32_frvfdpic_copy_private_bfd_data
Index: bfd/elf32-bfin.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-bfin.c,v
retrieving revision 1.14
diff -u -p -r1.14 elf32-bfin.c
--- bfd/elf32-bfin.c	20 Jun 2006 02:22:13 -0000	1.14
+++ bfd/elf32-bfin.c	20 Jun 2006 03:56:43 -0000
@@ -4156,7 +4156,6 @@ elf32_bfinfdpic_always_size_sections (bf
   if (!info->relocatable)
     {
       struct elf_link_hash_entry *h;
-      asection *sec;
 
       /* Force a PT_GNU_STACK segment to be created.  */
       if (! elf_tdata (output_bfd)->stack_flags)
@@ -4182,64 +4181,51 @@ elf32_bfinfdpic_always_size_sections (bf
 	  h->def_regular = 1;
 	  h->type = STT_OBJECT;
 	}
-
-      /* Create a stack section, and set its alignment.  */
-      sec = bfd_make_section (output_bfd, ".stack");
-
-      if (sec == NULL
-	  || ! bfd_set_section_alignment (output_bfd, sec, 3))
-	return FALSE;
     }
 
   return TRUE;
 }
 
 static bfd_boolean
-elf32_bfinfdpic_modify_segment_map (bfd *output_bfd,
-				   struct bfd_link_info *info)
+elf32_bfinfdpic_modify_program_headers (bfd *output_bfd,
+					struct bfd_link_info *info)
 {
+  struct elf_obj_tdata *tdata = elf_tdata (output_bfd);
   struct elf_segment_map *m;
+  Elf_Internal_Phdr *p;
 
   /* objcopy and strip preserve what's already there using
      elf32_bfinfdpic_copy_private_bfd_data ().  */
   if (! info)
     return TRUE;
 
-  for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
+  for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
     if (m->p_type == PT_GNU_STACK)
       break;
 
   if (m)
     {
-      asection *sec = bfd_get_section_by_name (output_bfd, ".stack");
       struct elf_link_hash_entry *h;
 
-      if (sec)
+      /* Obtain the pointer to the __stacksize symbol.  */
+      h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
+				FALSE, FALSE, FALSE);
+      if (h)
 	{
-	  /* Obtain the pointer to the __stacksize symbol.  */
-	  h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
-				    FALSE, FALSE, FALSE);
 	  while (h->root.type == bfd_link_hash_indirect
 		 || h->root.type == bfd_link_hash_warning)
-	    h = (struct elf_link_hash_entry *)h->root.u.i.link;
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 	  BFD_ASSERT (h->root.type == bfd_link_hash_defined);
+	}
 
-	  /* Set the section size from the symbol value.  We
-	     intentionally ignore the symbol section.  */
-	  if (h->root.type == bfd_link_hash_defined)
-	    sec->size = h->root.u.def.value;
-	  else
-	    sec->size = DEFAULT_STACK_SIZE;
+      /* Set the header p_memsz from the symbol value.  We
+	 intentionally ignore the symbol section.  */
+      if (h && h->root.type == bfd_link_hash_defined)
+	p->p_memsz = h->root.u.def.value;
+      else
+	p->p_memsz = DEFAULT_STACK_SIZE;
 
-	  /* Add the stack section to the PT_GNU_STACK segment,
-	     such that its size and alignment requirements make it
-	     to the segment.  */
-	  if (m->count == 0)
-	    {
-	      m->sections[m->count] = sec;
-	      m->count++;
-	    }
-	}
+      p->p_align = 8;
     }
 
   return TRUE;
@@ -5594,9 +5580,9 @@ error_return:
 #undef elf_backend_always_size_sections
 #define elf_backend_always_size_sections \
 		elf32_bfinfdpic_always_size_sections
-#undef elf_backend_modify_segment_map
-#define elf_backend_modify_segment_map \
-		elf32_bfinfdpic_modify_segment_map
+#undef elf_backend_modify_program_headers
+#define elf_backend_modify_program_headers \
+		elf32_bfinfdpic_modify_program_headers
 #undef bfd_elf32_bfd_copy_private_bfd_data
 #define bfd_elf32_bfd_copy_private_bfd_data \
 		elf32_bfinfdpic_copy_private_bfd_data
Index: bfd/elfxx-ia64.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-ia64.c,v
retrieving revision 1.186
diff -u -p -r1.186 elfxx-ia64.c
--- bfd/elfxx-ia64.c	20 Jun 2006 02:22:13 -0000	1.186
+++ bfd/elfxx-ia64.c	20 Jun 2006 03:48:02 -0000
@@ -1737,17 +1737,30 @@ elfNN_ia64_modify_segment_map (bfd *abfd
 	}
     }
 
-  /* Turn on PF_IA_64_NORECOV if needed.  This involves traversing all of
-     the input sections for each output section in the segment and testing
-     for SHF_IA_64_NORECOV on each.  */
-  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+  return TRUE;
+}
+
+/* Turn on PF_IA_64_NORECOV if needed.  This involves traversing all of
+   the input sections for each output section in the segment and testing
+   for SHF_IA_64_NORECOV on each.  */
+
+static bfd_boolean
+elfNN_ia64_modify_program_headers (bfd *abfd,
+				   struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  struct elf_obj_tdata *tdata = elf_tdata (abfd);
+  struct elf_segment_map *m;
+  Elf_Internal_Phdr *p;
+
+  for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
     if (m->p_type == PT_LOAD)
       {
 	int i;
 	for (i = m->count - 1; i >= 0; --i)
 	  {
 	    struct bfd_link_order *order = m->sections[i]->map_head.link_order;
-	    while (order)
+
+	    while (order != NULL)
 	      {
 		if (order->type == bfd_indirect_link_order)
 		  {
@@ -1755,7 +1768,7 @@ elfNN_ia64_modify_segment_map (bfd *abfd
 		    bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
 		    if (flags & SHF_IA_64_NORECOV)
 		      {
-			m->p_flags |= PF_IA_64_NORECOV;
+			p->p_flags |= PF_IA_64_NORECOV;
 			goto found;
 		      }
 		  }
@@ -5728,6 +5741,8 @@ elfNN_hpux_backend_symbol_processing (bf
 	elfNN_ia64_additional_program_headers
 #define elf_backend_modify_segment_map \
 	elfNN_ia64_modify_segment_map
+#define elf_backend_modify_program_headers \
+	elfNN_ia64_modify_program_headers
 #define elf_info_to_howto \
 	elfNN_ia64_info_to_howto
 

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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