aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2025-04-28 07:12:48 +0800
committerH.J. Lu <hjl.tools@gmail.com>2025-04-29 15:39:54 +0800
commit5e247da8afb8b764cb111ce1a05e8cb8862a7f98 (patch)
treefeeca18d6239b42756fb9b36d13b79c8a046b7ff
parentb1f0f5b31c414b3445cdcbc5bf9ca31638c7712a (diff)
downloadbinutils-5e247da8afb8b764cb111ce1a05e8cb8862a7f98.zip
binutils-5e247da8afb8b764cb111ce1a05e8cb8862a7f98.tar.gz
binutils-5e247da8afb8b764cb111ce1a05e8cb8862a7f98.tar.bz2
elf: Properly set sh_offset for .tbss sections
Set sh_offset for .tbss sections to their nominal offset after aligning. They are not loaded from disk so the value doesn't really matter, except when the .tbss section is the first one in a PT_TLS segment. In that case, it sets the p_offset for the PT_TLS segment, which according to the ELF gABI ought to satisfy p_offset % p_align == p_vaddr % p_align. bfd/ PR ld/32896 * elf.c (assign_file_positions_for_load_sections): Properly set sh_offset for .tbss sections. ld/ PR ld/32896 * testsuite/ld-elf/tbss4.d: New file. * testsuite/ld-elf/tbss4.s: Likewise. Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
-rw-r--r--bfd/elf.c33
-rw-r--r--ld/testsuite/ld-elf/tbss4.d9
-rw-r--r--ld/testsuite/ld-elf/tbss4.s25
3 files changed, 51 insertions, 16 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index ee89dd9..b6f5070 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6292,27 +6292,28 @@ assign_file_positions_for_load_sections (bfd *abfd,
}
else
{
- if (p->p_type == PT_LOAD)
- {
- this_hdr->sh_offset = sec->filepos = off;
- if (this_hdr->sh_type != SHT_NOBITS)
- off += this_hdr->sh_size;
- }
- else if (this_hdr->sh_type == SHT_NOBITS
- && (this_hdr->sh_flags & SHF_TLS) != 0
- && this_hdr->sh_offset == 0)
+ if (this_hdr->sh_type == SHT_NOBITS
+ && (this_hdr->sh_flags & SHF_TLS) != 0
+ && this_hdr->sh_offset == 0)
{
- /* This is a .tbss section that didn't get a PT_LOAD.
- (See _bfd_elf_map_sections_to_segments "Create a
- final PT_LOAD".) Set sh_offset to the value it
- would have if we had created a zero p_filesz and
- p_memsz PT_LOAD header for the section. This
- also makes the PT_TLS header have the same
- p_offset value. */
+ /* Set sh_offset for .tbss sections to their nominal
+ offset after aligning. They are not loaded from
+ disk so the value doesn't really matter, except
+ when the .tbss section is the first one in a
+ PT_TLS segment. In that case it sets the
+ p_offset for the PT_TLS segment, which according
+ to the ELF gABI ought to satisfy
+ p_offset % p_align == p_vaddr % p_align. */
bfd_vma adjust = vma_page_aligned_bias (this_hdr->sh_addr,
off, align);
this_hdr->sh_offset = sec->filepos = off + adjust;
}
+ else if (p->p_type == PT_LOAD)
+ {
+ this_hdr->sh_offset = sec->filepos = off;
+ if (this_hdr->sh_type != SHT_NOBITS)
+ off += this_hdr->sh_size;
+ }
if (this_hdr->sh_type != SHT_NOBITS)
{
diff --git a/ld/testsuite/ld-elf/tbss4.d b/ld/testsuite/ld-elf/tbss4.d
new file mode 100644
index 0000000..77a865b
--- /dev/null
+++ b/ld/testsuite/ld-elf/tbss4.d
@@ -0,0 +1,9 @@
+#ld: -e _start --rosegment -z separate-code -z max-page-size=0x1000 -z common-page-size=0x1000
+#readelf: -l --wide
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#...
+ +TLS +0x0+1014 .*
+#...
+.* \.tbss
+#pass
diff --git a/ld/testsuite/ld-elf/tbss4.s b/ld/testsuite/ld-elf/tbss4.s
new file mode 100644
index 0000000..1e7ec3e
--- /dev/null
+++ b/ld/testsuite/ld-elf/tbss4.s
@@ -0,0 +1,25 @@
+# Writeable gcc_except_table is required in order to put this section after
+# the DATA_SEGMENT_ALIGN directive in the default linker script (and hence
+# in the same PT_LOAD as the PT_TLS segment, and hence so that the
+# gcc_except_table can affect the .tbss section location).
+ .section .gcc_except_table,"aw",%progbits
+# Alignment is needed -- otherwise gcc_except_table start position seems to
+# be adjusted so that the tbss section is fully aligned.
+ .align 4
+ .ascii "Odd number of chars"
+
+ .section .tbss,"awT",%nobits
+ .align 4
+ .type xyz, %object
+ .size xyz, 4
+xyz:
+ .zero 4
+
+ .data
+dataval:
+ .align 4
+ .ascii "x"
+
+ .text
+ .global _start
+_start: