This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ELF: Support the section flag 'o' in .section directive
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: binutils at sourceware dot org
- Date: Sun, 2 Feb 2020 18:20:59 -0800
- Subject: [PATCH] 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 set gc_mark if gc_mark of its linked-to section is
set after all sections, including backend specific ones, have been
garbage collected. To make it to work, _bfd_elf_gc_mark_extra_sections
must be called after elf_backend_gc_mark_extra_sections.
bfd/
PR gas/25381
* bfd-in2.h: Regenerated.
* elf32-arm.c (elf32_arm_gc_mark_extra_sections): Call
_bfd_elf_gc_mark_extra_sections last.
* elf32-csky.c (_bfd_elf_gc_mark_extra_sections): Likewise.
* elf32-tic6x.c (elf32_tic6x_gc_mark_extra_sections): Likewise.
* elfxx-mips.c (_bfd_mips_elf_gc_mark_extra_sections): Likewise.
* elflink.c (_bfd_elf_gc_mark_extra_sections): Set gc_mark if
gc_mark of its linked-to section is set.
* 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 gas/25381
* testsuite/ld-elf/elf.exp: Run PR gas/25381 tests.
* testsuite/ld-elf/pr25490-2-32.rd: New file.
* testsuite/ld-elf/pr25490-2-64.rd: Likewise.
* testsuite/ld-elf/pr25490-2.s: 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-32.rd: Likewise.
* testsuite/ld-elf/pr25490-4-64.rd: Likewise.
* testsuite/ld-elf/pr25490-4.s: 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-32.rd: Likewise.
* testsuite/ld-elf/pr25490-6-64.rd: Likewise.
* testsuite/ld-elf/pr25490-6.s: Likewise.
---
bfd/bfd-in2.h | 4 ++-
bfd/elf32-arm.c | 4 +--
bfd/elf32-csky.c | 4 +--
bfd/elf32-tic6x.c | 4 +--
bfd/elflink.c | 13 +++++++-
bfd/elfxx-mips.c | 4 +--
bfd/section.c | 4 ++-
gas/config/obj-elf.c | 52 ++++++++++++++++++++++++++---
gas/config/obj-elf.h | 1 +
gas/doc/as.texi | 27 +++++++++++++++
gas/testsuite/gas/elf/elf.exp | 4 +++
gas/testsuite/gas/elf/section18.d | 8 +++++
gas/testsuite/gas/elf/section18.s | 13 ++++++++
gas/testsuite/gas/elf/section19.d | 8 +++++
gas/testsuite/gas/elf/section19.s | 13 ++++++++
gas/testsuite/gas/elf/section20.d | 17 ++++++++++
gas/testsuite/gas/elf/section20.s | 13 ++++++++
gas/testsuite/gas/elf/section21.d | 2 ++
gas/testsuite/gas/elf/section21.l | 4 +++
gas/testsuite/gas/elf/section21.s | 15 +++++++++
ld/testsuite/ld-elf/elf.exp | 50 +++++++++++++++++++++++++++
ld/testsuite/ld-elf/pr25490-2-32.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-2-64.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-2.s | 9 +++++
ld/testsuite/ld-elf/pr25490-3-32.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-3-64.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-3.s | 18 ++++++++++
ld/testsuite/ld-elf/pr25490-4-32.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-4-64.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-4.s | 18 ++++++++++
ld/testsuite/ld-elf/pr25490-5-32.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-5-64.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-5.s | 17 ++++++++++
ld/testsuite/ld-elf/pr25490-6-32.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-6-64.rd | 7 ++++
ld/testsuite/ld-elf/pr25490-6.s | 28 ++++++++++++++++
36 files changed, 408 insertions(+), 16 deletions(-)
create mode 100644 gas/testsuite/gas/elf/section18.d
create mode 100644 gas/testsuite/gas/elf/section18.s
create mode 100644 gas/testsuite/gas/elf/section19.d
create mode 100644 gas/testsuite/gas/elf/section19.s
create mode 100644 gas/testsuite/gas/elf/section20.d
create mode 100644 gas/testsuite/gas/elf/section20.s
create mode 100644 gas/testsuite/gas/elf/section21.d
create mode 100644 gas/testsuite/gas/elf/section21.l
create mode 100644 gas/testsuite/gas/elf/section21.s
create mode 100644 ld/testsuite/ld-elf/pr25490-2-32.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-2-64.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-2.s
create mode 100644 ld/testsuite/ld-elf/pr25490-3-32.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-3-64.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-3.s
create mode 100644 ld/testsuite/ld-elf/pr25490-4-32.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-4-64.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-4.s
create mode 100644 ld/testsuite/ld-elf/pr25490-5-32.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-5-64.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-5.s
create mode 100644 ld/testsuite/ld-elf/pr25490-6-32.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-6-64.rd
create mode 100644 ld/testsuite/ld-elf/pr25490-6.s
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 09a5a39ff5e..2d26b81db38 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1185,10 +1185,12 @@ typedef struct bfd_section
/* Early in the link process, map_head and map_tail are used to build
a list of input sections attached to an output section. Later,
output sections use these fields for a list of bfd_link_order
- structs. */
+ structs. The linked_to_symbol_name field is for ELF assembler
+ internal use. */
union {
struct bfd_link_order *link_order;
struct bfd_section *s;
+ const char *linked_to_symbol_name;
} map_head, map_tail;
} asection;
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index faf8376f200..a6df8f331ce 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -15939,8 +15939,6 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
bfd_boolean debug_sec_need_to_be_marked = FALSE;
asection *isec;
- _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
-
out_attr = elf_known_obj_attributes_proc (info->output_bfd);
is_v8m = out_attr[Tag_CPU_arch].i >= TAG_CPU_ARCH_V8M_BASE
&& out_attr[Tag_CPU_arch_profile].i == 'M';
@@ -16024,6 +16022,8 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
first_bfd_browse = FALSE;
}
+ _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
+
return TRUE;
}
diff --git a/bfd/elf32-csky.c b/bfd/elf32-csky.c
index 04214f28ea5..3c5fcc82f5a 100644
--- a/bfd/elf32-csky.c
+++ b/bfd/elf32-csky.c
@@ -3032,8 +3032,6 @@ elf32_csky_gc_mark_extra_sections (struct bfd_link_info *info,
{
bfd *sub;
- _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
-
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
asection *o;
@@ -3043,6 +3041,8 @@ elf32_csky_gc_mark_extra_sections (struct bfd_link_info *info,
o->gc_mark = 1;
}
+ _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
+
return TRUE;
}
diff --git a/bfd/elf32-tic6x.c b/bfd/elf32-tic6x.c
index 39ca6992007..6308eded0b4 100644
--- a/bfd/elf32-tic6x.c
+++ b/bfd/elf32-tic6x.c
@@ -1935,8 +1935,6 @@ elf32_tic6x_gc_mark_extra_sections (struct bfd_link_info *info,
Elf_Internal_Shdr **elf_shdrp;
bfd_boolean again;
- _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
-
/* Marking EH data may cause additional code sections to be marked,
requiring multiple passes. */
again = TRUE;
@@ -1970,6 +1968,8 @@ elf32_tic6x_gc_mark_extra_sections (struct bfd_link_info *info,
}
}
+ _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
+
return TRUE;
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e4d92952aaf..8ad13b8b55f 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -13312,7 +13312,9 @@ _bfd_elf_gc_mark_debug_special_section_group (asection *grp)
}
}
-/* Keep debug and special sections. */
+/* Keep debug and special sections. NB: This function must be called
+ after elf_backend_gc_mark_extra_sections so that linked-to section
+ can be checkd properly. */
bfd_boolean
_bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
@@ -13345,6 +13347,15 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
&& (isec->flags & SEC_ALLOC) != 0
&& elf_section_type (isec) != SHT_NOTE)
some_kept = TRUE;
+ else
+ {
+ /* Since all sections, including backend specific ones,
+ have been garbage collected, mark this section if its
+ linked-to section is marked. */
+ asection *linked_to_sec = elf_linked_to_section (isec);
+ if (linked_to_sec && linked_to_sec->gc_mark)
+ isec->gc_mark = 1;
+ }
if (!debug_frag_seen
&& (isec->flags & SEC_DEBUGGING)
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index d7e3aed3b67..a2d6ace3236 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -12845,8 +12845,6 @@ _bfd_mips_elf_gc_mark_extra_sections (struct bfd_link_info *info,
{
bfd *sub;
- _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
-
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
asection *o;
@@ -12863,6 +12861,8 @@ _bfd_mips_elf_gc_mark_extra_sections (struct bfd_link_info *info,
}
}
+ _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
+
return TRUE;
}
diff --git a/bfd/section.c b/bfd/section.c
index 0c15a0d646f..7de0a2d7a85 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -544,10 +544,12 @@ CODE_FRAGMENT
. {* Early in the link process, map_head and map_tail are used to build
. a list of input sections attached to an output section. Later,
. output sections use these fields for a list of bfd_link_order
-. structs. *}
+. structs. The linked_to_symbol_name field is for ELF assembler
+. internal use. *}
. union {
. struct bfd_link_order *link_order;
. struct bfd_section *s;
+. const char *linked_to_symbol_name;
. } map_head, map_tail;
.} asection;
.
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 2958490c323..d7a07fec6bf 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
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
index 7cfcc254823..54af9ebc0e2 100644
--- a/gas/config/obj-elf.h
+++ b/gas/config/obj-elf.h
@@ -82,6 +82,7 @@ struct elf_obj_sy
struct elf_section_match
{
const char *group_name;
+ const char *linked_to_symbol_name;
unsigned int info;
unsigned int section_id;
flagword flags;
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 152bbfdd009..1554c51ad2f 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -6599,6 +6599,9 @@ section is allocatable
section is a GNU_MBIND section
@item e
section is excluded from executable and shared library.
+@item o
+section references a symbol defined in another section (the linked-to
+section) in the same file.
@item w
section is writable
@item x
@@ -6678,6 +6681,23 @@ which is a suffix of a larger string is considered a duplicate. Thus
@code{"def"} will be merged with @code{"abcdef"}; A reference to the first
@code{"def"} will be changed to a reference to @code{"abcdef"+3}.
+If @var{flags} contains the @code{o} flag, then the @var{type} argument
+must be present along with an additional field like this:
+
+@smallexample
+.section @var{name},"@var{flags}"o,@@@var{type},@var{SymbolName}
+@end smallexample
+
+The @var{SymbolName} field specifies the symbol name which the section
+references.
+
+Note: If both the @var{M} and @var{o} flags are present, then the fields
+for the Merge flag should come first, like this:
+
+@smallexample
+.section @var{name},"@var{flags}"Mo,@@@var{type},@var{entsize},@var{SymbolName}
+@end smallexample
+
If @var{flags} contains the @code{G} symbol then the @var{type} argument must
be present along with an additional field like this:
@@ -6702,6 +6722,13 @@ the Merge flag should come first, like this:
.section @var{name} , "@var{flags}"MG, @@@var{type}, @var{entsize}, @var{GroupName}[, @var{linkage}]
@end smallexample
+If both @code{o} flag and @code{G} flag are present, then the
+@var{SymbolName} field for @code{o} comes first, like this:
+
+@smallexample
+.section @var{name},"@var{flags}"oG,@@@var{type},@var{SymbolName},@var{GroupName}[,@var{linkage}]
+@end smallexample
+
If @var{flags} contains the @code{?} symbol then it may not also contain the
@code{G} symbol and the @var{GroupName} or @var{linkage} fields should not be
present. Instead, @code{?} says to consider the section that's current before
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 08c6830e0db..0f9b2672c4c 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -249,6 +249,10 @@ if { [is_elf_format] } then {
run_dump_test "section16a"
run_dump_test "section16b"
run_dump_test "section17"
+ run_dump_test "section18"
+ run_dump_test "section19"
+ run_dump_test "section20"
+ run_dump_test "section21"
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/section18.d b/gas/testsuite/gas/elf/section18.d
new file mode 100644
index 00000000000..a00b4a65f95
--- /dev/null
+++ b/gas/testsuite/gas/elf/section18.d
@@ -0,0 +1,8 @@
+#readelf: -SW
+#name: linked-to section 1
+
+#...
+ +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[48] +00 +WAL +.*
+#...
+ +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[48] +00 +WAL +.*
+#pass
diff --git a/gas/testsuite/gas/elf/section18.s b/gas/testsuite/gas/elf/section18.s
new file mode 100644
index 00000000000..d51eb681318
--- /dev/null
+++ b/gas/testsuite/gas/elf/section18.s
@@ -0,0 +1,13 @@
+ .text
+foo:
+ .section __patchable_function_entries,"awo",%progbits,foo
+ .dc.a .LPFE1
+ .text
+.LPFE1:
+ .byte 0
+ .section __patchable_function_entries,"awo",%progbits,bar
+ .dc.a .LPFE2
+ .text
+bar:
+.LPFE2:
+ .byte 0
diff --git a/gas/testsuite/gas/elf/section19.d b/gas/testsuite/gas/elf/section19.d
new file mode 100644
index 00000000000..4e500ad3bd2
--- /dev/null
+++ b/gas/testsuite/gas/elf/section19.d
@@ -0,0 +1,8 @@
+#readelf: -SW
+#name: linked-to section 2
+
+#...
+ +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[48] +00 +WAL +.*
+#...
+ +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[48] +00 +WAL +.*
+#pass
diff --git a/gas/testsuite/gas/elf/section19.s b/gas/testsuite/gas/elf/section19.s
new file mode 100644
index 00000000000..7d30ea1ff9c
--- /dev/null
+++ b/gas/testsuite/gas/elf/section19.s
@@ -0,0 +1,13 @@
+ .section .text,"ax",%progbits,unique,20
+foo:
+ .section __patchable_function_entries,"awo",%progbits,foo,unique,2
+ .dc.a .LPFE1
+ .section .text,"ax",%progbits,unique,20
+.LPFE1:
+ .byte 0
+ .section __patchable_function_entries,"awo",%progbits,bar,unique,102
+ .dc.a .LPFE2
+ .section .text,"ax",%progbits,unique,2
+bar:
+.LPFE2:
+ .byte 0
diff --git a/gas/testsuite/gas/elf/section20.d b/gas/testsuite/gas/elf/section20.d
new file mode 100644
index 00000000000..3e0b023f7ac
--- /dev/null
+++ b/gas/testsuite/gas/elf/section20.d
@@ -0,0 +1,17 @@
+#readelf: -SWg
+#name: linked-to section 3
+
+#...
+ +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[48] +00 +WALG +.*
+#...
+ +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[48] +00 +WALG +.*
+#...
+COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains [0-9]+ sections:
+ \[Index\] Name
+#...
+ \[[ 0-9]+\] __patchable_function_entries
+#...
+COMDAT group section \[[ 0-9]+\] `.group' \[bar\] contains [0-9]+ sections:
+#...
+ \[[ 0-9]+\] __patchable_function_entries
+#pass
diff --git a/gas/testsuite/gas/elf/section20.s b/gas/testsuite/gas/elf/section20.s
new file mode 100644
index 00000000000..1e9639ef4a7
--- /dev/null
+++ b/gas/testsuite/gas/elf/section20.s
@@ -0,0 +1,13 @@
+ .section .text,"axG",%progbits,foo,comdat
+foo:
+ .section __patchable_function_entries,"awoG",%progbits,foo,foo,comdat
+ .dc.a .LPFE1
+ .section .text,"axG",%progbits,foo,comdat
+.LPFE1:
+ .byte 0
+ .section __patchable_function_entries,"awoG",%progbits,bar,bar,comdat,unique,4
+ .dc.a .LPFE2
+ .section .text,"axG",%progbits,bar,comdat,unique,24
+bar:
+.LPFE2:
+ .byte 0
diff --git a/gas/testsuite/gas/elf/section21.d b/gas/testsuite/gas/elf/section21.d
new file mode 100644
index 00000000000..54fa9d419bc
--- /dev/null
+++ b/gas/testsuite/gas/elf/section21.d
@@ -0,0 +1,2 @@
+#name: incorrect linked-to symbols
+#error_output: section21.l
diff --git a/gas/testsuite/gas/elf/section21.l b/gas/testsuite/gas/elf/section21.l
new file mode 100644
index 00000000000..8b9af6118a9
--- /dev/null
+++ b/gas/testsuite/gas/elf/section21.l
@@ -0,0 +1,4 @@
+[^:]*: Assembler messages:
+[^:]*:11: Error: junk at end of line, first unrecognized character is `1'
+[^:]*: Error: undefined linked-to symbol `bar' on section `__patchable_function_entries'
+[^:]*: Error: undefined linked-to symbol `foo' on section `__patchable_function_entries'
diff --git a/gas/testsuite/gas/elf/section21.s b/gas/testsuite/gas/elf/section21.s
new file mode 100644
index 00000000000..ae5f848b299
--- /dev/null
+++ b/gas/testsuite/gas/elf/section21.s
@@ -0,0 +1,15 @@
+ .section __patchable_function_entries,"awo",%progbits,bar
+ .dc.a .LPFE1
+ .text
+.LPFE1:
+ .byte 0
+ .section __patchable_function_entries,"awo",%progbits,foo
+ .dc.a .LPFE2
+ .text
+.LPFE2:
+ .dc.a foo
+ .section __patchable_function_entries,"awo",%progbits,1foo
+ .dc.a .LPFE3
+ .text
+.LPFE3:
+ .byte 0
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index 989fb50d4ae..ea8cd884056 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -76,9 +76,19 @@ run_ld_link_tests [list \
if [is_elf64 tmpdir/symbol3w.a] {
set ASFLAGS "$ASFLAGS --defsym ALIGN=3"
set pr23900_1_exp "pr23900-1-64.rd"
+ set pr25490_2_exp "pr25490-2-64.rd"
+ set pr25490_3_exp "pr25490-3-64.rd"
+ set pr25490_4_exp "pr25490-4-64.rd"
+ set pr25490_5_exp "pr25490-5-64.rd"
+ set pr25490_6_exp "pr25490-6-64.rd"
} else {
set ASFLAGS "$ASFLAGS --defsym ALIGN=2"
set pr23900_1_exp "pr23900-1-32.rd"
+ set pr25490_2_exp "pr25490-2-32.rd"
+ set pr25490_3_exp "pr25490-3-32.rd"
+ set pr25490_4_exp "pr25490-4-32.rd"
+ set pr25490_5_exp "pr25490-5-32.rd"
+ set pr25490_6_exp "pr25490-6-32.rd"
}
@@ -172,6 +182,46 @@ if { [istarget *-*-*linux*]
]
}
+if [check_gc_sections_available] {
+ run_ld_link_tests [list \
+ [list "__patchable_function_entries section 2" \
+ "--gc-sections -e _start" \
+ "" \
+ "" \
+ {pr25490-2.s} \
+ [list [list "readelf" {-SW} $pr25490_2_exp]] \
+ "pr25490-2.exe"] \
+ [list "__patchable_function_entries section 3" \
+ "--gc-sections -e _start" \
+ "" \
+ "" \
+ {pr25490-3.s} \
+ [list [list "readelf" {-SW} $pr25490_3_exp]] \
+ "pr25490-3.exe"] \
+ [list "__patchable_function_entries section 4" \
+ "--gc-sections -e _start" \
+ "" \
+ "" \
+ {pr25490-4.s} \
+ [list [list "readelf" {-SW} $pr25490_4_exp]] \
+ "pr25490-4.exe"] \
+ [list "__patchable_function_entries section 5" \
+ "--gc-sections -e _start" \
+ "" \
+ "" \
+ {pr25490-5.s} \
+ [list [list "readelf" {-SW} $pr25490_5_exp]] \
+ "pr25490-5.exe"] \
+ [list "__patchable_function_entries section 6" \
+ "--gc-sections -e _start" \
+ "" \
+ "" \
+ {pr25490-6.s} \
+ [list [list "readelf" {-SW} $pr25490_6_exp]] \
+ "pr25490-6.exe"] \
+ ]
+}
+
set LDFLAGS $old_ldflags
set ASFLAGS $old_asflags
diff --git a/ld/testsuite/ld-elf/pr25490-2-32.rd b/ld/testsuite/ld-elf/pr25490-2-32.rd
new file mode 100644
index 00000000000..99ee4dbb5d7
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-2-32.rd
@@ -0,0 +1,7 @@
+#source: pr25490-2.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+4 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-2-64.rd b/ld/testsuite/ld-elf/pr25490-2-64.rd
new file mode 100644
index 00000000000..db086d5aafc
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-2-64.rd
@@ -0,0 +1,7 @@
+#source: pr25490-2.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+8 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-2.s b/ld/testsuite/ld-elf/pr25490-2.s
new file mode 100644
index 00000000000..856bb5fe9d3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-2.s
@@ -0,0 +1,9 @@
+ .text
+ .globl _start
+ .type _start, %function
+_start:
+ .section __patchable_function_entries,"awo",%progbits,_start
+ .dc.a .LPFE1
+ .text
+.LPFE1:
+ .byte 0
diff --git a/ld/testsuite/ld-elf/pr25490-3-32.rd b/ld/testsuite/ld-elf/pr25490-3-32.rd
new file mode 100644
index 00000000000..d2765f84c7f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-3-32.rd
@@ -0,0 +1,7 @@
+#source: pr25490-3.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+4 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-3-64.rd b/ld/testsuite/ld-elf/pr25490-3-64.rd
new file mode 100644
index 00000000000..5faeebe65d8
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-3-64.rd
@@ -0,0 +1,7 @@
+#source: pr25490-3.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+8 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-3.s b/ld/testsuite/ld-elf/pr25490-3.s
new file mode 100644
index 00000000000..427ad69b535
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-3.s
@@ -0,0 +1,18 @@
+ .section .text.bar,"ax",%progbits
+ .globl bar
+ .type bar, %function
+bar:
+ .section __patchable_function_entries,"awo",%progbits,bar
+ .dc.a .LPFE1
+ .section .text.bar,"ax",%progbits
+.LPFE1:
+ .byte 0
+ .section .text._start,"ax",%progbits
+ .globl _start
+ .type _start, %function
+_start:
+ .section __patchable_function_entries,"awo",%progbits,_start
+ .dc.a .LPFE2
+ .section .text._start,"ax",%progbits
+.LPFE2:
+ .byte 0
diff --git a/ld/testsuite/ld-elf/pr25490-4-32.rd b/ld/testsuite/ld-elf/pr25490-4-32.rd
new file mode 100644
index 00000000000..5667f40836b
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-4-32.rd
@@ -0,0 +1,7 @@
+#source: pr25490-4.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+8 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-4-64.rd b/ld/testsuite/ld-elf/pr25490-4-64.rd
new file mode 100644
index 00000000000..5a3b34dcd56
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-4-64.rd
@@ -0,0 +1,7 @@
+#source: pr25490-4.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+10 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-4.s b/ld/testsuite/ld-elf/pr25490-4.s
new file mode 100644
index 00000000000..9b3ffcad04d
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-4.s
@@ -0,0 +1,18 @@
+ .section .text.bar,"ax",%progbits
+ .globl bar
+ .type bar, %function
+bar:
+ .section __patchable_function_entries,"awo",%progbits,bar
+ .dc.a .LPFE1
+ .section .text.bar,"ax",%progbits
+.LPFE1:
+ .byte 0
+ .section .text._start,"ax",%progbits
+ .globl _start
+ .type _start, %function
+_start:
+ .section __patchable_function_entries,"awo",%progbits,_start
+ .dc.a .LPFE2
+ .section .text._start,"ax",%progbits
+.LPFE2:
+ .dc.a bar
diff --git a/ld/testsuite/ld-elf/pr25490-5-32.rd b/ld/testsuite/ld-elf/pr25490-5-32.rd
new file mode 100644
index 00000000000..32e19b8b5c8
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-5-32.rd
@@ -0,0 +1,7 @@
+#source: pr25490-5.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+8 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-5-64.rd b/ld/testsuite/ld-elf/pr25490-5-64.rd
new file mode 100644
index 00000000000..17358d5feda
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-5-64.rd
@@ -0,0 +1,7 @@
+#source: pr25490-5.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+10 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-5.s b/ld/testsuite/ld-elf/pr25490-5.s
new file mode 100644
index 00000000000..f9d46b8e0b0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-5.s
@@ -0,0 +1,17 @@
+ .text
+ .type bar, %function
+bar:
+ .section __patchable_function_entries,"awo",%progbits,bar
+ .dc.a .LPFE1
+ .text
+.LPFE1:
+ .byte 0
+ .text
+ .globl _start
+ .type _start, %function
+_start:
+ .section __patchable_function_entries,"awo",%progbits,_start
+ .dc.a .LPFE2
+ .text
+.LPFE2:
+ .byte 0
diff --git a/ld/testsuite/ld-elf/pr25490-6-32.rd b/ld/testsuite/ld-elf/pr25490-6-32.rd
new file mode 100644
index 00000000000..807e83159a8
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-6-32.rd
@@ -0,0 +1,7 @@
+#source: pr25490-6.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+c +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-6-64.rd b/ld/testsuite/ld-elf/pr25490-6-64.rd
new file mode 100644
index 00000000000..668eaa45601
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-6-64.rd
@@ -0,0 +1,7 @@
+#source: pr25490-6.s
+#ld: --gc-sections
+#readelf: -SW
+
+#...
+ +\[ *[0-9]+\] __patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+18 +00 +WAL +[0-9] +0 +1
+#pass
diff --git a/ld/testsuite/ld-elf/pr25490-6.s b/ld/testsuite/ld-elf/pr25490-6.s
new file mode 100644
index 00000000000..5f5a348d4d0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25490-6.s
@@ -0,0 +1,28 @@
+ .section .text,"axG",%progbits,bar,comdat
+ .globl bar
+ .type bar, %function
+bar:
+ .section __patchable_function_entries,"awo",%progbits,bar
+ .dc.a .LPFE1
+ .section .text,"axG",%progbits,bar,comdat
+.LPFE1:
+ .byte 0
+ .section .text,"axG",%progbits,foo,comdat
+ .globl foo
+ .type foo, %function
+foo:
+ .section __patchable_function_entries,"awo",%progbits,foo,unique,0
+ .dc.a .LPFE2
+ .section .text,"axG",%progbits,foo,comdat
+.LPFE2:
+ .byte 0
+ .section .text,"axG",%progbits,_start,comdat,unique,1
+ .globl _start
+ .type _start, %function
+_start:
+ .section __patchable_function_entries,"awoG",%progbits,_start,_start,comdat,unique,3
+ .dc.a .LPFE3
+ .section .text,"axG",%progbits,_start,comdat,unique,1
+.LPFE3:
+ .dc.a foo
+ .dc.a bar
--
2.24.1