Blame SOURCES/binutils-section-type.patch

a8cd6b
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
a8cd6b
index 3b2a4f49a9b..78a0a1dea42 100644
a8cd6b
--- a/bfd/bfd-in2.h
a8cd6b
+++ b/bfd/bfd-in2.h
a8cd6b
@@ -1170,6 +1170,9 @@ typedef struct bfd_section
a8cd6b
     This is used when support for non-contiguous memory regions is enabled.  */
a8cd6b
  struct bfd_section *already_assigned;
a8cd6b
 
a8cd6b
+  /* Explicitly specified section type, if non-zero. */
a8cd6b
+  unsigned int type;
a8cd6b
+
a8cd6b
 } asection;
a8cd6b
 
a8cd6b
 /* Relax table contains information about instructions which can
a8cd6b
@@ -1352,8 +1355,8 @@ discarded_section (const asection *sec)
a8cd6b
   /* symbol,                    symbol_ptr_ptr,                     */ \
a8cd6b
      (struct bfd_symbol *) SYM, &SEC.symbol,                           \
a8cd6b
                                                                        \
a8cd6b
-  /* map_head, map_tail, already_assigned                           */ \
a8cd6b
-     { NULL }, { NULL }, NULL                                          \
a8cd6b
+  /* map_head, map_tail, already_assigned, type                     */ \
a8cd6b
+     { NULL }, { NULL }, NULL, 0                                       \
a8cd6b
                                                                        \
a8cd6b
     }
a8cd6b
 
a8cd6b
diff --git a/bfd/elf.c b/bfd/elf.c
a8cd6b
index a67415e76e1..82b53be99f9 100644
a8cd6b
--- a/bfd/elf.c
a8cd6b
+++ b/bfd/elf.c
a8cd6b
@@ -3280,7 +3280,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
a8cd6b
 
a8cd6b
   /* If the section type is unspecified, we set it based on
a8cd6b
      asect->flags.  */
a8cd6b
-  if ((asect->flags & SEC_GROUP) != 0)
a8cd6b
+  if (asect->type != 0)
a8cd6b
+    sh_type = asect->type;
a8cd6b
+  else if ((asect->flags & SEC_GROUP) != 0)
a8cd6b
     sh_type = SHT_GROUP;
a8cd6b
   else
a8cd6b
     sh_type = bfd_elf_get_default_section_type (asect->flags);
a8cd6b
diff --git a/bfd/section.c b/bfd/section.c
a8cd6b
index 899438a1c5e..2de7dbf661a 100644
a8cd6b
--- a/bfd/section.c
a8cd6b
+++ b/bfd/section.c
a8cd6b
@@ -737,8 +737,8 @@ CODE_FRAGMENT
a8cd6b
 .  {* symbol,                    symbol_ptr_ptr,                     *}	\
a8cd6b
 .     (struct bfd_symbol *) SYM, &SEC.symbol,				\
a8cd6b
 .									\
a8cd6b
-.  {* map_head, map_tail, already_assigned                           *}	\
a8cd6b
-.     { NULL }, { NULL }, NULL						\
a8cd6b
+.  {* map_head, map_tail, already_assigned, type                     *}	\
a8cd6b
+.     { NULL }, { NULL }, NULL, 0						\
a8cd6b
 .									\
a8cd6b
 .    }
a8cd6b
 .
a8cd6b
diff --git a/ld/NEWS b/ld/NEWS
a8cd6b
index dbb402d1f8a..a498abaf0f9 100644
a8cd6b
--- a/ld/NEWS
a8cd6b
+++ b/ld/NEWS
a8cd6b
@@ -1,5 +1,8 @@
a8cd6b
 -*- text -*-
a8cd6b
 
a8cd6b
+* TYPE=<type> is now supported in an output section description to set the
a8cd6b
+  section type value.
a8cd6b
+
a8cd6b
 Changes in 2.38:
a8cd6b
 
a8cd6b
 * Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF
a8cd6b
diff --git a/ld/ld.texi b/ld/ld.texi
a8cd6b
index fc75e9b3625..d57e9221410 100644
a8cd6b
--- a/ld/ld.texi
a8cd6b
+++ b/ld/ld.texi
a8cd6b
@@ -5483,13 +5483,23 @@ loaded into memory when the program is run.
a8cd6b
 @item READONLY
a8cd6b
 The section should be marked as read-only.
a8cd6b
 @item DSECT
a8cd6b
-@itemx COPY
a8cd6b
-@itemx INFO
a8cd6b
-@itemx OVERLAY
a8cd6b
+@item COPY
a8cd6b
+@item INFO
a8cd6b
+@item OVERLAY
a8cd6b
 These type names are supported for backward compatibility, and are
a8cd6b
 rarely used.  They all have the same effect: the section should be
a8cd6b
 marked as not allocatable, so that no memory is allocated for the
a8cd6b
 section when the program is run.
a8cd6b
+@item TYPE = @var{type}
a8cd6b
+Set the section type to the integer @var{type}. When generating an ELF
a8cd6b
+output file, type names @code{SHT_PROGBITS}, @code{SHT_STRTAB},
a8cd6b
+@code{SHT_NOTE}, @code {SHT_NOBITS}, @code{SHT_INIT_ARRAY},
a8cd6b
+@code{SHT_FINI_ARRAY}, and @code{SHT_PREINIT_ARRAY} are also allowed
a8cd6b
+for @var{type}.  It is the user's responsibility to ensure that any
a8cd6b
+special requirements of the section type are met.
a8cd6b
+@item READONLY ( TYPE = @var{type} )
a8cd6b
+This form of the syntax combines the @var{READONLY} type with the
a8cd6b
+type specified by @var{type}.
a8cd6b
 @end table
a8cd6b
 
a8cd6b
 @kindex NOLOAD
a8cd6b
diff --git a/ld/ldgram.y b/ld/ldgram.y
a8cd6b
index 11c2f219c05..3a904e39482 100644
a8cd6b
--- a/ld/ldgram.y
a8cd6b
+++ b/ld/ldgram.y
a8cd6b
@@ -47,6 +47,7 @@
a8cd6b
 #endif
a8cd6b
 
a8cd6b
 static enum section_type sectype;
a8cd6b
+static etree_type *sectype_value;
a8cd6b
 static lang_memory_region_type *region;
a8cd6b
 
a8cd6b
 static bool ldgram_had_keep = false;
a8cd6b
@@ -139,6 +140,7 @@ static int error_index;
a8cd6b
 %token LD_FEATURE
a8cd6b
 %token NOLOAD DSECT COPY INFO OVERLAY
a8cd6b
 %token READONLY
a8cd6b
+%token TYPE
a8cd6b
 %token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
a8cd6b
 %token <integer> NEXT
a8cd6b
 %token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
a8cd6b
@@ -1058,9 +1060,8 @@ section:	NAME
a8cd6b
 			{
a8cd6b
 			  ldlex_popstate ();
a8cd6b
 			  ldlex_wild ();
a8cd6b
-			  lang_enter_output_section_statement($1, $3, sectype,
a8cd6b
-							      $5, $7, $4,
a8cd6b
-							      $8, $6);
a8cd6b
+			  lang_enter_output_section_statement ($1, $3, sectype,
a8cd6b
+					sectype_value, $5, $7, $4, $8, $6);
a8cd6b
 			}
a8cd6b
 		'{'
a8cd6b
 		statement_list_opt
a8cd6b
@@ -1130,8 +1131,10 @@ type:
a8cd6b
 	|  COPY    { sectype = noalloc_section; }
a8cd6b
 	|  INFO    { sectype = noalloc_section; }
a8cd6b
 	|  OVERLAY { sectype = noalloc_section; }
a8cd6b
+        |  READONLY '(' TYPE '=' exp ')' { sectype = typed_readonly_section; sectype_value = $5; }
a8cd6b
 	|  READONLY { sectype = readonly_section; }
a8cd6b
-	;
a8cd6b
+	|  TYPE '=' exp { sectype = type_section; sectype_value = $3; }
a8cd6b
+        ;
a8cd6b
 
a8cd6b
 atype:
a8cd6b
 		'(' type ')'
a8cd6b
diff --git a/ld/ldlang.c b/ld/ldlang.c
a8cd6b
index 474784c874a..1733f8e65c4 100644
a8cd6b
--- a/ld/ldlang.c
a8cd6b
+++ b/ld/ldlang.c
a8cd6b
@@ -1891,8 +1891,8 @@ lang_insert_orphan (asection *s,
a8cd6b
     address = exp_intop (0);
a8cd6b
 
a8cd6b
   os_tail = (lang_output_section_statement_type **) lang_os_list.tail;
a8cd6b
-  os = lang_enter_output_section_statement (secname, address, normal_section,
a8cd6b
-					    NULL, NULL, NULL, constraint, 0);
a8cd6b
+  os = lang_enter_output_section_statement (
a8cd6b
+      secname, address, normal_section, 0, NULL, NULL, NULL, constraint, 0);
a8cd6b
 
a8cd6b
   if (add_child == NULL)
a8cd6b
     add_child = &os->children;
a8cd6b
@@ -2635,10 +2635,12 @@ lang_add_section (lang_statement_list_type *ptr,
a8cd6b
     case normal_section:
a8cd6b
     case overlay_section:
a8cd6b
     case first_overlay_section:
a8cd6b
+    case type_section:
a8cd6b
       break;
a8cd6b
     case noalloc_section:
a8cd6b
       flags &= ~SEC_ALLOC;
a8cd6b
       break;
a8cd6b
+    case typed_readonly_section:
a8cd6b
     case readonly_section:
a8cd6b
       flags |= SEC_READONLY;
a8cd6b
       break;
a8cd6b
@@ -4209,6 +4211,7 @@ map_input_to_output_sections
a8cd6b
     {
a8cd6b
       lang_output_section_statement_type *tos;
a8cd6b
       flagword flags;
a8cd6b
+      unsigned int type = 0;
a8cd6b
 
a8cd6b
       switch (s->header.type)
a8cd6b
 	{
a8cd6b
@@ -4264,6 +4267,42 @@ map_input_to_output_sections
a8cd6b
 	    case readonly_section:
a8cd6b
 	      flags |= SEC_READONLY;
a8cd6b
 	      break;
a8cd6b
+	    case typed_readonly_section:
a8cd6b
+	      flags |= SEC_READONLY;
a8cd6b
+	      /* Fall through.  */
a8cd6b
+	    case type_section:
a8cd6b
+	      if (os->sectype_value->type.node_class == etree_name
a8cd6b
+		  && os->sectype_value->type.node_code == NAME)
a8cd6b
+		{
a8cd6b
+		  const char *name = os->sectype_value->name.name;
a8cd6b
+		  if (strcmp (name, "SHT_PROGBITS") == 0)
a8cd6b
+		    type = SHT_PROGBITS;
a8cd6b
+		  else if (strcmp (name, "SHT_STRTAB") == 0)
a8cd6b
+		    type = SHT_STRTAB;
a8cd6b
+		  else if (strcmp (name, "SHT_NOTE") == 0)
a8cd6b
+		    type = SHT_NOTE;
a8cd6b
+		  else if (strcmp (name, "SHT_NOBITS") == 0)
a8cd6b
+		    type = SHT_NOBITS;
a8cd6b
+		  else if (strcmp (name, "SHT_INIT_ARRAY") == 0)
a8cd6b
+		    type = SHT_INIT_ARRAY;
a8cd6b
+		  else if (strcmp (name, "SHT_FINI_ARRAY") == 0)
a8cd6b
+		    type = SHT_FINI_ARRAY;
a8cd6b
+		  else if (strcmp (name, "SHT_PREINIT_ARRAY") == 0)
a8cd6b
+		    type = SHT_PREINIT_ARRAY;
a8cd6b
+		  else
a8cd6b
+		    einfo (_ ("%F%P: invalid type for output section `%s'\n"),
a8cd6b
+			   os->name);
a8cd6b
+		}
a8cd6b
+	     else
a8cd6b
+	       {
a8cd6b
+		 exp_fold_tree_no_dot (os->sectype_value);
a8cd6b
+		 if (expld.result.valid_p)
a8cd6b
+		   type = expld.result.value;
a8cd6b
+		 else
a8cd6b
+		   einfo (_ ("%F%P: invalid type for output section `%s'\n"),
a8cd6b
+			  os->name);
a8cd6b
+	       }
a8cd6b
+	      break;
a8cd6b
 	    case noload_section:
a8cd6b
 	      if (bfd_get_flavour (link_info.output_bfd)
a8cd6b
 		  == bfd_target_elf_flavour)
a8cd6b
@@ -4276,6 +4315,7 @@ map_input_to_output_sections
a8cd6b
 	    init_os (os, flags | SEC_READONLY);
a8cd6b
 	  else
a8cd6b
 	    os->bfd_section->flags |= flags;
a8cd6b
+	  os->bfd_section->type = type;
a8cd6b
 	  break;
a8cd6b
 	case lang_input_section_enum:
a8cd6b
 	  break;
a8cd6b
@@ -7506,6 +7546,7 @@ lang_output_section_statement_type *
a8cd6b
 lang_enter_output_section_statement (const char *output_section_statement_name,
a8cd6b
 				     etree_type *address_exp,
a8cd6b
 				     enum section_type sectype,
a8cd6b
+				     etree_type *sectype_value,
a8cd6b
 				     etree_type *align,
a8cd6b
 				     etree_type *subalign,
a8cd6b
 				     etree_type *ebase,
a8cd6b
@@ -7523,10 +7564,12 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
a8cd6b
       os->addr_tree = address_exp;
a8cd6b
     }
a8cd6b
   os->sectype = sectype;
a8cd6b
-  if (sectype != noload_section)
a8cd6b
-    os->flags = SEC_NO_FLAGS;
a8cd6b
-  else
a8cd6b
+  if (sectype == type_section || sectype == typed_readonly_section)
a8cd6b
+    os->sectype_value = sectype_value;
a8cd6b
+  else if (sectype == noload_section)
a8cd6b
     os->flags = SEC_NEVER_LOAD;
a8cd6b
+  else
a8cd6b
+    os->flags = SEC_NO_FLAGS;
a8cd6b
   os->block_value = 1;
a8cd6b
 
a8cd6b
   /* Make next things chain into subchain of this.  */
a8cd6b
@@ -8842,7 +8885,7 @@ lang_enter_overlay_section (const char *name)
a8cd6b
   etree_type *size;
a8cd6b
 
a8cd6b
   lang_enter_output_section_statement (name, overlay_vma, overlay_section,
a8cd6b
-				       0, overlay_subalign, 0, 0, 0);
a8cd6b
+				       0, 0, overlay_subalign, 0, 0, 0);
a8cd6b
 
a8cd6b
   /* If this is the first section, then base the VMA of future
a8cd6b
      sections on this one.  This will work correctly even if `.' is
a8cd6b
diff --git a/ld/ldlang.h b/ld/ldlang.h
a8cd6b
index 0d057c9bee9..95f6e468b30 100644
a8cd6b
--- a/ld/ldlang.h
a8cd6b
+++ b/ld/ldlang.h
a8cd6b
@@ -122,7 +122,9 @@ enum section_type
a8cd6b
   overlay_section,
a8cd6b
   noload_section,
a8cd6b
   noalloc_section,
a8cd6b
-  readonly_section
a8cd6b
+  type_section,
a8cd6b
+  readonly_section,
a8cd6b
+  typed_readonly_section
a8cd6b
 };
a8cd6b
 
a8cd6b
 /* This structure holds a list of program headers describing
a8cd6b
@@ -166,6 +168,7 @@ typedef struct lang_output_section_statement_struct
a8cd6b
   int constraint;
a8cd6b
   flagword flags;
a8cd6b
   enum section_type sectype;
a8cd6b
+  etree_type *sectype_value;
a8cd6b
   unsigned int processed_vma : 1;
a8cd6b
   unsigned int processed_lma : 1;
a8cd6b
   unsigned int all_input_readonly : 1;
a8cd6b
@@ -545,7 +548,7 @@ extern void lang_add_output
a8cd6b
   (const char *, int from_script);
a8cd6b
 extern lang_output_section_statement_type *lang_enter_output_section_statement
a8cd6b
   (const char *, etree_type *, enum section_type, etree_type *, etree_type *,
a8cd6b
-   etree_type *, int, int);
a8cd6b
+   etree_type *, etree_type *, int, int);
a8cd6b
 extern void lang_final
a8cd6b
   (void);
a8cd6b
 extern void lang_relax_sections
a8cd6b
diff --git a/ld/ldlex.l b/ld/ldlex.l
a8cd6b
index 78db16e3a48..c38b46b9336 100644
a8cd6b
--- a/ld/ldlex.l
a8cd6b
+++ b/ld/ldlex.l
a8cd6b
@@ -323,6 +323,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
a8cd6b
 <EXPRESSION>"DSECT"			{ RTOKEN(DSECT); }
a8cd6b
 <EXPRESSION>"COPY"			{ RTOKEN(COPY); }
a8cd6b
 <EXPRESSION>"INFO"			{ RTOKEN(INFO); }
a8cd6b
+<EXPRESSION>"TYPE"			{ RTOKEN(TYPE); }
a8cd6b
 <SCRIPT,EXPRESSION>"ONLY_IF_RO"		{ RTOKEN(ONLY_IF_RO); }
a8cd6b
 <SCRIPT,EXPRESSION>"ONLY_IF_RW"		{ RTOKEN(ONLY_IF_RW); }
a8cd6b
 <SCRIPT,EXPRESSION>"SPECIAL"		{ RTOKEN(SPECIAL); }
a8cd6b
diff --git a/ld/mri.c b/ld/mri.c
a8cd6b
index b428ab0d0bf..5749870ef1e 100644
a8cd6b
--- a/ld/mri.c
a8cd6b
+++ b/ld/mri.c
a8cd6b
@@ -210,8 +210,8 @@ mri_draw_tree (void)
a8cd6b
 	    base = p->vma ? p->vma : exp_nameop (NAME, ".");
a8cd6b
 
a8cd6b
 	  lang_enter_output_section_statement (p->name, base,
a8cd6b
-					       p->ok_to_load ? normal_section : noload_section,
a8cd6b
-					       align, subalign, NULL, 0, 0);
a8cd6b
+	    p->ok_to_load ? normal_section : noload_section, 0,
a8cd6b
+	    align, subalign, NULL, 0, 0);
a8cd6b
 	  base = 0;
a8cd6b
 	  tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
a8cd6b
 	  tmp->next = NULL;
a8cd6b
diff --git a/ld/testsuite/ld-scripts/output-section-types.d b/ld/testsuite/ld-scripts/output-section-types.d
a8cd6b
index ab124fa4dd7..2ecacaba57d 100644
a8cd6b
--- a/ld/testsuite/ld-scripts/output-section-types.d
a8cd6b
+++ b/ld/testsuite/ld-scripts/output-section-types.d
a8cd6b
@@ -1,13 +1,17 @@
a8cd6b
 #ld: -Toutput-section-types.t
a8cd6b
 #source: align2a.s
a8cd6b
-#objdump: -h
a8cd6b
+#readelf: -S --wide
a8cd6b
 #target: [is_elf_format]
a8cd6b
 
a8cd6b
 #...
a8cd6b
-  . \.rom.*
a8cd6b
-[ 	]+ALLOC, READONLY
a8cd6b
-  . \.ro.*
a8cd6b
-[ 	]+CONTENTS, ALLOC, LOAD, READONLY, DATA
a8cd6b
-  . \.over.*
a8cd6b
-[ 	]+CONTENTS, READONLY
a8cd6b
+.* .rom          +NOBITS        +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
a8cd6b
+.* .ro           +PROGBITS      +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
a8cd6b
+.* .over         +PROGBITS      +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00  + +0 +0 +[1248]
a8cd6b
+.* progbits      +PROGBITS      +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
a8cd6b
+.* strtab        +STRTAB        +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
a8cd6b
+.* note          +NOTE          +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
a8cd6b
+.* init_array    +INIT_ARRAY    +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248]
a8cd6b
+.* fini_array    +FINI_ARRAY    +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248]
a8cd6b
+.* preinit_array +PREINIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248]
a8cd6b
+.* .ro.note      +NOTE          +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
a8cd6b
 #pass
a8cd6b
diff --git a/ld/testsuite/ld-scripts/output-section-types.t b/ld/testsuite/ld-scripts/output-section-types.t
a8cd6b
index d8fdfda1a03..18fc5c11980 100644
a8cd6b
--- a/ld/testsuite/ld-scripts/output-section-types.t
a8cd6b
+++ b/ld/testsuite/ld-scripts/output-section-types.t
a8cd6b
@@ -2,6 +2,13 @@ SECTIONS {
a8cd6b
   .rom  (NOLOAD)   : { LONG(1234); }
a8cd6b
   .ro   (READONLY) : { LONG(5678); }
a8cd6b
   .over (OVERLAY)  : { LONG(0123); }
a8cd6b
+  progbits (TYPE=SHT_PROGBITS) : { BYTE(1) }
a8cd6b
+  strtab (TYPE = SHT_STRTAB) : { BYTE(0) }
a8cd6b
+  note (TYPE =SHT_NOTE) : { BYTE(8) }
a8cd6b
+  init_array (TYPE= 14) : { QUAD(14) }
a8cd6b
+  fini_array ( TYPE=SHT_FINI_ARRAY) : { QUAD(15) }
a8cd6b
+  preinit_array (TYPE=SHT_PREINIT_ARRAY ) : { QUAD(16) }
a8cd6b
+  .ro.note   (READONLY (TYPE=SHT_NOTE)) : { LONG(5678); }
a8cd6b
   /DISCARD/        : { *(*) }
a8cd6b
 
a8cd6b
 }