Re: Orphan output section with multiple input sections
The last patch missed handling the case where the ideal place to put an orphan was after a non-existent output section statement, as can happen when not using the builtin linker scripts. This patch uses the updated flags for that case too, and extends the support to mmo and pe. PR ld/19162 * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Pass updated flags to lang_output_section_find_by_flags. * emultempl/mmo.em (mmo_place_orphan): Merge flags for any other input sections that might match a new output section to decide placement. * emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Likewise. * emultempl/pep.em (gld_${EMULATION_NAME}_place_orphan): Likewise. * ldlang.c (lang_output_section_find_by_flags): Add sec_flags param. * ldlang.h (lang_output_section_find_by_flags): Update prototype.
This commit is contained in:
parent
d85063237a
commit
936384714f
13
ld/ChangeLog
13
ld/ChangeLog
@ -1,3 +1,16 @@
|
||||
2015-10-29 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/19162
|
||||
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Pass
|
||||
updated flags to lang_output_section_find_by_flags.
|
||||
* emultempl/mmo.em (mmo_place_orphan): Merge flags for any
|
||||
other input sections that might match a new output section to
|
||||
decide placement.
|
||||
* emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
|
||||
* emultempl/pep.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
|
||||
* ldlang.c (lang_output_section_find_by_flags): Add sec_flags param.
|
||||
* ldlang.h (lang_output_section_find_by_flags): Update prototype.
|
||||
|
||||
2015-10-29 Matthias Klose <doko@ubuntu.com>
|
||||
|
||||
* ld.texinfo (Options <-rpath>): Fix typo.
|
||||
|
@ -2003,8 +2003,9 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
|
||||
}
|
||||
after = place->os;
|
||||
if (after == NULL)
|
||||
after = lang_output_section_find_by_flags
|
||||
(s, &place->os, _bfd_elf_match_sections_by_type);
|
||||
after
|
||||
= lang_output_section_find_by_flags (s, flags, &place->os,
|
||||
_bfd_elf_match_sections_by_type);
|
||||
if (after == NULL)
|
||||
/* *ABS* is always the first output section statement. */
|
||||
after = &lang_output_section_statement.head->output_section_statement;
|
||||
|
@ -88,6 +88,8 @@ mmo_place_orphan (asection *s,
|
||||
lang_output_section_statement_type *after;
|
||||
lang_output_section_statement_type *os;
|
||||
size_t i;
|
||||
flagword flags;
|
||||
asection *nexts;
|
||||
|
||||
/* We have nothing to say for anything other than a final link or
|
||||
for sections that are excluded. */
|
||||
@ -109,9 +111,21 @@ mmo_place_orphan (asection *s,
|
||||
A section without contents can have SEC_LOAD == 0, but we still
|
||||
want it attached to a sane section so the symbols appear as
|
||||
expected. */
|
||||
if ((s->flags & (SEC_ALLOC | SEC_READONLY)) != SEC_READONLY)
|
||||
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))
|
||||
flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
|
||||
^ SEC_READONLY);
|
||||
if ((flags & (SEC_ALLOC | SEC_READONLY)) != SEC_READONLY)
|
||||
for (i = 0; i < sizeof (holds) / sizeof (holds[0]); i++)
|
||||
if ((s->flags & holds[i].nonzero_flags) != 0)
|
||||
if ((flags & holds[i].nonzero_flags) != 0)
|
||||
{
|
||||
place = &holds[i].orphansave;
|
||||
if (place->os == NULL)
|
||||
|
@ -2209,6 +2209,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
|
||||
struct orphan_save *place;
|
||||
lang_output_section_statement_type *after;
|
||||
etree_type *address;
|
||||
flagword flags;
|
||||
asection *nexts;
|
||||
|
||||
if (!orphan_init_done)
|
||||
{
|
||||
@ -2226,14 +2228,26 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
|
||||
/* Try to put the new output section in a reasonable place based
|
||||
on the section name and section flags. */
|
||||
|
||||
flags = s->flags;
|
||||
nexts = s;
|
||||
while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)))
|
||||
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))
|
||||
flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
|
||||
^ SEC_READONLY);
|
||||
place = NULL;
|
||||
if ((s->flags & SEC_ALLOC) == 0)
|
||||
if ((flags & SEC_ALLOC) == 0)
|
||||
;
|
||||
else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|
||||
else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|
||||
place = &hold[orphan_bss];
|
||||
else if ((s->flags & SEC_READONLY) == 0)
|
||||
else if ((flags & SEC_READONLY) == 0)
|
||||
place = &hold[orphan_data];
|
||||
else if ((s->flags & SEC_CODE) == 0)
|
||||
else if ((flags & SEC_CODE) == 0)
|
||||
{
|
||||
place = (!strncmp (secname, ".idata\$", 7) ? &hold[orphan_idata]
|
||||
: &hold[orphan_rodata]);
|
||||
@ -2248,7 +2262,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
|
||||
place->os = lang_output_section_find (place->name);
|
||||
after = place->os;
|
||||
if (after == NULL)
|
||||
after = lang_output_section_find_by_flags (s, &place->os, NULL);
|
||||
after = lang_output_section_find_by_flags (s, flags, &place->os,
|
||||
NULL);
|
||||
if (after == NULL)
|
||||
/* *ABS* is always the first output section statement. */
|
||||
after = (&lang_output_section_statement.head
|
||||
|
@ -1980,6 +1980,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
|
||||
struct orphan_save *place;
|
||||
lang_output_section_statement_type *after;
|
||||
etree_type *address;
|
||||
flagword flags;
|
||||
asection *nexts;
|
||||
|
||||
if (!orphan_init_done)
|
||||
{
|
||||
@ -1997,14 +1999,26 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
|
||||
/* Try to put the new output section in a reasonable place based
|
||||
on the section name and section flags. */
|
||||
|
||||
flags = s->flags;
|
||||
nexts = s;
|
||||
while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)))
|
||||
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))
|
||||
flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
|
||||
^ SEC_READONLY);
|
||||
place = NULL;
|
||||
if ((s->flags & SEC_ALLOC) == 0)
|
||||
if ((flags & SEC_ALLOC) == 0)
|
||||
;
|
||||
else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|
||||
else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|
||||
place = &hold[orphan_bss];
|
||||
else if ((s->flags & SEC_READONLY) == 0)
|
||||
else if ((flags & SEC_READONLY) == 0)
|
||||
place = &hold[orphan_data];
|
||||
else if ((s->flags & SEC_CODE) == 0)
|
||||
else if ((flags & SEC_CODE) == 0)
|
||||
{
|
||||
place = (!strncmp (secname, ".idata\$", 7) ? &hold[orphan_idata]
|
||||
: &hold[orphan_rodata]);
|
||||
@ -2019,7 +2033,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
|
||||
place->os = lang_output_section_find (place->name);
|
||||
after = place->os;
|
||||
if (after == NULL)
|
||||
after = lang_output_section_find_by_flags (s, &place->os, NULL);
|
||||
after = lang_output_section_find_by_flags (s, flags, &place->os,
|
||||
NULL);
|
||||
if (after == NULL)
|
||||
/* *ABS* is always the first output section statement. */
|
||||
after = (&lang_output_section_statement.head
|
||||
|
@ -1499,11 +1499,12 @@ next_matching_output_section_statement (lang_output_section_statement_type *os,
|
||||
|
||||
lang_output_section_statement_type *
|
||||
lang_output_section_find_by_flags (const asection *sec,
|
||||
flagword sec_flags,
|
||||
lang_output_section_statement_type **exact,
|
||||
lang_match_sec_type_func match_type)
|
||||
{
|
||||
lang_output_section_statement_type *first, *look, *found;
|
||||
flagword look_flags, sec_flags, differ;
|
||||
flagword look_flags, differ;
|
||||
|
||||
/* We know the first statement on this list is *ABS*. May as well
|
||||
skip it. */
|
||||
@ -1511,7 +1512,6 @@ lang_output_section_find_by_flags (const asection *sec,
|
||||
first = first->next;
|
||||
|
||||
/* First try for an exact match. */
|
||||
sec_flags = sec->flags;
|
||||
found = NULL;
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
@ -1695,7 +1695,7 @@ lang_output_section_find_by_flags (const asection *sec,
|
||||
if (found || !match_type)
|
||||
return found;
|
||||
|
||||
return lang_output_section_find_by_flags (sec, NULL, NULL);
|
||||
return lang_output_section_find_by_flags (sec, sec_flags, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Find the last output section before given output statement.
|
||||
|
@ -592,7 +592,7 @@ extern void lang_process
|
||||
extern void ldlang_add_file
|
||||
(lang_input_statement_type *);
|
||||
extern lang_output_section_statement_type *lang_output_section_find_by_flags
|
||||
(const asection *, lang_output_section_statement_type **,
|
||||
(const asection *, flagword, lang_output_section_statement_type **,
|
||||
lang_match_sec_type_func);
|
||||
extern lang_output_section_statement_type *lang_insert_orphan
|
||||
(asection *, const char *, int, lang_output_section_statement_type *,
|
||||
|
Loading…
Reference in New Issue
Block a user