From: H.J. Lu Date: Sun, 27 Apr 2025 23:12:48 +0000 (+0800) Subject: elf: Properly set sh_offset for .tbss sections X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5e247da8afb8b764cb111ce1a05e8cb8862a7f98;p=thirdparty%2Fbinutils-gdb.git 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 --- diff --git a/bfd/elf.c b/bfd/elf.c index ee89dd909da..b6f50701928 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 00000000000..77a865b5e1a --- /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 00000000000..1e7ec3efb0c --- /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: