This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ELF: Add support for unique section ID to assembler
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: binutils at sourceware dot org
- Date: Sun, 2 Feb 2020 09:50:54 -0800
- Subject: [PATCH] ELF: Add support for unique section ID to assembler
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