ELF: Discard a section if any of its linked-to section has been discarded

Message ID 20200207021431.387289-1-hjl.tools@gmail.com
State New
Headers show
Series
  • ELF: Discard a section if any of its linked-to section has been discarded
Related show

Commit Message

H.J. Lu Feb. 7, 2020, 2:14 a.m.
Add ldelf_before_place_orphans to call before lang_place_orphans to
discard a section if any of its linked-to sections has been discarded.

	PR ld/25022
	* emultempl/aix.em (ld_${EMULATION_NAME}_emulation): Add
	before_place_orphans_default.
	* emultempl/armcoff.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/beos.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/generic.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/linux.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/msp430.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/pe.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/pep.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/ticoff.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/vanilla.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/elf.em (ld_${EMULATION_NAME}_emulation): Use
	ldelf_before_place_orphans.
	* ldelf.c (ldelf_before_place_orphans): New.
	* ldelf.h (ldelf_before_place_orphans): Likewise.
	* ldemul.c (ldemul_before_place_orphans): Likewise.
	(before_place_orphans_default): Likewise.
	* ldemul.h (ldemul_before_place_orphans): Likewise.
	(before_place_orphans_default): Likewise.
	(ld_emulation_xfer_struct): Add before_place_orphans.
	* ldlang.c (lang_process): Call ldemul_before_place_orphans
	before lang_place_orphans.
	* testsuite/ld-elf/pr25022.d: New file.
	* testsuite/ld-elf/pr25022.s: Likewise.
	* testsuite/ld-elf/pr25022.t: Likewise.
---
 ld/emultempl/aix.em           |  1 +
 ld/emultempl/armcoff.em       |  1 +
 ld/emultempl/beos.em          |  1 +
 ld/emultempl/elf.em           |  1 +
 ld/emultempl/generic.em       |  1 +
 ld/emultempl/linux.em         |  1 +
 ld/emultempl/msp430.em        |  1 +
 ld/emultempl/pe.em            |  1 +
 ld/emultempl/pep.em           |  1 +
 ld/emultempl/ticoff.em        |  1 +
 ld/emultempl/vanilla.em       |  1 +
 ld/ldelf.c                    | 29 +++++++++++++++++++++++++++++
 ld/ldelf.h                    |  1 +
 ld/ldemul.c                   | 11 +++++++++++
 ld/ldemul.h                   |  7 +++++++
 ld/ldlang.c                   |  2 ++
 ld/testsuite/ld-elf/pr25022.d |  9 +++++++++
 ld/testsuite/ld-elf/pr25022.s | 11 +++++++++++
 ld/testsuite/ld-elf/pr25022.t |  1 +
 19 files changed, 82 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/pr25022.d
 create mode 100644 ld/testsuite/ld-elf/pr25022.s
 create mode 100644 ld/testsuite/ld-elf/pr25022.t

-- 
2.24.1

Comments

Alan Modra Feb. 7, 2020, 3:29 a.m. | #1
On Thu, Feb 06, 2020 at 06:14:31PM -0800, H.J. Lu wrote:
> Add ldelf_before_place_orphans to call before lang_place_orphans to

> discard a section if any of its linked-to sections has been discarded.

> 

> 	PR ld/25022

> 	* emultempl/aix.em (ld_${EMULATION_NAME}_emulation): Add

> 	before_place_orphans_default.

> 	* emultempl/armcoff.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/beos.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/generic.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/linux.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/msp430.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/pe.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/pep.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/ticoff.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/vanilla.em (ld_${EMULATION_NAME}_emulation): Likewise.

> 	* emultempl/elf.em (ld_${EMULATION_NAME}_emulation): Use

> 	ldelf_before_place_orphans.

> 	* ldelf.c (ldelf_before_place_orphans): New.

> 	* ldelf.h (ldelf_before_place_orphans): Likewise.

> 	* ldemul.c (ldemul_before_place_orphans): Likewise.

> 	(before_place_orphans_default): Likewise.

> 	* ldemul.h (ldemul_before_place_orphans): Likewise.

> 	(before_place_orphans_default): Likewise.

> 	(ld_emulation_xfer_struct): Add before_place_orphans.

> 	* ldlang.c (lang_process): Call ldemul_before_place_orphans

> 	before lang_place_orphans.

> 	* testsuite/ld-elf/pr25022.d: New file.

> 	* testsuite/ld-elf/pr25022.s: Likewise.

> 	* testsuite/ld-elf/pr25022.t: Likewise.


OK.

-- 
Alan Modra
Australia Development Lab, IBM
Fangrui Song Feb. 8, 2020, 6:14 p.m. | #2
On 2020-02-06, H.J. Lu wrote:
>Add ldelf_before_place_orphans to call before lang_place_orphans to

>discard a section if any of its linked-to sections has been discarded.

>

>	PR ld/25022

>	* emultempl/aix.em (ld_${EMULATION_NAME}_emulation): Add

>	before_place_orphans_default.

>	* emultempl/armcoff.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/beos.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/generic.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/linux.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/msp430.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/pe.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/pep.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/ticoff.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/vanilla.em (ld_${EMULATION_NAME}_emulation): Likewise.

>	* emultempl/elf.em (ld_${EMULATION_NAME}_emulation): Use

>	ldelf_before_place_orphans.

>	* ldelf.c (ldelf_before_place_orphans): New.

>	* ldelf.h (ldelf_before_place_orphans): Likewise.

>	* ldemul.c (ldemul_before_place_orphans): Likewise.

>	(before_place_orphans_default): Likewise.

>	* ldemul.h (ldemul_before_place_orphans): Likewise.

>	(before_place_orphans_default): Likewise.

>	(ld_emulation_xfer_struct): Add before_place_orphans.

>	* ldlang.c (lang_process): Call ldemul_before_place_orphans

>	before lang_place_orphans.

>	* testsuite/ld-elf/pr25022.d: New file.

>	* testsuite/ld-elf/pr25022.s: Likewise.

>	* testsuite/ld-elf/pr25022.t: Likewise.

>---

> ld/emultempl/aix.em           |  1 +

> ld/emultempl/armcoff.em       |  1 +

> ld/emultempl/beos.em          |  1 +

> ld/emultempl/elf.em           |  1 +

> ld/emultempl/generic.em       |  1 +

> ld/emultempl/linux.em         |  1 +

> ld/emultempl/msp430.em        |  1 +

> ld/emultempl/pe.em            |  1 +

> ld/emultempl/pep.em           |  1 +

> ld/emultempl/ticoff.em        |  1 +

> ld/emultempl/vanilla.em       |  1 +

> ld/ldelf.c                    | 29 +++++++++++++++++++++++++++++

> ld/ldelf.h                    |  1 +

> ld/ldemul.c                   | 11 +++++++++++

> ld/ldemul.h                   |  7 +++++++

> ld/ldlang.c                   |  2 ++

> ld/testsuite/ld-elf/pr25022.d |  9 +++++++++

> ld/testsuite/ld-elf/pr25022.s | 11 +++++++++++

> ld/testsuite/ld-elf/pr25022.t |  1 +

> 19 files changed, 82 insertions(+)

> create mode 100644 ld/testsuite/ld-elf/pr25022.d

> create mode 100644 ld/testsuite/ld-elf/pr25022.s

> create mode 100644 ld/testsuite/ld-elf/pr25022.t

>

>diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em

>index c39491eab43..2da38709899 100644

>--- a/ld/emultempl/aix.em

>+++ b/ld/emultempl/aix.em

>@@ -1541,6 +1541,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {

>   after_parse_default,

>   gld${EMULATION_NAME}_after_open,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   gld${EMULATION_NAME}_set_output_arch,

>   gld${EMULATION_NAME}_choose_target,

>diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em

>index 0528c637b68..c539e2facca 100644

>--- a/ld/emultempl/armcoff.em

>+++ b/ld/emultempl/armcoff.em

>@@ -263,6 +263,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   after_parse_default,

>   gld${EMULATION_NAME}_after_open,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   set_output_arch_default,

>   ldemul_default_target,

>diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em

>index 97cde99c335..2c3e5e5370d 100644

>--- a/ld/emultempl/beos.em

>+++ b/ld/emultempl/beos.em

>@@ -763,6 +763,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   after_parse_default,

>   gld_${EMULATION_NAME}_after_open,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   set_output_arch_default,

>   ldemul_default_target,

>diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em

>index 42c552b36ed..bb7e5375303 100644

>--- a/ld/emultempl/elf.em

>+++ b/ld/emultempl/elf.em

>@@ -880,6 +880,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   ${LDEMUL_AFTER_PARSE-ldelf_after_parse},

>   ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},

>   ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default},

>+  ${LDEMUL_BEFORE_PLACE_ORPHANS-ldelf_before_place_orphans},

>   ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation},

>   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},

>   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},

>diff --git a/ld/emultempl/generic.em b/ld/emultempl/generic.em

>index e140514e8ef..a39c9332075 100644

>--- a/ld/emultempl/generic.em

>+++ b/ld/emultempl/generic.em

>@@ -138,6 +138,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   ${LDEMUL_AFTER_PARSE-after_parse_default},

>   ${LDEMUL_AFTER_OPEN-after_open_default},

>   ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default},

>+  ${LDEMUL_BEFORE_PLACE_ORPHANS-before_place_orphans_default},

>   ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},

>   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},

>   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},

>diff --git a/ld/emultempl/linux.em b/ld/emultempl/linux.em

>index fea8da486dc..f4ae6cfba29 100644

>--- a/ld/emultempl/linux.em

>+++ b/ld/emultempl/linux.em

>@@ -190,6 +190,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   after_parse_default,

>   after_open_default,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   set_output_arch_default,

>   ldemul_default_target,

>diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em

>index df940672bac..861c1dcda0a 100644

>--- a/ld/emultempl/msp430.em

>+++ b/ld/emultempl/msp430.em

>@@ -825,6 +825,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   ${LDEMUL_AFTER_PARSE-after_parse_default},

>   msp430_elf_after_open,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   msp430_elf_after_allocation,

>   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},

>   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},

>diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em

>index 97fb1468aac..db23b221d66 100644

>--- a/ld/emultempl/pe.em

>+++ b/ld/emultempl/pe.em

>@@ -2354,6 +2354,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   gld_${EMULATION_NAME}_after_parse,

>   gld_${EMULATION_NAME}_after_open,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   set_output_arch_default,

>   ldemul_default_target,

>diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em

>index e8f5ca503fb..3d09a0a6b13 100644

>--- a/ld/emultempl/pep.em

>+++ b/ld/emultempl/pep.em

>@@ -2153,6 +2153,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   gld_${EMULATION_NAME}_after_parse,

>   gld_${EMULATION_NAME}_after_open,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   set_output_arch_default,

>   ldemul_default_target,

>diff --git a/ld/emultempl/ticoff.em b/ld/emultempl/ticoff.em

>index 2b6fae64a08..60c0da9f1b1 100644

>--- a/ld/emultempl/ticoff.em

>+++ b/ld/emultempl/ticoff.em

>@@ -163,6 +163,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =

>   after_parse_default,

>   after_open_default,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   set_output_arch_default,

>   ldemul_default_target,

>diff --git a/ld/emultempl/vanilla.em b/ld/emultempl/vanilla.em

>index e17316fb5a2..ae6f6e4175d 100644

>--- a/ld/emultempl/vanilla.em

>+++ b/ld/emultempl/vanilla.em

>@@ -64,6 +64,7 @@ struct ld_emulation_xfer_struct ld_vanilla_emulation =

>   after_parse_default,

>   after_open_default,

>   after_check_relocs_default,

>+  before_place_orphans_default,

>   after_allocation_default,

>   vanilla_set_output_arch,

>   ldemul_default_target,

>diff --git a/ld/ldelf.c b/ld/ldelf.c

>index 2e27cf48a81..3ac3bb4e0a5 100644

>--- a/ld/ldelf.c

>+++ b/ld/ldelf.c

>@@ -2134,3 +2134,32 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint)

>

>   return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);

> }

>+

>+void

>+ldelf_before_place_orphans (void)

>+{

>+  bfd *abfd;

>+

>+  for (abfd = link_info.input_bfds;

>+       abfd != (bfd *) NULL; abfd = abfd->link.next)

>+    if (bfd_get_flavour (abfd) == bfd_target_elf_flavour

>+	&& bfd_count_sections (abfd) != 0

>+	&& !bfd_input_just_syms (abfd))

>+      {

>+	asection *isec;

>+	for (isec = abfd->sections; isec != NULL; isec = isec->next)

>+	  {

>+	    /* Discard a section if any of its linked-to section has

>+	       been discarded.  */

>+	    asection *linked_to_sec;

>+	    for (linked_to_sec = elf_linked_to_section (isec);

>+		 linked_to_sec != NULL;

>+		 linked_to_sec = elf_linked_to_section (linked_to_sec))

>+	      if (discarded_section (linked_to_sec))

>+		{

>+		  isec->output_section = bfd_abs_section_ptr;

>+		  break;

>+		}

>+	  }

>+      }

>+}

>diff --git a/ld/ldelf.h b/ld/ldelf.h

>index 492649b2934..2a58a0c1359 100644

>--- a/ld/ldelf.h

>+++ b/ld/ldelf.h

>@@ -30,3 +30,4 @@ extern bfd_boolean ldelf_open_dynamic_archive

>   (const char *, search_dirs_type *, lang_input_statement_type *);

> extern lang_output_section_statement_type *ldelf_place_orphan

>   (asection *, const char *, int);

>+extern void ldelf_before_place_orphans (void);

>diff --git a/ld/ldemul.c b/ld/ldemul.c

>index 1f5228d2a4a..fa6dfdd18ed 100644

>--- a/ld/ldemul.c

>+++ b/ld/ldemul.c

>@@ -71,6 +71,12 @@ ldemul_after_check_relocs (void)

>   ld_emulation->after_check_relocs ();

> }

>

>+void

>+ldemul_before_place_orphans (void)

>+{

>+  ld_emulation->before_place_orphans ();

>+}

>+

> void

> ldemul_after_allocation (void)

> {

>@@ -266,6 +272,11 @@ after_check_relocs_default (void)

> {

> }

>

>+void

>+before_place_orphans_default (void)

>+{

>+}

>+

> void

> after_allocation_default (void)

> {

>diff --git a/ld/ldemul.h b/ld/ldemul.h

>index bde74dfa9a1..44e3a92aa7e 100644

>--- a/ld/ldemul.h

>+++ b/ld/ldemul.h

>@@ -36,6 +36,8 @@ extern void ldemul_after_open

>   (void);

> extern void ldemul_after_check_relocs

>   (void);

>+extern void ldemul_before_place_orphans

>+  (void);

> extern void ldemul_after_allocation

>   (void);

> extern void ldemul_before_allocation

>@@ -80,6 +82,8 @@ extern void after_open_default

>   (void);

> extern void after_check_relocs_default

>   (void);

>+extern void before_place_orphans_default

>+  (void);

> extern void after_allocation_default

>   (void);

> extern void before_allocation_default

>@@ -129,6 +133,9 @@ typedef struct ld_emulation_xfer_struct {

>   /* Run after checking relocations.  */

>   void   (*after_check_relocs)  (void);

>

>+  /* Run before placing orphans.  */

>+  void   (*before_place_orphans)  (void);

>+

>   /* Run after allocating output sections.  */

>   void   (*after_allocation)  (void);

>

>diff --git a/ld/ldlang.c b/ld/ldlang.c

>index 91c160b5604..528ed22c1bc 100644

>--- a/ld/ldlang.c

>+++ b/ld/ldlang.c

>@@ -7837,6 +7837,8 @@ lang_process (void)

>      output statement, so that it isn't reordered.  */

>   process_insert_statements (&lang_os_list.head->header.next);

>

>+  ldemul_before_place_orphans ();

>+

>   /* Find any sections not attached explicitly and handle them.  */

>   lang_place_orphans ();

>

>diff --git a/ld/testsuite/ld-elf/pr25022.d b/ld/testsuite/ld-elf/pr25022.d

>new file mode 100644

>index 00000000000..9a397523a31

>--- /dev/null

>+++ b/ld/testsuite/ld-elf/pr25022.d

>@@ -0,0 +1,9 @@

>+#ld: -T pr25022.t

>+#readelf: -SW

>+#xfail: msp*-*

>+# msp* doesn't use ldelf_before_place_orphans.

>+

>+#failif

>+#...

>+ +\[ *[0-9]+\] \.(bar|moo|zed) +.*

>+#...

>diff --git a/ld/testsuite/ld-elf/pr25022.s b/ld/testsuite/ld-elf/pr25022.s

>new file mode 100644

>index 00000000000..ace4f25f2bc

>--- /dev/null

>+++ b/ld/testsuite/ld-elf/pr25022.s

>@@ -0,0 +1,11 @@

>+	.section .foo,"a"

>+	.dc.a 0

>+

>+	.section .moo,"ao",%progbits,.zed

>+	.dc.a 0

>+

>+	.section .bar,"ao",%progbits,.foo

>+	.dc.a 0

>+

>+	.section .zed,"ao",%progbits,.foo

>+	.dc.a 0

>diff --git a/ld/testsuite/ld-elf/pr25022.t b/ld/testsuite/ld-elf/pr25022.t

>new file mode 100644

>index 00000000000..bb9aa81e0f3

>--- /dev/null

>+++ b/ld/testsuite/ld-elf/pr25022.t

>@@ -0,0 +1 @@

>+SECTIONS { /DISCARD/ : { *(.foo) } }

>-- 

>2.24.1


Is the second rule listed on
https://sourceware.org/ml/binutils/2020-02/msg00035.html respected?

> For a non-SHF_ALLOC section, it is a GC root only if all the following

> conditions are satisfied:

> ...

> * it is not in a section group with at least one SHF_ALLOC section.

>   If it belongs to such a section group, we expect a

>     SHF_ALLOC section in the section group responsible for making the

>     whole group alive. This semantic is at least expected by


If A (with SHF_LINK_ORDER) is in a section group with no SHF_ALLOC
section, we should not garbage collect A.
H.J. Lu Feb. 8, 2020, 8:22 p.m. | #3
On Sat, Feb 8, 2020 at 10:14 AM Fangrui Song <i@maskray.me> wrote:
>

> On 2020-02-06, H.J. Lu wrote:

> >Add ldelf_before_place_orphans to call before lang_place_orphans to

> >discard a section if any of its linked-to sections has been discarded.

> >

> >       PR ld/25022

> >       * emultempl/aix.em (ld_${EMULATION_NAME}_emulation): Add

> >       before_place_orphans_default.

> >       * emultempl/armcoff.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/beos.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/generic.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/linux.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/msp430.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/pe.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/pep.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/ticoff.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/vanilla.em (ld_${EMULATION_NAME}_emulation): Likewise.

> >       * emultempl/elf.em (ld_${EMULATION_NAME}_emulation): Use

> >       ldelf_before_place_orphans.

> >       * ldelf.c (ldelf_before_place_orphans): New.

> >       * ldelf.h (ldelf_before_place_orphans): Likewise.

> >       * ldemul.c (ldemul_before_place_orphans): Likewise.

> >       (before_place_orphans_default): Likewise.

> >       * ldemul.h (ldemul_before_place_orphans): Likewise.

> >       (before_place_orphans_default): Likewise.

> >       (ld_emulation_xfer_struct): Add before_place_orphans.

> >       * ldlang.c (lang_process): Call ldemul_before_place_orphans

> >       before lang_place_orphans.

> >       * testsuite/ld-elf/pr25022.d: New file.

> >       * testsuite/ld-elf/pr25022.s: Likewise.

> >       * testsuite/ld-elf/pr25022.t: Likewise.

>

> Is the second rule listed on

> https://sourceware.org/ml/binutils/2020-02/msg00035.html respected?

>

> > For a non-SHF_ALLOC section, it is a GC root only if all the following

> > conditions are satisfied:

> > ...

> > * it is not in a section group with at least one SHF_ALLOC section.

> >   If it belongs to such a section group, we expect a

> >     SHF_ALLOC section in the section group responsible for making the

> >     whole group alive. This semantic is at least expected by

>

> If A (with SHF_LINK_ORDER) is in a section group with no SHF_ALLOC

> section, we should not garbage collect A.


Testcase please.

-- 
H.J.

Patch

diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em
index c39491eab43..2da38709899 100644
--- a/ld/emultempl/aix.em
+++ b/ld/emultempl/aix.em
@@ -1541,6 +1541,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   after_parse_default,
   gld${EMULATION_NAME}_after_open,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   gld${EMULATION_NAME}_set_output_arch,
   gld${EMULATION_NAME}_choose_target,
diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em
index 0528c637b68..c539e2facca 100644
--- a/ld/emultempl/armcoff.em
+++ b/ld/emultempl/armcoff.em
@@ -263,6 +263,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   after_parse_default,
   gld${EMULATION_NAME}_after_open,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   set_output_arch_default,
   ldemul_default_target,
diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em
index 97cde99c335..2c3e5e5370d 100644
--- a/ld/emultempl/beos.em
+++ b/ld/emultempl/beos.em
@@ -763,6 +763,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   after_parse_default,
   gld_${EMULATION_NAME}_after_open,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   set_output_arch_default,
   ldemul_default_target,
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index 42c552b36ed..bb7e5375303 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -880,6 +880,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_AFTER_PARSE-ldelf_after_parse},
   ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
   ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default},
+  ${LDEMUL_BEFORE_PLACE_ORPHANS-ldelf_before_place_orphans},
   ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation},
   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
diff --git a/ld/emultempl/generic.em b/ld/emultempl/generic.em
index e140514e8ef..a39c9332075 100644
--- a/ld/emultempl/generic.em
+++ b/ld/emultempl/generic.em
@@ -138,6 +138,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_AFTER_PARSE-after_parse_default},
   ${LDEMUL_AFTER_OPEN-after_open_default},
   ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default},
+  ${LDEMUL_BEFORE_PLACE_ORPHANS-before_place_orphans_default},
   ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
diff --git a/ld/emultempl/linux.em b/ld/emultempl/linux.em
index fea8da486dc..f4ae6cfba29 100644
--- a/ld/emultempl/linux.em
+++ b/ld/emultempl/linux.em
@@ -190,6 +190,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   after_parse_default,
   after_open_default,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   set_output_arch_default,
   ldemul_default_target,
diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em
index df940672bac..861c1dcda0a 100644
--- a/ld/emultempl/msp430.em
+++ b/ld/emultempl/msp430.em
@@ -825,6 +825,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_AFTER_PARSE-after_parse_default},
   msp430_elf_after_open,
   after_check_relocs_default,
+  before_place_orphans_default,
   msp430_elf_after_allocation,
   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 97fb1468aac..db23b221d66 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -2354,6 +2354,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_after_parse,
   gld_${EMULATION_NAME}_after_open,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   set_output_arch_default,
   ldemul_default_target,
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index e8f5ca503fb..3d09a0a6b13 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -2153,6 +2153,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_after_parse,
   gld_${EMULATION_NAME}_after_open,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   set_output_arch_default,
   ldemul_default_target,
diff --git a/ld/emultempl/ticoff.em b/ld/emultempl/ticoff.em
index 2b6fae64a08..60c0da9f1b1 100644
--- a/ld/emultempl/ticoff.em
+++ b/ld/emultempl/ticoff.em
@@ -163,6 +163,7 @@  struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   after_parse_default,
   after_open_default,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   set_output_arch_default,
   ldemul_default_target,
diff --git a/ld/emultempl/vanilla.em b/ld/emultempl/vanilla.em
index e17316fb5a2..ae6f6e4175d 100644
--- a/ld/emultempl/vanilla.em
+++ b/ld/emultempl/vanilla.em
@@ -64,6 +64,7 @@  struct ld_emulation_xfer_struct ld_vanilla_emulation =
   after_parse_default,
   after_open_default,
   after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
   vanilla_set_output_arch,
   ldemul_default_target,
diff --git a/ld/ldelf.c b/ld/ldelf.c
index 2e27cf48a81..3ac3bb4e0a5 100644
--- a/ld/ldelf.c
+++ b/ld/ldelf.c
@@ -2134,3 +2134,32 @@  ldelf_place_orphan (asection *s, const char *secname, int constraint)
 
   return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
 }
+
+void
+ldelf_before_place_orphans (void)
+{
+  bfd *abfd;
+
+  for (abfd = link_info.input_bfds;
+       abfd != (bfd *) NULL; abfd = abfd->link.next)
+    if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+	&& bfd_count_sections (abfd) != 0
+	&& !bfd_input_just_syms (abfd))
+      {
+	asection *isec;
+	for (isec = abfd->sections; isec != NULL; isec = isec->next)
+	  {
+	    /* Discard a section if any of its linked-to section has
+	       been discarded.  */
+	    asection *linked_to_sec;
+	    for (linked_to_sec = elf_linked_to_section (isec);
+		 linked_to_sec != NULL;
+		 linked_to_sec = elf_linked_to_section (linked_to_sec))
+	      if (discarded_section (linked_to_sec))
+		{
+		  isec->output_section = bfd_abs_section_ptr;
+		  break;
+		}
+	  }
+      }
+}
diff --git a/ld/ldelf.h b/ld/ldelf.h
index 492649b2934..2a58a0c1359 100644
--- a/ld/ldelf.h
+++ b/ld/ldelf.h
@@ -30,3 +30,4 @@  extern bfd_boolean ldelf_open_dynamic_archive
   (const char *, search_dirs_type *, lang_input_statement_type *);
 extern lang_output_section_statement_type *ldelf_place_orphan
   (asection *, const char *, int);
+extern void ldelf_before_place_orphans (void);
diff --git a/ld/ldemul.c b/ld/ldemul.c
index 1f5228d2a4a..fa6dfdd18ed 100644
--- a/ld/ldemul.c
+++ b/ld/ldemul.c
@@ -71,6 +71,12 @@  ldemul_after_check_relocs (void)
   ld_emulation->after_check_relocs ();
 }
 
+void
+ldemul_before_place_orphans (void)
+{
+  ld_emulation->before_place_orphans ();
+}
+
 void
 ldemul_after_allocation (void)
 {
@@ -266,6 +272,11 @@  after_check_relocs_default (void)
 {
 }
 
+void
+before_place_orphans_default (void)
+{
+}
+
 void
 after_allocation_default (void)
 {
diff --git a/ld/ldemul.h b/ld/ldemul.h
index bde74dfa9a1..44e3a92aa7e 100644
--- a/ld/ldemul.h
+++ b/ld/ldemul.h
@@ -36,6 +36,8 @@  extern void ldemul_after_open
   (void);
 extern void ldemul_after_check_relocs
   (void);
+extern void ldemul_before_place_orphans
+  (void);
 extern void ldemul_after_allocation
   (void);
 extern void ldemul_before_allocation
@@ -80,6 +82,8 @@  extern void after_open_default
   (void);
 extern void after_check_relocs_default
   (void);
+extern void before_place_orphans_default
+  (void);
 extern void after_allocation_default
   (void);
 extern void before_allocation_default
@@ -129,6 +133,9 @@  typedef struct ld_emulation_xfer_struct {
   /* Run after checking relocations.  */
   void   (*after_check_relocs)  (void);
 
+  /* Run before placing orphans.  */
+  void   (*before_place_orphans)  (void);
+
   /* Run after allocating output sections.  */
   void   (*after_allocation)  (void);
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 91c160b5604..528ed22c1bc 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -7837,6 +7837,8 @@  lang_process (void)
      output statement, so that it isn't reordered.  */
   process_insert_statements (&lang_os_list.head->header.next);
 
+  ldemul_before_place_orphans ();
+
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
diff --git a/ld/testsuite/ld-elf/pr25022.d b/ld/testsuite/ld-elf/pr25022.d
new file mode 100644
index 00000000000..9a397523a31
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25022.d
@@ -0,0 +1,9 @@ 
+#ld: -T pr25022.t
+#readelf: -SW
+#xfail: msp*-*
+# msp* doesn't use ldelf_before_place_orphans.
+
+#failif
+#...
+ +\[ *[0-9]+\] \.(bar|moo|zed) +.*
+#...
diff --git a/ld/testsuite/ld-elf/pr25022.s b/ld/testsuite/ld-elf/pr25022.s
new file mode 100644
index 00000000000..ace4f25f2bc
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25022.s
@@ -0,0 +1,11 @@ 
+	.section .foo,"a"
+	.dc.a 0
+
+	.section .moo,"ao",%progbits,.zed
+	.dc.a 0
+
+	.section .bar,"ao",%progbits,.foo
+	.dc.a 0
+
+	.section .zed,"ao",%progbits,.foo
+	.dc.a 0
diff --git a/ld/testsuite/ld-elf/pr25022.t b/ld/testsuite/ld-elf/pr25022.t
new file mode 100644
index 00000000000..bb9aa81e0f3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25022.t
@@ -0,0 +1 @@ 
+SECTIONS { /DISCARD/ : { *(.foo) } }