[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