diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2020-02-06 18:04:58 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2020-02-06 18:05:10 -0800 |
commit | b7d072167715829eed0622616f6ae0182900de3e (patch) | |
tree | 5015f461be45da594a9a8b5e80356e083033224e /gas/config/obj-elf.c | |
parent | 3c83b08abfff01d45ce78cabd29e83923b270c3b (diff) | |
download | gdb-b7d072167715829eed0622616f6ae0182900de3e.zip gdb-b7d072167715829eed0622616f6ae0182900de3e.tar.gz 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.c | 52 |
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 |