aboutsummaryrefslogtreecommitdiff
path: root/gas/config/obj-elf.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-02-06 18:04:58 -0800
committerH.J. Lu <hjl.tools@gmail.com>2020-02-06 18:05:10 -0800
commitb7d072167715829eed0622616f6ae0182900de3e (patch)
tree5015f461be45da594a9a8b5e80356e083033224e /gas/config/obj-elf.c
parent3c83b08abfff01d45ce78cabd29e83923b270c3b (diff)
downloadfsf-binutils-gdb-b7d072167715829eed0622616f6ae0182900de3e.zip
fsf-binutils-gdb-b7d072167715829eed0622616f6ae0182900de3e.tar.gz
fsf-binutils-gdb-b7d072167715829eed0622616f6ae0182900de3e.tar.bz2
ELF: Support the section flag 'o' in .section directive
As shown in https://sourceware.org/bugzilla/show_bug.cgi?id=25490 --gc-sections will silently remove __patchable_function_entries section and generate corrupt result. This patch adds the section flag 'o' to .section directive: .section __patchable_function_entries,"awo",@progbits,foo .section __patchable_function_entries,"awoG",@progbits,foo,foo,comdat .section __patchable_function_entries,"awo",@progbits,bar,unique,4 .section __patchable_function_entries,"awoG",@progbits,foo,foo,comdat,unique,1 which specifies the symbol name which the section references. Assmebler will set its elf_linked_to_section to a local section where the symbol is defined. Linker is updated to call mark_hook if gc_mark of any of its linked-to sections is set after all sections, except for backend specific ones, have been garbage collected. bfd/ PR gas/25381 * bfd-in2.h: Regenerated. * elflink.c (_bfd_elf_gc_mark_extra_sections): Call mark_hook on section if gc_mark of any of its linked-to sections is set and don't set gc_mark again. * section.c (asection): Add linked_to_symbol_name to map_head union. gas/ PR gas/25381 * config/obj-elf.c (get_section): Also check linked_to_symbol_name. (obj_elf_change_section): Also set map_head.linked_to_symbol_name. (obj_elf_parse_section_letters): Handle the 'o' flag. (build_group_lists): Renamed to ... (build_additional_section_info): This. Set elf_linked_to_section from map_head.linked_to_symbol_name. (elf_adjust_symtab): Updated. * config/obj-elf.h (elf_section_match): Add linked_to_symbol_name. * doc/as.texi: Document the 'o' flag. * testsuite/gas/elf/elf.exp: Run PR gas/25381 tests. * testsuite/gas/elf/section18.d: New file. * testsuite/gas/elf/section18.s: Likewise. * testsuite/gas/elf/section19.d: Likewise. * testsuite/gas/elf/section19.s: Likewise. * testsuite/gas/elf/section20.d: Likewise. * testsuite/gas/elf/section20.s: Likewise. * testsuite/gas/elf/section21.d: Likewise. * testsuite/gas/elf/section21.l: Likewise. * testsuite/gas/elf/section21.s: Likewise. ld/ PR ld/24526 PR ld/25021 PR ld/25490 * testsuite/ld-elf/elf.exp: Run PR ld/25490 tests. * testsuite/ld-elf/pr24526.d: New file. * testsuite/ld-elf/pr24526.s: Likewise. * testsuite/ld-elf/pr25021.d: Likewise. * testsuite/ld-elf/pr25021.s: Likewise. * testsuite/ld-elf/pr25490-2-16.rd: Likewise. * testsuite/ld-elf/pr25490-2-32.rd: Likewise. * testsuite/ld-elf/pr25490-2-64.rd: Likewise. * testsuite/ld-elf/pr25490-2.s: Likewise. * testsuite/ld-elf/pr25490-3-16.rd: Likewise. * testsuite/ld-elf/pr25490-3-32.rd: Likewise. * testsuite/ld-elf/pr25490-3-64.rd: Likewise. * testsuite/ld-elf/pr25490-3.s: Likewise. * testsuite/ld-elf/pr25490-4-16.rd: Likewise. * testsuite/ld-elf/pr25490-4-32.rd: Likewise. * testsuite/ld-elf/pr25490-4-64.rd: Likewise. * testsuite/ld-elf/pr25490-4.s: Likewise. * testsuite/ld-elf/pr25490-5-16.rd: Likewise. * testsuite/ld-elf/pr25490-5-32.rd: Likewise. * testsuite/ld-elf/pr25490-5-64.rd: Likewise. * testsuite/ld-elf/pr25490-5.s: Likewise. * testsuite/ld-elf/pr25490-6-16.rd: Likewise. * testsuite/ld-elf/pr25490-6-32.rd: Likewise. * testsuite/ld-elf/pr25490-6-64.rd: Likewise. * testsuite/ld-elf/pr25490-6.s: Likewise.
Diffstat (limited to 'gas/config/obj-elf.c')
-rw-r--r--gas/config/obj-elf.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 2958490..d7a07fe 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -524,6 +524,8 @@ get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *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);
+ const char *linked_to_symbol_name
+ = sec->map_head.linked_to_symbol_name;
unsigned int info = elf_section_data (sec)->this_hdr.sh_info;
return (info == match->info
@@ -533,7 +535,12 @@ get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
&& (group_name == gname
|| (group_name != NULL
&& gname != NULL
- && strcmp (group_name, gname) == 0)));
+ && strcmp (group_name, gname) == 0))
+ && (linked_to_symbol_name == match->linked_to_symbol_name
+ || (linked_to_symbol_name != NULL
+ && match->linked_to_symbol_name != NULL
+ && strcmp (linked_to_symbol_name,
+ match->linked_to_symbol_name) == 0)));
}
/* Handle the .section pseudo-op. This code supports two different
@@ -740,6 +747,10 @@ obj_elf_change_section (const char *name,
sec->section_id = match_p->section_id;
flags |= match_p->flags;
+ /* Set the linked-to symbol name. */
+ sec->map_head.linked_to_symbol_name
+ = match_p->linked_to_symbol_name;
+
bfd_set_section_flags (sec, flags);
if (flags & SEC_MERGE)
sec->entsize = entsize;
@@ -801,6 +812,9 @@ obj_elf_parse_section_letters (char *str, size_t len,
case 'e':
attr |= SHF_EXCLUDE;
break;
+ case 'o':
+ attr |= SHF_LINK_ORDER;
+ break;
case 'w':
attr |= SHF_WRITE;
break;
@@ -841,7 +855,7 @@ obj_elf_parse_section_letters (char *str, size_t len,
default:
{
const char *bad_msg = _("unrecognized .section attribute:"
- " want a,e,w,x,M,S,G,T or number");
+ " want a,e,o,w,x,M,S,G,T or number");
#ifdef md_elf_section_letter
bfd_vma md_attr = md_elf_section_letter (*str, &bad_msg);
if (md_attr != (bfd_vma) -1)
@@ -1154,6 +1168,19 @@ obj_elf_section (int push)
attr &= ~SHF_MERGE;
}
+ if ((attr & SHF_LINK_ORDER) != 0 && *input_line_pointer == ',')
+ {
+ char c;
+ unsigned int length;
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ c = get_symbol_name (& beg);
+ (void) restore_line_pointer (c);
+ length = input_line_pointer - beg;
+ if (length)
+ match.linked_to_symbol_name = xmemdup0 (beg, length);
+ }
+
if ((attr & SHF_GROUP) != 0 && is_clone)
{
as_warn (_("? section flag ignored with G present"));
@@ -2476,10 +2503,12 @@ static struct group_list groups;
/* Called via bfd_map_over_sections. If SEC is a member of a group,
add it to a list of sections belonging to the group. INF is a
pointer to a struct group_list, which is where we store the head of
- each list. */
+ each list. If its link_to_symbol_name isn't NULL, set up its
+ linked-to section. */
static void
-build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
+build_additional_section_info (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec, void *inf)
{
struct group_list *list = (struct group_list *) inf;
const char *group_name = elf_group_name (sec);
@@ -2487,6 +2516,18 @@ build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
unsigned int *elem_idx;
unsigned int *idx_ptr;
+ if (sec->map_head.linked_to_symbol_name)
+ {
+ symbolS *linked_to_sym;
+ linked_to_sym = symbol_find (sec->map_head.linked_to_symbol_name);
+ if (!linked_to_sym || !S_IS_DEFINED (linked_to_sym))
+ as_bad (_("undefined linked-to symbol `%s' on section `%s'"),
+ sec->map_head.linked_to_symbol_name,
+ bfd_section_name (sec));
+ else
+ elf_linked_to_section (sec) = S_GET_SEGMENT (linked_to_sym);
+ }
+
if (group_name == NULL)
return;
@@ -2533,7 +2574,8 @@ elf_adjust_symtab (void)
groups.num_group = 0;
groups.head = NULL;
groups.indexes = hash_new ();
- bfd_map_over_sections (stdoutput, build_group_lists, &groups);
+ bfd_map_over_sections (stdoutput, build_additional_section_info,
+ &groups);
/* Make the SHT_GROUP sections that describe each section group. We
can't set up the section contents here yet, because elf section