From 1887ae7304dced5b081ee200a9e27fbb8f180143 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 3 Oct 2018 13:25:16 -0700 Subject: [PATCH] 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. --- ld/ChangeLog | 6 +++ ld/ldlang.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 81d2ce4e66..f17a8f27d8 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,9 @@ +2018-10-03 H.J. Lu + + PR ld/23658 + * ldlang.c (lang_insert_orphan): Group and sort output note + sections by section alignments. + 2018-09-25 Eric Botcazou * testsuite/ld-elf/pr14156b.d: Adjust for extra symbols. diff --git a/ld/ldlang.c b/ld/ldlang.c index 1ac5eb1ee2..1a27787193 100644 --- a/ld/ldlang.c +++ b/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); -- 2.34.1