[PATCH] gas: Add pushuniquesection and --unique-pushsection
Zhiyuan Lv
zhiyuan.lv@linux.intel.com
Fri May 16 06:44:59 GMT 2025
Tested-by: Zhiyuan Lv <zhiyuan.lv@linux.intel.com>
Regards,
-Zhiyuan
On Fri, May 16, 2025 at 02:15:27PM +0800, H.J. Lu wrote:
> Linker kernel uses .pushsection directive extensively. But when
> -ffunction-sections is used to build kernel, for
>
> __attribute__((always_inline))
> static void inline
> test_section(void)
> {
> asm goto("jmp 1f\n"
> "\t.pushsection .alt_section, \"ax\"\n"
> "1:\n"
> "\tjmp %l[t_label]\n"
> "\t.popsection\n"
> : :
> : : t_label);
> t_label:
> return;
> }
>
> void
> foo(void)
> {
> test_section();
> }
>
> void
> bar(void)
> {
> test_section();
> }
>
> we get
>
> .text
> .section .text.foo,"ax",@progbits
> .p2align 4
> .globl foo
> .type foo, @function
> foo:
> .LFB1:
> .cfi_startproc
> jmp 1f
> .pushsection .alt_section, "ax"
> 1:
> jmp .L2
> .popsection
>
> .L2:
> ret
> .L3:
> .cfi_endproc
> .LFE1:
> .size foo, .-foo
> .section .text.bar,"ax",@progbits
> .p2align 4
> .globl bar
> .type bar, @function
> bar:
> .LFB2:
> .cfi_startproc
> jmp 1f
> .pushsection .alt_section, "ax"
> 1:
> jmp .L6
> .popsection
>
> .L6:
> ret
> .L7:
> .cfi_endproc
> .LFE2:
> .size bar, .-bar
>
> Functions foo and bar are placed in the different sections. But since
> ".pushsection .alt_section" always generates the same .alt_section
> section for foo and bar, --gc-sections doesn't remove foo when bar is
> referenced while foo isn't. To help linker to remove the unreferenced
> functions with .pushsection directive:
>
> 1. Add --unique-pushsection option to ELF assembler to append the current
> section name to the new section name for .pushsection.
> 2. Add ".pushuniquesection" directive to ELF assembler to append the
> current section name to the new section name.
>
> Tested with small test cases and kernel build, all working fine. Below
> are the details:
>
> OS: Ubuntu 24.04
> GCC: 14.2.0 in Ubuntu default
> Binutils: 2.44.50, built with this patch
>
> Test cases:
> 1. compile test.c with assembler new parameter "--unique-pushsection"
> 2. modify test.c to use ".pushuniquesection" and compile
> 3. try (2) with "--unique-pushsection" parameter
> 4. build Linux kernel 6.12 with the new parameter for some specific files
>
> All can see that unused functions were removed as expected and kernel
> works correctly.
>
> gas/
>
> PR gas/32961
> * NEWS: Mention --unique-pushsection and .pushuniquesection.
> * as.c (flag_unique_pushsection): New.
> (show_usage): Also show --unique-pushsection.
> (parse_args): Support --unique-pushsection.
> * as.h (flag_unique_pushsection): New.
> * config/obj-elf.c (elf_pseudo_table): Add pushuniquesection.
> (change_section): Change the push argument to int and append
> the previous section name to the new section name for
> .pushuniquesection or .pushsection with --unique-pushsection.
> (obj_elf_change_section): Pass 0 to change_section.
> * doc/as.texi: Document --unique-pushsection and
> .pushuniquesection.
> * testsuite/gas/elf/elf.exp: Run pushsection-1 and
> pushsection-2.
> * testsuite/gas/elf/pushsection-1.d: New file.
> * testsuite/gas/elf/pushsection-1.s: Likewise.
> * testsuite/gas/elf/pushsection-2.d: Likewise.
> * testsuite/gas/elf/pushsection-2.s: Likewise.
>
> ld/
>
> PR gas/32961
> * testsuite/ld-elf/pushsection-1.d: New file.
> * testsuite/ld-elf/pushsection-1.s: Likewise.
> * testsuite/ld-elf/pushsection-2.d: Likewise.
> * testsuite/ld-elf/pushsection-2.s: Likewise.
> * testsuite/ld-elf/pushsection-3.d: Likewise.
> * testsuite/ld-elf/pushsection-3.s: Likewise.
> * testsuite/ld-elf/pushsection-4.s: Likewise.
> * testsuite/ld-elf/pushsection-4.d: Likewise.
>
> --
> H.J.
> From 88345a3ade92a67ad8bf98f75ed3bf4102843ed9 Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Tue, 13 May 2025 15:00:51 +0800
> Subject: [PATCH] gas: Add pushuniquesection and --unique-pushsection
>
> Linker kernel uses .pushsection directive extensively. But when
> -ffunction-sections is used to build kernel, for
>
> __attribute__((always_inline))
> static void inline
> test_section(void)
> {
> asm goto("jmp 1f\n"
> "\t.pushsection .alt_section, \"ax\"\n"
> "1:\n"
> "\tjmp %l[t_label]\n"
> "\t.popsection\n"
> : :
> : : t_label);
> t_label:
> return;
> }
>
> void
> foo(void)
> {
> test_section();
> }
>
> void
> bar(void)
> {
> test_section();
> }
>
> we get
>
> .text
> .section .text.foo,"ax",@progbits
> .p2align 4
> .globl foo
> .type foo, @function
> foo:
> .LFB1:
> .cfi_startproc
> jmp 1f
> .pushsection .alt_section, "ax"
> 1:
> jmp .L2
> .popsection
>
> .L2:
> ret
> .L3:
> .cfi_endproc
> .LFE1:
> .size foo, .-foo
> .section .text.bar,"ax",@progbits
> .p2align 4
> .globl bar
> .type bar, @function
> bar:
> .LFB2:
> .cfi_startproc
> jmp 1f
> .pushsection .alt_section, "ax"
> 1:
> jmp .L6
> .popsection
>
> .L6:
> ret
> .L7:
> .cfi_endproc
> .LFE2:
> .size bar, .-bar
>
> Functions foo and bar are placed in the different sections. But since
> ".pushsection .alt_section" always generates the same .alt_section
> section for foo and bar, --gc-sections doesn't remove foo when bar is
> referenced while foo isn't. To help linker to remove the unreferenced
> functions with .pushsection directive:
>
> 1. Add --unique-pushsection option to ELF assembler to append the current
> section name to the new section name for .pushsection.
> 2. Add ".pushuniquesection" directive to ELF assembler to append the
> current section name to the new section name.
>
> Tested with small test cases and kernel build, all working fine. Below
> are the details:
>
> OS: Ubuntu 24.04
> GCC: 14.2.0 in Ubuntu default
> Binutils: 2.44.50, built with this patch
>
> Test cases:
> 1. compile test.c with assembler new parameter "--unique-pushsection"
> 2. modify test.c to use ".pushuniquesection" and compile
> 3. try (2) with "--unique-pushsection" parameter
> 4. build Linux kernel 6.12 with the new parameter for some specific files
>
> All can see that unused functions were removed as expected and kernel
> works correctly.
>
> gas/
>
> PR gas/32961
> * NEWS: Mention --unique-pushsection and .pushuniquesection.
> * as.c (flag_unique_pushsection): New.
> (show_usage): Also show --unique-pushsection.
> (parse_args): Support --unique-pushsection.
> * as.h (flag_unique_pushsection): New.
> * config/obj-elf.c (elf_pseudo_table): Add pushuniquesection.
> (change_section): Change the push argument to int and append
> the previous section name to the new section name for
> .pushuniquesection or .pushsection with --unique-pushsection.
> (obj_elf_change_section): Pass 0 to change_section.
> * doc/as.texi: Document --unique-pushsection and
> .pushuniquesection.
> * testsuite/gas/elf/elf.exp: Run pushsection-1 and
> pushsection-2.
> * testsuite/gas/elf/pushsection-1.d: New file.
> * testsuite/gas/elf/pushsection-1.s: Likewise.
> * testsuite/gas/elf/pushsection-2.d: Likewise.
> * testsuite/gas/elf/pushsection-2.s: Likewise.
>
> ld/
>
> PR gas/32961
> * testsuite/ld-elf/pushsection-1.d: New file.
> * testsuite/ld-elf/pushsection-1.s: Likewise.
> * testsuite/ld-elf/pushsection-2.d: Likewise.
> * testsuite/ld-elf/pushsection-2.s: Likewise.
> * testsuite/ld-elf/pushsection-3.d: Likewise.
> * testsuite/ld-elf/pushsection-3.s: Likewise.
> * testsuite/ld-elf/pushsection-4.s: Likewise.
> * testsuite/ld-elf/pushsection-4.d: Likewise.
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
> gas/NEWS | 6 ++
> gas/as.c | 12 +++-
> gas/as.h | 3 +
> gas/config/obj-elf.c | 10 ++-
> gas/doc/as.texi | 25 ++++++--
> gas/testsuite/gas/elf/elf.exp | 3 +
> gas/testsuite/gas/elf/pushsection-1.d | 25 ++++++++
> gas/testsuite/gas/elf/pushsection-1.s | 60 ++++++++++++++++++
> gas/testsuite/gas/elf/pushsection-2.d | 24 +++++++
> gas/testsuite/gas/elf/pushsection-2.s | 60 ++++++++++++++++++
> ld/testsuite/ld-elf/pushsection-1.d | 13 ++++
> ld/testsuite/ld-elf/pushsection-1.s | 60 ++++++++++++++++++
> ld/testsuite/ld-elf/pushsection-2.d | 12 ++++
> ld/testsuite/ld-elf/pushsection-2.s | 60 ++++++++++++++++++
> ld/testsuite/ld-elf/pushsection-3.d | 13 ++++
> ld/testsuite/ld-elf/pushsection-3.s | 90 +++++++++++++++++++++++++++
> ld/testsuite/ld-elf/pushsection-4.d | 13 ++++
> ld/testsuite/ld-elf/pushsection-4.s | 90 +++++++++++++++++++++++++++
> 18 files changed, 572 insertions(+), 7 deletions(-)
> create mode 100644 gas/testsuite/gas/elf/pushsection-1.d
> create mode 100644 gas/testsuite/gas/elf/pushsection-1.s
> create mode 100644 gas/testsuite/gas/elf/pushsection-2.d
> create mode 100644 gas/testsuite/gas/elf/pushsection-2.s
> create mode 100644 ld/testsuite/ld-elf/pushsection-1.d
> create mode 100644 ld/testsuite/ld-elf/pushsection-1.s
> create mode 100644 ld/testsuite/ld-elf/pushsection-2.d
> create mode 100644 ld/testsuite/ld-elf/pushsection-2.s
> create mode 100644 ld/testsuite/ld-elf/pushsection-3.d
> create mode 100644 ld/testsuite/ld-elf/pushsection-3.s
> create mode 100644 ld/testsuite/ld-elf/pushsection-4.d
> create mode 100644 ld/testsuite/ld-elf/pushsection-4.s
>
> diff --git a/gas/NEWS b/gas/NEWS
> index 42c3329d83e..57da2b0af1a 100644
> --- a/gas/NEWS
> +++ b/gas/NEWS
> @@ -1,5 +1,11 @@
> -*- text -*-
>
> +* Add --unique-pushsection option to ELF assembler to append the current
> + section name to the new section name for .pushsection.
> +
> +* Add ".pushuniquesection" directive to ELF assembler to append the
> + current section name to the new section name.
> +
> * Support for x86 AVX10.2 256 bit rounding has been dropped, as all the
> hardware would directly support 512 bit vecotr width.
>
> diff --git a/gas/as.c b/gas/as.c
> index 7edac577d16..66a8b21d555 100644
> --- a/gas/as.c
> +++ b/gas/as.c
> @@ -111,6 +111,7 @@ unsigned int dwarf_level = 3;
> #if defined OBJ_ELF || defined OBJ_MAYBE_ELF
> int flag_use_elf_stt_common = DEFAULT_GENERATE_ELF_STT_COMMON;
> bool flag_generate_build_notes = DEFAULT_GENERATE_BUILD_NOTES;
> +bool flag_unique_pushsection = false;
> #endif
>
> segT reg_section;
> @@ -311,6 +312,8 @@ Options:\n\
> fprintf (stream, _("\
> generate GNU Build notes if none are present in the input\n"));
> fprintf (stream, _("\
> + --unique-pushsection Create a unique section for .pushsection\n"));
> + fprintf (stream, _("\
> --gsframe generate SFrame stack trace information\n"));
> # if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
> fprintf (stream, _("\
> @@ -507,7 +510,8 @@ parse_args (int * pargc, char *** pargv)
> OPTION_SFRAME,
> OPTION_SCFI,
> OPTION_INFO,
> - OPTION_NOINFO
> + OPTION_NOINFO,
> + OPTION_UNIQUE_PUSHSECTION
> /* When you add options here, check that they do
> not collide with OPTION_MD_BASE. See as.h. */
> };
> @@ -538,6 +542,8 @@ parse_args (int * pargc, char *** pargv)
> ,{"elf-stt-common", required_argument, NULL, OPTION_ELF_STT_COMMON}
> ,{"sectname-subst", no_argument, NULL, OPTION_SECTNAME_SUBST}
> ,{"generate-missing-build-notes", required_argument, NULL, OPTION_ELF_BUILD_NOTES}
> + ,{"unique-pushsection", no_argument, NULL,
> + OPTION_UNIQUE_PUSHSECTION}
> ,{"gsframe", no_argument, NULL, OPTION_SFRAME}
> # if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
> ,{"scfi", required_argument, NULL, OPTION_SCFI}
> @@ -1035,6 +1041,10 @@ This program has absolutely no warranty.\n"));
> flag_gen_sframe = 1;
> break;
>
> + case OPTION_UNIQUE_PUSHSECTION:
> + flag_unique_pushsection = true;
> + break;
> +
> #endif /* OBJ_ELF */
>
> case 'Z':
> diff --git a/gas/as.h b/gas/as.h
> index 826d88db013..c58fcf492aa 100644
> --- a/gas/as.h
> +++ b/gas/as.h
> @@ -628,6 +628,9 @@ extern int flag_use_elf_stt_common;
> be generated if none are in the input files. */
> extern bool flag_generate_build_notes;
>
> +/* TRUE if each .pushsection should create a unique section. */
> +extern bool flag_unique_pushsection;
> +
> /* If section name substitution sequences should be honored */
> COMMON int flag_sectname_subst;
> #endif
> diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
> index bc981f05dd5..af574d48005 100644
> --- a/gas/config/obj-elf.c
> +++ b/gas/config/obj-elf.c
> @@ -91,6 +91,7 @@ static const pseudo_typeS elf_pseudo_table[] =
> {"sect", obj_elf_section, 0},
> {"sect.s", obj_elf_section, 0},
> {"pushsection", obj_elf_section, 1},
> + {"pushuniquesection", obj_elf_section, 2},
> {"popsection", obj_elf_popsection, 0},
> {"size", obj_elf_size, 0},
> {"type", obj_elf_type, 0},
> @@ -588,7 +589,7 @@ change_section (const char *name,
> int entsize,
> struct elf_section_match *match_p,
> bool linkonce,
> - bool push,
> + int push,
> subsegT new_subsection)
> {
> asection *old_sec;
> @@ -622,6 +623,11 @@ change_section (const char *name,
>
> obj_elf_section_change_hook ();
>
> + if (push
> + && previous_section
> + && (push > 1 || flag_unique_pushsection))
> + name = concat (name, previous_section->name, NULL);
> +
> unsigned int *group_idx = NULL;
> if (match_p->group_name)
> old_sec = group_section_find (match_p, name, &group_idx);
> @@ -879,7 +885,7 @@ obj_elf_change_section (const char *name,
> struct elf_section_match *match_p,
> bool linkonce)
> {
> - change_section (name, type, attr, entsize, match_p, linkonce, false, 0);
> + change_section (name, type, attr, entsize, match_p, linkonce, 0, 0);
> }
>
> static bfd_vma
> diff --git a/gas/doc/as.texi b/gas/doc/as.texi
> index 40d45f75d18..94ad098d849 100644
> --- a/gas/doc/as.texi
> +++ b/gas/doc/as.texi
> @@ -240,6 +240,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
> [@b{--gdwarf-<N>}] [@b{--gdwarf-sections}]
> [@b{--gdwarf-cie-version}=@var{VERSION}]
> [@b{--generate-missing-build-notes=[no|yes]}]
> + [@b{--unique-pushsection}]
> [@b{--gsframe}]
> [@b{--hash-size}=@var{N}]
> [@b{--help}] [@b{--target-help}]
> @@ -853,6 +854,11 @@ attribute notes if none are present in the input sources.
> The default can be controlled by the @option{--enable-generate-build-notes}
> configure option.
>
> +@item --unique-pushsection
> +@itemx --unique-pushsection
> +Append the current section name to the new section name for
> +@code{.pushsection} directive.
> +
> @item --gsframe
> @itemx --gsframe
> Create @var{.sframe} section from CFI directives.
> @@ -4621,6 +4627,7 @@ Some machine configurations provide additional directives.
> * Purgem:: @code{.purgem @var{name}}
> @ifset ELF
> * PushSection:: @code{.pushsection @var{name}}
> +* PushUniqueSection:: @code{.pushuniquesection @var{name}}
> @end ifset
>
> * Quad:: @code{.quad @var{bignums}}
> @@ -6593,8 +6600,9 @@ undefined.
> @cindex Section Stack
> This is one of the ELF section stack manipulation directives. The others are
> @code{.section} (@pxref{Section}), @code{.subsection} (@pxref{SubSection}),
> -@code{.pushsection} (@pxref{PushSection}), and @code{.previous}
> -(@pxref{Previous}).
> +@code{.pushsection} (@pxref{PushSection}),
> +@code{.pushuniquesection} (@pxref{PushUniqueSection}), and
> +@code{.previous} (@pxref{Previous}).
>
> This directive replaces the current section (and subsection) with the top
> section (and subsection) on the section stack. This section is popped off the
> @@ -6609,8 +6617,9 @@ stack.
> @cindex Section Stack
> This is one of the ELF section stack manipulation directives. The others are
> @code{.section} (@pxref{Section}), @code{.subsection} (@pxref{SubSection}),
> -@code{.pushsection} (@pxref{PushSection}), and @code{.popsection}
> -(@pxref{PopSection}).
> +@code{.pushsection} (@pxref{PushSection}),
> +@code{.pushuniquesection} (@pxref{PushUniqueSection}), and
> +@code{.popsection} (@pxref{PopSection}).
>
> This directive swaps the current section (and subsection) with most recently
> referenced section/subsection pair prior to this one. Multiple
> @@ -6721,6 +6730,14 @@ top of the section stack, and then replaces the current section and
> subsection with @code{name} and @code{subsection}. The optional
> @code{flags}, @code{type} and @code{arguments} are treated the same
> as in the @code{.section} (@pxref{Section}) directive.
> +
> +@node PushUniqueSection
> +@section @code{.pushuniquesection @var{name} [, @var{subsection}] [, "@var{flags}"[, @@@var{type}[,@var{arguments}]]]}
> +
> +@cindex @code{pushuniquesection} directive
> +@cindex Section Stack
> +This directive is similar to @code{pushsection}, except that the current
> +section name is appended to the new section name.
> @end ifset
>
> @node Quad
> diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
> index 1f42c3f3723..94f7b2ba52f 100644
> --- a/gas/testsuite/gas/elf/elf.exp
> +++ b/gas/testsuite/gas/elf/elf.exp
> @@ -388,4 +388,7 @@ if { [is_elf_format] } then {
> run_dump_test "bignums" $dump_opts
> run_dump_test "section-symbol-redef"
> run_dump_test "pr27228"
> +
> + run_dump_test "pushsection-1"
> + run_dump_test "pushsection-2"
> }
> diff --git a/gas/testsuite/gas/elf/pushsection-1.d b/gas/testsuite/gas/elf/pushsection-1.d
> new file mode 100644
> index 00000000000..c716ae1d377
> --- /dev/null
> +++ b/gas/testsuite/gas/elf/pushsection-1.d
> @@ -0,0 +1,25 @@
> +#as: --unique-pushsection
> +#readelf: -SW
> +# .pushsection always creates the named section, but the
> +# test harness translates ".text" into "P" for the RX...
> +#xfail: rx-*
> +
> +#...
> + \[..\] \.text\.foo0 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.foo0 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.foo1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.foo2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.foo2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.foo3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.foo3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.entry_func +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.entry_func +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#pass
> diff --git a/gas/testsuite/gas/elf/pushsection-1.s b/gas/testsuite/gas/elf/pushsection-1.s
> new file mode 100644
> index 00000000000..d0196ab7b1a
> --- /dev/null
> +++ b/gas/testsuite/gas/elf/pushsection-1.s
> @@ -0,0 +1,60 @@
> + .section .text.foo0,"ax",%progbits
> + .p2align 4
> + .globl foo0
> + .type foo0, %function
> +foo0:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L0
> + .popsection
> +.L0:
> + .dc.a 0
> + .size foo0, .-foo0
> + .section .text.foo1,"ax",%progbits
> + .p2align 4
> + .globl foo1
> + .type foo1, %function
> +foo1:
> + .dc.a 0
> + .size foo1, .-foo1
> + .section .text.foo2,"ax",%progbits
> + .p2align 4
> + .globl foo2
> + .type foo2, %function
> +foo2:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L4
> + .popsection
> +.L4:
> + .dc.a 0
> + .size foo2, .-foo2
> + .section .text.foo3,"ax",%progbits
> + .p2align 4
> + .globl foo3
> + .type foo3, %function
> +foo3:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L7
> + .popsection
> +.L7:
> + .dc.a 0
> + .size foo3, .-foo3
> + .section .text.entry_func,"ax",%progbits
> + .p2align 4
> + .globl entry_func
> + .type entry_func, %function
> +entry_func:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L10
> + .popsection
> +.L10:
> + .dc.a foo0
> + .size entry_func, .-entry_func
> + .section .note.GNU-stack,"",%progbits
> diff --git a/gas/testsuite/gas/elf/pushsection-2.d b/gas/testsuite/gas/elf/pushsection-2.d
> new file mode 100644
> index 00000000000..2b8d2ca5432
> --- /dev/null
> +++ b/gas/testsuite/gas/elf/pushsection-2.d
> @@ -0,0 +1,24 @@
> +#readelf: -SW
> +# .pushsection always creates the named section, but the
> +# test harness translates ".text" into "P" for the RX...
> +#xfail: rx-*
> +
> +#...
> + \[..\] \.text\.foo0 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.foo0 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.foo1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.foo2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.foo2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.foo3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.foo3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.text\.entry_func +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#...
> + \[..\] \.alt_section\.text\.entry_func +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
> +#pass
> diff --git a/gas/testsuite/gas/elf/pushsection-2.s b/gas/testsuite/gas/elf/pushsection-2.s
> new file mode 100644
> index 00000000000..335ab260d42
> --- /dev/null
> +++ b/gas/testsuite/gas/elf/pushsection-2.s
> @@ -0,0 +1,60 @@
> + .section .text.foo0,"ax",%progbits
> + .p2align 4
> + .globl foo0
> + .type foo0, %function
> +foo0:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L0
> + .popsection
> +.L0:
> + .dc.a 0
> + .size foo0, .-foo0
> + .section .text.foo1,"ax",%progbits
> + .p2align 4
> + .globl foo1
> + .type foo1, %function
> +foo1:
> + .dc.a 0
> + .size foo1, .-foo1
> + .section .text.foo2,"ax",%progbits
> + .p2align 4
> + .globl foo2
> + .type foo2, %function
> +foo2:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L4
> + .popsection
> +.L4:
> + .dc.a 0
> + .size foo2, .-foo2
> + .section .text.foo3,"ax",%progbits
> + .p2align 4
> + .globl foo3
> + .type foo3, %function
> +foo3:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L7
> + .popsection
> +.L7:
> + .dc.a 0
> + .size foo3, .-foo3
> + .section .text.entry_func,"ax",%progbits
> + .p2align 4
> + .globl entry_func
> + .type entry_func, %function
> +entry_func:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L10
> + .popsection
> +.L10:
> + .dc.a foo0
> + .size entry_func, .-entry_func
> + .section .note.GNU-stack,"",%progbits
> diff --git a/ld/testsuite/ld-elf/pushsection-1.d b/ld/testsuite/ld-elf/pushsection-1.d
> new file mode 100644
> index 00000000000..49c47282f6a
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-1.d
> @@ -0,0 +1,13 @@
> +#as: --unique-pushsection
> +#ld: --gc-sections -e entry_func
> +#nm: -n
> +#xfail: [is_generic] fr30-*-* frv-*-elf ft32-*-* iq2000-*-* mn10200-*-*
> +#xfail: msp430-* mt-*-* z80-*-*
> +# Generic linker targets don't comply with all orhpan section merging
> +# rules. z80 fails since a, b, c, d are registers for z80.
> +
> +#failif
> +#...
> +.* T foo2
> +.* T foo3
> +#...
> diff --git a/ld/testsuite/ld-elf/pushsection-1.s b/ld/testsuite/ld-elf/pushsection-1.s
> new file mode 100644
> index 00000000000..d0196ab7b1a
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-1.s
> @@ -0,0 +1,60 @@
> + .section .text.foo0,"ax",%progbits
> + .p2align 4
> + .globl foo0
> + .type foo0, %function
> +foo0:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L0
> + .popsection
> +.L0:
> + .dc.a 0
> + .size foo0, .-foo0
> + .section .text.foo1,"ax",%progbits
> + .p2align 4
> + .globl foo1
> + .type foo1, %function
> +foo1:
> + .dc.a 0
> + .size foo1, .-foo1
> + .section .text.foo2,"ax",%progbits
> + .p2align 4
> + .globl foo2
> + .type foo2, %function
> +foo2:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L4
> + .popsection
> +.L4:
> + .dc.a 0
> + .size foo2, .-foo2
> + .section .text.foo3,"ax",%progbits
> + .p2align 4
> + .globl foo3
> + .type foo3, %function
> +foo3:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L7
> + .popsection
> +.L7:
> + .dc.a 0
> + .size foo3, .-foo3
> + .section .text.entry_func,"ax",%progbits
> + .p2align 4
> + .globl entry_func
> + .type entry_func, %function
> +entry_func:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L10
> + .popsection
> +.L10:
> + .dc.a foo0
> + .size entry_func, .-entry_func
> + .section .note.GNU-stack,"",%progbits
> diff --git a/ld/testsuite/ld-elf/pushsection-2.d b/ld/testsuite/ld-elf/pushsection-2.d
> new file mode 100644
> index 00000000000..9f8cb90b69d
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-2.d
> @@ -0,0 +1,12 @@
> +#ld: --gc-sections -e entry_func
> +#nm: -n
> +#xfail: [is_generic] fr30-*-* frv-*-elf ft32-*-* iq2000-*-* mn10200-*-*
> +#xfail: msp430-* mt-*-* z80-*-*
> +# Generic linker targets don't comply with all orhpan section merging
> +# rules. z80 fails since a, b, c, d are registers for z80.
> +
> +#failif
> +#...
> +.* T foo2
> +.* T foo3
> +#...
> diff --git a/ld/testsuite/ld-elf/pushsection-2.s b/ld/testsuite/ld-elf/pushsection-2.s
> new file mode 100644
> index 00000000000..335ab260d42
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-2.s
> @@ -0,0 +1,60 @@
> + .section .text.foo0,"ax",%progbits
> + .p2align 4
> + .globl foo0
> + .type foo0, %function
> +foo0:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L0
> + .popsection
> +.L0:
> + .dc.a 0
> + .size foo0, .-foo0
> + .section .text.foo1,"ax",%progbits
> + .p2align 4
> + .globl foo1
> + .type foo1, %function
> +foo1:
> + .dc.a 0
> + .size foo1, .-foo1
> + .section .text.foo2,"ax",%progbits
> + .p2align 4
> + .globl foo2
> + .type foo2, %function
> +foo2:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L4
> + .popsection
> +.L4:
> + .dc.a 0
> + .size foo2, .-foo2
> + .section .text.foo3,"ax",%progbits
> + .p2align 4
> + .globl foo3
> + .type foo3, %function
> +foo3:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L7
> + .popsection
> +.L7:
> + .dc.a 0
> + .size foo3, .-foo3
> + .section .text.entry_func,"ax",%progbits
> + .p2align 4
> + .globl entry_func
> + .type entry_func, %function
> +entry_func:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L10
> + .popsection
> +.L10:
> + .dc.a foo0
> + .size entry_func, .-entry_func
> + .section .note.GNU-stack,"",%progbits
> diff --git a/ld/testsuite/ld-elf/pushsection-3.d b/ld/testsuite/ld-elf/pushsection-3.d
> new file mode 100644
> index 00000000000..cbb08ccd247
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-3.d
> @@ -0,0 +1,13 @@
> +#as: --unique-pushsection
> +#ld: --gc-sections -e entry_func
> +#nm: -n
> +#xfail: [is_generic] fr30-*-* frv-*-elf ft32-*-* iq2000-*-* mn10200-*-*
> +#xfail: msp430-* mt-*-* z80-*-*
> +# Generic linker targets don't comply with all orhpan section merging
> +# rules. z80 fails since a, b, c, d are registers for z80.
> +
> +#failif
> +#...
> +.* T foo2
> +.* T foo3
> +#...
> diff --git a/ld/testsuite/ld-elf/pushsection-3.s b/ld/testsuite/ld-elf/pushsection-3.s
> new file mode 100644
> index 00000000000..7909714dbd4
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-3.s
> @@ -0,0 +1,90 @@
> + .section .text.foo0,"ax",%progbits
> + .p2align 4
> + .globl foo0
> + .section __patchable_function_entries,"awo",%progbits,.LPFE1
> + .p2align 3
> + .dc.a .LPFE0
> + .section .text.foo0
> +.LPFE0:
> + .dc.a 0
> + .type foo0, %function
> +foo0:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L0
> + .popsection
> +.L0:
> + .dc.a 0
> + .size foo0, .-foo0
> + .section .text.foo1,"ax",%progbits
> + .p2align 4
> + .globl foo1
> + .section __patchable_function_entries,"awo",%progbits,.LPFE1
> + .p2align 3
> + .dc.a .LPFE1
> + .section .text.foo1
> +.LPFE1:
> + .dc.a 0
> + .type foo1, %function
> +foo1:
> + .dc.a 0
> + .size foo1, .-foo1
> + .section .text.foo2,"ax",%progbits
> + .p2align 4
> + .globl foo2
> + .section __patchable_function_entries,"awo",%progbits,.LPFE2
> + .p2align 3
> + .dc.a .LPFE2
> + .section .text.foo2
> +.LPFE2:
> + .dc.a 0
> + .type foo2, %function
> +foo2:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L4
> + .popsection
> +.L4:
> + .dc.a 0
> + .size foo2, .-foo2
> + .section .text.foo3,"ax",%progbits
> + .p2align 4
> + .globl foo3
> + .section __patchable_function_entries,"awo",%progbits,.LPFE3
> + .p2align 3
> + .dc.a .LPFE3
> + .section .text.foo3
> +.LPFE3:
> + .dc.a 0
> + .type foo3, %function
> +foo3:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L7
> + .popsection
> +.L7:
> + .dc.a 0
> + .size foo3, .-foo3
> + .section .text.entry_func,"ax",%progbits
> + .p2align 4
> + .globl entry_func
> + .section __patchable_function_entries,"awo",%progbits,.LPFE4
> + .p2align 3
> + .dc.a .LPFE4
> + .section .text.entry_func
> +.LPFE4:
> + .dc.a 0
> + .type entry_func, %function
> +entry_func:
> + .dc.a 1f
> + .pushsection .alt_section, "ax"
> +1:
> + .dc.a .L10
> + .popsection
> +.L10:
> + .dc.a foo0
> + .size entry_func, .-entry_func
> + .section .note.GNU-stack,"",%progbits
> diff --git a/ld/testsuite/ld-elf/pushsection-4.d b/ld/testsuite/ld-elf/pushsection-4.d
> new file mode 100644
> index 00000000000..bfe562496d7
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-4.d
> @@ -0,0 +1,13 @@
> +#source: pushsection-4.s
> +#ld: --gc-sections -e entry_func
> +#nm: -n
> +#xfail: [is_generic] fr30-*-* frv-*-elf ft32-*-* iq2000-*-* mn10200-*-*
> +#xfail: msp430-* mt-*-* z80-*-*
> +# Generic linker targets don't comply with all orhpan section merging
> +# rules. z80 fails since a, b, c, d are registers for z80.
> +
> +#failif
> +#...
> +.* T foo2
> +.* T foo3
> +#...
> diff --git a/ld/testsuite/ld-elf/pushsection-4.s b/ld/testsuite/ld-elf/pushsection-4.s
> new file mode 100644
> index 00000000000..b2dc6245f0a
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pushsection-4.s
> @@ -0,0 +1,90 @@
> + .section .text.foo0,"ax",%progbits
> + .p2align 4
> + .globl foo0
> + .section __patchable_function_entries,"awo",%progbits,.LPFE1
> + .p2align 3
> + .dc.a .LPFE0
> + .section .text.foo0
> +.LPFE0:
> + .dc.a 0
> + .type foo0, %function
> +foo0:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L0
> + .popsection
> +.L0:
> + .dc.a 0
> + .size foo0, .-foo0
> + .section .text.foo1,"ax",%progbits
> + .p2align 4
> + .globl foo1
> + .section __patchable_function_entries,"awo",%progbits,.LPFE1
> + .p2align 3
> + .dc.a .LPFE1
> + .section .text.foo1
> +.LPFE1:
> + .dc.a 0
> + .type foo1, %function
> +foo1:
> + .dc.a 0
> + .size foo1, .-foo1
> + .section .text.foo2,"ax",%progbits
> + .p2align 4
> + .globl foo2
> + .section __patchable_function_entries,"awo",%progbits,.LPFE2
> + .p2align 3
> + .dc.a .LPFE2
> + .section .text.foo2
> +.LPFE2:
> + .dc.a 0
> + .type foo2, %function
> +foo2:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L4
> + .popsection
> +.L4:
> + .dc.a 0
> + .size foo2, .-foo2
> + .section .text.foo3,"ax",%progbits
> + .p2align 4
> + .globl foo3
> + .section __patchable_function_entries,"awo",%progbits,.LPFE3
> + .p2align 3
> + .dc.a .LPFE3
> + .section .text.foo3
> +.LPFE3:
> + .dc.a 0
> + .type foo3, %function
> +foo3:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L7
> + .popsection
> +.L7:
> + .dc.a 0
> + .size foo3, .-foo3
> + .section .text.entry_func,"ax",%progbits
> + .p2align 4
> + .globl entry_func
> + .section __patchable_function_entries,"awo",%progbits,.LPFE4
> + .p2align 3
> + .dc.a .LPFE4
> + .section .text.entry_func
> +.LPFE4:
> + .dc.a 0
> + .type entry_func, %function
> +entry_func:
> + .dc.a 1f
> + .pushuniquesection .alt_section, "ax"
> +1:
> + .dc.a .L10
> + .popsection
> +.L10:
> + .dc.a foo0
> + .size entry_func, .-entry_func
> + .section .note.GNU-stack,"",%progbits
> --
> 2.49.0
>
More information about the Binutils
mailing list