From f3e660db14a0a95f3953496d8beb7c58ef34c6d5 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 8 Oct 2018 04:39:09 -0700 Subject: [PATCH] ELF: Properly group and place orphan note sections Properly group orphan note sections. When placing orphan note section as the first note section, place it after the section before all note sections. PR ld/23658 * ldlang.c (lang_insert_orphan): Properly group and place orphan note sections. Properly handle orphan note section before all note sections. * testsuite/ld-elf/pr23658-1.d: Renamed to ... * testsuite/ld-elf/pr23658-1a.d: This. Updated. * testsuite/ld-elf/pr23658-1b.d: New test. * testsuite/ld-elf/pr23658-1c.d: Likewise. --- ld/ChangeLog | 11 ++ ld/ldlang.c | 150 +++++++++++------- .../ld-elf/{pr23658-1.d => pr23658-1a.d} | 6 +- ld/testsuite/ld-elf/pr23658-1b.d | 16 ++ ld/testsuite/ld-elf/pr23658-1c.d | 13 ++ 5 files changed, 140 insertions(+), 56 deletions(-) rename ld/testsuite/ld-elf/{pr23658-1.d => pr23658-1a.d} (65%) create mode 100644 ld/testsuite/ld-elf/pr23658-1b.d create mode 100644 ld/testsuite/ld-elf/pr23658-1c.d diff --git a/ld/ChangeLog b/ld/ChangeLog index e0a6f7209e3..6c322c30cfe 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,14 @@ +2018-10-08 H.J. Lu + + PR ld/23658 + * ldlang.c (lang_insert_orphan): Properly group and place orphan + note sections. Properly handle orphan note section before all + note sections. + * testsuite/ld-elf/pr23658-1.d: Renamed to ... + * testsuite/ld-elf/pr23658-1a.d: This. Updated. + * testsuite/ld-elf/pr23658-1b.d: New test. + * testsuite/ld-elf/pr23658-1c.d: Likewise. + 2018-10-08 Alan Modra * ldexp.c (fold_name ): Set link_info.load_phdrs. diff --git a/ld/ldlang.c b/ld/ldlang.c index 0041f57116d..8d35e0da43b 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1879,6 +1879,7 @@ lang_insert_orphan (asection *s, { asection *snew, *as; bfd_boolean place_after = place->stmt == NULL; + bfd_boolean insert_after = TRUE; snew = os->bfd_section; @@ -1934,7 +1935,9 @@ lang_insert_orphan (asection *s, 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; + bfd_boolean after_sec_note = FALSE; + + static asection *first_orphan_note = NULL; /* Group and sort output note section by alignments in ascending order. */ @@ -1942,11 +1945,12 @@ lang_insert_orphan (asection *s, 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; + /* Search from the beginning for the last output note + section with equal or larger alignments. NB: Don't + place orphan note section after non-note sections. */ - for (sec = as; + first_orphan_note = NULL; + for (sec = link_info.output_bfd->sections; (sec != NULL && !bfd_is_abs_section (sec)); sec = sec->next) @@ -1954,52 +1958,34 @@ lang_insert_orphan (asection *s, && elf_section_type (sec) == SHT_NOTE && (sec->flags & SEC_LOAD) != 0) { - if (!first_note) - first_note = sec; + if (!first_orphan_note) + first_orphan_note = sec; if (sec->alignment_power >= s->alignment_power) after_sec = sec; } + else if (first_orphan_note) + { + /* Stop if there is non-note section after the first + orphan note section. */ + break; + } - if (after_sec) - after_sec_note = TRUE; - else + /* If this will be the first orphan note section, it can + be placed at the default location. */ + after_sec_note = first_orphan_note != NULL; + if (after_sec == NULL && after_sec_note) { - /* 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; - } + /* If all output note sections have smaller + alignments, place the section before all + output orphan note sections. */ + after_sec = first_orphan_note; + insert_after = FALSE; } } - else + else if (first_orphan_note) { - /* Don't place non-note sections in the middle of note - sections. */ + /* Don't place non-note sections in the middle of orphan + note sections. */ after_sec_note = TRUE; after_sec = as; for (sec = as->next; @@ -2015,20 +2001,68 @@ lang_insert_orphan (asection *s, { 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) + /* Search forward to insert OS after AFTER_SEC output + statement. */ + lang_output_section_statement_type *stmt, *next; + bfd_boolean found = FALSE; + for (stmt = after; stmt != NULL; stmt = next) + { + next = stmt->next; + if (insert_after) + { + if (stmt->bfd_section == after_sec) + { + place_after = TRUE; + found = TRUE; + after = stmt; + break; + } + } + else + { + /* If INSERT_AFTER is FALSE, place OS before + AFTER_SEC output statement. */ + if (next && next->bfd_section == after_sec) + { + place_after = TRUE; + found = TRUE; + after = stmt; + break; + } + } + } + + /* Search backward to insert OS after AFTER_SEC output + statement. */ + if (!found) + for (stmt = after; stmt != NULL; stmt = stmt->prev) { - place_after = TRUE; - after = stmt; - break; + if (insert_after) + { + if (stmt->bfd_section == after_sec) + { + place_after = TRUE; + after = stmt; + break; + } + } + else + { + /* If INSERT_AFTER is FALSE, place OS before + AFTER_SEC output statement. */ + if (stmt->next->bfd_section == after_sec) + { + place_after = TRUE; + after = stmt; + break; + } + } } } - if (after_sec == NULL || after_sec->next != snew) + if (after_sec == NULL + || (insert_after && after_sec->next != snew) + || (!insert_after && after_sec->prev != snew)) { /* Unlink the section. */ bfd_section_list_remove (link_info.output_bfd, snew); @@ -2036,8 +2070,14 @@ lang_insert_orphan (asection *s, /* 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); + { + if (insert_after) + bfd_section_list_insert_after (link_info.output_bfd, + after_sec, snew); + else + bfd_section_list_insert_before (link_info.output_bfd, + after_sec, snew); + } else bfd_section_list_prepend (link_info.output_bfd, snew); } diff --git a/ld/testsuite/ld-elf/pr23658-1.d b/ld/testsuite/ld-elf/pr23658-1a.d similarity index 65% rename from ld/testsuite/ld-elf/pr23658-1.d rename to ld/testsuite/ld-elf/pr23658-1a.d index e21206b38af..5cfc7d27918 100644 --- a/ld/testsuite/ld-elf/pr23658-1.d +++ b/ld/testsuite/ld-elf/pr23658-1a.d @@ -7,8 +7,12 @@ #readelf: -l --wide # Since generic linker targets don't place SHT_NOTE sections as orphan, # SHT_NOTE sections aren't grouped nor sorted. -#xfail: cr16-* crx-* d30v-* dlx-* fr30-* frv-* ft32-* iq2000-* +#xfail: d30v-* dlx-* fr30-* frv-*-elf ft32-* iq2000-* #xfail: m68hc12-* mn10200-* moxie-* mt-* msp430-* pj-* xgate-* +# The following targets don't support --build-id. +#xfail: cr16-* crx-* visium-* xc16x-* +# The following targets place .note.gnu.build-id in unusual places. +#xfail: pru-* #... +[0-9]+ +\.note\.4 \.note\.1 + diff --git a/ld/testsuite/ld-elf/pr23658-1b.d b/ld/testsuite/ld-elf/pr23658-1b.d new file mode 100644 index 00000000000..a8e7d16f492 --- /dev/null +++ b/ld/testsuite/ld-elf/pr23658-1b.d @@ -0,0 +1,16 @@ +#source: pr23658-1a.s +#source: pr23658-1b.s +#source: pr23658-1c.s +#source: pr23658-1d.s +#source: start.s +#ld: +#readelf: -l --wide +# Since generic linker targets don't place SHT_NOTE sections as orphan, +# SHT_NOTE sections aren't grouped nor sorted. +#xfail: d30v-* dlx-* fr30-* frv-*-elf ft32-* iq2000-* +#xfail: mn10200-* moxie-* mt-* msp430-* pj-* xgate-* + +#... + +[0-9]+ +\.note\.4 \.note\.1( .note.gnu.property|) + + +[0-9]+ +\.note\.2 .note\.3( .note.gnu.property|) + +#pass diff --git a/ld/testsuite/ld-elf/pr23658-1c.d b/ld/testsuite/ld-elf/pr23658-1c.d new file mode 100644 index 00000000000..6d8fd7e5376 --- /dev/null +++ b/ld/testsuite/ld-elf/pr23658-1c.d @@ -0,0 +1,13 @@ +#source: pr23658-1a.s +#source: pr23658-1b.s +#source: pr23658-1c.s +#source: pr23658-1d.s +#source: start.s +#ld: --build-id -shared +#readelf: -l --wide +#target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi + +#... + +[0-9]+ +\.note\.4 \.note\.1 + + +[0-9]+ +\.note.gnu.build-id \.note\.2 .note\.3 + +#pass -- 2.30.2