[PATCH v3] elf: Don't set sh_offset of .tbss sections beyond EOF

H.J. Lu hjl.tools@gmail.com
Tue Apr 29 21:38:00 GMT 2025


If there is no .tdata section, 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.
	(make_mapping): Set has_tdata if there is .tdata section.
	(assign_file_positions_for_load_sections): Don't set sh_offset
	of .tbss sections beyond EOF if there is no .tdata section.
	(rewrite_elf_program_header): Set has_tdata if there is .tdata
	section.
	(copy_elf_program_header): Likewise.

include/

	PR ld/32896
	* elf/internal.h (elf_segment_map): Add has_tdata.

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 <hjl.tools@gmail.com>
---
 bfd/elf.c                   | 26 ++++++++++++++++++++++++--
 include/elf/internal.h      |  2 ++
 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 +++++++++++++++++++++
 7 files changed, 83 insertions(+), 3 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..d53f252d3ca 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4875,6 +4875,10 @@ _bfd_elf_find_segment_containing_section (bfd * abfd, asection * section)
   return NULL;
 }
 
+#define IS_TDATA(s) \
+  (((s)->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) \
+   == (SEC_THREAD_LOCAL | SEC_LOAD))
+
 /* Create a mapping from a set of sections to a program segment.  */
 
 static struct elf_segment_map *
@@ -4897,7 +4901,11 @@ make_mapping (bfd *abfd,
   m->next = NULL;
   m->p_type = PT_LOAD;
   for (i = from, hdrpp = sections + from; i < to; i++, hdrpp++)
-    m->sections[i - from] = *hdrpp;
+    {
+      m->sections[i - from] = *hdrpp;
+      if (IS_TDATA (*hdrpp))
+	m->has_tdata = 1;
+    }
   m->count = to - from;
 
   if (from == 0 && phdr)
@@ -6306,7 +6314,15 @@ 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 is no .tdata section, 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 (!m->has_tdata
+		      && 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)
 		{
@@ -7721,6 +7737,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd, bfd_vma maxpagesize)
 	{
 	  if (INCLUDE_SECTION_IN_SEGMENT (section, segment, opb, p_paddr_valid))
 	    {
+	      if (IS_TDATA (section))
+		map->has_tdata = 1;
+
 	      output_section = section->output_section;
 
 	      sections[j++] = section;
@@ -8158,6 +8177,9 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
 	      this_hdr = &(elf_section_data(section)->this_hdr);
 	      if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
 		{
+		  if (IS_TDATA (section))
+		    map->has_tdata = 1;
+
 		  map->sections[isec++] = section->output_section;
 		  if ((section->flags & SEC_ALLOC) != 0)
 		    {
diff --git a/include/elf/internal.h b/include/elf/internal.h
index 9c546741ad8..54add8fe49a 100644
--- a/include/elf/internal.h
+++ b/include/elf/internal.h
@@ -296,6 +296,8 @@ struct elf_segment_map
      flag set are placed after one with includes_filehdr set, and
      before PT_LOAD headers without this flag set.  */
   unsigned int no_sort_lma : 1;
+  /* Whether this segment has .tdata section.  */
+  unsigned int has_tdata : 1;
   /* Index holding original order before sorting segments.  */
   unsigned int idx;
   /* Number of sections (may be 0).  */
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



More information about the Binutils mailing list