Orphan output section with multiple input sections

If given input sections with differing flags, we'd like to place the
section according to the final output section flags.

bfd/
	PR ld/19162
	* elflink.c (_bfd_elf_gc_mark_reloc): Move code iterating over
	linker input bfds..
	* section.c (bfd_get_next_section_by_name): ..to here.  Add ibfd param.
	(bfd_get_linker_section): Adjust bfd_get_next_section_by_name call.
	* tekhex.c (first_phase): Likewise.
	* elflink.c (bfd_elf_gc_sections): Likewise.
	* bfd-in2.h: Regenerate.
ld/
	PR ld/19162
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Check flags
	before calling _bfd_elf_match_sections_by_type.  Merge flags for
	any other input sections that might match a new output section to
	decide placement.
This commit is contained in:
Alan Modra 2015-10-28 17:18:13 +10:30
parent 26656b1dc6
commit 199af15039
7 changed files with 71 additions and 40 deletions

View File

@ -1,3 +1,14 @@
2015-10-28 Alan Modra <amodra@gmail.com>
PR ld/19162
* elflink.c (_bfd_elf_gc_mark_reloc): Move code iterating over
linker input bfds..
* section.c (bfd_get_next_section_by_name): ..to here. Add ibfd param.
(bfd_get_linker_section): Adjust bfd_get_next_section_by_name call.
* tekhex.c (first_phase): Likewise.
* elflink.c (bfd_elf_gc_sections): Likewise.
* bfd-in2.h: Regenerate.
2015-10-27 Laurent Alfonsi <laurent.alfonsi@st.com>
Christophe Monat <christophe.monat@st.com>

View File

@ -1810,7 +1810,7 @@ void bfd_section_list_clear (bfd *);
asection *bfd_get_section_by_name (bfd *abfd, const char *name);
asection *bfd_get_next_section_by_name (asection *sec);
asection *bfd_get_next_section_by_name (bfd *ibfd, asection *sec);
asection *bfd_get_linker_section (bfd *abfd, const char *name);

View File

@ -12179,8 +12179,6 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop);
while (rsec != NULL)
{
asection *s;
if (!rsec->gc_mark)
{
if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour
@ -12191,22 +12189,7 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
}
if (!start_stop)
break;
s = bfd_get_next_section_by_name (rsec);
if (s == NULL)
{
bfd *i = rsec->owner;
if (i != NULL)
{
while ((i = i->link.next) != NULL)
{
s = bfd_get_section_by_name (i, rsec->name);
if (s != NULL)
break;
}
}
}
rsec = s;
rsec = bfd_get_next_section_by_name (rsec->owner, rsec);
}
return TRUE;
}
@ -12757,7 +12740,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
&& (sec->flags & SEC_LINKER_CREATED) == 0)
elf_eh_frame_section (sub) = sec;
fini_reloc_cookie_for_section (&cookie, sec);
sec = bfd_get_next_section_by_name (sec);
sec = bfd_get_next_section_by_name (NULL, sec);
}
}

View File

@ -903,16 +903,18 @@ FUNCTION
bfd_get_next_section_by_name
SYNOPSIS
asection *bfd_get_next_section_by_name (asection *sec);
asection *bfd_get_next_section_by_name (bfd *ibfd, asection *sec);
DESCRIPTION
Given @var{sec} is a section returned by @code{bfd_get_section_by_name},
return the next most recently created section attached to the same
BFD with the same name. Return NULL if no such section exists.
BFD with the same name, or if no such section exists in the same BFD and
IBFD is non-NULL, the next section with the same name in any input
BFD following IBFD. Return NULL on finding no section.
*/
asection *
bfd_get_next_section_by_name (asection *sec)
bfd_get_next_section_by_name (bfd *ibfd, asection *sec)
{
struct section_hash_entry *sh;
const char *name;
@ -930,6 +932,16 @@ bfd_get_next_section_by_name (asection *sec)
&& strcmp (sh->root.string, name) == 0)
return &sh->section;
if (ibfd != NULL)
{
while ((ibfd = ibfd->link.next) != NULL)
{
asection *s = bfd_get_section_by_name (ibfd, name);
if (s != NULL)
return s;
}
}
return NULL;
}
@ -951,7 +963,7 @@ bfd_get_linker_section (bfd *abfd, const char *name)
asection *sec = bfd_get_section_by_name (abfd, name);
while (sec != NULL && (sec->flags & SEC_LINKER_CREATED) == 0)
sec = bfd_get_next_section_by_name (sec);
sec = bfd_get_next_section_by_name (NULL, sec);
return sec;
}

View File

@ -459,7 +459,8 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
else
{
if (alt_section == NULL)
alt_section = bfd_get_next_section_by_name (section);
alt_section
= bfd_get_next_section_by_name (NULL, section);
if (alt_section == NULL)
alt_section = bfd_make_section_anyway_with_flags
(abfd, section->name,
@ -476,7 +477,8 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
else
{
if (alt_section == NULL)
alt_section = bfd_get_next_section_by_name (section);
alt_section
= bfd_get_next_section_by_name (NULL, section);
if (alt_section == NULL)
alt_section = bfd_make_section_anyway_with_flags
(abfd, section->name,

View File

@ -1,3 +1,11 @@
2015-10-28 Alan Modra <amodra@gmail.com>
PR ld/19162
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Check flags
before calling _bfd_elf_match_sections_by_type. Merge flags for
any other input sections that might match a new output section to
decide placement.
2015-10-27 Laurent Alfonsi <laurent.alfonsi@st.com>
Christophe Monat <christophe.monat@st.com>

View File

@ -1852,6 +1852,8 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
int isdyn = 0;
int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
flagword flags;
asection *nexts;
if (!bfd_link_relocatable (&link_info)
&& link_info.combreloc
@ -1890,11 +1892,11 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
if (os->bfd_section != NULL
&& (os->bfd_section->flags == 0
|| (_bfd_elf_match_sections_by_type (link_info.output_bfd,
os->bfd_section,
s->owner, s)
&& ((s->flags ^ os->bfd_section->flags)
& (SEC_LOAD | SEC_ALLOC)) == 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.
@ -1950,28 +1952,41 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
stored right after the program headers where the OS can read it
in the first page. */
flags = s->flags;
nexts = s;
while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)) != NULL)
if (nexts->output_section == NULL
&& (nexts->flags & SEC_EXCLUDE) == 0
&& ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0
&& (nexts->owner->flags & DYNAMIC) == 0
&& nexts->owner->usrdata != NULL
&& !(((lang_input_statement_type *) nexts->owner->usrdata)
->flags.just_syms)
&& _bfd_elf_match_sections_by_type (nexts->owner, nexts, s->owner, s))
flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
^ SEC_READONLY);
place = NULL;
if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
if ((flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
place = &hold[orphan_nonalloc];
else if ((s->flags & SEC_ALLOC) == 0)
else if ((flags & SEC_ALLOC) == 0)
;
else if ((s->flags & SEC_LOAD) != 0
else if ((flags & SEC_LOAD) != 0
&& ((iself && sh_type == SHT_NOTE)
|| (!iself && CONST_STRNEQ (secname, ".note"))))
place = &hold[orphan_interp];
else if ((s->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];
else if ((s->flags & SEC_SMALL_DATA) != 0)
else if ((flags & SEC_SMALL_DATA) != 0)
place = &hold[orphan_sdata];
else if ((s->flags & SEC_THREAD_LOCAL) != 0)
else if ((flags & SEC_THREAD_LOCAL) != 0)
place = &hold[orphan_tdata];
else if ((s->flags & SEC_READONLY) == 0)
else if ((flags & SEC_READONLY) == 0)
place = &hold[orphan_data];
else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
|| (!iself && CONST_STRNEQ (secname, ".rel")))
&& (s->flags & SEC_LOAD) != 0)
&& (flags & SEC_LOAD) != 0)
place = &hold[orphan_rel];
else if ((s->flags & SEC_CODE) == 0)
else if ((flags & SEC_CODE) == 0)
place = &hold[orphan_rodata];
else
place = &hold[orphan_text];