[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