forked from Imagelibrary/binutils-gdb
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.
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user