Marking ia64 psABI conformance (Re: PATCH: Support the .note.GNU-property section)

H. J. Lu hjl@lucon.org
Thu Jun 5 22:11:00 GMT 2003


On Thu, Jun 05, 2003 at 02:06:17PM -0700, Richard Henderson wrote:
> On Thu, Jun 05, 2003 at 10:50:52AM -0700, H. J. Lu wrote:
> > But it isn't safe without knowing if a .o file is ABI conforming or not.
> 
> Correct.
> 
> > With my proposal, the .o files generated by ABI conforming
> > compiler will have the NT_GNU_PROPETRTY_IA_64_PRESERVE_GP set and
> > the linker can use it to detect the possible run-time failure and
> > issue a warning.
> 
> All such .o files?  Meaning that you'll get Intel and HP and (...)
> to change their object file generation?

Intel is ok with this. If HP wants to link against gcc generated
.o files safely with full optimization, the answer is yes.

> 
> Anyway, for something this platform specific, you might as well use
> an e_flags bit.

It is no binary compatible. Please keep in mind this only affects
.o files, executables and DSOs are ok. It doesn't make senses to
ask everyone to upgrade their whole IA64 system just to support
the ia64 psABI conforming .o files generated by the new gcc.

Here is the updated one to support --execstack/--noexecstack in gas.

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

2003-06-04  H.J. Lu <hongjiu.lu@intel.com>

	* elf-bfd.h (elf_backend_data): Add elf_backend_copy_common_property,
	elf_backend_copy_target_property,
	elf_backend_merge_property,
	elf_backend_merge_target_property,
	elf_backend_print_property and
	elf_backend_print_target_property.
	(elf_obj_tdata): Remove stack_flags. Add property, gflags
	and psflags.
	(_bfd_elf_copy_property): Declared.
	(_bfd_elf_copy_target_property): Likewise.
	(_bfd_elf_merge_property): Likewise.
	(_bfd_elf_merge_target_property): Likewise.
	(_bfd_elf_print_property): Likewise.

	* elf.c (_bfd_elf_make_section_from_shdr): Handle the
	GNU_PROPERTY_NOTE_SECTION section.
	(_bfd_elf_copy_private_bfd_data): Also copy property flags.
	(_bfd_elf_merge_private_bfd_data): New.
	(_bfd_elf_print_private_bfd_data): Also print property flags.
	(map_sections_to_segments): Check the property and gflags
	field instead of the stack_flags field.
	(_bfd_elf_merge_property): New function.
	(_bfd_elf_merge_target_property): Likewise.
	(_bfd_elf_copy_property): Likewise.
	(_bfd_elf_copy_target_property): Likewise.
	(_bfd_elf_print_property): Likewise.

	* elflink.h (bfd_elfNN_size_dynamic_sections): Use the
	property and gflags fields instead of the stack_flags field.
	Keep only one property note section for relocatabe output.

	* elfxx-ia64.c (elfNN_ia64_merge_private_bfd_data): Call
	_bfd_elf_merge_property.
	* elfxx-target.h (bfd_elfNN_bfd_merge_private_bfd_data): Defined
	to _bfd_elf_merge_private_bfd_data.
	(elf_backend_copy_property): New.
	(elf_backend_copy_target_property): Likewise.
	(elf_backend_merge_property): Likewise.
	(elf_backend_merge_target_property): Likewise.
	(elf_backend_print_property): Likewise.
	(elf_backend_print_target_property): Likewise.
	(elf_backend_data): Add elf_backend_copy_property,
	elf_backend_copy_target_property, elf_backend_merge_property,
	elf_backend_merge_target_property, elf_backend_print_property
	and elf_backend_print_target_property.

gas/

2003-06-05  H.J. Lu <hongjiu.lu@intel.com>

	* as.c (main): Call obj_elf_check_property_note () to handle
	--execstack/--noexecstack.

	* as.h (obj_elf_check_property_note): New. Declared.

	* config/obj-elf.c (obj_elf_check_property_note): New. Defined.

include/elf/

2003-06-04  H.J. Lu <hongjiu.lu@intel.com>

	* common.h (GNU_PROPERTY_NOTE_SECTION): New.
	(NT_GNU_PROPERTY_TYPE): Likewise.
	(NT_GNU_PROPERTY_NAME): Likewise.
	(NT_GNU_PROPERTY_EXEC_STACK): Likewise.
	(NT_GNU_PROPERTY_RESERVED): Likewise.
	(NT_GNU_PROPERTY_DEFAULT): Likewise.

ld/

2003-06-04  H.J. Lu <hongjiu.lu@intel.com>

	* scripttempl/elf.sc (STACKNOTE): Removed.
	(PROPERTYNOTE): New.

--- binutils/bfd/elf-bfd.h.prop	2003-06-04 07:30:53.000000000 -0700
+++ binutils/bfd/elf-bfd.h	2003-06-05 13:48:27.000000000 -0700
@@ -848,6 +848,34 @@ struct elf_backend_data
   enum elf_reloc_type_class (*elf_backend_reloc_type_class)
     PARAMS ((const Elf_Internal_Rela *));
 
+  /* This function copies property flags from one object module to
+     another.  */ 
+  bfd_boolean (*elf_backend_copy_property)
+    PARAMS ((bfd *, bfd *));
+
+  /* This function copies target specific property flags from one
+     object module to another.  */ 
+  bfd_boolean (*elf_backend_copy_target_property)
+    PARAMS ((bfd *, bfd *));
+
+  /* This function merges property flags from one object module to
+     another.  */ 
+  bfd_boolean (*elf_backend_merge_property)
+    PARAMS ((bfd *, bfd *));
+
+  /* This function merges target specific property flags from one
+     object module to another.  */ 
+  bfd_boolean (*elf_backend_merge_target_property)
+    PARAMS ((bfd *, bfd *));
+
+  /* This function prints out property flags.  */
+  bfd_boolean (*elf_backend_print_property)
+    PARAMS ((bfd *, PTR));
+
+  /* This function prints out target specific property flags.  */
+  bfd_boolean (*elf_backend_print_target_property)
+    PARAMS ((bfd *, PTR));
+
   /* This function, if defined, removes information about discarded functions
      from other sections which mention them.  */
   bfd_boolean (*elf_backend_discard_info)
@@ -1254,8 +1282,14 @@ struct elf_obj_tdata
   /* Number of symbol version references we are about to emit.  */
   unsigned int cverrefs;
 
-  /* Segment flags for the PT_GNU_STACK segment.  */
-  unsigned int stack_flags;  
+  /* There is a .note.GNU-property section.  */
+  bfd_boolean property;
+
+  /* Generic flags in .note.GNU-property.  */
+  unsigned long gflags;  
+
+  /* Processor specific flags in .note.GNU-property.  */
+  unsigned long psflags;  
 
   /* Symbol version definitions in external objects.  */
   Elf_Internal_Verdef *verdef;
@@ -1337,8 +1371,21 @@ extern Elf_Internal_Sym *bfd_elf_get_elf
 extern const char *bfd_elf_local_sym_name
   PARAMS ((bfd *, Elf_Internal_Sym *));
 
+extern bfd_boolean _bfd_elf_copy_property
+  PARAMS ((bfd *, bfd *));
+extern bfd_boolean _bfd_elf_copy_target_property
+  PARAMS ((bfd *, bfd *));
+extern bfd_boolean _bfd_elf_merge_property
+  PARAMS ((bfd *, bfd *));
+extern bfd_boolean _bfd_elf_merge_target_property
+  PARAMS ((bfd *, bfd *));
+extern bfd_boolean _bfd_elf_print_property
+  PARAMS ((bfd *, PTR));
+
 extern bfd_boolean _bfd_elf_copy_private_bfd_data
   PARAMS ((bfd *, bfd *));
+extern bfd_boolean _bfd_elf_merge_private_bfd_data
+  PARAMS ((bfd *, bfd *));
 extern bfd_boolean _bfd_elf_print_private_bfd_data
   PARAMS ((bfd *, PTR));
 extern void bfd_elf_print_symbol
--- binutils/bfd/elf.c.prop	2003-06-04 07:30:53.000000000 -0700
+++ binutils/bfd/elf.c	2003-06-05 14:27:51.000000000 -0700
@@ -817,6 +817,75 @@ _bfd_elf_make_section_from_shdr (abfd, h
   if (! bfd_set_section_flags (abfd, newsect, flags))
     return FALSE;
 
+  if (strcmp (name, GNU_PROPERTY_NOTE_SECTION) == 0)
+    {
+      bfd_size_type buffer_size;
+      char *buffer;
+      unsigned long namesz;
+      unsigned long descsz;
+      unsigned long type;
+
+      buffer_size = newsect->_raw_size;
+      if (buffer_size == 0)
+	{
+	  (*_bfd_error_handler)
+	    (_("%s: empty GNU property note section `%s'"),
+	     bfd_archive_filename (abfd), name);
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+
+      buffer = bfd_malloc (buffer_size);
+      if (buffer == NULL)
+	return FALSE;
+
+      if (! bfd_get_section_contents (abfd, newsect, buffer,
+				      (file_ptr) 0, buffer_size))
+	{
+	  (*_bfd_error_handler)
+	    (_("%s: failed to read GNU property note section `%s'"),
+	     bfd_archive_filename (abfd), name);
+	  return FALSE;
+	}
+
+      namesz = bfd_get_32 (abfd, buffer);
+      descsz = bfd_get_32 (abfd, buffer + offsetof (Elf_External_Note,
+						    descsz));
+      if (descsz != 8)
+	{
+	  (*_bfd_error_handler)
+	    (_("%s: invalid size of flags, %d != 8, in GNU property note section `%s'"),
+	     bfd_archive_filename (abfd), descsz, name);
+	  free (buffer);
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+
+      type = bfd_get_32 (abfd, buffer + offsetof (Elf_External_Note,
+						  type));
+      if (type != NT_GNU_PROPERTY_TYPE)
+	{
+	  (*_bfd_error_handler)
+	    (_("%s: invalid type, %d != %d, in GNU property note section `%s'"),
+	     bfd_archive_filename (abfd), type, NT_GNU_PROPERTY_TYPE,
+	     name);
+	  free (buffer);
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+
+      elf_tdata (abfd)->gflags
+       	= bfd_get_32 (abfd, buffer + ((namesz + 3) / 4) * 4
+			    + offsetof (Elf_External_Note, name));
+      elf_tdata (abfd)->psflags
+       	= bfd_get_32 (abfd, buffer + ((namesz + 3) / 4) * 4 + 4
+			    + offsetof (Elf_External_Note, name));
+
+      elf_tdata (abfd)->property = TRUE;
+
+      free (buffer);
+    }
+
   if ((flags & SEC_ALLOC) != 0)
     {
       Elf_Internal_Phdr *phdr;
@@ -1021,6 +1090,8 @@ _bfd_elf_copy_private_bfd_data (ibfd, ob
      bfd *ibfd;
      bfd *obfd;
 {
+  struct elf_backend_data *bed;
+
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return TRUE;
@@ -1032,7 +1103,25 @@ _bfd_elf_copy_private_bfd_data (ibfd, ob
   elf_gp (obfd) = elf_gp (ibfd);
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = TRUE;
-  return TRUE;
+  bed = get_elf_backend_data (obfd);
+  return (*bed->elf_backend_copy_property) (ibfd, obfd);
+}
+
+/* Merge the program header and other data from one object module to
+   another.  */
+
+bfd_boolean
+_bfd_elf_merge_private_bfd_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  struct elf_backend_data *bed;
+
+  if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return TRUE;
+
+  bed = get_elf_backend_data (obfd);
+  return (*bed->elf_backend_merge_property) (ibfd, obfd);
 }
 
 /* Print out the program headers.  */
@@ -1046,6 +1135,7 @@ _bfd_elf_print_private_bfd_data (abfd, f
   Elf_Internal_Phdr *p;
   asection *s;
   bfd_byte *dynbuf = NULL;
+  struct elf_backend_data *bed;
 
   p = elf_tdata (abfd)->phdr;
   if (p != NULL)
@@ -1267,7 +1357,8 @@ _bfd_elf_print_private_bfd_data (abfd, f
 	}
     }
 
-  return TRUE;
+  bed = get_elf_backend_data (abfd);
+  return (*bed->elf_backend_print_property) (abfd, farg);
 
  error_return:
   if (dynbuf != NULL)
@@ -3517,7 +3608,7 @@ map_sections_to_segments (abfd)
       pm = &m->next;
     }
 
-  if (elf_tdata (abfd)->stack_flags)
+  if (elf_tdata (abfd)->property)
     {
       amt = sizeof (struct elf_segment_map);
       m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
@@ -3525,7 +3616,10 @@ map_sections_to_segments (abfd)
 	goto error_return;
       m->next = NULL;
       m->p_type = PT_GNU_STACK;
-      m->p_flags = elf_tdata (abfd)->stack_flags;
+      if (elf_tdata (abfd)->gflags | NT_GNU_PROPERTY_EXEC_STACK)
+        m->p_flags = PF_R | PF_W | PF_X;
+      else
+        m->p_flags = PF_R | PF_W;
       m->p_flags_valid = 1;
 
       *pm = m;
@@ -4118,7 +4212,7 @@ get_program_header_size (abfd)
       ++segs;
     }
 
-  if (elf_tdata (abfd)->stack_flags)
+  if (elf_tdata (abfd)->property)
     {
       /* We need a PT_GNU_STACK segment.  */
       ++segs;
@@ -7614,3 +7708,156 @@ bfd_elf_bfd_from_remote_memory (templ, e
   return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
     (templ, ehdr_vma, loadbasep, target_read_memory);
 }
+
+/* Merge property flags from one object module to another.  */
+
+bfd_boolean
+_bfd_elf_merge_property (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  unsigned long in_gflags, out_gflags;
+  bfd_boolean in_property;
+  struct elf_backend_data *bed;
+
+   /* If the input format is not ELF, assume there is no property
+      note section.  */
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+    in_property = FALSE;
+  else
+    in_property = elf_tdata (ibfd)->property;
+
+  /* If there is no property note section, use the default bits. */
+  if (in_property)
+    in_gflags = elf_tdata (ibfd)->gflags;
+  else
+    in_gflags = NT_GNU_PROPERTY_DEFAULT;
+
+  if (elf_tdata (obfd)->property)
+    out_gflags = elf_tdata (obfd)->gflags;
+  else
+    out_gflags = NT_GNU_PROPERTY_DEFAULT;
+
+  if ((in_gflags & NT_GNU_PROPERTY_RESERVED)
+      || (out_gflags & NT_GNU_PROPERTY_RESERVED))
+    {
+      (*_bfd_error_handler)
+	(_("%s: reserved common property bits in gflags are set: 0x%x"),
+	 bfd_archive_filename ((in_gflags & NT_GNU_PROPERTY_RESERVED)
+			       ? ibfd : obfd),
+	 (in_gflags & NT_GNU_PROPERTY_RESERVED)
+	 ? in_gflags : out_gflags);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  elf_tdata (obfd)->property |= in_property;
+  elf_tdata (obfd)->gflags = out_gflags | in_gflags;
+
+  bed = get_elf_backend_data (obfd);
+  return (*bed->elf_backend_merge_target_property) (ibfd, obfd);
+}
+
+/* Merge target property flags from one object module to another.  */
+
+bfd_boolean
+_bfd_elf_merge_target_property (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  if (elf_tdata (ibfd)->psflags || elf_tdata (obfd)->psflags)
+    {
+      (*_bfd_error_handler)
+	(_("%s: processor specific property bits in psflags are set: 0x%x"),
+	 bfd_archive_filename (elf_tdata (ibfd)->psflags
+			       ? ibfd : obfd),
+	 elf_tdata (ibfd)->psflags
+	 ? elf_tdata (ibfd)->psflags : elf_tdata (obfd)->psflags);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Copy property flags from one object module to another.  */
+
+bfd_boolean
+_bfd_elf_copy_property (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  unsigned long in_gflags;
+  bfd_boolean in_property;
+  struct elf_backend_data *bed;
+
+   /* If the input format is not ELF, assume there is no property
+      note section.  */
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+    in_property = FALSE;
+  else
+    in_property = elf_tdata (ibfd)->property;
+
+  /* If there is no property note section, use the default bits. */
+  if (in_property)
+    in_gflags = elf_tdata (ibfd)->gflags;
+  else
+    in_gflags = NT_GNU_PROPERTY_DEFAULT;
+
+  if (in_gflags & NT_GNU_PROPERTY_RESERVED)
+    {
+      (*_bfd_error_handler)
+	(_("%s: reserved common property bits in gflags are set: 0x%x"),
+	 bfd_archive_filename (ibfd), in_gflags);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  elf_tdata (obfd)->property = in_property;
+  elf_tdata (obfd)->gflags = in_gflags;
+
+  bed = get_elf_backend_data (obfd);
+  return (*bed->elf_backend_copy_target_property) (ibfd, obfd);
+}
+
+/* Copy target property flags from one object module to another.  */
+
+bfd_boolean
+_bfd_elf_copy_target_property (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  if (elf_tdata (ibfd)->psflags)
+    {
+      (*_bfd_error_handler)
+	(_("%s: processor specific property bits in psflags are set: 0x%x"),
+	 bfd_archive_filename (ibfd), elf_tdata (ibfd)->psflags);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  elf_tdata (obfd)->psflags = elf_tdata (ibfd)->psflags;
+  return TRUE;
+}
+
+/* Print out property flags.  */
+
+bfd_boolean
+_bfd_elf_print_property (abfd, farg)
+     bfd *abfd;
+     PTR farg;
+{
+  if (elf_tdata (abfd)->property)
+    {
+      FILE *f = (FILE *) farg;
+      struct elf_backend_data *bed;
+
+      fprintf (f, _("\nGNU Property:\n"));
+      if (elf_tdata (abfd)->gflags & NT_GNU_PROPERTY_EXEC_STACK)
+	fprintf (f, _("\tNT_GNU_PROPERTY_EXEC_STACK\n"));
+      bed = get_elf_backend_data (abfd);
+      return (*bed->elf_backend_print_target_property) (abfd, farg);
+    }
+  else
+    return TRUE;
+}
--- binutils/bfd/elflink.h.prop	2003-06-04 07:30:53.000000000 -0700
+++ binutils/bfd/elflink.h	2003-06-05 12:43:47.000000000 -0700
@@ -1938,15 +1938,21 @@ NAME(bfd_elf,size_dynamic_sections) (out
     return TRUE;
 
   if (info->execstack)
-    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
+    {
+      elf_tdata (output_bfd)->property = TRUE;
+      elf_tdata (output_bfd)->gflags |= NT_GNU_PROPERTY_EXEC_STACK;
+    }
   else if (info->noexecstack)
-    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
-  else
+    {
+      elf_tdata (output_bfd)->property = TRUE;
+      elf_tdata (output_bfd)->gflags &= ~NT_GNU_PROPERTY_EXEC_STACK;
+    }
+  else if (info->relocateable)
     {
       bfd *inputobj;
-      asection *notesec = NULL;
-      int exec = 0;
+      asection *foundone = NULL;
 
+      /* We keep one property note section and get rid of the rest.  */
       for (inputobj = info->input_bfds;
 	   inputobj;
 	   inputobj = inputobj->link_next)
@@ -1955,22 +1961,57 @@ NAME(bfd_elf,size_dynamic_sections) (out
 
 	  if (inputobj->flags & DYNAMIC)
 	    continue;
-	  s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
+	  s = bfd_get_section_by_name (inputobj,
+				       GNU_PROPERTY_NOTE_SECTION);
 	  if (s)
 	    {
-	      if (s->flags & SEC_CODE)
-		exec = PF_X;
-	      notesec = s;
+	      if (foundone == NULL)
+		{
+		  unsigned long namesz;
+		  unsigned long descsz;
+		  bfd_byte *contents;
+		  
+		  if (elf_section_data (s)->this_hdr.contents != NULL)
+		    contents = elf_section_data (s)->this_hdr.contents;
+		  else
+		    {
+		      contents = (bfd_byte *) bfd_malloc (s->_raw_size);
+		      if (contents == NULL)
+			return FALSE;
+
+		      if (! bfd_get_section_contents (inputobj, s,
+						      contents,
+						      (file_ptr) 0,
+						      s->_raw_size))
+			return FALSE;
+
+		      /* Cache the section contents for
+		         elf_link_input_bfd.  */
+		      elf_section_data (s)->this_hdr.contents = contents;
+		    }
+		  
+		  /* Now we update the note section.  */
+		  namesz = bfd_get_32 (inputobj, contents);
+		  descsz = bfd_get_32 (inputobj,
+				       contents
+				       + offsetof (Elf_External_Note,
+						   descsz));
+		  bfd_put_32 (inputobj,
+			      elf_tdata (output_bfd)->gflags,
+			      contents + ((namesz + 3) / 4) * 4
+			      + offsetof (Elf_External_Note, name));
+		  bfd_put_32 (inputobj,
+			      elf_tdata (output_bfd)->psflags,
+			      contents + ((namesz + 3) / 4) * 4 + 4
+			      + offsetof (Elf_External_Note, name));
+		  foundone = s;
+		}
+	      else
+		{
+		  s->_cooked_size = 0;
+		  s->_raw_size = 0;
+		}
 	    }
-	  else
-	    exec = PF_X;
-	}
-      if (notesec)
-	{
-	  elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
-	  if (exec && info->relocateable
-	      && notesec->output_section != bfd_abs_section_ptr)
-	    notesec->output_section->flags |= SEC_CODE;
 	}
     }
 
--- binutils/bfd/elfxx-ia64.c.prop	2003-06-02 07:27:26.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c	2003-06-05 12:43:47.000000000 -0700
@@ -4741,13 +4741,17 @@ elfNN_ia64_merge_private_bfd_data (ibfd,
 {
   flagword out_flags;
   flagword in_flags;
-  bfd_boolean ok = TRUE;
+  bfd_boolean ok;
 
   /* Don't even pretend to support mixed-format linking.  */
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return FALSE;
 
+  ok = _bfd_elf_merge_property (ibfd, obfd);
+  if (! ok)
+    return ok;
+
   in_flags  = elf_elfheader (ibfd)->e_flags;
   out_flags = elf_elfheader (obfd)->e_flags;
 
--- binutils/bfd/elfxx-target.h.prop	2003-05-21 14:36:02.000000000 -0700
+++ binutils/bfd/elfxx-target.h	2003-06-05 12:43:47.000000000 -0700
@@ -163,7 +163,7 @@
 #endif
 #ifndef bfd_elfNN_bfd_merge_private_bfd_data
 #define bfd_elfNN_bfd_merge_private_bfd_data \
-  ((bfd_boolean (*) PARAMS ((bfd *, bfd *))) bfd_true)
+  _bfd_elf_merge_private_bfd_data
 #endif
 #ifndef bfd_elfNN_bfd_set_private_flags
 #define bfd_elfNN_bfd_set_private_flags \
@@ -383,6 +383,25 @@
 #ifndef elf_backend_reloc_type_class
 #define elf_backend_reloc_type_class		_bfd_elf_reloc_type_class
 #endif
+#ifndef elf_backend_copy_property
+#define elf_backend_copy_property		_bfd_elf_copy_property
+#endif
+#ifndef elf_backend_copy_target_property
+#define elf_backend_copy_target_property	_bfd_elf_copy_target_property
+#endif
+#ifndef elf_backend_merge_property
+#define elf_backend_merge_property		_bfd_elf_merge_property
+#endif
+#ifndef elf_backend_merge_target_property
+#define elf_backend_merge_target_property	_bfd_elf_merge_target_property
+#endif
+#ifndef elf_backend_print_property
+#define elf_backend_print_property		_bfd_elf_print_property
+#endif
+#ifndef elf_backend_print_target_property
+#define elf_backend_print_target_property \
+  ((bfd_boolean (*) PARAMS ((bfd *, PTR))) bfd_true)
+#endif
 #ifndef elf_backend_discard_info
 #define elf_backend_discard_info		NULL
 #endif
@@ -487,6 +506,12 @@ static const struct elf_backend_data elf
   elf_backend_sprintf_vma,
   elf_backend_fprintf_vma,
   elf_backend_reloc_type_class,
+  elf_backend_copy_property,
+  elf_backend_copy_target_property,
+  elf_backend_merge_property,
+  elf_backend_merge_target_property,
+  elf_backend_print_property,
+  elf_backend_print_target_property,
   elf_backend_discard_info,
   elf_backend_ignore_discarded_relocs,
   elf_backend_write_section,
--- binutils/gas/as.c.prop	2003-06-05 12:31:53.000000000 -0700
+++ binutils/gas/as.c	2003-06-05 15:03:03.000000000 -0700
@@ -932,16 +932,7 @@ main (argc, argv)
 #endif
 
 #if defined BFD_ASSEMBLER && (defined OBJ_ELF || defined OBJ_MAYBE_ELF)
-  if ((flag_execstack || flag_noexecstack)
-      && OUTPUT_FLAVOR == bfd_target_elf_flavour)
-    {
-      segT gnustack;
-
-      gnustack = subseg_new (".note.GNU-stack", 0);
-      bfd_set_section_flags (stdoutput, gnustack,
-			     SEC_READONLY | (flag_execstack ? SEC_CODE : 0));
-                                                                             
-    }
+  obj_elf_check_property_note ();
 #endif
 
   /* If we've been collecting dwarf2 .debug_line info, either for
--- binutils/gas/as.h.prop	2003-06-05 12:31:53.000000000 -0700
+++ binutils/gas/as.h	2003-06-05 14:53:56.000000000 -0700
@@ -634,6 +634,10 @@ int generic_force_reloc PARAMS ((struct 
 #endif
 #endif
 
+#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
+extern void obj_elf_check_property_note PARAMS ((void));
+#endif
+
 #include "write.h"
 #include "frags.h"
 #include "hash.h"
--- binutils/gas/config/obj-elf.c.prop	2003-06-05 12:43:46.000000000 -0700
+++ binutils/gas/config/obj-elf.c	2003-06-05 14:58:00.000000000 -0700
@@ -2333,6 +2333,47 @@ elf_init_stab_section (seg)
     obj_elf_init_stab_section (seg);
 }
 
+void
+obj_elf_check_property_note ()
+{
+  segT s;
+
+  if ((!flag_execstack && !flag_noexecstack) || !IS_ELF)
+    return;
+
+  s = bfd_get_section_by_name (stdoutput, GNU_PROPERTY_NOTE_SECTION);
+  if (s)
+    {
+      /* FIXME: There is a GNU property section. How to update it?  */
+    }
+  else
+    {
+      char *p;
+      unsigned long gflags;
+      Elf_External_Note note ATTRIBUTE_UNUSED;
+
+      s = subseg_new (GNU_PROPERTY_NOTE_SECTION, 0);
+
+      p = frag_more (sizeof (note.namesz));
+      md_number_to_chars (p, (valueT) sizeof (NT_GNU_PROPERTY_NAME),
+			  sizeof (note.namesz));
+      p = frag_more (sizeof (note.descsz));
+      md_number_to_chars (p, (valueT) 8, sizeof (note.descsz));
+      p = frag_more (sizeof (note.type));
+      md_number_to_chars (p, (valueT) NT_GNU_PROPERTY_TYPE, 
+			  sizeof (note.type));
+      p = frag_more (sizeof (NT_GNU_PROPERTY_NAME));
+      strcpy (p, NT_GNU_PROPERTY_NAME);
+      frag_align (2, 0, 0);
+      p = frag_more (4);
+      gflags = flag_execstack ? NT_GNU_PROPERTY_EXEC_STACK : 0;
+      md_number_to_chars (p, (valueT) gflags, 4);
+      p = frag_more (4);
+      md_number_to_chars (p, (valueT) 0, 4);
+      frag_align (2, 0, 0);
+    }
+}
+
 const struct format_ops elf_format_ops =
 {
   bfd_target_elf_flavour,
--- binutils/include/elf/common.h.prop	2003-06-04 07:31:07.000000000 -0700
+++ binutils/include/elf/common.h	2003-06-05 14:27:24.000000000 -0700
@@ -406,6 +406,25 @@
 
 #define NT_FREEBSD_ABI_TAG	1
 
+/* The name of the note section used to store properties.  */
+#define GNU_PROPERTY_NOTE_SECTION ".note.GNU-property"
+
+/* Values for .note.GNU-property notes. Note name is "GNU property".  */
+
+#define NT_GNU_PROPERTY_TYPE		1
+#define NT_GNU_PROPERTY_NAME		"GNU property"
+
+/* Bits in the first generic flag.  */
+
+/* Need executable stack.  */
+#define NT_GNU_PROPERTY_EXEC_STACK	(0x1 << 0)
+
+/* Reserved bits.  */
+#define NT_GNU_PROPERTY_RESERVED	~(NT_GNU_PROPERTY_EXEC_STACK)
+
+/* Default bits if the GNU_PROPERTY_NOTE_SECTION section is missing.  */
+#define NT_GNU_PROPERTY_DEFAULT		NT_GNU_PROPERTY_EXEC_STACK
+
 /* These three macros disassemble and assemble a symbol table st_info field,
    which contains the symbol binding and symbol type.  The STB_ and STT_
    defines identify the binding and type.  */
--- binutils/ld/scripttempl/elf.sc.prop	2003-06-04 07:31:11.000000000 -0700
+++ binutils/ld/scripttempl/elf.sc	2003-06-05 12:43:47.000000000 -0700
@@ -84,7 +84,7 @@ INTERP=".interp       ${RELOCATING-0} : 
 PLT=".plt          ${RELOCATING-0} : { *(.plt) }"
 DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
 RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
-STACKNOTE="/DISCARD/ : { *(.note.GNU-stack) }"
+PROPERTYNOTE="/DISCARD/ : { *(.note.GNU-property) }"
 if test -z "${NO_SMALL_DATA}"; then
   SBSS=".sbss         ${RELOCATING-0} :
   {
@@ -397,6 +397,6 @@ cat <<EOF
   ${STACK_ADDR+${STACK}}
   ${OTHER_SECTIONS}
   ${RELOCATING+${OTHER_END_SYMBOLS}}
-  ${RELOCATING+${STACKNOTE}}
+  ${RELOCATING+${PROPERTYNOTE}}
 }
 EOF


More information about the Binutils mailing list