]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
elf: Properly set sh_offset for .tbss sections
authorH.J. Lu <hjl.tools@gmail.com>
Sun, 27 Apr 2025 23:12:48 +0000 (07:12 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 29 Apr 2025 07:39:54 +0000 (15:39 +0800)
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>
bfd/elf.c
ld/testsuite/ld-elf/tbss4.d [new file with mode: 0644]
ld/testsuite/ld-elf/tbss4.s [new file with mode: 0644]

index ee89dd909dafb4d70a0a781a769d139fc926f6ce..b6f507019288cc3cd268f156f999c0a70bfa5d9b 100644 (file)
--- 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 (file)
index 0000000..77a865b
--- /dev/null
@@ -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 (file)
index 0000000..1e7ec3e
--- /dev/null
@@ -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: