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

Maciej W. Rozycki macro@sourceware.org
Wed Feb 18 08:00:41 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=31d589588ea43f234e9d06af1d8f0e08981e4c12

commit 31d589588ea43f234e9d06af1d8f0e08981e4c12
Author: Maciej W. Rozycki <macro@orcam.me.uk>
Date:   Wed Feb 18 07:58:31 2026 +0000

    ELF/BFD: Factor in inter-section padding for DYNAMIC segment
    
    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.

Diff:
---
 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(-)

diff --git a/bfd/elf.c b/bfd/elf.c
index bdb355a6787..a8e1834b8f2 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6304,6 +6304,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
 	  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
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-1.d b/ld/testsuite/ld-mips-elf/dynamic-sections-1.d
new file mode 100644
index 00000000000..84e700f2eb4
--- /dev/null
+++ b/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     
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-1.ld b/ld/testsuite/ld-mips-elf/dynamic-sections-1.ld
new file mode 100644
index 00000000000..4ba13cfe019
--- /dev/null
+++ b/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/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-1i1.d b/ld/testsuite/ld-mips-elf/dynamic-sections-1i1.d
new file mode 100644
index 00000000000..e43129d6204
--- /dev/null
+++ b/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 
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-1i2.d b/ld/testsuite/ld-mips-elf/dynamic-sections-1i2.d
new file mode 100644
index 00000000000..b628f5524bf
--- /dev/null
+++ b/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 
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-2.d b/ld/testsuite/ld-mips-elf/dynamic-sections-2.d
new file mode 100644
index 00000000000..e25bdc19f35
--- /dev/null
+++ b/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
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-2.ld b/ld/testsuite/ld-mips-elf/dynamic-sections-2.ld
new file mode 100644
index 00000000000..a7e77865398
--- /dev/null
+++ b/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/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-2i1.d b/ld/testsuite/ld-mips-elf/dynamic-sections-2i1.d
new file mode 100644
index 00000000000..a498b91dcc7
--- /dev/null
+++ b/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 
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections-2i2.d b/ld/testsuite/ld-mips-elf/dynamic-sections-2i2.d
new file mode 100644
index 00000000000..493482e433f
--- /dev/null
+++ b/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
diff --git a/ld/testsuite/ld-mips-elf/dynamic-sections.s b/ld/testsuite/ld-mips-elf/dynamic-sections.s
new file mode 100644
index 00000000000..34c32823a92
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/dynamic-sections.s
@@ -0,0 +1,5 @@
+	.data
+	.globl	foo
+foo:
+	.dc.a	foo
+	.size	foo, . - foo
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index c9e67324cf4..7f51eb62538 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/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-cvs mailing list