[PATCH v2] gas: Add --unique-pushsection

H.J. Lu hjl.tools@gmail.com
Fri May 16 21:15:26 GMT 2025


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:

Add --unique-pushsection option to ELF assembler to append the current
section name to the new section name for .pushsection.

Another option is to replace ".pushsection .alt_section" with
".pushsection .alt_section%S" and compile with -Wa,--sectname-subst.

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 ".pushsection .alt_section%S" and compile with
-Wa,--sectname-subst
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.
	* 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 (change_section): Append the previous section
	name to the new section name for .pushsection with
	--unique-pushsection.
	* doc/as.texi: Document --unique-pushsection.
	* testsuite/gas/elf/elf.exp: Run PR gas/32961 tests.
	* testsuite/gas/elf/pushsection-1.d: New file.
	* testsuite/gas/elf/pushsection-1.s: Likewise.
	* testsuite/gas/elf/pushsection-2.s: Likewise.
	* testsuite/gas/elf/pushsection-2a.d: Likewise.
	* testsuite/gas/elf/pushsection-2b.d: 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.s: Likewise.
	* testsuite/ld-elf/pushsection-2a.d: Likewise.
	* testsuite/ld-elf/pushsection-2b.d: 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-4a.d: Likewise.
	* testsuite/ld-elf/pushsection-4b.d: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Tested-by: Zhiyuan Lv <zhiyuan.lv@linux.intel.com>
---
 gas/NEWS                               |  3 +
 gas/as.c                               | 12 +++-
 gas/as.h                               |  3 +
 gas/config/obj-elf.c                   |  5 ++
 gas/doc/as.texi                        |  6 ++
 gas/testsuite/gas/elf/elf.exp          |  4 ++
 gas/testsuite/gas/elf/pushsection-1.d  | 25 +++++++
 gas/testsuite/gas/elf/pushsection-1.s  | 60 +++++++++++++++++
 gas/testsuite/gas/elf/pushsection-2.s  | 60 +++++++++++++++++
 gas/testsuite/gas/elf/pushsection-2a.d | 26 ++++++++
 gas/testsuite/gas/elf/pushsection-2b.d | 26 ++++++++
 ld/testsuite/ld-elf/pushsection-1.d    | 13 ++++
 ld/testsuite/ld-elf/pushsection-1.s    | 60 +++++++++++++++++
 ld/testsuite/ld-elf/pushsection-2.s    | 60 +++++++++++++++++
 ld/testsuite/ld-elf/pushsection-2a.d   | 14 ++++
 ld/testsuite/ld-elf/pushsection-2b.d   | 14 ++++
 ld/testsuite/ld-elf/pushsection-3.d    | 13 ++++
 ld/testsuite/ld-elf/pushsection-3.s    | 90 ++++++++++++++++++++++++++
 ld/testsuite/ld-elf/pushsection-4.s    | 90 ++++++++++++++++++++++++++
 ld/testsuite/ld-elf/pushsection-4a.d   | 14 ++++
 ld/testsuite/ld-elf/pushsection-4b.d   | 14 ++++
 21 files changed, 611 insertions(+), 1 deletion(-)
 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.s
 create mode 100644 gas/testsuite/gas/elf/pushsection-2a.d
 create mode 100644 gas/testsuite/gas/elf/pushsection-2b.d
 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.s
 create mode 100644 ld/testsuite/ld-elf/pushsection-2a.d
 create mode 100644 ld/testsuite/ld-elf/pushsection-2b.d
 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.s
 create mode 100644 ld/testsuite/ld-elf/pushsection-4a.d
 create mode 100644 ld/testsuite/ld-elf/pushsection-4b.d

diff --git a/gas/NEWS b/gas/NEWS
index 42c3329d83e..9d4e9c1b84d 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add --unique-pushsection option to ELF assembler to append the current
+  section name to the new section name for .pushsection.
+
 * 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..6b02c6e2756 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -622,6 +622,11 @@ change_section (const char *name,
 
   obj_elf_section_change_hook ();
 
+  if (push
+      && previous_section
+      && 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);
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 40d45f75d18..26db3530acb 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.
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 1f42c3f3723..9702f531a9e 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -388,4 +388,8 @@ 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-2a"
+    run_dump_test "pushsection-2b"
 }
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.s b/gas/testsuite/gas/elf/pushsection-2.s
new file mode 100644
index 00000000000..d78d603e3d0
--- /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
+	.pushsection .alt_section%S, "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%S, "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%S, "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%S, "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-2a.d b/gas/testsuite/gas/elf/pushsection-2a.d
new file mode 100644
index 00000000000..c70eae05116
--- /dev/null
+++ b/gas/testsuite/gas/elf/pushsection-2a.d
@@ -0,0 +1,26 @@
+#source: pushsection-2.s
+#as: --sectname-subst
+#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-2b.d b/gas/testsuite/gas/elf/pushsection-2b.d
new file mode 100644
index 00000000000..e95a09f67ba
--- /dev/null
+++ b/gas/testsuite/gas/elf/pushsection-2b.d
@@ -0,0 +1,26 @@
+#source: pushsection-2.s
+#as: --sectname-subst --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\.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\.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\.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\.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/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.s b/ld/testsuite/ld-elf/pushsection-2.s
new file mode 100644
index 00000000000..d78d603e3d0
--- /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
+	.pushsection .alt_section%S, "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%S, "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%S, "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%S, "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-2a.d b/ld/testsuite/ld-elf/pushsection-2a.d
new file mode 100644
index 00000000000..efedc35aeb4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pushsection-2a.d
@@ -0,0 +1,14 @@
+#source: pushsection-2.s
+#as: --sectname-subst
+#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-2b.d b/ld/testsuite/ld-elf/pushsection-2b.d
new file mode 100644
index 00000000000..dd475f90b2e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pushsection-2b.d
@@ -0,0 +1,14 @@
+#source: pushsection-2.s
+#as: --sectname-subst --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.d b/ld/testsuite/ld-elf/pushsection-3.d
new file mode 100644
index 00000000000..49c47282f6a
--- /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.s b/ld/testsuite/ld-elf/pushsection-4.s
new file mode 100644
index 00000000000..5ffe2983a9a
--- /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
+	.pushsection .alt_section%S, "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%S, "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%S, "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%S, "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-4a.d b/ld/testsuite/ld-elf/pushsection-4a.d
new file mode 100644
index 00000000000..9d3155369f7
--- /dev/null
+++ b/ld/testsuite/ld-elf/pushsection-4a.d
@@ -0,0 +1,14 @@
+#source: pushsection-4.s
+#as: --sectname-subst
+#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-4b.d b/ld/testsuite/ld-elf/pushsection-4b.d
new file mode 100644
index 00000000000..a0f5ae93a9f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pushsection-4b.d
@@ -0,0 +1,14 @@
+#source: pushsection-4.s
+#as: --sectname-subst --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
+#...
-- 
2.49.0



More information about the Binutils mailing list