From f678201d93b75d23da29d2a8aa4d825219199c3c Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 28 Apr 2025 07:12:48 +0800 Subject: [PATCH v2] elf: Don't set sh_offset of .tbss sections beyond EOF If there are no prior .tdata nor .tbss sections, put meaningless sh_offset of .tbss sections without file contents somewhere within the first page, in an attempt to not point past EOF and avoid sh_offset of zero. bfd/ PR ld/32896 * elf.c (IS_TDATA): New. (assign_file_positions_for_load_sections): Don't set sh_offset of .tbss sections beyond EOF if there are no prior .tdata nor .tbss sections. ld/ PR ld/32896 * testsuite/ld-elf/tbss4.d: Updated. * testsuite/ld-elf/tbss5.d: New file. * testsuite/ld-elf/tbss5.s: Likewise. * testsuite/ld-elf/tbss6.d: Likewise. * testsuite/ld-elf/tbss6.s: Likewise. Signed-off-by: H.J. Lu --- bfd/elf.c | 22 ++++++++++++++++++---- ld/testsuite/ld-elf/tbss4.d | 2 +- ld/testsuite/ld-elf/tbss5.d | 9 +++++++++ ld/testsuite/ld-elf/tbss5.s | 14 ++++++++++++++ ld/testsuite/ld-elf/tbss6.d | 12 ++++++++++++ ld/testsuite/ld-elf/tbss6.s | 21 +++++++++++++++++++++ 6 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 ld/testsuite/ld-elf/tbss5.d create mode 100644 ld/testsuite/ld-elf/tbss5.s create mode 100644 ld/testsuite/ld-elf/tbss6.d create mode 100644 ld/testsuite/ld-elf/tbss6.s diff --git a/bfd/elf.c b/bfd/elf.c index b6f50701928..8049b5efca6 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4983,6 +4983,9 @@ elf_modify_segment_map (bfd *abfd, #define IS_TBSS(s) \ ((s->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) == SEC_THREAD_LOCAL) +#define IS_TDATA(s) \ + ((s->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) \ + == (SEC_THREAD_LOCAL | SEC_LOAD)) /* Set up a mapping from BFD sections to program segments. Update NEED_LAYOUT if the section layout is changed. */ @@ -5922,6 +5925,8 @@ assign_file_positions_for_load_sections (bfd *abfd, bfd_vma off_adjust; /* Octets. */ bool no_contents; bfd_size_type align_pagesize; + asection *sec; + int seen_tls_section; /* An ELF segment (described by Elf_Internal_Phdr) may contain a number of sections with contents contributing to both p_filesz @@ -6195,9 +6200,10 @@ assign_file_positions_for_load_sections (bfd *abfd, core files, for sections in PT_NOTE segments. assign_file_positions_for_non_load_sections will set filepos for other sections and update p_filesz for other segments. */ - for (i = 0, secpp = m->sections; i < m->count; i++, secpp++) + seen_tls_section = 0; + for (i = 0, secpp = m->sections; i < m->count; i++, secpp++, + seen_tls_section |= IS_TBSS (sec) || IS_TDATA (sec)) { - asection *sec; bfd_size_type align; Elf_Internal_Shdr *this_hdr; @@ -6306,7 +6312,16 @@ assign_file_positions_for_load_sections (bfd *abfd, 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; + file_ptr aligned_off = off + adjust; + /* If there are no prior .tdata nor .tbss sections, + put meaningless sh_offset of .tbss sections + without file contents somewhere within the first + page, in an attempt to not point past EOF and + avoid sh_offset of zero. */ + if (!seen_tls_section + && aligned_off >= (file_ptr) maxpagesize) + aligned_off = (aligned_off + align - 1) % align + 1; + this_hdr->sh_offset = sec->filepos = aligned_off; } else if (p->p_type == PT_LOAD) { @@ -6395,7 +6410,6 @@ assign_file_positions_for_load_sections (bfd *abfd, for (i = 0; i < m->count; i++) { Elf_Internal_Shdr *this_hdr; - asection *sec; sec = m->sections[i]; this_hdr = &(elf_section_data(sec)->this_hdr); diff --git a/ld/testsuite/ld-elf/tbss4.d b/ld/testsuite/ld-elf/tbss4.d index 77a865b5e1a..fabc2d57b41 100644 --- a/ld/testsuite/ld-elf/tbss4.d +++ b/ld/testsuite/ld-elf/tbss4.d @@ -3,7 +3,7 @@ #target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu* #... - +TLS +0x0+1014 .* + +TLS +0x0+4 .* #... .* \.tbss #pass diff --git a/ld/testsuite/ld-elf/tbss5.d b/ld/testsuite/ld-elf/tbss5.d new file mode 100644 index 00000000000..a935091fc5e --- /dev/null +++ b/ld/testsuite/ld-elf/tbss5.d @@ -0,0 +1,9 @@ +#ld: -e _start --rosegment -z separate-code -z max-page-size=0x10000 -z common-page-size=0x10000 +#readelf: -l --wide +#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu* + +#... + +TLS +0x0+400 .* +#... +.* \.tbss +#pass diff --git a/ld/testsuite/ld-elf/tbss5.s b/ld/testsuite/ld-elf/tbss5.s new file mode 100644 index 00000000000..c172e243df1 --- /dev/null +++ b/ld/testsuite/ld-elf/tbss5.s @@ -0,0 +1,14 @@ + .section .gcc_except_table,"aw",%progbits + .p2align 4 + .ascii "Odd number of chars" + + .section .tbss,"awT",%nobits + .p2align 10 + .type abc, %object + .size abc, 4 +abc: + .zero 4 + + .text + .global _start +_start: diff --git a/ld/testsuite/ld-elf/tbss6.d b/ld/testsuite/ld-elf/tbss6.d new file mode 100644 index 00000000000..457f64b42a4 --- /dev/null +++ b/ld/testsuite/ld-elf/tbss6.d @@ -0,0 +1,12 @@ +#ld: -e _start --rosegment -z separate-code -z max-page-size=0x10000 -z common-page-size=0x10000 +#readelf: -S -l --wide +#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu* + +#... + \[ [0-9]+\] \.tdata +PROGBITS +0+4[0-9]+0400 010400 0+4 00 WAT +0 +0 1024 + \[ [0-9]+\] \.tbss +NOBITS +0+4[0-9]+0800 010800 0+4 00 WAT +0 +0 1024 +#... + +TLS +0x0+10400 .* +#... +.* \.tdata \.tbss +#pass diff --git a/ld/testsuite/ld-elf/tbss6.s b/ld/testsuite/ld-elf/tbss6.s new file mode 100644 index 00000000000..8750038f226 --- /dev/null +++ b/ld/testsuite/ld-elf/tbss6.s @@ -0,0 +1,21 @@ + .section .gcc_except_table,"aw",@progbits + .p2align 4 + .ascii "Odd number of chars" + + .section .tbss,"awT",%nobits + .p2align 10 + .type abc, %object + .size abc, 4 +abc: + .zero 4 + + .section .tdata,"awT",%progbits + .p2align 10 + .type foo, %object + .size foo, 4 +foo: + .zero 4 + + .text + .global _start +_start: -- 2.49.0