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.
+2020-02-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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.
+
2020-02-01 Nick Clifton <nickc@redhat.com>
* config.bfd: Move the c30-aout and tic30-aout targets onto the
/* 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;
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. */
}
#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, \
/* 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, */
. {* 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;
.
. 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. *}
.}
.
.#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, \
+2020-02-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR gas/25380
+ * objdump.c (sym_ok): Return FALSE if 2 sections are in the
+ same file with different section pointers.
+
2020-02-01 Nick Clifton <nickc@redhat.com>
* README-how-to-make-a-release: Update with more details on the
{
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
+2020-02-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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.
+
2020-02-02 H.J. Lu <hongjiu.lu@intel.com>
* testsuite/gas/elf/section13.s: Replace @nobits with %nobits.
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
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)
{
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 ();
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;
#endif
else
{
- if (group_name == NULL)
+ if (match_p->group_name == NULL)
as_warn (_("setting incorrect section attributes for %s"),
name);
override = TRUE;
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);
void
obj_elf_section (int push)
{
- const char *name, *group_name;
+ const char *name;
char *beg;
int type, dummy;
bfd_vma attr;
int entsize;
int linkonce;
subsegT new_subsection = -1;
- unsigned int info = 0;
+ struct elf_section_match match;
if (flag_mri)
{
if (name == NULL)
return;
+ memset (&match, 0, sizeof (match));
+
symbolS * sym;
if ((sym = symbol_find (name)) != NULL
&& ! symbol_section_p (sym)
type = SHT_NULL;
attr = 0;
gnu_attr = 0;
- group_name = NULL;
entsize = 0;
linkonce = 0;
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 == ',')
{
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
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)
{
#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
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);
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;
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));
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. */
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);
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);
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);
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);
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
{
#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);
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)
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);
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. */
{
| ((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);
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;
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));
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. */
@code{G} with those same @var{GroupName} and @var{linkage} fields implicitly.
If not, then the @code{?} symbol has no effect.
+The optional @var{unique,@code{<number>}} argument must come last. It
+assigns @var{@code{<number>}} as a unique section ID to distinguish
+different sections with the same section name like these:
+
+@smallexample
+.section @var{name},"@var{flags}",@@@var{type},@var{unique,@code{<number>}}
+.section @var{name},"@var{flags}"G,@@@var{type},@var{GroupName},[@var{linkage}],@var{unique,@code{<number>}}
+.section @var{name},"@var{flags}"MG,@@@var{type},@var{entsize},@var{GroupName}[,@var{linkage}],@var{unique,@code{<number>}}
+@end smallexample
+
+The valid values of @var{@code{<number>}} are between 0 and 4294967295.
+
If no flags are specified, the default flags depend upon the section name. If
the section name is not recognized, the default will be for the section to have
none of the above flags: it will not be allocated in memory, nor writable, nor
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
--- /dev/null
+#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
+#...
--- /dev/null
+ .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
--- /dev/null
+ .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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#name: incorrect section ID
+#error_output: section17.l
--- /dev/null
+[^:]*: 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 `,'
--- /dev/null
+ .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
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"
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"
--- /dev/null
+#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
--- /dev/null
+ .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
--- /dev/null
+#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
+2020-02-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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.
+
2020-01-30 Jan Beulich <jbeulich@suse.com>
* ld.texi: Remove space between @option and brace.
.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
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
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
- .section .rodata.str1.1,"aMS",@progbits,1
+ .section .rodata.foo,"aMS",@progbits,1,unique,1
.LC0:
.string "PASS"
.text
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