diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2018-10-03 13:25:16 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2018-10-03 13:25:30 -0700 |
commit | 1887ae7304dced5b081ee200a9e27fbb8f180143 (patch) | |
tree | a17cacf4b0450b002ef0c325e97b2efbc973b513 /ld/ldlang.c | |
parent | 23e463ed7c0d289e2291aaefd576bf02efd98df8 (diff) | |
download | gdb-1887ae7304dced5b081ee200a9e27fbb8f180143.zip gdb-1887ae7304dced5b081ee200a9e27fbb8f180143.tar.gz gdb-1887ae7304dced5b081ee200a9e27fbb8f180143.tar.bz2 |
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.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 140 |
1 files changed, 139 insertions, 1 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index 1ac5eb1..1a27787 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); |