[committed] MIPS/BFD: Avoid section ordering breaking DYNAMIC segment for IRIX 5

Maciej W. Rozycki macro@orcam.me.uk
Wed Feb 18 08:03:42 GMT 2026


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.
---
 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(-)

binutils-bfd-mips-irix-dynamic-first.diff
Index: binutils-gdb/bfd/elfxx-mips.c
===================================================================
--- binutils-gdb.orig/bfd/elfxx-mips.c
+++ binutils-gdb/bfd/elfxx-mips.c
@@ -12889,7 +12889,9 @@ _bfd_mips_elf_modify_segment_map (bfd *a
 	}
       /* 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 *a
       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 *a
 		  bfd_size_type sz;
 
 		  if (low > s->vma)
-		    low = s->vma;
+		    continue;
 		  sz = s->size;
 		  if (high < s->vma + sz)
 		    high = s->vma + sz;
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-3.d
===================================================================
--- /dev/null
+++ binutils-gdb/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
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-3.ld
===================================================================
--- /dev/null
+++ binutils-gdb/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/ : { *(*) }
+}
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-3i1.d
===================================================================
--- /dev/null
+++ binutils-gdb/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 
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-3i2.d
===================================================================
--- /dev/null
+++ binutils-gdb/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
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-4.d
===================================================================
--- /dev/null
+++ binutils-gdb/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
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-4.ld
===================================================================
--- /dev/null
+++ binutils-gdb/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/ : { *(*) }
+}
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-4i1.d
===================================================================
--- /dev/null
+++ binutils-gdb/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 
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-4i2.d
===================================================================
--- /dev/null
+++ binutils-gdb/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
Index: binutils-gdb/ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
--- binutils-gdb.orig/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ binutils-gdb/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 mailing list