public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] ELF: Add support for unique section ID to assembler
@ 2020-02-02 17:51 H.J. Lu
  2020-02-03  0:22 ` Alan Modra
  0 siblings, 1 reply; 5+ messages in thread
From: H.J. Lu @ 2020-02-02 17:51 UTC (permalink / raw)
  To: binutils

Clang's integrated assembler supports multiple section with the same
name:

	.section .text,"ax",@progbits,unique,1
	nop
	.section .text,"ax",@progbits,unique,2
	nop

"unique,N" assigns the number, N, as the section ID, to a section.  The
valid values of the section ID are between 0 and 4294967295.  It can be
used to distinguish different sections with the same section name.

This is useful with -fno-unique-section-names -ffunction-sections.
-ffunction-sections by default generates .text.foo, .text.bar, etc.
Using the same string can save lots of space in .strtab.

This patch adds section_id to bfd_section and reuses the linker
internal bit in BFD section flags, SEC_LINKER_CREATED, for assmebler
internal use to mark valid section_id.  It also updates objdump to
compare section pointers if 2 sections comes from the same file since
2 different sections can have the same section name.

bfd/

	PR gas/25380
	* bfd-in2.h: Regenerated.
	* ecoff.c (bfd_debug_section): Add section_id.
	* section.c (bfd_section): Add section_id.
	(SEC_ASSEMBLER_SECTION_ID): New.
	(BFD_FAKE_SECTION): Add section_id.

binutils/

	PR gas/25380
	* objdump.c (sym_ok): Return FALSE if 2 sections are in the
	same file with different section pointers.

gas/

	PR gas/25380
	* config/obj-elf.c (section_match): Removed.
	(get_section): Also match SEC_ASSEMBLER_SECTION_ID and
	section_id.
	(obj_elf_change_section): Replace info and group_name arguments
	with match_p.  Also update the section ID and flags from match_p.
	(obj_elf_section): Handle "unique,N".  Update call to
	obj_elf_change_section.
	* config/obj-elf.h (elf_section_match): New.
	(obj_elf_change_section): Updated.
	* config/tc-arm.c (start_unwind_section): Update call to
	obj_elf_change_section.
	* config/tc-ia64.c (obj_elf_vms_common): Likewise.
	* config/tc-microblaze.c (microblaze_s_data): Likewise.
	(microblaze_s_sdata): Likewise.
	(microblaze_s_rdata): Likewise.
	(microblaze_s_bss): Likewise.
	* config/tc-mips.c (s_change_section): Likewise.
	* config/tc-msp430.c (msp430_profiler): Likewise.
	* config/tc-rx.c (parse_rx_section): Likewise.
	* config/tc-tic6x.c (tic6x_start_unwind_section): Likewise.
	* doc/as.texi: Document "unique,N" in .section directive.
	* testsuite/gas/elf/elf.exp: Run "unique,N" tests.
	* testsuite/gas/elf/section15.d: New file.
	* testsuite/gas/elf/section15.s: Likewise.
	* testsuite/gas/elf/section16.s: Likewise.
	* testsuite/gas/elf/section16a.d: Likewise.
	* testsuite/gas/elf/section16b.d: Likewise.
	* testsuite/gas/elf/section17.d: Likewise.
	* testsuite/gas/elf/section17.l: Likewise.
	* testsuite/gas/elf/section17.s: Likewise.
	* testsuite/gas/i386/unique.d: Likewise.
	* testsuite/gas/i386/unique.s: Likewise.
	* testsuite/gas/i386/x86-64-unique.d: Likewise.
	* testsuite/gas/i386/i386.exp: Run unique and x86-64-unique.

ld/

	PR gas/25380
	* testsuite/ld-i386/pr22001-1c.S: Use "unique,N" in .section
	directives.
	* testsuite/ld-i386/tls-gd1.S: Likewise.
	* testsuite/ld-x86-64/pr21481b.S: Likewise.
---
 bfd/bfd-in2.h                          |  12 ++-
 bfd/ecoff.c                            |   6 +-
 bfd/section.c                          |  12 ++-
 binutils/objdump.c                     |   7 ++
 gas/config/obj-elf.c                   | 121 +++++++++++++++++++------
 gas/config/obj-elf.h                   |  12 ++-
 gas/config/tc-arm.c                    |  10 +-
 gas/config/tc-ia64.c                   |   2 +-
 gas/config/tc-microblaze.c             |  12 +--
 gas/config/tc-mips.c                   |   2 +-
 gas/config/tc-msp430.c                 |   2 +-
 gas/config/tc-rx.c                     |   4 +-
 gas/config/tc-tic6x.c                  |  10 +-
 gas/doc/as.texi                        |   5 +
 gas/testsuite/gas/elf/elf.exp          |   4 +
 gas/testsuite/gas/elf/section15.d      |  24 +++++
 gas/testsuite/gas/elf/section15.s      |  38 ++++++++
 gas/testsuite/gas/elf/section16.s      |  33 +++++++
 gas/testsuite/gas/elf/section16a.d     |  36 ++++++++
 gas/testsuite/gas/elf/section16b.d     |  36 ++++++++
 gas/testsuite/gas/elf/section17.d      |   2 +
 gas/testsuite/gas/elf/section17.l      |   4 +
 gas/testsuite/gas/elf/section17.s      |   6 ++
 gas/testsuite/gas/i386/i386.exp        |   2 +
 gas/testsuite/gas/i386/unique.d        |  48 ++++++++++
 gas/testsuite/gas/i386/unique.s        |  36 ++++++++
 gas/testsuite/gas/i386/x86-64-unique.d |  48 ++++++++++
 ld/testsuite/ld-i386/pr22001-1c.S      |   4 +-
 ld/testsuite/ld-i386/tls-gd1.S         |   5 +-
 ld/testsuite/ld-x86-64/pr21481b.S      |   4 +-
 30 files changed, 483 insertions(+), 64 deletions(-)
 create mode 100644 gas/testsuite/gas/elf/section15.d
 create mode 100644 gas/testsuite/gas/elf/section15.s
 create mode 100644 gas/testsuite/gas/elf/section16.s
 create mode 100644 gas/testsuite/gas/elf/section16a.d
 create mode 100644 gas/testsuite/gas/elf/section16b.d
 create mode 100644 gas/testsuite/gas/elf/section17.d
 create mode 100644 gas/testsuite/gas/elf/section17.l
 create mode 100644 gas/testsuite/gas/elf/section17.s
 create mode 100644 gas/testsuite/gas/i386/unique.d
 create mode 100644 gas/testsuite/gas/i386/unique.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-unique.d

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8144b167e04..c890520ccb1 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -795,6 +795,10 @@ typedef struct bfd_section
   /* A unique sequence number.  */
   unsigned int id;
 
+  /* A unique section number which can be used by assembler to
+     distinguish different sections with the same section name.  */
+  unsigned int section_id;
+
   /* Which section in the bfd; 0..n-1 as sections are created in a bfd.  */
   unsigned int index;
 
@@ -928,6 +932,10 @@ typedef struct bfd_section
      else up the line will take care of it later.  */
 #define SEC_LINKER_CREATED           0x100000
 
+  /* This section contains a section ID to distinguish different
+     sections withe the same section name.  */
+#define SEC_ASSEMBLER_SECTION_ID     0x100000
+
   /* This section should not be subject to garbage collection.
      Also set to inform the linker that this section should not be
      listed in the link map as discarded.  */
@@ -1329,8 +1337,8 @@ discarded_section (const asection *sec)
 }
 
 #define BFD_FAKE_SECTION(SEC, SYM, NAME, IDX, FLAGS)                   \
-  /* name, id,  index, next, prev, flags, user_set_vma,            */  \
-  {  NAME, IDX, 0,     NULL, NULL, FLAGS, 0,                           \
+  /* name, id,  section_id, index, next, prev, flags, user_set_vma, */ \
+  {  NAME, IDX, 0,          0,     NULL, NULL, FLAGS, 0,               \
                                                                        \
   /* linker_mark, linker_has_input, gc_mark, decompress_status,    */  \
      0,           0,                1,       0,                        \
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index f2713626d60..050fd7b5081 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -52,8 +52,10 @@
 /* This stuff is somewhat copied from coffcode.h.  */
 static asection bfd_debug_section =
 {
-  /* name,	id,  index, next, prev, flags, user_set_vma,	   */
-     "*DEBUG*", 0,   0,	    NULL, NULL, 0,     0,
+  /* name,	id,  section_id, index, next, prev, flags,	  */
+     "*DEBUG*", 0,   0,		 0,	NULL, NULL, 0,
+  /* user_set_vma,	   */
+     0,
   /* linker_mark, linker_has_input, gc_mark, compress_status,	   */
      0,		  0,		    1,	     0,
   /* segment_mark, sec_info_type, use_rela_p,			   */
diff --git a/bfd/section.c b/bfd/section.c
index d42c2b4287e..161ed33edc4 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -154,6 +154,10 @@ CODE_FRAGMENT
 .  {* A unique sequence number.  *}
 .  unsigned int id;
 .
+.  {* A unique section number which can be used by assembler to
+.     distinguish different sections with the same section name.  *}
+.  unsigned int section_id;
+.
 .  {* Which section in the bfd; 0..n-1 as sections are created in a bfd.  *}
 .  unsigned int index;
 .
@@ -287,6 +291,10 @@ CODE_FRAGMENT
 .     else up the line will take care of it later.  *}
 .#define SEC_LINKER_CREATED           0x100000
 .
+.  {* This section contains a section ID to distinguish different
+.     sections withe the same section name.  *}
+.#define SEC_ASSEMBLER_SECTION_ID     0x100000
+.
 .  {* This section should not be subject to garbage collection.
 .     Also set to inform the linker that this section should not be
 .     listed in the link map as discarded.  *}
@@ -688,8 +696,8 @@ CODE_FRAGMENT
 .}
 .
 .#define BFD_FAKE_SECTION(SEC, SYM, NAME, IDX, FLAGS)			\
-.  {* name, id,  index, next, prev, flags, user_set_vma,            *}	\
-.  {  NAME, IDX, 0,     NULL, NULL, FLAGS, 0,				\
+.  {* name, id,  section_id, index, next, prev, flags, user_set_vma, *}	\
+.  {  NAME, IDX, 0,          0,     NULL, NULL, FLAGS, 0,		\
 .									\
 .  {* linker_mark, linker_has_input, gc_mark, decompress_status,    *}	\
 .     0,           0,                1,       0,			\
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 60a39671292..17c0637b350 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -1065,6 +1065,13 @@ sym_ok (bfd_boolean               want_section,
 {
   if (want_section)
     {
+      /* NB: An object file can have different sections with the same
+         section name.  Compare compare section pointers if they have
+	 the same owner.  */
+      if (sorted_syms[place]->section->owner == sec->owner
+	  && sorted_syms[place]->section != sec)
+	return FALSE;
+
       /* Note - we cannot just compare section pointers because they could
 	 be different, but the same...  Ie the symbol that we are trying to
 	 find could have come from a separate debug info file.  Under such
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 7cf921c051f..2958490c323 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -518,22 +518,18 @@ struct section_stack
 
 static struct section_stack *section_stack;
 
-/* Match both section group name and the sh_info field.  */
-struct section_match
-{
-  const char *group_name;
-  unsigned int info;
-};
-
 static bfd_boolean
 get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
 {
-  struct section_match *match = (struct section_match *) inf;
+  struct elf_section_match *match = (struct elf_section_match *) inf;
   const char *gname = match->group_name;
   const char *group_name = elf_group_name (sec);
   unsigned int info = elf_section_data (sec)->this_hdr.sh_info;
 
   return (info == match->info
+	  && ((bfd_section_flags (sec) & SEC_ASSEMBLER_SECTION_ID)
+	       == (match->flags & SEC_ASSEMBLER_SECTION_ID))
+	  && sec->section_id == match->section_id
 	  && (group_name == gname
 	      || (group_name != NULL
 		  && gname != NULL
@@ -561,10 +557,9 @@ get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
 void
 obj_elf_change_section (const char *name,
 			unsigned int type,
-			unsigned int info,
 			bfd_vma attr,
 			int entsize,
-			const char *group_name,
+			struct elf_section_match *match_p,
 			int linkonce,
 			int push)
 {
@@ -573,7 +568,12 @@ obj_elf_change_section (const char *name,
   flagword flags;
   const struct elf_backend_data *bed;
   const struct bfd_elf_special_section *ssect;
-  struct section_match match;
+
+  if (match_p == NULL)
+    {
+      static struct elf_section_match unused_match;
+      match_p = &unused_match;
+    }
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
@@ -594,10 +594,8 @@ obj_elf_change_section (const char *name,
   previous_section = now_seg;
   previous_subsection = now_subseg;
 
-  match.group_name = group_name;
-  match.info = info;
   old_sec = bfd_get_section_by_name_if (stdoutput, name, get_section,
-					(void *) &match);
+					(void *) match_p);
   if (old_sec)
     {
       sec = old_sec;
@@ -696,7 +694,7 @@ obj_elf_change_section (const char *name,
 #endif
 	  else
 	    {
-	      if (group_name == NULL)
+	      if (match_p->group_name == NULL)
 		as_warn (_("setting incorrect section attributes for %s"),
 			 name);
 	      override = TRUE;
@@ -732,16 +730,20 @@ obj_elf_change_section (const char *name,
 	type = bfd_elf_get_default_section_type (flags);
       elf_section_type (sec) = type;
       elf_section_flags (sec) = attr;
-      elf_section_data (sec)->this_hdr.sh_info = info;
+      elf_section_data (sec)->this_hdr.sh_info = match_p->info;
 
       /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
       if (type == SHT_NOBITS)
 	seg_info (sec)->bss = 1;
 
+      /* Set the section ID and flags.  */
+      sec->section_id = match_p->section_id;
+      flags |= match_p->flags;
+
       bfd_set_section_flags (sec, flags);
       if (flags & SEC_MERGE)
 	sec->entsize = entsize;
-      elf_group_name (sec) = group_name;
+      elf_group_name (sec) = match_p->group_name;
 
       /* Add a symbol for this section to the symbol table.  */
       secsym = symbol_find (name);
@@ -1006,7 +1008,7 @@ obj_elf_section_name (void)
 void
 obj_elf_section (int push)
 {
-  const char *name, *group_name;
+  const char *name;
   char *beg;
   int type, dummy;
   bfd_vma attr;
@@ -1014,7 +1016,7 @@ obj_elf_section (int push)
   int entsize;
   int linkonce;
   subsegT new_subsection = -1;
-  unsigned int info = 0;
+  struct elf_section_match match;
 
   if (flag_mri)
     {
@@ -1040,6 +1042,8 @@ obj_elf_section (int push)
   if (name == NULL)
     return;
 
+  memset (&match, 0, sizeof (match));
+
   symbolS * sym;
   if ((sym = symbol_find (name)) != NULL
       && ! symbol_section_p (sym)
@@ -1054,7 +1058,6 @@ obj_elf_section (int push)
   type = SHT_NULL;
   attr = 0;
   gnu_attr = 0;
-  group_name = NULL;
   entsize = 0;
   linkonce = 0;
 
@@ -1159,8 +1162,8 @@ obj_elf_section (int push)
 	  if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
 	    {
 	      ++input_line_pointer;
-	      group_name = obj_elf_section_name ();
-	      if (group_name == NULL)
+	      match.group_name = obj_elf_section_name ();
+	      if (match.group_name == NULL)
 		attr &= ~SHF_GROUP;
 	      else if (*input_line_pointer == ',')
 		{
@@ -1186,26 +1189,86 @@ obj_elf_section (int push)
 	      const char *now_group = elf_group_name (now_seg);
 	      if (now_group != NULL)
 		{
-		  group_name = xstrdup (now_group);
+		  match.group_name = xstrdup (now_group);
 		  linkonce = (now_seg->flags & SEC_LINK_ONCE) != 0;
 		}
 	    }
 
 	  if ((gnu_attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',')
 	    {
+	      char *save = input_line_pointer;
 	      ++input_line_pointer;
 	      SKIP_WHITESPACE ();
 	      if (ISDIGIT (* input_line_pointer))
 		{
 		  char *t = input_line_pointer;
-		  info = strtoul (input_line_pointer,
-				  &input_line_pointer, 0);
-		  if (info == (unsigned int) -1)
+		  match.info = strtoul (input_line_pointer,
+					&input_line_pointer, 0);
+		  if (match.info == (unsigned int) -1)
 		    {
 		      as_warn (_("unsupported mbind section info: %s"), t);
-		      info = 0;
+		      match.info = 0;
 		    }
 		}
+	      else
+		input_line_pointer = save;
+	    }
+
+	  if (*input_line_pointer == ',')
+	    {
+	      char *save = input_line_pointer;
+	      ++input_line_pointer;
+	      SKIP_WHITESPACE ();
+	      if (strncmp (input_line_pointer, "unique", 6) == 0)
+		{
+		  input_line_pointer += 6;
+		  SKIP_WHITESPACE ();
+		  if (*input_line_pointer == ',')
+		    {
+		      ++input_line_pointer;
+		      SKIP_WHITESPACE ();
+		      if (ISDIGIT (* input_line_pointer))
+			{
+			  bfd_vma id;
+			  bfd_boolean overflow;
+			  char *t = input_line_pointer;
+			  if (sizeof (bfd_vma) <= sizeof (unsigned long))
+			    {
+			      errno = 0;
+			      id = strtoul (input_line_pointer,
+					    &input_line_pointer, 0);
+			      overflow = (id == (unsigned long) -1
+					  && errno == ERANGE);
+			    }
+			  else
+			    {
+			      id = bfd_scan_vma
+				(input_line_pointer,
+				 (const char **) &input_line_pointer, 0);
+			      overflow = id == ~(bfd_vma) 0;
+			    }
+			  if (overflow || id > (unsigned int) -1)
+			    {
+			      char *linefeed, saved_char = 0;
+			      if ((linefeed = strchr (t, '\n')) != NULL)
+				{
+				  saved_char = *linefeed;
+				  *linefeed = '\0';
+				}
+			      as_bad (_("unsupported section id: %s"), t);
+			      if (saved_char)
+				*linefeed = saved_char;
+			    }
+			  else
+			    {
+			      match.section_id = id;
+			      match.flags |= SEC_ASSEMBLER_SECTION_ID;
+			    }
+			}
+		    }
+		}
+	      else
+		input_line_pointer = save;
 	    }
 	}
       else
@@ -1238,8 +1301,8 @@ obj_elf_section (int push)
 done:
   demand_empty_rest_of_line ();
 
-  obj_elf_change_section (name, type, info, attr, entsize, group_name,
-			  linkonce, push);
+  obj_elf_change_section (name, type, attr, entsize, &match, linkonce,
+			  push);
 
   if ((gnu_attr & SHF_GNU_MBIND) != 0)
     {
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
index b0a5a2d7b82..7cfcc254823 100644
--- a/gas/config/obj-elf.h
+++ b/gas/config/obj-elf.h
@@ -77,6 +77,16 @@ struct elf_obj_sy
 #endif
 };
 
+/* Match section group name, the sh_info field and the section_id
+   field.  */
+struct elf_section_match
+{
+  const char *group_name;
+  unsigned int info;
+  unsigned int section_id;
+  flagword flags;
+};
+
 #define OBJ_SYMFIELD_TYPE struct elf_obj_sy
 
 #ifndef FALSE
@@ -162,7 +172,7 @@ extern void obj_elf_common (int);
 extern void obj_elf_data (int);
 extern void obj_elf_text (int);
 extern void obj_elf_change_section
-  (const char *, unsigned int, unsigned int, bfd_vma, int, const char *,
+  (const char *, unsigned int, bfd_vma, int, struct elf_section_match *,
    int, int);
 extern void obj_elf_vtable_inherit (int);
 extern void obj_elf_vtable_entry (int);
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index bb0b03e35ea..26a76f3fe12 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -27011,7 +27011,7 @@ start_unwind_section (const segT text_seg, int idx)
   const char * text_name;
   const char * prefix;
   const char * prefix_once;
-  const char * group_name;
+  struct elf_section_match match;
   char * sec_name;
   int type;
   int flags;
@@ -27045,13 +27045,13 @@ start_unwind_section (const segT text_seg, int idx)
 
   flags = SHF_ALLOC;
   linkonce = 0;
-  group_name = 0;
+  memset (&match, 0, sizeof (match));
 
   /* Handle COMDAT group.  */
   if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
     {
-      group_name = elf_group_name (text_seg);
-      if (group_name == NULL)
+      match.group_name = elf_group_name (text_seg);
+      if (match.group_name == NULL)
 	{
 	  as_bad (_("Group section `%s' has no group signature"),
 		  segment_name (text_seg));
@@ -27062,7 +27062,7 @@ start_unwind_section (const segT text_seg, int idx)
       linkonce = 1;
     }
 
-  obj_elf_change_section (sec_name, type, 0, flags, 0, group_name,
+  obj_elf_change_section (sec_name, type, flags, 0, &match,
 			  linkonce, 0);
 
   /* Set the section link for index tables.  */
diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c
index fbddd54120a..f908ba51fa3 100644
--- a/gas/config/tc-ia64.c
+++ b/gas/config/tc-ia64.c
@@ -1139,7 +1139,7 @@ obj_elf_vms_common (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 
   obj_elf_change_section
-    (sec_name, SHT_NOBITS, 0,
+    (sec_name, SHT_NOBITS,
      SHF_ALLOC | SHF_WRITE | SHF_IA_64_VMS_OVERLAID | SHF_IA_64_VMS_GLOBAL,
      0, NULL, 1, 0);
 
diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
index f4ae298b5b8..24ea3582447 100644
--- a/gas/config/tc-microblaze.c
+++ b/gas/config/tc-microblaze.c
@@ -149,7 +149,7 @@ static void
 microblaze_s_data (int ignore ATTRIBUTE_UNUSED)
 {
 #ifdef OBJ_ELF
-  obj_elf_change_section (".data", SHT_PROGBITS, 0, SHF_ALLOC+SHF_WRITE,
+  obj_elf_change_section (".data", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE,
 			  0, 0, 0, 0);
 #else
   s_data (ignore);
@@ -162,7 +162,7 @@ static void
 microblaze_s_sdata (int ignore ATTRIBUTE_UNUSED)
 {
 #ifdef OBJ_ELF
-  obj_elf_change_section (".sdata", SHT_PROGBITS, 0, SHF_ALLOC+SHF_WRITE,
+  obj_elf_change_section (".sdata", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE,
 			  0, 0, 0, 0);
 #else
   s_data (ignore);
@@ -281,7 +281,7 @@ microblaze_s_rdata (int localvar)
   if (localvar == 0)
     {
       /* rodata.  */
-      obj_elf_change_section (".rodata", SHT_PROGBITS, 0, SHF_ALLOC,
+      obj_elf_change_section (".rodata", SHT_PROGBITS, SHF_ALLOC,
 			      0, 0, 0, 0);
       if (rodata_segment == 0)
 	rodata_segment = subseg_new (".rodata", 0);
@@ -289,7 +289,7 @@ microblaze_s_rdata (int localvar)
   else
     {
       /* 1 .sdata2.  */
-      obj_elf_change_section (".sdata2", SHT_PROGBITS, 0, SHF_ALLOC,
+      obj_elf_change_section (".sdata2", SHT_PROGBITS, SHF_ALLOC,
 			      0, 0, 0, 0);
     }
 #else
@@ -302,12 +302,12 @@ microblaze_s_bss (int localvar)
 {
 #ifdef OBJ_ELF
   if (localvar == 0) /* bss.  */
-    obj_elf_change_section (".bss", SHT_NOBITS, 0, SHF_ALLOC+SHF_WRITE,
+    obj_elf_change_section (".bss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE,
 			    0, 0, 0, 0);
   else if (localvar == 1)
     {
       /* sbss.  */
-      obj_elf_change_section (".sbss", SHT_NOBITS, 0, SHF_ALLOC+SHF_WRITE,
+      obj_elf_change_section (".sbss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE,
 			      0, 0, 0, 0);
       if (sbss_segment == 0)
 	sbss_segment = subseg_new (".sbss", 0);
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index fc6898834e7..6244d8ac091 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -16418,7 +16418,7 @@ s_change_section (int ignore ATTRIBUTE_UNUSED)
   if (section_type == SHT_MIPS_DWARF)
     section_type = SHT_PROGBITS;
 
-  obj_elf_change_section (section_name, section_type, 0, section_flag,
+  obj_elf_change_section (section_name, section_type, section_flag,
 			  section_entry_size, 0, 0, 0);
 
   if (now_seg->name != section_name)
diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c
index 57538824e92..840e5137ae7 100644
--- a/gas/config/tc-msp430.c
+++ b/gas/config/tc-msp430.c
@@ -620,7 +620,7 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED)
   subseg = now_subseg;
 
   /* Now go to .profiler section.  */
-  obj_elf_change_section (".profiler", SHT_PROGBITS, 0, 0, 0, 0, 0, 0);
+  obj_elf_change_section (".profiler", SHT_PROGBITS, 0, 0, 0, 0, 0);
 
   /* Save flags.  */
   emit_expr (& exp, 2);
diff --git a/gas/config/tc-rx.c b/gas/config/tc-rx.c
index b406e03b079..febdb5ab956 100644
--- a/gas/config/tc-rx.c
+++ b/gas/config/tc-rx.c
@@ -491,7 +491,7 @@ parse_rx_section (char * name)
       else
 	type = SHT_NOBITS;
 
-      obj_elf_change_section (name, type, 0, attr, 0, NULL, FALSE, FALSE);
+      obj_elf_change_section (name, type, attr, 0, NULL, FALSE, FALSE);
     }
   else /* Try not to redefine a section, especially B_1.  */
     {
@@ -506,7 +506,7 @@ parse_rx_section (char * name)
 	| ((flags & SEC_STRINGS) ? SHF_STRINGS : 0)
 	| ((flags & SEC_THREAD_LOCAL) ? SHF_TLS : 0);
 
-      obj_elf_change_section (name, type, 0, attr, 0, NULL, FALSE, FALSE);
+      obj_elf_change_section (name, type, attr, 0, NULL, FALSE, FALSE);
     }
 
   bfd_set_section_alignment (now_seg, align);
diff --git a/gas/config/tc-tic6x.c b/gas/config/tc-tic6x.c
index 9a506ed1e55..9f5b24e648d 100644
--- a/gas/config/tc-tic6x.c
+++ b/gas/config/tc-tic6x.c
@@ -4606,7 +4606,7 @@ tic6x_start_unwind_section (const segT text_seg, int idx)
   const char * text_name;
   const char * prefix;
   const char * prefix_once;
-  const char * group_name;
+  struct elf_section_match match;
   size_t prefix_len;
   size_t text_len;
   char * sec_name;
@@ -4649,13 +4649,13 @@ tic6x_start_unwind_section (const segT text_seg, int idx)
 
   flags = SHF_ALLOC;
   linkonce = 0;
-  group_name = 0;
+  memset (&match, 0, sizeof (match));
 
   /* Handle COMDAT group.  */
   if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
     {
-      group_name = elf_group_name (text_seg);
-      if (group_name == NULL)
+      match.group_name = elf_group_name (text_seg);
+      if (match.group_name == NULL)
 	{
 	  as_bad (_("group section `%s' has no group signature"),
 		  segment_name (text_seg));
@@ -4666,7 +4666,7 @@ tic6x_start_unwind_section (const segT text_seg, int idx)
       linkonce = 1;
     }
 
-  obj_elf_change_section (sec_name, type, 0, flags, 0, group_name,
+  obj_elf_change_section (sec_name, type, flags, 0, &match,
 			  linkonce, 0);
 
   /* Set the section link for index tables.  */
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index fa155096159..c86c38c1f03 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -6693,6 +6693,11 @@ particular section belongs.  The optional linkage field can contain:
 indicates that only one copy of this section should be retained
 @item .gnu.linkonce
 an alias for comdat
+
+@item unique,@code{<number>}
+assigns @code{<number>} as a unique section ID to distinguish different
+sections with the same section name.  The valid values of @code{<number>}
+are between 0 and 4294967295.
 @end table
 
 Note: if both the @var{M} and @var{G} flags are present then the fields for
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 5a298fe5832..08c6830e0db 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -245,6 +245,10 @@ if { [is_elf_format] } then {
     run_dump_test "section12b"
     run_dump_test "section13"
     run_dump_test "section14"
+    run_dump_test "section15"
+    run_dump_test "section16a"
+    run_dump_test "section16b"
+    run_dump_test "section17"
     run_dump_test "dwarf2-1" $dump_opts
     run_dump_test "dwarf2-2" $dump_opts
     run_dump_test "dwarf2-3" $dump_opts
diff --git a/gas/testsuite/gas/elf/section15.d b/gas/testsuite/gas/elf/section15.d
new file mode 100644
index 00000000000..a7cda1394f4
--- /dev/null
+++ b/gas/testsuite/gas/elf/section15.d
@@ -0,0 +1,24 @@
+#objdump: -s
+#name: elf section15
+# .pushsection always creates the named section, but the
+# test harness translates ".text" into "P" for the RX...
+#notarget: rx-*
+
+.*: +file format .*
+
+# The MIPS includes a 'section .reginfo' and such here.
+#...
+Contents of section .bar:
+ 0000 00000000 00000000 0000 .*
+Contents of section .bar:
+ 0000 0102 .*
+Contents of section .bar:
+ 0000 0102 .*
+Contents of section .bar:
+ 0000 0103 .*
+Contents of section .bar:
+ 0000 04 .*
+Contents of section .text:
+ 0000 feff .*
+# Arm includes a .ARM.attributes section here
+#...
diff --git a/gas/testsuite/gas/elf/section15.s b/gas/testsuite/gas/elf/section15.s
new file mode 100644
index 00000000000..949cd84f89d
--- /dev/null
+++ b/gas/testsuite/gas/elf/section15.s
@@ -0,0 +1,38 @@
+	.section .bar,"a",unique,0
+	.byte 0
+ .pushsection .bar,2,"a",unique,1
+	.byte 2
+ .popsection
+	.byte 0
+ .pushsection .bar,3,"a",unique,2
+	.byte 2
+ .popsection
+	.byte 0
+ .pushsection .bar,2,"a", %progbits,unique,3
+	.byte 3
+ .popsection
+	.byte 0
+ .pushsection .bar,"",unique,4
+	.byte 4
+ .popsection
+	.byte 0
+ .pushsection .text,1,"axG",%progbits,foo,comdat,unique,0xffffffff
+	.byte -1
+ .popsection
+	.byte 0
+ .pushsection .text,"axG",%progbits,foo,comdat,unique,0xffffffff
+	.byte -2
+ .popsection
+	.byte 0
+ .pushsection .bar,"a",unique,1
+	.byte 1
+ .popsection
+	.byte 0
+ .pushsection .bar,"a", %progbits,unique,3
+	.byte 1
+ .popsection
+	.byte 0
+ .pushsection .bar,"a",unique,2
+	.byte 1
+ .popsection
+	.byte 0
diff --git a/gas/testsuite/gas/elf/section16.s b/gas/testsuite/gas/elf/section16.s
new file mode 100644
index 00000000000..77e20a368f7
--- /dev/null
+++ b/gas/testsuite/gas/elf/section16.s
@@ -0,0 +1,33 @@
+	.section .mbind.data,"adw",%progbits,unique,0
+	.byte 1
+
+	.section .mbind.data,"adw",%progbits,0x3,unique,1
+	.byte 2
+
+	.section .mbind.text,"adx",%progbits,unique,2
+	.byte 3
+
+	.section .mbind.text,"adx",%progbits,0x3,unique,3
+	.byte 4
+
+	.section .mbind.bss,"adw",%nobits,unique,4
+	.zero 5
+
+	.section .mbind.bss,"adw",%nobits,0x3,unique,5
+	.zero 6
+
+	.section .mbind.rodata,"adG",%progbits,.foo_group,comdat,0x2,unique,6
+	.byte 7
+
+	.section .mbind.data,"adGw",%progbits,.foo_group,comdat,unique,7
+	.byte 8
+
+	.section .mbind.data,"adGw",%progbits,.foo_group,comdat,0x3,unique,8
+	.byte 9
+
+	# Check that .pushsection works as well.
+	.pushsection .mbind.text,"adGx",%progbits,.foo_group,comdat,0x3,unique,9
+	.byte 10
+
+	.popsection
+	.byte 11
diff --git a/gas/testsuite/gas/elf/section16a.d b/gas/testsuite/gas/elf/section16a.d
new file mode 100644
index 00000000000..d1abf570c61
--- /dev/null
+++ b/gas/testsuite/gas/elf/section16a.d
@@ -0,0 +1,36 @@
+#source: section16.s
+#as: --no-pad-sections
+#readelf: -Sg --wide
+#name: mbind sections
+# A number of targets do not support SHF_GNU_MBIND
+#xfail: arm*-*-netbsdelf* arm*-*-nto* msp430-*-* visium-*-*
+#xfail: *-*-hpux* *-*-cloudabi
+
+#...
+  \[[ 0-9]+\] \.mbind\.data[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+1 00 WAD  0   0  1
+#...
+  \[[ 0-9]+\] \.mbind\.data[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+1 00 WAD  0   3  1
+#...
+  \[[ 0-9]+\] \.mbind\.text[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+1 00 AXD  0   0  .
+#...
+  \[[ 0-9]+\] \.mbind\.text[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+1 00 AXD  0   3  .
+#...
+  \[[ 0-9]+\] \.mbind\.bss[ 	]+NOBITS[ 	]+0+0 0+[0-9a-f]+ 0+5 00 WAD  0   0  1
+#...
+  \[[ 0-9]+\] \.mbind\.bss[ 	]+NOBITS[ 	]+0+0 0+[0-9a-f]+ 0+6 00 WAD  0   3  1
+#...
+  \[[ 0-9]+\] \.mbind\.rodata[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+1 00 AGD  0   2  1
+#...
+  \[[ 0-9]+\] \.mbind\.data[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+1 00 WAGD  0   0  1
+#...
+  \[[ 0-9]+\] \.mbind\.data[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+2 00 WAGD  0   3  1
+#...
+  \[[ 0-9]+\] \.mbind\.text[ 	]+PROGBITS[ 	]+0+0 0+[0-9a-f]+ 0+1 00 AXGD  0   3  1
+#...
+COMDAT group section \[    1\] `\.group' \[\.foo_group\] contains . sections:
+[ 	]+\[Index\][ 	]+Name
+[ 	]+\[[ 0-9]+][ 	]+\.mbind\.rodata
+[ 	]+\[[ 0-9]+][ 	]+\.mbind\.data
+[ 	]+\[[ 0-9]+][ 	]+\.mbind\.data
+[ 	]+\[[ 0-9]+][ 	]+\.mbind\.text
+#pass
diff --git a/gas/testsuite/gas/elf/section16b.d b/gas/testsuite/gas/elf/section16b.d
new file mode 100644
index 00000000000..a146c0de7e1
--- /dev/null
+++ b/gas/testsuite/gas/elf/section16b.d
@@ -0,0 +1,36 @@
+#source: section16.s
+#as: --no-pad-sections
+#objdump: -s
+#name: mbind section contents
+# RX annoyingly reorders the sections so that they do not match the sequence
+# expected below.
+#xfail: rx-*-*
+# A number of targets do not support SHF_GNU_MBIND
+#xfail: arm*-*-netbsdelf* arm*-*-nto* msp430-*-* visium-*-*
+#xfail: *-*-hpux* *-*-cloudabi
+
+#...
+Contents of section .mbind.data:
+ 0000 01                                   .               
+#...
+Contents of section .mbind.data:
+ 0000 02                                   .               
+#...
+Contents of section .mbind.text:
+ 0000 03                                   .               
+#...
+Contents of section .mbind.text:
+ 0000 04                                   .               
+#...
+Contents of section .mbind.rodata:
+ 0000 07                                   .               
+#...
+Contents of section .mbind.data:
+ 0000 08                                   .               
+#...
+Contents of section .mbind.data:
+ 0000 090b                                 ..              
+#...
+Contents of section .mbind.text:
+ 0000 0a                                   .               
+#pass
diff --git a/gas/testsuite/gas/elf/section17.d b/gas/testsuite/gas/elf/section17.d
new file mode 100644
index 00000000000..3efdc22abfe
--- /dev/null
+++ b/gas/testsuite/gas/elf/section17.d
@@ -0,0 +1,2 @@
+#name: incorrect section ID
+#error_output: section17.l
diff --git a/gas/testsuite/gas/elf/section17.l b/gas/testsuite/gas/elf/section17.l
new file mode 100644
index 00000000000..5b3e2b6d340
--- /dev/null
+++ b/gas/testsuite/gas/elf/section17.l
@@ -0,0 +1,4 @@
+[^:]*: Assembler messages:
+[^:]*:1: Error: unsupported section id: 0x100000000
+[^:]*:3: Error: junk at end of line, first unrecognized character is `f'
+[^:]*:5: Error: junk at end of line, first unrecognized character is `,'
diff --git a/gas/testsuite/gas/elf/section17.s b/gas/testsuite/gas/elf/section17.s
new file mode 100644
index 00000000000..43de1d7f2b6
--- /dev/null
+++ b/gas/testsuite/gas/elf/section17.s
@@ -0,0 +1,6 @@
+	.section .data,"aw",%progbits,unique,0x100000000
+	.byte 0
+	.section .bss,"aw",%nobits,unique,foo
+	.byte 0
+	.section .text,"ax",%progbits,unique,1,foo
+	.byte 0
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index feab8c2be95..ffeff0c101a 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -491,6 +491,7 @@ if [expr ([istarget "i*86-*-*"] ||  [istarget "x86_64-*-*"]) && [gas_32_check]]
     run_list_test "inval-pseudo" "-al"
     run_dump_test "nop-1"
     run_dump_test "nop-2"
+    run_dump_test "unique"
     run_dump_test "optimize-1"
     run_dump_test "optimize-1a"
     run_dump_test "optimize-2"
@@ -1050,6 +1051,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
     run_dump_test "x86-64-movd-intel"
     run_dump_test "x86-64-nop-1"
     run_dump_test "x86-64-nop-2"
+    run_dump_test "x86-64-unique"
     run_dump_test "x86-64-movsxd"
     run_dump_test "x86-64-movsxd-intel"
     run_list_test "x86-64-movsxd-inval" "-al"
diff --git a/gas/testsuite/gas/i386/unique.d b/gas/testsuite/gas/i386/unique.d
new file mode 100644
index 00000000000..0337733d992
--- /dev/null
+++ b/gas/testsuite/gas/i386/unique.d
@@ -0,0 +1,48 @@
+#objdump: -dw
+#name: i386 unique sections
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <foo>:
+ +[a-f0-9]+:	89 c3                	mov    %eax,%ebx
+ +[a-f0-9]+:	c3                   	ret    
+
+Disassembly of section .text:
+
+0+ <bar>:
+ +[a-f0-9]+:	31 c3                	xor    %eax,%ebx
+ +[a-f0-9]+:	c3                   	ret    
+
+Disassembly of section .text:
+
+0+ <foo1>:
+ +[a-f0-9]+:	89 c3                	mov    %eax,%ebx
+ +[a-f0-9]+:	c3                   	ret    
+
+Disassembly of section .text:
+
+0+ <bar1>:
+ +[a-f0-9]+:	01 c3                	add    %eax,%ebx
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	c3                   	ret    
+
+Disassembly of section .text:
+
+0+ <bar2>:
+ +[a-f0-9]+:	29 c3                	sub    %eax,%ebx
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	c3                   	ret    
+
+Disassembly of section .text:
+
+0+ <foo2>:
+ +[a-f0-9]+:	31 c3                	xor    %eax,%ebx
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	c3                   	ret    
+#pass
diff --git a/gas/testsuite/gas/i386/unique.s b/gas/testsuite/gas/i386/unique.s
new file mode 100644
index 00000000000..89b23b0fc66
--- /dev/null
+++ b/gas/testsuite/gas/i386/unique.s
@@ -0,0 +1,36 @@
+	.section .text,"ax",@progbits,unique,1
+foo:
+	mov %eax, %ebx
+	.section .text,"ax",@progbits,unique,2
+bar:
+	xor %eax, %ebx
+	.section .text,"ax",@progbits,unique,1
+	ret
+	.section .text,"ax",@progbits,unique,2
+	ret
+	.section .text,"axG",@progbits,foo,comdat,unique,1
+foo1:
+	mov	%eax, %ebx
+	.section .text,"axG",@progbits,bar,comdat,unique,1
+bar1:
+	add	%eax, %ebx
+	.section .text,"axG",@progbits,bar,comdat,unique,2
+bar2:
+	sub	%eax, %ebx
+	.section .text,"axG",@progbits,foo,comdat,unique,2
+foo2:
+	xor	%eax, %ebx
+	.section .text,"axG",@progbits,bar,comdat,unique,1
+	nop
+	ret
+	.section .text,"axG",@progbits,foo,comdat,unique,1
+	ret
+	.section .text,"axG",@progbits,bar,comdat,unique,2
+	nop
+	nop
+	nop
+	ret
+	.section .text,"axG",@progbits,foo,comdat,unique,2
+	nop
+	nop
+	ret
diff --git a/gas/testsuite/gas/i386/x86-64-unique.d b/gas/testsuite/gas/i386/x86-64-unique.d
new file mode 100644
index 00000000000..4cfd30d5e9d
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-unique.d
@@ -0,0 +1,48 @@
+#source: unique.s
+#objdump: -dw
+#name: 64bit unique sections
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <foo>:
+ +[a-f0-9]+:	89 c3                	mov    %eax,%ebx
+ +[a-f0-9]+:	c3                   	retq   
+
+Disassembly of section .text:
+
+0+ <bar>:
+ +[a-f0-9]+:	31 c3                	xor    %eax,%ebx
+ +[a-f0-9]+:	c3                   	retq   
+
+Disassembly of section .text:
+
+0+ <foo1>:
+ +[a-f0-9]+:	89 c3                	mov    %eax,%ebx
+ +[a-f0-9]+:	c3                   	retq   
+
+Disassembly of section .text:
+
+0+ <bar1>:
+ +[a-f0-9]+:	01 c3                	add    %eax,%ebx
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	c3                   	retq   
+
+Disassembly of section .text:
+
+0+ <bar2>:
+ +[a-f0-9]+:	29 c3                	sub    %eax,%ebx
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	c3                   	retq   
+
+Disassembly of section .text:
+
+0+ <foo2>:
+ +[a-f0-9]+:	31 c3                	xor    %eax,%ebx
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	90                   	nop
+ +[a-f0-9]+:	c3                   	retq   
+#pass
diff --git a/ld/testsuite/ld-i386/pr22001-1c.S b/ld/testsuite/ld-i386/pr22001-1c.S
index 2c1041dba77..51094efce35 100644
--- a/ld/testsuite/ld-i386/pr22001-1c.S
+++ b/ld/testsuite/ld-i386/pr22001-1c.S
@@ -1,7 +1,7 @@
 	.section	.rodata.str1.1,"aMS",@progbits,1
 .LC0:
 	.string	"PASS"
-	.section	.text.startup,"ax",@progbits
+	.section	.text,"ax",@progbits,unique,1
 	.p2align 4,,15
 	.globl	main
 	.type	main, @function
@@ -41,7 +41,7 @@ main:
 	addl	$16, %esp
 	jmp	.L3
 	.size	main, .-main
-	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+	.section .text,"axG",@progbits,__x86.get_pc_thunk.bx,comdat,unique,2
 	.globl	__x86.get_pc_thunk.bx
 	.hidden	__x86.get_pc_thunk.bx
 	.type	__x86.get_pc_thunk.bx, @function
diff --git a/ld/testsuite/ld-i386/tls-gd1.S b/ld/testsuite/ld-i386/tls-gd1.S
index 3b16eab6aa2..cf5c913560c 100644
--- a/ld/testsuite/ld-i386/tls-gd1.S
+++ b/ld/testsuite/ld-i386/tls-gd1.S
@@ -47,15 +47,14 @@ test_gd:
 	movzbl	%al, %eax
 	ret
 	.size	test_gd, .-test_gd
-	.section	.text.unlikely
-	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+	.section .text,"axG",@progbits,__x86.get_pc_thunk.bx,comdat,unique,1
 	.globl	__x86.get_pc_thunk.bx
 	.hidden	__x86.get_pc_thunk.bx
 	.type	__x86.get_pc_thunk.bx, @function
 __x86.get_pc_thunk.bx:
 	movl	(%esp), %ebx
 	ret
-	.section	.text.__x86.get_pc_thunk.cx,"axG",@progbits,__x86.get_pc_thunk.cx,comdat
+	.section .text,"axG",@progbits,__x86.get_pc_thunk.cx,comdat,unique,2
 	.globl	__x86.get_pc_thunk.cx
 	.hidden	__x86.get_pc_thunk.cx
 	.type	__x86.get_pc_thunk.cx, @function
diff --git a/ld/testsuite/ld-x86-64/pr21481b.S b/ld/testsuite/ld-x86-64/pr21481b.S
index 583ec77d121..d66c86f2286 100644
--- a/ld/testsuite/ld-x86-64/pr21481b.S
+++ b/ld/testsuite/ld-x86-64/pr21481b.S
@@ -1,4 +1,4 @@
-	.section	.rodata.str1.1,"aMS",@progbits,1
+	.section .rodata.foo,"aMS",@progbits,1,unique,1
 .LC0:
 	.string	"PASS"
 	.text
@@ -40,7 +40,7 @@ call_func1:
 	jmp	*func1@GOTPCREL(%rip)
 	.size	call_func1, .-call_func1
 	.globl	func1_p
-	.section	.rodata,"a",@progbits
+	.section .rodata.foo,"a",@progbits,unique,2
 	.align 8
 	.size	func1_p, 8
 	.type	func1_p, @object
-- 
2.24.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-02-03  1:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-02 17:51 [PATCH] ELF: Add support for unique section ID to assembler H.J. Lu
2020-02-03  0:22 ` Alan Modra
2020-02-03  1:05   ` H.J. Lu
2020-02-03  1:10     ` Fangrui Song
2020-02-03  1:16       ` H.J. Lu

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).