ELF checks for orphan placement

The loop checking for previous orphan placement should run even when
the output is non-ELF.

	PR ld/21884
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Revert
	last change.  Rename iself to elfinput.  Expand comments.  Condition
	ELF checks on having both input and output ELF files.  Extract..
	(elf_orphan_compatible): ..this new function.
This commit is contained in:
Alan Modra
2017-08-03 14:01:34 +09:30
parent 5f66bad45b
commit 2e9246e077
2 changed files with 55 additions and 29 deletions

View File

@ -1,3 +1,11 @@
2017-08-03 Alan Modra <amodra@gmail.com>
PR ld/21884
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Revert
last change. Rename iself to elfinput. Expand comments. Condition
ELF checks on having both input and output ELF files. Extract..
(elf_orphan_compatible): ..this new function.
2017-08-02 H.J. Lu <hongjiu.lu@intel.com> 2017-08-02 H.J. Lu <hongjiu.lu@intel.com>
PR ld/21884 PR ld/21884

View File

@ -2008,6 +2008,29 @@ output_rel_find (asection *sec, int isdyn)
return last; return last;
} }
/* Return whether IN is suitable to be part of OUT. */
static bfd_boolean
elf_orphan_compatible (asection *in, asection *out)
{
/* Non-zero sh_info implies a section with SHF_INFO_LINK with
unknown semantics for the generic linker, or a SHT_REL/SHT_RELA
section where sh_info specifies a symbol table. (We won't see
SHT_GROUP, SHT_SYMTAB or SHT_DYNSYM sections here.) We clearly
can't merge SHT_REL/SHT_RELA using differing symbol tables, and
shouldn't merge sections with differing unknown semantics. */
if (elf_section_data (out)->this_hdr.sh_info
!= elf_section_data (in)->this_hdr.sh_info)
return FALSE;
/* We can't merge two sections with differing SHF_EXCLUDE when doing
a relocatable link. */
if (bfd_link_relocatable (&link_info)
&& ((elf_section_flags (out) ^ elf_section_flags (in)) & SHF_EXCLUDE) != 0)
return FALSE;
return _bfd_elf_match_sections_by_type (link_info.output_bfd, out,
in->owner, in);
}
/* Place an orphan section. We use this to put random SHF_ALLOC /* Place an orphan section. We use this to put random SHF_ALLOC
sections in the right segment. */ sections in the right segment. */
@ -2064,8 +2087,9 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
lang_output_section_statement_type *match_by_name = NULL; lang_output_section_statement_type *match_by_name = NULL;
int isdyn = 0; int isdyn = 0;
int iself = s->owner->xvec->flavour == bfd_target_elf_flavour; int elfinput = s->owner->xvec->flavour == bfd_target_elf_flavour;
unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL; int elfoutput = link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour;
unsigned int sh_type = elfinput ? elf_section_type (s) : SHT_NULL;
flagword flags; flagword flags;
asection *nexts; asection *nexts;
@ -2073,7 +2097,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
&& link_info.combreloc && link_info.combreloc
&& (s->flags & SEC_ALLOC)) && (s->flags & SEC_ALLOC))
{ {
if (iself) if (elfinput)
switch (sh_type) switch (sh_type)
{ {
case SHT_RELA: case SHT_RELA:
@ -2095,6 +2119,8 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
} }
if (!bfd_link_relocatable (&link_info) if (!bfd_link_relocatable (&link_info)
&& elfinput
&& elfoutput
&& (s->flags & SEC_ALLOC) != 0 && (s->flags & SEC_ALLOC) != 0
&& (elf_section_flags (s) & SHF_GNU_MBIND) != 0) && (elf_section_flags (s) & SHF_GNU_MBIND) != 0)
{ {
@ -2135,9 +2161,11 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
secname = ".mbind.text"; secname = ".mbind.text";
} }
/* Look through the script to see where to place this section. */ /* Look through the script to see where to place this section. The
if (constraint == 0 script includes entries added by previous lang_insert_orphan
&& link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour) calls, so this loop puts multiple compatible orphans of the same
name into a single output section. */
if (constraint == 0)
for (os = lang_output_section_find (secname); for (os = lang_output_section_find (secname);
os != NULL; os != NULL;
os = next_matching_output_section_statement (os, 0)) os = next_matching_output_section_statement (os, 0))
@ -2146,29 +2174,19 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
lang_insert_orphan to create a new output section. */ lang_insert_orphan to create a new output section. */
constraint = SPECIAL; constraint = SPECIAL;
/* SEC_EXCLUDE is cleared when doing a relocatable link. But /* Check to see if we already have an output section statement
we can't merge 2 input sections with the same name when only with this name, and its bfd section has compatible flags.
one of them has SHF_EXCLUDE. Don't merge 2 sections with
different sh_info. */
if (os->bfd_section != NULL
&& (elf_section_data (os->bfd_section)->this_hdr.sh_info
== elf_section_data (s)->this_hdr.sh_info)
&& (os->bfd_section->flags == 0
|| ((!bfd_link_relocatable (&link_info)
|| (iself && (((elf_section_flags (s)
^ elf_section_flags (os->bfd_section))
& SHF_EXCLUDE) == 0)))
&& ((s->flags ^ os->bfd_section->flags)
& (SEC_LOAD | SEC_ALLOC)) == 0
&& _bfd_elf_match_sections_by_type (link_info.output_bfd,
os->bfd_section,
s->owner, s))))
{
/* We already have an output section statement with this
name, and its bfd section has compatible flags.
If the section already exists but does not have any flags If the section already exists but does not have any flags
set, then it has been created by the linker, probably as a set, then it has been created by the linker, possibly as a
result of a --section-start command line switch. */ result of a --section-start command line switch. */
if (os->bfd_section != NULL
&& (os->bfd_section->flags == 0
|| (((s->flags ^ os->bfd_section->flags)
& (SEC_LOAD | SEC_ALLOC)) == 0
&& (!elfinput
|| !elfoutput
|| elf_orphan_compatible (s, os->bfd_section)))))
{
lang_add_section (&os->children, s, NULL, os); lang_add_section (&os->children, s, NULL, os);
return os; return os;
} }
@ -2244,8 +2262,8 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
else if ((flags & SEC_ALLOC) == 0) else if ((flags & SEC_ALLOC) == 0)
; ;
else if ((flags & SEC_LOAD) != 0 else if ((flags & SEC_LOAD) != 0
&& ((iself && sh_type == SHT_NOTE) && ((elfinput && sh_type == SHT_NOTE)
|| (!iself && CONST_STRNEQ (secname, ".note")))) || (!elfinput && CONST_STRNEQ (secname, ".note"))))
place = &hold[orphan_interp]; place = &hold[orphan_interp];
else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0) else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0)
place = &hold[orphan_bss]; place = &hold[orphan_bss];
@ -2255,8 +2273,8 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
place = &hold[orphan_tdata]; place = &hold[orphan_tdata];
else if ((flags & SEC_READONLY) == 0) else if ((flags & SEC_READONLY) == 0)
place = &hold[orphan_data]; place = &hold[orphan_data];
else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL)) else if (((elfinput && (sh_type == SHT_RELA || sh_type == SHT_REL))
|| (!iself && CONST_STRNEQ (secname, ".rel"))) || (!elfinput && CONST_STRNEQ (secname, ".rel")))
&& (flags & SEC_LOAD) != 0) && (flags & SEC_LOAD) != 0)
place = &hold[orphan_rel]; place = &hold[orphan_rel];
else if ((flags & SEC_CODE) == 0) else if ((flags & SEC_CODE) == 0)