public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Fangrui Song <maskray@google.com>
To: binutils@sourceware.org, Alan Modra <amodra@gmail.com>,
	 Nick Clifton <nickc@redhat.com>
Cc: Luca Boccassi <bluca@debian.org>, Fangrui Song <maskray@google.com>
Subject: [PATCH] ld: Support customized output section type
Date: Tue,  1 Feb 2022 23:10:44 -0800	[thread overview]
Message-ID: <20220202071044.1480421-1-maskray@google.com> (raw)

The current output section type allows to set the ELF section type to
SHT_PROGBITS or SHT_NOLOAD. This patch allows an arbitrary section value
to be specified. Some ELF section type names are supported as well,
e.g.:

    note (TYPE=SHT_NOTE) : { BYTE(8) }
    init_array (TYPE=14) : { BYTE(14) }
    fini_array (TYPE=SHT_FINI_ARRAY) : { BYTE(15) }

bfd/
    PR ld/28841
    * bfd-in2.h (struct bfd_section): Add type.
    (discarded_section): Add field.
    * elf.c (elf_fake_sections): Handle bfd_section::type.
    * section.c (BFD_FAKE_SECTION): Add field.
    * mri.c (mri_draw_tree): Update function call.

ld/
    PR ld/28841
    * ld.texi: Document new output section type.
    * ldlex.l: Add new token TYPE.
    * ldgram.y: Handle TYPE=exp.
    * ldlang.h: Add type_section to list of section types.
    * ldlang.c (lang_add_section): Handle type_section.
    (map_input_to_output_sections): Handle type_section.
    * testsuite/ld-scripts/output-section-types.t: Add tests.
    * testsuite/ld-scripts/output-section-types.d: Update.
---
 bfd/bfd-in2.h                                 |  7 ++-
 bfd/elf.c                                     |  4 +-
 bfd/section.c                                 |  4 +-
 ld/ld.texi                                    |  4 ++
 ld/ldgram.y                                   |  9 ++--
 ld/ldlang.c                                   | 49 ++++++++++++++++---
 ld/ldlang.h                                   |  4 +-
 ld/ldlex.l                                    |  1 +
 ld/mri.c                                      |  4 +-
 .../ld-scripts/output-section-types.d         | 16 +++---
 .../ld-scripts/output-section-types.t         |  5 ++
 11 files changed, 82 insertions(+), 25 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8e815bab624..91ec68d0391 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1170,6 +1170,9 @@ typedef struct bfd_section
     This is used when support for non-contiguous memory regions is enabled.  */
  struct bfd_section *already_assigned;
 
+  /* Explicitly specified section type, if non-zero. */
+  unsigned int type;
+
 } asection;
 
 /* Relax table contains information about instructions which can
@@ -1352,8 +1355,8 @@ discarded_section (const asection *sec)
   /* symbol,                    symbol_ptr_ptr,                     */ \
      (struct bfd_symbol *) SYM, &SEC.symbol,                           \
                                                                        \
-  /* map_head, map_tail, already_assigned                           */ \
-     { NULL }, { NULL }, NULL                                          \
+  /* map_head, map_tail, already_assigned, type                     */ \
+     { NULL }, { NULL }, NULL, 0                                       \
                                                                        \
     }
 
diff --git a/bfd/elf.c b/bfd/elf.c
index 14c2c7ba734..1ebe7b425c4 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3279,7 +3279,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
 
   /* If the section type is unspecified, we set it based on
      asect->flags.  */
-  if ((asect->flags & SEC_GROUP) != 0)
+  if (asect->type != 0)
+    sh_type = asect->type;
+  else if ((asect->flags & SEC_GROUP) != 0)
     sh_type = SHT_GROUP;
   else
     sh_type = bfd_elf_get_default_section_type (asect->flags);
diff --git a/bfd/section.c b/bfd/section.c
index 899438a1c5e..2de7dbf661a 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -737,8 +737,8 @@ CODE_FRAGMENT
 .  {* symbol,                    symbol_ptr_ptr,                     *}	\
 .     (struct bfd_symbol *) SYM, &SEC.symbol,				\
 .									\
-.  {* map_head, map_tail, already_assigned                           *}	\
-.     { NULL }, { NULL }, NULL						\
+.  {* map_head, map_tail, already_assigned, type                     *}	\
+.     { NULL }, { NULL }, NULL, 0						\
 .									\
 .    }
 .
diff --git a/ld/ld.texi b/ld/ld.texi
index fc75e9b3625..e3a1e02ed25 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -5490,6 +5490,10 @@ These type names are supported for backward compatibility, and are
 rarely used.  They all have the same effect: the section should be
 marked as not allocatable, so that no memory is allocated for the
 section when the program is run.
+@item TYPE = @var{type}
+Set the section type to the integer @var{type}. For the ELF output
+file, some type names (e.g. @code{SHT_NOTE}) are also allowed for
+@var{type}.
 @end table
 
 @kindex NOLOAD
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 11c2f219c05..f5e3a834a26 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -47,6 +47,7 @@
 #endif
 
 static enum section_type sectype;
+static etree_type *sectype_value;
 static lang_memory_region_type *region;
 
 static bool ldgram_had_keep = false;
@@ -139,6 +140,7 @@ static int error_index;
 %token LD_FEATURE
 %token NOLOAD DSECT COPY INFO OVERLAY
 %token READONLY
+%token TYPE
 %token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
 %token <integer> NEXT
 %token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
@@ -1058,9 +1060,8 @@ section:	NAME
 			{
 			  ldlex_popstate ();
 			  ldlex_wild ();
-			  lang_enter_output_section_statement($1, $3, sectype,
-							      $5, $7, $4,
-							      $8, $6);
+			  lang_enter_output_section_statement ($1, $3, sectype,
+					sectype_value, $5, $7, $4, $8, $6);
 			}
 		'{'
 		statement_list_opt
@@ -1131,7 +1132,7 @@ type:
 	|  INFO    { sectype = noalloc_section; }
 	|  OVERLAY { sectype = noalloc_section; }
 	|  READONLY { sectype = readonly_section; }
-	;
+	|  TYPE '=' exp { sectype = type_section; sectype_value = $3; }
 
 atype:
 		'(' type ')'
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5dd3df12a0f..a0a3c09f9a9 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1891,8 +1891,8 @@ lang_insert_orphan (asection *s,
     address = exp_intop (0);
 
   os_tail = (lang_output_section_statement_type **) lang_os_list.tail;
-  os = lang_enter_output_section_statement (secname, address, normal_section,
-					    NULL, NULL, NULL, constraint, 0);
+  os = lang_enter_output_section_statement (
+      secname, address, normal_section, 0, NULL, NULL, NULL, constraint, 0);
 
   if (add_child == NULL)
     add_child = &os->children;
@@ -2635,6 +2635,7 @@ lang_add_section (lang_statement_list_type *ptr,
     case normal_section:
     case overlay_section:
     case first_overlay_section:
+    case type_section:
       break;
     case noalloc_section:
       flags &= ~SEC_ALLOC;
@@ -4209,6 +4210,7 @@ map_input_to_output_sections
     {
       lang_output_section_statement_type *tos;
       flagword flags;
+      unsigned int type = 0;
 
       switch (s->header.type)
 	{
@@ -4261,6 +4263,37 @@ map_input_to_output_sections
 	    case noalloc_section:
 	      flags = SEC_HAS_CONTENTS;
 	      break;
+	    case type_section:
+	      if (os->sectype_value->type.node_class == etree_name
+		  && os->sectype_value->type.node_code == NAME)
+		{
+		  const char *name = os->sectype_value->name.name;
+		  if (strcmp (name, "SHT_PROGBITS") == 0)
+		    type = SHT_PROGBITS;
+		  else if (strcmp (name, "SHT_NOTE") == 0)
+		    type = SHT_NOTE;
+		  else if (strcmp (name, "SHT_NOBITS") == 0)
+		    type = SHT_NOBITS;
+		  else if (strcmp (name, "SHT_INIT_ARRAY") == 0)
+		    type = SHT_INIT_ARRAY;
+		  else if (strcmp (name, "SHT_FINI_ARRAY") == 0)
+		    type = SHT_FINI_ARRAY;
+		  else if (strcmp (name, "SHT_PREINIT_ARRAY") == 0)
+		    type = SHT_PREINIT_ARRAY;
+		  else
+		    einfo (_ ("%F%P: invalid type for output section `%s'\n"),
+			   os->name);
+		}
+	     else
+	       {
+		 exp_fold_tree_no_dot (os->sectype_value);
+		 if (expld.result.valid_p)
+		   type = expld.result.value;
+		 else
+		   einfo (_ ("%F%P: invalid type for output section `%s'\n"),
+			  os->name);
+	       }
+	      break;
 	    case readonly_section:
 	      flags |= SEC_READONLY;
 	      break;
@@ -4276,6 +4309,7 @@ map_input_to_output_sections
 	    init_os (os, flags | SEC_READONLY);
 	  else
 	    os->bfd_section->flags |= flags;
+	  os->bfd_section->type = type;
 	  break;
 	case lang_input_section_enum:
 	  break;
@@ -7564,6 +7598,7 @@ lang_output_section_statement_type *
 lang_enter_output_section_statement (const char *output_section_statement_name,
 				     etree_type *address_exp,
 				     enum section_type sectype,
+				     etree_type *sectype_value,
 				     etree_type *align,
 				     etree_type *subalign,
 				     etree_type *ebase,
@@ -7581,10 +7616,12 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
       os->addr_tree = address_exp;
     }
   os->sectype = sectype;
-  if (sectype != noload_section)
-    os->flags = SEC_NO_FLAGS;
-  else
+  if (sectype == type_section)
+    os->sectype_value = sectype_value;
+  else if (sectype == noload_section)
     os->flags = SEC_NEVER_LOAD;
+  else
+    os->flags = SEC_NO_FLAGS;
   os->block_value = 1;
 
   /* Make next things chain into subchain of this.  */
@@ -8901,7 +8938,7 @@ lang_enter_overlay_section (const char *name)
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, overlay_section,
-				       0, overlay_subalign, 0, 0, 0);
+				       0, 0, overlay_subalign, 0, 0, 0);
 
   /* If this is the first section, then base the VMA of future
      sections on this one.  This will work correctly even if `.' is
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 0d057c9bee9..20b953eeac6 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -122,6 +122,7 @@ enum section_type
   overlay_section,
   noload_section,
   noalloc_section,
+  type_section,
   readonly_section
 };
 
@@ -166,6 +167,7 @@ typedef struct lang_output_section_statement_struct
   int constraint;
   flagword flags;
   enum section_type sectype;
+  etree_type *sectype_value;
   unsigned int processed_vma : 1;
   unsigned int processed_lma : 1;
   unsigned int all_input_readonly : 1;
@@ -545,7 +547,7 @@ extern void lang_add_output
   (const char *, int from_script);
 extern lang_output_section_statement_type *lang_enter_output_section_statement
   (const char *, etree_type *, enum section_type, etree_type *, etree_type *,
-   etree_type *, int, int);
+   etree_type *, etree_type *, int, int);
 extern void lang_final
   (void);
 extern void lang_relax_sections
diff --git a/ld/ldlex.l b/ld/ldlex.l
index 78db16e3a48..c38b46b9336 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -323,6 +323,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <EXPRESSION>"DSECT"			{ RTOKEN(DSECT); }
 <EXPRESSION>"COPY"			{ RTOKEN(COPY); }
 <EXPRESSION>"INFO"			{ RTOKEN(INFO); }
+<EXPRESSION>"TYPE"			{ RTOKEN(TYPE); }
 <SCRIPT,EXPRESSION>"ONLY_IF_RO"		{ RTOKEN(ONLY_IF_RO); }
 <SCRIPT,EXPRESSION>"ONLY_IF_RW"		{ RTOKEN(ONLY_IF_RW); }
 <SCRIPT,EXPRESSION>"SPECIAL"		{ RTOKEN(SPECIAL); }
diff --git a/ld/mri.c b/ld/mri.c
index b428ab0d0bf..5749870ef1e 100644
--- a/ld/mri.c
+++ b/ld/mri.c
@@ -210,8 +210,8 @@ mri_draw_tree (void)
 	    base = p->vma ? p->vma : exp_nameop (NAME, ".");
 
 	  lang_enter_output_section_statement (p->name, base,
-					       p->ok_to_load ? normal_section : noload_section,
-					       align, subalign, NULL, 0, 0);
+	    p->ok_to_load ? normal_section : noload_section, 0,
+	    align, subalign, NULL, 0, 0);
 	  base = 0;
 	  tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
 	  tmp->next = NULL;
diff --git a/ld/testsuite/ld-scripts/output-section-types.d b/ld/testsuite/ld-scripts/output-section-types.d
index ab124fa4dd7..56b88ce6342 100644
--- a/ld/testsuite/ld-scripts/output-section-types.d
+++ b/ld/testsuite/ld-scripts/output-section-types.d
@@ -1,13 +1,15 @@
 #ld: -Toutput-section-types.t
 #source: align2a.s
-#objdump: -h
+#readelf: -S --wide
 #target: [is_elf_format]
 
 #...
-  . \.rom.*
-[ 	]+ALLOC, READONLY
-  . \.ro.*
-[ 	]+CONTENTS, ALLOC, LOAD, READONLY, DATA
-  . \.over.*
-[ 	]+CONTENTS, READONLY
+.* .rom          +NOBITS        +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +[0-9] +0 +[1248]
+.* .ro           +PROGBITS      +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +[0-9] +0 +[1248]
+.* .over         +PROGBITS      +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00  + +[0-9] +0 +[1248]
+.* progbits      +PROGBITS      +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +[0-9] +0 +[1248]
+.* note          +NOTE          +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +[0-9] +0 +[1248]
+.* init_array    +INIT_ARRAY    +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +[0-9] +0 +[1248]
+.* fini_array    +FINI_ARRAY    +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +[0-9] +0 +[1248]
+.* preinit_array +PREINIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +[0-9] +0 +[1248]
 #pass
diff --git a/ld/testsuite/ld-scripts/output-section-types.t b/ld/testsuite/ld-scripts/output-section-types.t
index d8fdfda1a03..834e5869d79 100644
--- a/ld/testsuite/ld-scripts/output-section-types.t
+++ b/ld/testsuite/ld-scripts/output-section-types.t
@@ -2,6 +2,11 @@ SECTIONS {
   .rom  (NOLOAD)   : { LONG(1234); }
   .ro   (READONLY) : { LONG(5678); }
   .over (OVERLAY)  : { LONG(0123); }
+  progbits (TYPE=SHT_PROGBITS) : { BYTE(1) }
+  note (TYPE=SHT_NOTE) : { BYTE(8) }
+  init_array (TYPE=14) : { BYTE(14) }
+  fini_array (TYPE=SHT_FINI_ARRAY) : { BYTE(15) }
+  preinit_array (TYPE=SHT_PREINIT_ARRAY) : { BYTE(16) }
   /DISCARD/        : { *(*) }
 
 }
-- 
2.35.0.rc2.247.g8bbb082509-goog


             reply	other threads:[~2022-02-02  7:11 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-02  7:10 Fangrui Song [this message]
2022-02-02 11:36 ` Nick Clifton
2022-02-02 11:46   ` Luca Boccassi
2022-02-02 18:32   ` Fangrui Song
2022-02-03 18:36     ` Luca Boccassi
2022-02-03 19:46       ` Fangrui Song
2022-02-03 20:04         ` Luca Boccassi
2022-02-03 20:48           ` Fangrui Song
2022-02-04 16:05           ` Michael Matz
2022-02-21 19:35 ` Mike Frysinger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220202071044.1480421-1-maskray@google.com \
    --to=maskray@google.com \
    --cc=amodra@gmail.com \
    --cc=binutils@sourceware.org \
    --cc=bluca@debian.org \
    --cc=nickc@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).