Post by Alan ModraPost by H.J. LuI couldn't find a way to place a note section after the dummy
abs_output_section.
INSERT BEFORE manages to do it. Please revert commit 1887ae7304
if you really can't sort out the logic. That commit causes needless
reordering of sections, as shown by the spu-elf ovl testsuite
failures.
Here is the patch. OK for master?
H.J.
---
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/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 ++
4 files changed, 129 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/ldlang.c b/ld/ldlang.c
index 1a27787193..4cb482719e 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1876,6 +1876,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;
@@ -1931,7 +1932,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. */
@@ -1939,11 +1942,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 code 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)
@@ -1951,52 +1955,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;
@@ -2012,20 +1998,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);
@@ -2033,8 +2067,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 e21206b38a..5cfc7d2791 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 0000000000..a8e7d16f49
--- /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 0000000000..6d8fd7e537
--- /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.17.1