[binutils-gdb] MIPS/BFD: Avoid section ordering breaking DYNAMIC segment for IRIX 5
Maciej W. Rozycki
macro@sourceware.org
Wed Feb 18 08:00:46 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a5b91b33252959d679a777dd6a455f11b91f90a1
commit a5b91b33252959d679a777dd6a455f11b91f90a1
Author: Maciej W. Rozycki <macro@orcam.me.uk>
Date: Wed Feb 18 07:58:31 2026 +0000
MIPS/BFD: Avoid section ordering breaking DYNAMIC segment for IRIX 5
With MIPS targets using the IRIX 5 linker emulation the DYNAMIC segment,
unusually, gets all of: `.dynamic', `.hash', `.dynsym', and `.dynstr'
sections mapped to, as well as any other sections placed in between.
No attention is paid as to which of these sections comes first though,
which would make such a DYNAMIC segment unusable at load time unless it
starts with the `.dynamic' section, if not for LD terminating the link
with:
The first section in the PT_DYNAMIC segment is not the .dynamic section
error message.
Our standard linker scripts ensure the correct section ordering, however
a user-supplied script may not, and it seems suboptimal to prevent users
from reordering sections to their liking.
Modify MIPS IRIX 5 linker emulation handling then so that only `.hash',
`.dynsym', and `.dynstr' sections that come after `.dynamic' in output,
and any other sections placed in between, get mapped to the DYNAMIC
segment.
This preserves exact IRIX 5 semantics for all the conforming scripts,
while letting people use a different order rather than getting a link
error. The error result previously issued means there is no backwards
compatibility to consider as no output used to be produced.
This removes a number of test failures:
-FAIL: PROVIDE_HIDDEN test (auxiliary shared object)
-FAIL: PROVIDE_HIDDEN test 4
-FAIL: PROVIDE_HIDDEN test 6
-FAIL: PROVIDE_HIDDEN test 10
-FAIL: PROVIDE_HIDDEN test 12
-FAIL: readelf version information
-FAIL: PR ld/20828 forcibly exported symbol version without section GC
-FAIL: PR ld/21233 dynamic symbols with section GC (auxiliary shared library)
across MIPS targets using the IRIX 5 linker emulation, such as
`mips-sgi-irix5', `mips-elf', `mips-rtems', etc.
Diff:
---
bfd/elfxx-mips.c | 15 +++++++++------
ld/testsuite/ld-mips-elf/dynamic-sections-3.d | 6 ++++++
ld/testsuite/ld-mips-elf/dynamic-sections-3.ld | 12 ++++++++++++
ld/testsuite/ld-mips-elf/dynamic-sections-3i1.d | 21 +++++++++++++++++++++
ld/testsuite/ld-mips-elf/dynamic-sections-3i2.d | 6 ++++++
ld/testsuite/ld-mips-elf/dynamic-sections-4.d | 6 ++++++
ld/testsuite/ld-mips-elf/dynamic-sections-4.ld | 12 ++++++++++++
ld/testsuite/ld-mips-elf/dynamic-sections-4i1.d | 21 +++++++++++++++++++++
ld/testsuite/ld-mips-elf/dynamic-sections-4i2.d | 6 ++++++
ld/testsuite/ld-mips-elf/mips-elf.exp | 2 ++
10 files changed, 101 insertions(+), 6 deletions(-)
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 6d38e492dfc..6feaa706029 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -12889,7 +12889,9 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
}
/* On IRIX5, the PT_DYNAMIC segment includes the .dynamic,
.dynstr, .dynsym, and .hash sections, and everything in
- between. */
+ between. We avoid any sections though ahead of .dynamic,
+ which needs to be first to be usable. This can only ever
+ happen with a non-standard linker script. */
for (pm = &elf_seg_map (abfd); *pm != NULL;
pm = &(*pm)->next)
if ((*pm)->p_type == PT_DYNAMIC)
@@ -12906,18 +12908,19 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
if (SGI_COMPAT (abfd)
&& m != NULL
&& m->count == 1
- && strcmp (m->sections[0]->name, ".dynamic") == 0)
+ && strcmp (m->sections[0]->name, ".dynamic") == 0
+ && (m->sections[0]->flags & SEC_LOAD) != 0)
{
static const char *sec_names[] =
{
- ".dynamic", ".dynstr", ".dynsym", ".hash"
+ ".dynstr", ".dynsym", ".hash"
};
bfd_vma low, high;
unsigned int i, c;
struct elf_segment_map *n;
- low = ~(bfd_vma) 0;
- high = 0;
+ low = m->sections[0]->vma;
+ high = low + m->sections[0]->size;
for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
{
s = bfd_get_section_by_name (abfd, sec_names[i]);
@@ -12926,7 +12929,7 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
bfd_size_type sz;
if (low > s->vma)
- low = s->vma;
+ continue;
sz = s->size;
if (high < s->vma + sz)
high = s->vma + sz;
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-3.d b/ld/testsuite/ld-mips-elf/dynamic-sections-3.d
new file mode 100644
index 00000000000..2ee3baf1a75
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-3.d
@@ -0,0 +1,6 @@
+#name: Dynamic segment sections 3
+#ld: -shared -T dynamic-sections-3.ld
+#readelf: -Wl
+#target: [check_shared_lib_support]
+#source: dynamic-sections.s
+#dump: dynamic-sections-1.d
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-3.ld b/ld/testsuite/ld-mips-elf/dynamic-sections-3.ld
new file mode 100644
index 00000000000..b3dbff0952a
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-3.ld
@@ -0,0 +1,12 @@
+SECTIONS
+{
+ .MIPS.abiflags : { *(.MIPS.abiflags) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .dynamic : { *(.dynamic) }
+ .hash : { *(.hash) }
+ .rel.dyn : { *(.rel.dyn) }
+ .data : { *(.data) }
+ .got : { *(.got) }
+ /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-3i1.d b/ld/testsuite/ld-mips-elf/dynamic-sections-3i1.d
new file mode 100644
index 00000000000..c00fbf862fc
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-3i1.d
@@ -0,0 +1,21 @@
+#name: Dynamic segment sections 3
+#ld: -shared -T dynamic-sections-3.ld
+#readelf: -Wl
+#target: [check_shared_lib_support]
+#source: dynamic-sections.s
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x0
+There are 3 program headers, starting at offset .*
+
+Program Headers:
+ Type Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
+ ABIFLAGS .*
+ LOAD .*
+ DYNAMIC [^ ]+ +[^ ]+ +[^ ]+ +(0x[0-9a-f]+) +\1 +.*
+
+ Section to Segment mapping:
+ Segment Sections\.\.\.
+ 00 .*
+ 01 .*
+ 02 \.dynamic \.hash
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-3i2.d b/ld/testsuite/ld-mips-elf/dynamic-sections-3i2.d
new file mode 100644
index 00000000000..e16d35c2d51
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-3i2.d
@@ -0,0 +1,6 @@
+#name: Dynamic segment sections 3
+#ld: -shared -T dynamic-sections-3.ld
+#readelf: -Wl
+#target: [check_shared_lib_support]
+#source: dynamic-sections.s
+#dump: dynamic-sections-1i2.d
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-4.d b/ld/testsuite/ld-mips-elf/dynamic-sections-4.d
new file mode 100644
index 00000000000..2479105e816
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-4.d
@@ -0,0 +1,6 @@
+#name: Dynamic segment sections 4
+#ld: -shared -T dynamic-sections-4.ld
+#readelf: -Wl
+#target: [check_shared_lib_support]
+#source: dynamic-sections.s
+#dump: dynamic-sections-1.d
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-4.ld b/ld/testsuite/ld-mips-elf/dynamic-sections-4.ld
new file mode 100644
index 00000000000..247cdd22c62
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-4.ld
@@ -0,0 +1,12 @@
+SECTIONS
+{
+ .MIPS.abiflags : { *(.MIPS.abiflags) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .dynamic : { *(.dynamic) }
+ .data : { *(.data) }
+ .hash : { *(.hash) }
+ .rel.dyn : { *(.rel.dyn) }
+ .got : { *(.got) }
+ /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-4i1.d b/ld/testsuite/ld-mips-elf/dynamic-sections-4i1.d
new file mode 100644
index 00000000000..6d0fcce480e
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-4i1.d
@@ -0,0 +1,21 @@
+#name: Dynamic segment sections 4
+#ld: -shared -T dynamic-sections-4.ld
+#readelf: -Wl
+#target: [check_shared_lib_support]
+#source: dynamic-sections.s
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x0
+There are 3 program headers, starting at offset .*
+
+Program Headers:
+ Type Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
+ ABIFLAGS .*
+ LOAD .*
+ DYNAMIC [^ ]+ +[^ ]+ +[^ ]+ +(0x[0-9a-f]+) +\1 +.*
+
+ Section to Segment mapping:
+ Segment Sections\.\.\.
+ 00 .*
+ 01 .*
+ 02 \.dynamic \.data \.hash
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-4i2.d b/ld/testsuite/ld-mips-elf/dynamic-sections-4i2.d
new file mode 100644
index 00000000000..dd9a7239594
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections-4i2.d
@@ -0,0 +1,6 @@
+#name: Dynamic segment sections 4
+#ld: -shared -T dynamic-sections-4.ld
+#readelf: -Wl
+#target: [check_shared_lib_support]
+#source: dynamic-sections.s
+#dump: dynamic-sections-1i2.d
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index 7f51eb62538..f1bbd81827f 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -1808,3 +1808,5 @@ foreach { abi } $abis {
run_dump_test "dynamic-sections-1${irixn}"
run_dump_test "dynamic-sections-2${irixn}"
+run_dump_test "dynamic-sections-3${irixn}"
+run_dump_test "dynamic-sections-4${irixn}"
More information about the Binutils-cvs
mailing list