[PATCH] ELF/BFD: Factor in inter-section padding for DYNAMIC segment

Maciej W. Rozycki macro@orcam.me.uk
Fri Feb 13 16:24:25 GMT 2026


The vast majority of ELF targets only maps the `.dynamic' section in the 
DYNAMIC segment, however MIPS targets using the IRIX 5 linker emulation 
place all of: `.dynamic', `.hash', `.dynsym', and `.dynstr' sections 
there, as well as any other sections placed in between.  While the four 
named sections have a fixed 4-byte alignment, other sections may require 
a larger alignment causing extra padding to be produced as the sections 
are laid out in linker output and mapped to segments.  It is taken into 
account in calculating the size for segments of the LOAD and TLS types, 
but not for the DYNAMIC one.

Consequently the segment may get truncated, as illustrated with the
`dynamic-sections-2' test case included, which causes the following 
mapping to be produced with the `mips-sgi-irix5' target, as well as 
numerous bare metal ones such as `mips-elf' or `mips-rtems':

There are 12 section headers, starting at offset 0x139c:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .MIPS.abiflags    MIPS_ABIFLAGS   00000000 001000 000018 18   A  0   0  8
  [ 2] .dynamic          DYNAMIC         00000018 001018 0000c8 00   A  6   0  4
  [ 3] .hash             HASH            000000e0 0010e0 00002c 00   A  5   0  4
  [ 4] .data             PROGBITS        00000110 001110 000010 00  WA  0   0 16
  [ 5] .dynsym           DYNSYM          00000120 001120 000060 10   A  6   2  4
  [ 6] .dynstr           STRTAB          00000180 001180 000049 00   A  0   0  4
  [ 7] .rel.dyn          REL             000001cc 0011cc 000010 08   A  5   0  4
  [ 8] .got              PROGBITS        000001e0 0011e0 00000c 04 WAp  0   0 16
  [ 9] .symtab           SYMTAB          00000000 0011ec 0000f0 10     10   9  4
  [10] .strtab           STRTAB          00000000 0012dc 000063 00      0   0  1
  [11] .shstrtab         STRTAB          00000000 00133f 00005d 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), p (processor specific)

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  ABIFLAGS       0x001000 0x00000000 0x00000000 0x00018 0x00018 R   0x8
  LOAD           0x001000 0x00000000 0x00000000 0x001ec 0x001ec RW  0x1000
  DYNAMIC        0x001018 0x00000018 0x00000018 0x001b1 0x001ad RW  0x10

 Section to Segment mapping:
  Segment Sections...
   00     .MIPS.abiflags 
   01     .MIPS.abiflags .dynamic .hash .data .dynsym .dynstr .rel.dyn .got 
   02     .dynamic .hash .data .dynsym 

-- notice `.dynstr' missing from the section to segment mapping shown 
above, owing to the trailing part of the section extending beyond the 
end of the segment, and the memory size of the DYNAMIC segment smaller 
than its file size.

Apply the same memory size adjustment for padding to segments of the 
DYNAMIC type as already made for segments of the LOAD and TLS types, 
observing that semantically DYNAMIC segments are analogous except for 
only having the lone `.dynamic' section mapped with the vast majority 
of ELF targets.
---
Hi,

 Regression-tested across 263 targets.  OK to apply?

  Maciej
---
 bfd/elf.c                                       |    1 +
 ld/testsuite/ld-mips-elf/dynamic-sections-1.d   |   23 +++++++++++++++++++++++
 ld/testsuite/ld-mips-elf/dynamic-sections-1.ld  |   12 ++++++++++++
 ld/testsuite/ld-mips-elf/dynamic-sections-1i1.d |   21 +++++++++++++++++++++
 ld/testsuite/ld-mips-elf/dynamic-sections-1i2.d |   21 +++++++++++++++++++++
 ld/testsuite/ld-mips-elf/dynamic-sections-2.d   |    6 ++++++
 ld/testsuite/ld-mips-elf/dynamic-sections-2.ld  |   12 ++++++++++++
 ld/testsuite/ld-mips-elf/dynamic-sections-2i1.d |   21 +++++++++++++++++++++
 ld/testsuite/ld-mips-elf/dynamic-sections-2i2.d |    6 ++++++
 ld/testsuite/ld-mips-elf/dynamic-sections.s     |    5 +++++
 ld/testsuite/ld-mips-elf/mips-elf.exp           |    6 +++++-
 11 files changed, 133 insertions(+), 1 deletion(-)

binutils-bfd-dynamic-align.diff
Index: binutils-gdb/bfd/elf.c
===================================================================
--- binutils-gdb.orig/bfd/elf.c
+++ binutils-gdb/bfd/elf.c
@@ -6304,6 +6304,7 @@ assign_file_positions_for_load_sections
 	  align = (bfd_size_type) 1 << bfd_section_alignment (sec);
 
 	  if ((p->p_type == PT_LOAD
+	       || p->p_type == PT_DYNAMIC
 	       || p->p_type == PT_TLS)
 	      && (this_hdr->sh_type != SHT_NOBITS
 		  || ((this_hdr->sh_flags & SHF_ALLOC) != 0
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1.d
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1.d
@@ -0,0 +1,23 @@
+#name: Dynamic segment sections 1
+#ld: -shared -T dynamic-sections-1.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 4 program headers, starting at offset .*
+
+Program Headers:
+  Type           Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
+  ABIFLAGS       .*
+  LOAD           .*
+  DYNAMIC        [^ ]+ +[^ ]+ +[^ ]+ +(0x[0-9a-f]+) +\1 +.*
+  NULL           .*
+
+ Section to Segment mapping:
+  Segment Sections\.\.\.
+   00     .*
+   01     .*
+   02     \.dynamic 
+   03     
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1.ld
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1.ld
@@ -0,0 +1,12 @@
+SECTIONS
+{
+  .MIPS.abiflags : { *(.MIPS.abiflags) }
+  .dynamic : { *(.dynamic) }
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .rel.dyn : { *(.rel.dyn) }
+  .data : { *(.data) }
+  .got : { *(.got) }
+  /DISCARD/ : { *(*) }
+}
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1i1.d
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1i1.d
@@ -0,0 +1,21 @@
+#name: Dynamic segment sections 1
+#ld: -shared -T dynamic-sections-1.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 \.dynsym \.dynstr 
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1i2.d
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-1i2.d
@@ -0,0 +1,21 @@
+#name: Dynamic segment sections 1
+#ld: -shared -T dynamic-sections-1.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 
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-2.d
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-2.d
@@ -0,0 +1,6 @@
+#name: Dynamic segment sections 2
+#ld: -shared -T dynamic-sections-2.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-2.ld
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-2.ld
@@ -0,0 +1,12 @@
+SECTIONS
+{
+  .MIPS.abiflags : { *(.MIPS.abiflags) }
+  .dynamic : { *(.dynamic) }
+  .hash : { *(.hash) }
+  .data : { *(.data) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .rel.dyn : { *(.rel.dyn) }
+  .got : { *(.got) }
+  /DISCARD/ : { *(*) }
+}
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-2i1.d
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-2i1.d
@@ -0,0 +1,21 @@
+#name: Dynamic segment sections 2
+#ld: -shared -T dynamic-sections-2.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 \.data \.dynsym \.dynstr 
Index: binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-2i2.d
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections-2i2.d
@@ -0,0 +1,6 @@
+#name: Dynamic segment sections 2
+#ld: -shared -T dynamic-sections-2.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.s
===================================================================
--- /dev/null
+++ binutils-gdb/ld/testsuite/ld-mips-elf/dynamic-sections.s
@@ -0,0 +1,5 @@
+	.data
+	.globl	foo
+foo:
+	.dc.a	foo
+	.size	foo, . - foo
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
@@ -269,12 +269,13 @@ if {[istarget *-*-openbsd*] } {
     set abi_asflags(n64) "-march=from-abi -64"
     set abi_ldflags(o32) -melf32bsmip
     set abi_ldflags(n64) -melf64bmip
-    set irixemul 1
+    set irixemul 2
 } else {
     set abi_asflags(o32) -32
     set irixemul 1
 }
 set tmips [expr $irixemul ? {""} : {"t"}]
+set irixn [expr $irixemul ? {"i${irixemul}"} : {""}]
 
 if { $linux_gnu } {
     run_ld_link_tests [list \
@@ -1804,3 +1805,6 @@ foreach { abi } $abis {
 	    [list "readelf -WS sections-2-${abi}${tmips}${ps2}.rd"] \
 	    "sections-2-${abi}"]]
 }
+
+run_dump_test "dynamic-sections-1${irixn}"
+run_dump_test "dynamic-sections-2${irixn}"


More information about the Binutils mailing list