This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: linker script, /DISCARD/ section and SHT_GROUP
Hi Guys,
> I don't see anything particularly strange. A section group typically
> is used to package up code, data and debug info for a function. You
> normally want to include or exclude the whole group, but in some cases
> you might want to exclude all sections of a particular type. An
> obvious example is when stripping debug info. Other abnormal cases
> surely exist, allowed for by /DISCARD/.
The problem is that discarding sections in this way breaks the semantics
of the ELF section group, so at the very least we ought to document this
behaviour.
Attached however is a proposed patch to change the linker's behaviour so
that it would behave in the following way:
* If a /DISCARD/ed section is not part of an ELF group, then always
discard it, just like before.
* Otherwise if any of the other sections in the group are the subject
of a KEEP directive, then treat the section as an orphan. (I did not
want to reparse the linker script to see if the section matched some
other section directive). This will usually mean that the section will
be retained, unless orphans are being discarded.
* Otherwise discard the section as normal.
* If the --verbose linker option is in effect then generate information
messages when then /DISCARD/ section interacts with an ELF group.
So new behaviour would only happen when /DISCARD/ and KEEP intersect, and
then only if orphans are being retained in the output.
What do you think, would this work ?
Cheers
Nick
2019-11-19 Nick Clifton <nickc@redhat.com>
* ldelf.c (ldelf_discard_section): New function. Checks for a
section that is going to be discard, but which is part of a
section group. If any other sections in the group must be kept
then treat the section as an orphan instead.
* ldelf.h (ldelf_discard_section): Prototype.
* ldemul.c (ldemul_discard_section): New function. If the
discard_section in the xfer struct has been initialised then
invoke it.
* ldemul.h (ldemul_discard_section): Prototype.
(ld_emulation_xfer_struct): Add discard_section field.
* ldlang.c (lang_add_section): Call ldmeul_discard_section.
(ldlang_place_orphans): Return the output section statement to
which the section has been attached.
* ldlang.h (LANG_FOR_EACH_INPUT_STATEMENT): Allow for the
file_chain being empty.
* emultempl/aix.em (ld_emulation_xfer_struct): Initialise the
discard_section field.
* emultempl/armcoff.em (ld_emulation_xfer_struct): Likewise
* emultempl/beos.em (ld_emulation_xfer_struct): Likewise
* emultempl/elf.em (ld_emulation_xfer_struct): Likewise
* emultempl/generic.em (ld_emulation_xfer_struct): Likewise
* emultempl/linux.em (ld_emulation_xfer_struct): Likewise
* emultempl/msp430.em (ld_emulation_xfer_struct): Likewise
* emultempl/pe.em (ld_emulation_xfer_struct): Likewise
* emultempl/pep.em (ld_emulation_xfer_struct): Likewise
* emultempl/ticoff.em (ld_emulation_xfer_struct): Likewise
* emultempl/vanilla.em (ld_emulation_xfer_struct): Likewise
* ld.texi (Output Section Discarding): Update description of the
behaviour of the /DISCARD/ output section.
* NEWS: Mention this new behaviour.
* testsuite/ld-elf/group10.d: Use a test specific linker script.
Skip test for ELF based targets which do not use the ELF emulation
layer. Update expected output.
* testsuite/ld-elf/group10.ld: New file.
* testsuite/ld-elf/pr22836-2.d: Use a test specific linker script.
Update expected output.
* testsuite/ld-elf/pr22836-2.t: New file.
* testsuite/ld-elf/discard4.d: New test.
* testsuite/ld-elf/discard4.s: New test source file.
* testsuite/ld-elf/discard4.t: New test linker script.
diff --git a/ld/NEWS b/ld/NEWS
index bc21c39c05..389f48d1b0 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,11 @@
-*- text -*-
+* Sections that match the /DISCARD/ output section in linker scripts will no
+ longer be discarded if they are part of an ELF section group and one or
+ more of the other sections in this group are subject to a KEEP directive.
+ This change will only happen however provided that orphan sections are not
+ being discarded, since retained /DISCARD/ed sections are treated as orphans.
+
* cr16c support removed.
Changes in 2.33:
diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em
index f4441109d2..10fda4da65 100644
--- a/ld/emultempl/aix.em
+++ b/ld/emultempl/aix.em
@@ -1563,6 +1563,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
NULL, /* new_vers_pattern */
NULL, /* extra_map_file_text */
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL}
};
EOF
diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em
index 0eda136c83..6b3946b029 100644
--- a/ld/emultempl/armcoff.em
+++ b/ld/emultempl/armcoff.em
@@ -285,6 +285,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
NULL, /* new_vers_pattern */
NULL, /* extra_map_file_text */
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL}
};
EOF
diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em
index 4dbccf16de..c2d5b627c9 100644
--- a/ld/emultempl/beos.em
+++ b/ld/emultempl/beos.em
@@ -785,6 +785,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
NULL, /* new_vers_pattern */
NULL, /* extra_map_file_text */
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL}
};
EOF
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index dcd9523900..b1d54b1727 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -902,6 +902,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
${LDEMUL_NEW_VERS_PATTERN-NULL},
${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-ldelf_discard_section}
};
EOF
diff --git a/ld/emultempl/generic.em b/ld/emultempl/generic.em
index 17c9eb11d5..d78305e67a 100644
--- a/ld/emultempl/generic.em
+++ b/ld/emultempl/generic.em
@@ -160,6 +160,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
${LDEMUL_NEW_VERS_PATTERN-NULL},
${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL}
};
EOF
diff --git a/ld/emultempl/linux.em b/ld/emultempl/linux.em
index e32c74a546..1bf7421fec 100644
--- a/ld/emultempl/linux.em
+++ b/ld/emultempl/linux.em
@@ -212,6 +212,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
NULL, /* new_vers_pattern */
NULL, /* extra_map_file_text */
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL}
};
EOF
diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em
index 96d42c8a16..ec59fee80a 100644
--- a/ld/emultempl/msp430.em
+++ b/ld/emultempl/msp430.em
@@ -847,7 +847,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
${LDEMUL_NEW_VERS_PATTERN-NULL},
${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL}
};
EOF
#
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index c4c6464c3c..44fdb3b629 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -2369,6 +2369,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
NULL, /* new_vers_pattern. */
NULL, /* extra_map_file_text. */
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL}
};
EOF
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index ec2d83fa63..9154fd76e6 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -2168,6 +2168,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
NULL, /* new_vers_pattern. */
NULL, /* extra_map_file_text */
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL},
};
EOF
diff --git a/ld/emultempl/ticoff.em b/ld/emultempl/ticoff.em
index 09f1953a4a..94aebba57e 100644
--- a/ld/emultempl/ticoff.em
+++ b/ld/emultempl/ticoff.em
@@ -185,6 +185,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
NULL, /* new_vers_pattern */
NULL, /* extra_map_file_text */
${LDEMUL_EMIT_CTF_EARLY-NULL},
- ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
+ ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL},
+ ${LDEMUL_DISCARD_SECTION-NULL},
};
EOF
diff --git a/ld/emultempl/vanilla.em b/ld/emultempl/vanilla.em
index 1e2955ff0d..2662fafed1 100644
--- a/ld/emultempl/vanilla.em
+++ b/ld/emultempl/vanilla.em
@@ -86,6 +86,7 @@ struct ld_emulation_xfer_struct ld_vanilla_emulation =
NULL, /* new_vers_pattern */
NULL, /* extra_map_file_text */
NULL, /* emit_ctf_early */
- NULL /* examine_strtab_for_ctf */
+ NULL, /* examine_strtab_for_ctf */
+ NULL /* discard_section */
};
EOF
diff --git a/ld/ld.texi b/ld/ld.texi
index 3b2d05411f..2fbb59adbe 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -4994,6 +4994,12 @@ The special output section name @samp{/DISCARD/} may be used to discard
input sections. Any input sections which are assigned to an output
section named @samp{/DISCARD/} are not included in the output file.
+Note however that if the section is part of an ELF section group, and
+other sections in the group are the subject of a @samp{KEEP}
+directive, then the section will be treated as an orphan instead.
+This will usually mean that the section is retained unless the
+@option{--orphan-handling} option has been set to @option{discard}.
+
@node Output Section Attributes
@subsection Output Section Attributes
@cindex output section attributes
diff --git a/ld/ldelf.c b/ld/ldelf.c
index b27917c5fc..3a7c5eab6a 100644
--- a/ld/ldelf.c
+++ b/ld/ldelf.c
@@ -2134,3 +2134,101 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint)
return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
}
+
+bfd_boolean
+ldelf_discard_section (bfd_boolean discard,
+ asection * section,
+ lang_output_section_statement_type ** output)
+{
+ if (bfd_get_flavour (link_info.output_bfd) != bfd_target_elf_flavour
+ || section->used_by_bfd == NULL
+ || ! bfd_elf_is_group_section (link_info.output_bfd, section))
+ return discard;
+
+ asection *sec;
+ asection *firstsec = NULL;
+
+ /* Check for an ELF section group, which might change our decision. */
+ if (discard)
+ {
+ for (sec = elf_next_in_group (section);
+ sec != NULL && sec != section;
+ sec = elf_next_in_group (sec))
+ {
+ if (firstsec == NULL)
+ firstsec = sec;
+ else if (firstsec == sec)
+ break;
+
+ if (sec->flags & SEC_KEEP)
+ {
+ if (strcmp ((*output)->name, DISCARD_SECTION_NAME) == 0)
+ {
+ if (config.orphan_handling == orphan_handling_discard)
+ {
+ if (verbose)
+ einfo (_("%P: %pB: warning: /DISCARD/ed section %pA is in a group with kept section %pA - discarded because orphans are being discarded too\n"),
+ link_info.output_bfd, section, sec);
+ }
+ else
+ {
+ if (verbose)
+ einfo (_("%P: %pB: warning: /DISCARD/ed section %pA is in a group with kept section %pA - ignoring the discard\n"),
+ link_info.output_bfd, section, sec);
+ discard = FALSE;
+ *output = ldemul_place_orphan (section, section->name, 0);
+ }
+ }
+ else
+ {
+ if (verbose)
+ einfo (_("%P: %pB: note: discard of section %pA ignored because it is in a group with kept section %pA\n"),
+ link_info.output_bfd, section, sec);
+ discard = FALSE;
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ bfd_boolean keep = (section->flags & SEC_KEEP) == SEC_KEEP;
+ asection * discarding = NULL;
+
+ ASSERT (section != bfd_abs_section_ptr);
+
+ for (sec = elf_next_in_group (section);
+ sec != NULL && sec != section;
+ sec = elf_next_in_group (sec))
+ {
+ if (firstsec == NULL)
+ firstsec = sec;
+ else if (firstsec == sec)
+ break;
+
+ if (sec->flags & SEC_KEEP)
+ {
+ keep = TRUE;
+ break;
+ }
+ else if (sec->output_section == bfd_abs_section_ptr)
+ {
+ discarding = sec;
+ }
+ }
+
+ /* If we did not find any must-keep sections and we did
+ find a we-are-going-to-discard section then discard
+ this one as well. */
+ if (!keep && discarding != NULL)
+ {
+ if (verbose)
+ einfo (_("%P: %pB: note: discarding section %pA as it is in a group with discarded section %pA\n"),
+ link_info.output_bfd, section, discarding);
+ /* Marked for discard. */
+ discard = TRUE;
+ }
+ }
+
+ return discard;
+}
diff --git a/ld/ldelf.h b/ld/ldelf.h
index 88ca14152f..59cb1bd295 100644
--- a/ld/ldelf.h
+++ b/ld/ldelf.h
@@ -30,3 +30,5 @@ 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 bfd_boolean ldelf_discard_section
+ (bfd_boolean, asection *, lang_output_section_statement_type **);
diff --git a/ld/ldemul.c b/ld/ldemul.c
index 090f1ebfa7..2156411d8e 100644
--- a/ld/ldemul.c
+++ b/ld/ldemul.c
@@ -115,6 +115,16 @@ ldemul_get_script (int *isfile)
return ld_emulation->get_script (isfile);
}
+bfd_boolean
+ldemul_discard_section (bfd_boolean discard,
+ asection * section,
+ lang_output_section_statement_type ** output)
+{
+ if (ld_emulation->discard_section == NULL)
+ return discard;
+ return ld_emulation->discard_section (discard, section, output);
+}
+
bfd_boolean
ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search,
lang_input_statement_type *entry)
diff --git a/ld/ldemul.h b/ld/ldemul.h
index bc12b3e277..c3b3aa95d8 100644
--- a/ld/ldemul.h
+++ b/ld/ldemul.h
@@ -100,6 +100,8 @@ extern struct bfd_elf_version_expr *ldemul_new_vers_pattern
(struct bfd_elf_version_expr *);
extern void ldemul_extra_map_file_text
(bfd *, struct bfd_link_info *, FILE *);
+extern bfd_boolean ldemul_discard_section
+ (bfd_boolean, asection *, lang_output_section_statement_type **);
/* Return 1 if we are emitting CTF early, and 0 if ldemul_examine_strtab_for_ctf
will be called by the target. */
extern int ldemul_emit_ctf_early
@@ -109,7 +111,8 @@ extern void ldemul_examine_strtab_for_ctf
(struct ctf_file *, struct elf_sym_strtab *, bfd_size_type,
struct elf_strtab_hash *);
-typedef struct ld_emulation_xfer_struct {
+typedef struct ld_emulation_xfer_struct
+{
/* Run before parsing the command line and script file.
Set the architecture, maybe other things. */
void (*before_parse) (void);
@@ -229,6 +232,13 @@ typedef struct ld_emulation_xfer_struct {
bfd_link_callback is invoked by per-target code. */
void (*examine_strtab_for_ctf) (struct ctf_file *, struct elf_sym_strtab *,
bfd_size_type, struct elf_strtab_hash *);
+
+ /* Called to allow the emulation to decide if a section should be discarded.
+ The current decision is in DISCARD. Returns the new, possibly unaltered
+ value. If necessary the OUTPUT section can be changed as well. */
+ bfd_boolean (*discard_section) (bfd_boolean discard, asection *,
+ lang_output_section_statement_type **);
+
} ld_emulation_xfer_type;
typedef enum {
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 8cc5cf7f90..3e3e6a0289 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -574,7 +574,7 @@ extern asection *section_for_dot
#define LANG_FOR_EACH_INPUT_STATEMENT(statement) \
lang_input_statement_type *statement; \
- for (statement = &file_chain.head->input_statement; \
+ for (statement = file_chain.head == NULL ? NULL : &file_chain.head->input_statement; \
statement != NULL; \
statement = statement->next)
diff --git a/ld/testsuite/ld-elf/group10.d b/ld/testsuite/ld-elf/group10.d
index 6dbe49e090..f6d806fe93 100644
--- a/ld/testsuite/ld-elf/group10.d
+++ b/ld/testsuite/ld-elf/group10.d
@@ -1,6 +1,8 @@
#source: group10.s
-#ld: -r -T group.ld
+#ld: -r -T group10.ld
#readelf: -Sg --wide
+# These targets do not use the standard "elf" emulation and so they miss out on group discard support.
+#skip: alpha-* d30v-* dlx-* fr30-* frv-* ft32-* iq2000-* mn10200-* moxie-* msp430-* ms1-* mt-* pj-* s12z-* xgate*-*-*
#...
group section \[[ 0-9]+\] `\.group' \[foo_group\] contains . sections:
@@ -9,4 +11,5 @@ group section \[[ 0-9]+\] `\.group' \[foo_group\] contains . sections:
#...
\[[ 0-9]+\] \.rodata\.str.*
\[[ 0-9]+\] \.data.*
+ \[[ 0-9]+\] \.dropme.*
\[[ 0-9]+\] \.keepme.*
diff --git a/ld/testsuite/ld-elf/pr22836-2.d b/ld/testsuite/ld-elf/pr22836-2.d
index 10133e4b90..3f61b5bbad 100644
--- a/ld/testsuite/ld-elf/pr22836-2.d
+++ b/ld/testsuite/ld-elf/pr22836-2.d
@@ -1,7 +1,9 @@
#source: pr22836-2.s
-#ld: -r -S
+#ld: -r -S -T pr22836-2.t
#readelf: -g --wide
-group section \[[ 0-9]+\] `\.group' \[foo\] contains 1 section.*
+group section \[[ 0-9]+\] `\.group' \[foo\] contains . section.*
\[Index\] Name
+#...
\[[ 0-9]+\] \.comment
+#...
--- /dev/null 2019-11-18 09:25:26.434438417 +0000
+++ ld/testsuite/ld-elf/discard4.d 2019-11-19 12:58:06.531304548 +0000
@@ -0,0 +1,15 @@
+#source: discard4.s
+#ld: -T discard4.t
+#readelf: --sections --wide
+# These targets do not use the standard "elf" emulation and so they miss out on group discard support.
+#skip: alpha-* d30v-* dlx-* fr30-* frv-* ft32-* iq2000-* mn10200-* moxie-* msp430-* ms1-* mt-* pj-* s12z-* xgate*-*
+
+#...
+.*.delme.*
+#...
+.*.keepme.*
+#...
+.*.eitheror.*
+#...
+.*.orphan.*
+#pass
--- /dev/null 2019-11-18 09:25:26.434438417 +0000
+++ ld/testsuite/ld-elf/discard4.s 2019-11-19 12:54:51.914808757 +0000
@@ -0,0 +1,19 @@
+
+.globl delme, keepme, eitheror, orphan
+
+.section .delme,"aG",%note,foo,comdat
+delme:
+ .byte 0
+
+.section .keepme,"axG",%progbits,foo,comdat
+keepme:
+ .byte 0
+
+.section .eitheror,"awG",%nobits,foo,comdat
+eitheror:
+ .byte 0
+
+.section .orphan,"G",%note,foo,comdat
+orphan:
+ .byte 0
+
--- /dev/null 2019-11-18 09:25:26.434438417 +0000
+++ ld/testsuite/ld-elf/discard4.t 2019-11-18 15:23:52.809458562 +0000
@@ -0,0 +1,9 @@
+
+SECTIONS
+{
+ /DISCARD/ : { *(.delme) }
+ .keepme : { KEEP (*(.keepme)) }
+ .eitheror : { *(.eitheror) }
+}
+
+
--- /dev/null 2019-11-18 09:25:26.434438417 +0000
+++ ld/testsuite/ld-elf/group10.ld 2019-11-18 14:06:33.561403985 +0000
@@ -0,0 +1,12 @@
+PHDRS
+{
+ header PT_PHDR PHDRS ;
+ image PT_LOAD PHDRS;
+}
+
+SECTIONS
+{
+ . = 0x1000;
+ .text : { *(.text) KEEP (*(.keepme)) *(.rodata.brlt) } :image :header
+ /DISCARD/ : { *(.dropme) *(.reginfo) *(.MIPS.abiflags) }
+}
--- /dev/null 2019-11-18 09:25:26.434438417 +0000
+++ ld/testsuite/ld-elf/pr22836-2.t 2019-11-18 15:26:27.591364796 +0000
@@ -0,0 +1,6 @@
+SECTIONS
+{
+ . = 0x1000;
+ .comment : { KEEP (*(.comment)) }
+ /DISCARD/ : { *(.debug_macro) *(.reginfo) *(.MIPS.abiflags) }
+}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index eedcb7f405..d9aa749226 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2530,6 +2530,8 @@ lang_add_section (lang_statement_list_type *ptr,
if (strcmp (output->name, DISCARD_SECTION_NAME) == 0)
discard = TRUE;
+ discard = ldemul_discard_section (discard, section, & output);
+
if (discard)
{
if (section->output_section == NULL)
@@ -6911,14 +6913,16 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
/* Handle a single orphan section S, placing the orphan into an appropriate
output section. The effects of the --orphan-handling command line
- option are handled here. */
+ option are handled here. Returns the output section statement now
+ containing the orphan. */
-static void
+static lang_output_section_statement_type *
ldlang_place_orphan (asection *s)
{
+ lang_output_section_statement_type *os;
+
if (config.orphan_handling == orphan_handling_discard)
{
- lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0,
TRUE);
if (os->addr_tree == NULL
@@ -6929,7 +6933,6 @@ ldlang_place_orphan (asection *s)
}
else
{
- lang_output_section_statement_type *os;
const char *name = s->name;
int constraint = 0;
@@ -6956,6 +6959,8 @@ ldlang_place_orphan (asection *s)
"placed in section `%s'\n"),
s, s->owner, os->name);
}
+
+ return os;
}
/* Run through the input files and ensure that every input section has