ELF: Group and sort output note sections by section alignments
To support putting all adjacent SHT_NOTE sections with the same section alignment into a single PT_NOTE segment, lang_insert_orphan must group and sort output note sections by section alignments in both output section list as well as output section statement list. PR ld/23658 * ldlang.c (lang_insert_orphan): Group and sort output note sections by section alignments.
This commit is contained in:
parent
23e463ed7c
commit
1887ae7304
@ -1,3 +1,9 @@
|
||||
2018-10-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/23658
|
||||
* ldlang.c (lang_insert_orphan): Group and sort output note
|
||||
sections by section alignments.
|
||||
|
||||
2018-09-25 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* testsuite/ld-elf/pr14156b.d: Adjust for extra symbols.
|
||||
|
140
ld/ldlang.c
140
ld/ldlang.c
@ -1875,6 +1875,7 @@ lang_insert_orphan (asection *s,
|
||||
if (after != NULL && os->bfd_section != NULL)
|
||||
{
|
||||
asection *snew, *as;
|
||||
bfd_boolean place_after = place->stmt == NULL;
|
||||
|
||||
snew = os->bfd_section;
|
||||
|
||||
@ -1912,6 +1913,142 @@ lang_insert_orphan (asection *s,
|
||||
/* Now tack it back on in the right place. */
|
||||
bfd_section_list_append (link_info.output_bfd, snew);
|
||||
}
|
||||
else if ((bfd_get_flavour (link_info.output_bfd)
|
||||
== bfd_target_elf_flavour)
|
||||
&& (bfd_get_flavour (s->owner)
|
||||
== bfd_target_elf_flavour)
|
||||
&& ((elf_section_type (s) == SHT_NOTE
|
||||
&& (s->flags & SEC_LOAD) != 0)
|
||||
|| (elf_section_type (as) == SHT_NOTE
|
||||
&& (as->flags & SEC_LOAD) != 0)))
|
||||
{
|
||||
/* Make sure that output note sections are grouped and sorted
|
||||
by alignments when inserting a note section or insert a
|
||||
section after a note section, */
|
||||
asection *sec;
|
||||
/* A specific section after which the output note section
|
||||
should be placed. */
|
||||
asection *after_sec;
|
||||
/* True if we need to insert the orphan section after a
|
||||
specific section to maintain output note section order. */
|
||||
bfd_boolean after_sec_note;
|
||||
|
||||
/* Group and sort output note section by alignments in
|
||||
ascending order. */
|
||||
after_sec = NULL;
|
||||
if (elf_section_type (s) == SHT_NOTE
|
||||
&& (s->flags & SEC_LOAD) != 0)
|
||||
{
|
||||
/* Search forward for the last output note section
|
||||
with equal or larger alignments. */
|
||||
asection *first_note = NULL;
|
||||
|
||||
for (sec = as;
|
||||
(sec != NULL
|
||||
&& !bfd_is_abs_section (sec));
|
||||
sec = sec->next)
|
||||
if (sec != snew
|
||||
&& elf_section_type (sec) == SHT_NOTE
|
||||
&& (sec->flags & SEC_LOAD) != 0)
|
||||
{
|
||||
if (!first_note)
|
||||
first_note = sec;
|
||||
if (sec->alignment_power >= s->alignment_power)
|
||||
after_sec = sec;
|
||||
}
|
||||
|
||||
if (after_sec)
|
||||
after_sec_note = TRUE;
|
||||
else
|
||||
{
|
||||
/* Search backward for the first output note section
|
||||
as well as the last output note section with equal
|
||||
or larger alignments. */
|
||||
after_sec = NULL;
|
||||
for (sec = as;
|
||||
(sec != NULL
|
||||
&& !bfd_is_abs_section (sec));
|
||||
sec = sec->prev)
|
||||
if (sec != snew
|
||||
&& elf_section_type (sec) == SHT_NOTE
|
||||
&& (sec->flags & SEC_LOAD) != 0)
|
||||
{
|
||||
first_note = sec;
|
||||
if (!after_sec
|
||||
&& sec->alignment_power >= s->alignment_power)
|
||||
after_sec = sec;
|
||||
}
|
||||
|
||||
/* If this will be the first note section, it can be
|
||||
placed at the default location. */
|
||||
after_sec_note = first_note != NULL;
|
||||
if (after_sec == NULL && after_sec_note)
|
||||
{
|
||||
/* If all output note sections have smaller
|
||||
alignments, place the section before all
|
||||
output note sections. AFTER_SEC will be
|
||||
NULL if FIRST_NOTE is the first output
|
||||
section. */
|
||||
after_sec = first_note->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't place non-note sections in the middle of note
|
||||
sections. */
|
||||
after_sec_note = TRUE;
|
||||
after_sec = as;
|
||||
for (sec = as->next;
|
||||
(sec != NULL
|
||||
&& !bfd_is_abs_section (sec));
|
||||
sec = sec->next)
|
||||
if (elf_section_type (sec) == SHT_NOTE
|
||||
&& (sec->flags & SEC_LOAD) != 0)
|
||||
after_sec = sec;
|
||||
}
|
||||
|
||||
if (after_sec_note)
|
||||
{
|
||||
if (after_sec)
|
||||
{
|
||||
/* Insert OS after AFTER_SEC output statement. */
|
||||
lang_output_section_statement_type *stmt;
|
||||
for (stmt = after;
|
||||
stmt != NULL;
|
||||
stmt = stmt->next)
|
||||
if (stmt->bfd_section == after_sec)
|
||||
{
|
||||
place_after = TRUE;
|
||||
after = stmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (after_sec == NULL || after_sec->next != snew)
|
||||
{
|
||||
/* Unlink the section. */
|
||||
bfd_section_list_remove (link_info.output_bfd, snew);
|
||||
|
||||
/* Place SNEW after AFTER_SEC. If AFTER_SEC is NULL,
|
||||
prepend SNEW. */
|
||||
if (after_sec)
|
||||
bfd_section_list_insert_after (link_info.output_bfd,
|
||||
after_sec, snew);
|
||||
else
|
||||
bfd_section_list_prepend (link_info.output_bfd, snew);
|
||||
}
|
||||
}
|
||||
else if (as != snew && as->prev != snew)
|
||||
{
|
||||
/* Unlink the section. */
|
||||
bfd_section_list_remove (link_info.output_bfd, snew);
|
||||
|
||||
/* Now tack it back on in the right place. */
|
||||
bfd_section_list_insert_before (link_info.output_bfd,
|
||||
as, snew);
|
||||
}
|
||||
}
|
||||
else if (as != snew && as->prev != snew)
|
||||
{
|
||||
/* Unlink the section. */
|
||||
@ -1938,7 +2075,8 @@ lang_insert_orphan (asection *s,
|
||||
{
|
||||
lang_output_section_statement_type *newly_added_os;
|
||||
|
||||
if (place->stmt == NULL)
|
||||
/* Place OS after AFTER if AFTER_NOTE is TRUE. */
|
||||
if (place_after)
|
||||
{
|
||||
lang_statement_union_type **where = insert_os_after (after);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user