[PATCH] ld: Account for .tbss size on Arm embedded targets

Torbjörn SVENSSON torbjorn.svensson@foss.st.com
Wed Sep 2 14:08:11 GMT 2026


Changes since v1:

- Reformulated commit message.
- Dropped special tls-app-eabi.d file.
- Generatlized tls-app.d to allow any address by replacing with wildcards.
- Set tls_nobits_occupies_vma to true based on value of ${EMBEDDED}.
- Renamed "FLASH" to "ROM" in tls-nobits-vma.ld to make it easier to read.

Note, I've only set tls_nobits_occupies_vma in armelf.em. For other
embedded targets, similar statements needs to be added to the other
.em files, but since I have no way of testing those, I've left that out
of this patch.

Ok for master?

Kind regards,
Torbjörn

--

Embedded programs allocate TLS storage directly, so if .tdata consumses
VMA, then .tbss must also do so.  Otherwise, a following section such as
.bss can overlap it.

Keep the existing behavior for non-embedded targets, and add tests for
static, executable, PIE, and dynamic links.

This change aligns with LLVM lld behavior for .tbss.

ld/

	* ld.h: New build-time property tls_nobits_occupies_vma.
	* ldlang.c: Make .tbss occupy VMA when tls_nobits_occupies_vma
	is true.
	* emultempl/armelf.em: Set tls_nobits_occupies_vma to true for
	EMBEDDED=yes targets.
	* testsuite/ld-arm/arm-elf.exp: Run the new tests.
	* testsuite/ld-arm/tls-app.d: Replace addresses with wildcards.
	* testsuite/ld-arm/tls-nobits-vma-dynamic.d: New.
	* testsuite/ld-arm/tls-nobits-vma-exec.d: New.
	* testsuite/ld-arm/tls-nobits-vma-pie.d: New.
	* testsuite/ld-arm/tls-nobits-vma-static.d: New.
	* testsuite/ld-arm/tls-nobits-vma.ld: New.
	* testsuite/ld-arm/tls-nobits-vma.s: New.

Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
---
 ld/emultempl/armelf.em                       |  1 +
 ld/ld.h                                      |  4 +++
 ld/ldlang.c                                  | 15 ++++++-----
 ld/testsuite/ld-arm/arm-elf.exp              |  7 +++++
 ld/testsuite/ld-arm/tls-app.d                | 12 ++++-----
 ld/testsuite/ld-arm/tls-nobits-vma-dynamic.d | 27 +++++++++++++++++++
 ld/testsuite/ld-arm/tls-nobits-vma-exec.d    | 22 +++++++++++++++
 ld/testsuite/ld-arm/tls-nobits-vma-pie.d     | 28 ++++++++++++++++++++
 ld/testsuite/ld-arm/tls-nobits-vma-static.d  | 22 +++++++++++++++
 ld/testsuite/ld-arm/tls-nobits-vma.ld        | 13 +++++++++
 ld/testsuite/ld-arm/tls-nobits-vma.s         | 11 ++++++++
 11 files changed, 150 insertions(+), 12 deletions(-)
 create mode 100644 ld/testsuite/ld-arm/tls-nobits-vma-dynamic.d
 create mode 100644 ld/testsuite/ld-arm/tls-nobits-vma-exec.d
 create mode 100644 ld/testsuite/ld-arm/tls-nobits-vma-pie.d
 create mode 100644 ld/testsuite/ld-arm/tls-nobits-vma-static.d
 create mode 100644 ld/testsuite/ld-arm/tls-nobits-vma.ld
 create mode 100644 ld/testsuite/ld-arm/tls-nobits-vma.s

diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index f70bcf34b8b..6f03332ed2b 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -58,6 +58,7 @@ gld${EMULATION_NAME}_before_parse (void)
 #endif /* not TARGET_ */
   input_flags.dynamic = ${DYNAMIC_LINK-true};
   config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
+  config.tls_nobits_occupies_vma = `if test "x${EMBEDDED}" = xyes ; then echo true ; else echo false ; fi`;
   config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo true ; else echo false ; fi`;
 EOF
 if test -n "$COMMONPAGESIZE"; then
diff --git a/ld/ld.h b/ld/ld.h
index 76825e4253c..8f83a9da4d1 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -236,6 +236,10 @@ typedef struct
      parameter.  */
   bool has_shared;
 
+  /* If TRUE, TLS NOBITS sections consume VMA like other allocated
+     sections.  */
+  bool tls_nobits_occupies_vma;
+
   /* If TRUE, build constructors.  */
   bool build_constructors;
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 65494acca00..35b884bd98a 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5890,8 +5890,11 @@ sort_sections_by_vma (const void *arg1, const void *arg2)
 #define IS_TBSS(s) \
   ((s->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == SEC_THREAD_LOCAL)
 
+#define TBSS_EFFECTIVELY_ZERO(s) \
+  (IS_TBSS (s) && !config.tls_nobits_occupies_vma)
+
 #define IGNORE_SECTION(s) \
-  ((s->flags & SEC_ALLOC) == 0 || IS_TBSS (s))
+  ((s->flags & SEC_ALLOC) == 0 || TBSS_EFFECTIVELY_ZERO (s))
 
 /* Check to see if any allocated sections overlap with other allocated
    sections.  This can happen if a linker script specifies the output
@@ -6433,8 +6436,8 @@ lang_size_sections_1
 	    if (bfd_is_abs_section (os->bfd_section) || os->ignored)
 	      break;
 
-	    /* .tbss sections effectively have zero size.  */
-	    if (!IS_TBSS (os->bfd_section)
+	    /* Hosted .tbss sections effectively have zero size.  */
+	    if (!TBSS_EFFECTIVELY_ZERO (os->bfd_section)
 		|| bfd_link_relocatable (&link_info))
 	      dotdelta = TO_ADDR (os->bfd_section->size);
 	    else
@@ -6813,7 +6816,7 @@ lang_size_relro_segment_1 (void)
 	bfd_vma start, end, bump;
 
 	end = start = sec->vma;
-	if (!IS_TBSS (sec))
+	if (!TBSS_EFFECTIVELY_ZERO (sec))
 	  end += TO_ADDR (sec->size);
 	bump = desired_end - end;
 	/* We'd like to increase START by BUMP, but we must heed
@@ -6936,8 +6939,8 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 		  {
 		    newdot = os->bfd_section->vma;
 
-		    /* .tbss sections effectively have zero size.  */
-		    if (!IS_TBSS (os->bfd_section)
+		    /* Hosted .tbss sections effectively have zero size.  */
+		    if (!TBSS_EFFECTIVELY_ZERO (os->bfd_section)
 			|| bfd_link_relocatable (&link_info))
 		      newdot += TO_ADDR (os->bfd_section->size);
 
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index ad27c1f86c9..7b05db3a172 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -432,6 +432,13 @@ run_dump_test "rel32-reject"
 run_dump_test "rel32-reject-pie"
 run_dump_test "pie-bind-locally"
 
+if {[istarget "arm*-*-eabi*"]} {
+    run_dump_test "tls-nobits-vma-static"
+    run_dump_test "tls-nobits-vma-exec"
+    run_dump_test "tls-nobits-vma-pie"
+    run_dump_test "tls-nobits-vma-dynamic"
+}
+
 # Exclude non-ARM-EABI targets.
 
 if { [istarget "arm*-*-netbsd*"] } {
diff --git a/ld/testsuite/ld-arm/tls-app.d b/ld/testsuite/ld-arm/tls-app.d
index 985e11ecf3e..605f3dd1167 100644
--- a/ld/testsuite/ld-arm/tls-app.d
+++ b/ld/testsuite/ld-arm/tls-app.d
@@ -10,9 +10,9 @@ Disassembly of section .text:
     8[0-9a-f]+:	e1a00000 	nop			@ \(mov r0, r0\)
     8[0-9a-f]+:	e1a00000 	nop			@ \(mov r0, r0\)
     8[0-9a-f]+:	e1a0f00e 	mov	pc, lr
-    8[0-9a-f]+:	000080bc 	.word	0x000080bc
-    8[0-9a-f]+:	000080b4 	.word	0x000080b4
-    8[0-9a-f]+:	000080ac 	.word	0x000080ac
-    8[0-9a-f]+:	00000004 	.word	0x00000004
-    8[0-9a-f]+:	000080c4 	.word	0x000080c4
-    8[0-9a-f]+:	00000014 	.word	0x00000014
+    8[0-9a-f]+:	[0-9a-f]+ 	.word	0x.*
+    8[0-9a-f]+:	[0-9a-f]+ 	.word	0x.*
+    8[0-9a-f]+:	[0-9a-f]+ 	.word	0x.*
+    8[0-9a-f]+:	[0-9a-f]+ 	.word	0x.*
+    8[0-9a-f]+:	[0-9a-f]+ 	.word	0x.*
+    8[0-9a-f]+:	[0-9a-f]+ 	.word	0x.*
diff --git a/ld/testsuite/ld-arm/tls-nobits-vma-dynamic.d b/ld/testsuite/ld-arm/tls-nobits-vma-dynamic.d
new file mode 100644
index 00000000000..e6990bbbdaa
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-nobits-vma-dynamic.d
@@ -0,0 +1,27 @@
+#source: tls-nobits-vma.s
+#ld: -shared -T tls-nobits-vma.ld
+#readelf: -hSW
+
+ELF Header:
+#...
+  Type: +DYN \(Shared object file\)
+#...
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ +0+ +0+ +0+ +0 +0 +0
+  \[ 1\] \.dynsym +DYNSYM +00008000 +[0-9a-f]+ +000010 +10 +A +2 +1 +4
+  \[ 2\] \.dynstr +STRTAB +00008010 +[0-9a-f]+ +000001 +00 +A +0 +0 +1
+  \[ 3\] \.hash +HASH +00008014 +[0-9a-f]+ +000010 +04 +A +1 +0 +4
+  \[ 4\] \.data +PROGBITS +00001000 +[0-9a-f]+ +000004 +00 +WA +0 +0 +4
+  \[ 5\] \.dynamic +DYNAMIC +00001004 +[0-9a-f]+ +000058 +08 +WA +2 +0 +4
+  \[ 6\] \.got\.plt +PROGBITS +0000105c +[0-9a-f]+ +00000c +04 +WA +0 +0 +4
+  \[ 7\] \.tdata +PROGBITS +00001068 +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[ 8\] \.tbss +NOBITS +0000106c +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[ 9\] \.bss +NOBITS +00001070 +[0-9a-f]+ +000008 +00 +WA +0 +0 +4
+  \[10\] \.ARM\.attributes +ARM_ATTRIBUTES +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[11\] \.symtab +SYMTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +10 +12 +[0-9]+ +4
+  \[12\] \.strtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[13\] \.shstrtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+Key to Flags:
+#...
diff --git a/ld/testsuite/ld-arm/tls-nobits-vma-exec.d b/ld/testsuite/ld-arm/tls-nobits-vma-exec.d
new file mode 100644
index 00000000000..89e0fa1ef18
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-nobits-vma-exec.d
@@ -0,0 +1,22 @@
+#source: tls-nobits-vma.s
+#ld: -T tls-nobits-vma.ld
+#readelf: -hSW
+
+ELF Header:
+#...
+  Type: +EXEC \(Executable file\)
+#...
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ +0+ +0+ +0+ +0 +0 +0
+  \[ 1\] \.data +PROGBITS +00001000 +[0-9a-f]+ +000004 +00 +WA +0 +0 +4
+  \[ 2\] \.tdata +PROGBITS +00001004 +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[ 3\] \.tbss +NOBITS +00001008 +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[ 4\] \.bss +NOBITS +0000100c +[0-9a-f]+ +000008 +00 +WA +0 +0 +4
+  \[ 5\] \.ARM\.attributes +ARM_ATTRIBUTES +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[ 6\] \.symtab +SYMTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +10 +7 +[0-9]+ +4
+  \[ 7\] \.strtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[ 8\] \.shstrtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+Key to Flags:
+#...
diff --git a/ld/testsuite/ld-arm/tls-nobits-vma-pie.d b/ld/testsuite/ld-arm/tls-nobits-vma-pie.d
new file mode 100644
index 00000000000..562de1aca0a
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-nobits-vma-pie.d
@@ -0,0 +1,28 @@
+#source: tls-nobits-vma.s
+#ld: -pie -T tls-nobits-vma.ld
+#readelf: -hSW
+
+ELF Header:
+#...
+  Type: +EXEC \(Executable file\)
+#...
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ +0+ +0+ +0+ +0 +0 +0
+  \[ 1\] \.interp +PROGBITS +00008000 +[0-9a-f]+ +000011 +00 +A +0 +0 +1
+  \[ 2\] \.dynsym +DYNSYM +00008014 +[0-9a-f]+ +000010 +10 +A +3 +1 +4
+  \[ 3\] \.dynstr +STRTAB +00008024 +[0-9a-f]+ +000001 +00 +A +0 +0 +1
+  \[ 4\] \.hash +HASH +00008028 +[0-9a-f]+ +000010 +04 +A +2 +0 +4
+  \[ 5\] \.data +PROGBITS +00001000 +[0-9a-f]+ +000004 +00 +WA +0 +0 +4
+  \[ 6\] \.dynamic +DYNAMIC +00001004 +[0-9a-f]+ +000068 +08 +WA +3 +0 +4
+  \[ 7\] \.got\.plt +PROGBITS +0000106c +[0-9a-f]+ +00000c +04 +WA +0 +0 +4
+  \[ 8\] \.tdata +PROGBITS +00001078 +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[ 9\] \.tbss +NOBITS +0000107c +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[10\] \.bss +NOBITS +00001080 +[0-9a-f]+ +000008 +00 +WA +0 +0 +4
+  \[11\] \.ARM\.attributes +ARM_ATTRIBUTES +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[12\] \.symtab +SYMTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +10 +13 +[0-9]+ +4
+  \[13\] \.strtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[14\] \.shstrtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+Key to Flags:
+#...
diff --git a/ld/testsuite/ld-arm/tls-nobits-vma-static.d b/ld/testsuite/ld-arm/tls-nobits-vma-static.d
new file mode 100644
index 00000000000..40cf6204763
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-nobits-vma-static.d
@@ -0,0 +1,22 @@
+#source: tls-nobits-vma.s
+#ld: -static -T tls-nobits-vma.ld
+#readelf: -hSW
+
+ELF Header:
+#...
+  Type: +EXEC \(Executable file\)
+#...
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ +0+ +0+ +0+ +0 +0 +0
+  \[ 1\] \.data +PROGBITS +00001000 +[0-9a-f]+ +000004 +00 +WA +0 +0 +4
+  \[ 2\] \.tdata +PROGBITS +00001004 +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[ 3\] \.tbss +NOBITS +00001008 +[0-9a-f]+ +000004 +00 WAT +0 +0 +4
+  \[ 4\] \.bss +NOBITS +0000100c +[0-9a-f]+ +000008 +00 +WA +0 +0 +4
+  \[ 5\] \.ARM\.attributes +ARM_ATTRIBUTES +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[ 6\] \.symtab +SYMTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +10 +7 +[0-9]+ +4
+  \[ 7\] \.strtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+  \[ 8\] \.shstrtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
+Key to Flags:
+#...
diff --git a/ld/testsuite/ld-arm/tls-nobits-vma.ld b/ld/testsuite/ld-arm/tls-nobits-vma.ld
new file mode 100644
index 00000000000..4c872fe474e
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-nobits-vma.ld
@@ -0,0 +1,13 @@
+MEMORY
+{
+  ROM (rx) : ORIGIN = 0x8000, LENGTH = 0x1000
+  RAM (rw) : ORIGIN = 0x1000, LENGTH = 0x1000
+}
+
+SECTIONS
+{
+  .data : ALIGN(4) { *(.data) } >RAM AT>ROM
+  .tdata : ALIGN(4) { *(.tdata) } >RAM AT>ROM
+  .tbss (NOLOAD) : ALIGN(4) { *(.tbss) } >RAM
+  .bss (NOLOAD) : ALIGN(4) { *(.bss) } >RAM
+}
diff --git a/ld/testsuite/ld-arm/tls-nobits-vma.s b/ld/testsuite/ld-arm/tls-nobits-vma.s
new file mode 100644
index 00000000000..df2607251b1
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-nobits-vma.s
@@ -0,0 +1,11 @@
+	.section .data,"aw",%progbits
+	.word 1
+
+	.section .tdata,"awT",%progbits
+	.word 2
+
+	.section .tbss,"awT",%nobits
+	.space 4
+
+	.section .bss,"aw",%nobits
+	.space 8
-- 
2.43.0



More information about the Binutils mailing list