From 33fe2e5a8d7a2af31832436cfa5b3f9b48e43aa7 Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Thu, 28 Aug 2025 16:03:29 -0500 Subject: [PATCH] Fix only TBSS sections causing empty segment TBSS sections are special, they do not consume any virtual memory size at load time, they incur a cost only when setting up size of the initial TLS image by either libc or libpthread. Creating a segment when a TBSS section is encountered causes linker to create an empty segment. Resolves #353 Signed-off-by: Shankar Easwaran --- lib/Target/CreateProgramHeaders.hpp | 17 +++++++++-------- test/AArch64/standalone/TLS_DESC/DESC.test | 8 ++++---- test/AArch64/standalone/TLS_IE/IE.test | 8 ++++---- .../standalone/TLS/OnlyTBSS/Inputs/script.t | 14 ++++++++++++++ .../TLS/OnlyTBSS/Inputs/scripttbssnewregion.t | 16 ++++++++++++++++ .../Common/standalone/TLS/OnlyTBSS/Inputs/tls.c | 4 ++++ .../standalone/TLS/OnlyTBSS/OnlyTBSS.test | 14 ++++++++++++++ test/Hexagon/TLS/headers/headers.test | 2 -- test/Hexagon/linux/TLS/headers/headers.test | 2 -- 9 files changed, 65 insertions(+), 20 deletions(-) create mode 100644 test/Common/standalone/TLS/OnlyTBSS/Inputs/script.t create mode 100644 test/Common/standalone/TLS/OnlyTBSS/Inputs/scripttbssnewregion.t create mode 100644 test/Common/standalone/TLS/OnlyTBSS/Inputs/tls.c create mode 100644 test/Common/standalone/TLS/OnlyTBSS/OnlyTBSS.test diff --git a/lib/Target/CreateProgramHeaders.hpp b/lib/Target/CreateProgramHeaders.hpp index bdea0a907..7b0db5a77 100644 --- a/lib/Target/CreateProgramHeaders.hpp +++ b/lib/Target/CreateProgramHeaders.hpp @@ -369,15 +369,16 @@ bool GNULDBackend::createProgramHdrs() { if (config().options().isOMagic()) cur_flag = (cur_flag & ~llvm::ELF::PF_W); - // getSegmentFlag returns 0 if the section is not allocatable. - if ((cur_flag != prev_flag) && (isCurAlloc)) - createPT_LOAD = true; + if (!cur->isTBSS()) { + if ((cur_flag != prev_flag) && (isCurAlloc)) + createPT_LOAD = true; - if (linkerScriptHasMemoryCommand && (cur_mem_region != prev_mem_region)) - createPT_LOAD = true; + if (linkerScriptHasMemoryCommand && (cur_mem_region != prev_mem_region)) + createPT_LOAD = true; - if (linkerScriptHasMemoryCommand && (cur_mem_region != prev_mem_region)) - createPT_LOAD = true; + if (linkerScriptHasMemoryCommand && (cur_mem_region != prev_mem_region)) + createPT_LOAD = true; + } // If the current section is alloc section and if the previous section is // NOBITS and current is PROGBITS, we need to create a new segment. @@ -408,7 +409,7 @@ bool GNULDBackend::createProgramHdrs() { // If Program headers are not specified and the vma difference is big // lets create a PT_LOAD to adjust the offset. - if (std::abs(vmaoffset) > (int64_t)segAlign) + if ((std::abs(vmaoffset) > (int64_t)segAlign) && (!cur->isTBSS())) createPT_LOAD = true; } } diff --git a/test/AArch64/standalone/TLS_DESC/DESC.test b/test/AArch64/standalone/TLS_DESC/DESC.test index 6adac0826..aedd1977d 100644 --- a/test/AArch64/standalone/TLS_DESC/DESC.test +++ b/test/AArch64/standalone/TLS_DESC/DESC.test @@ -3,8 +3,8 @@ RUN: %link %linkopts -march aarch64 -static %t.o -z max-page-size=0x1000 -o %t. RUN: llvm-objdump -d %t.out | %filecheck %s #CHECK: {{.*}} <_test_tls_desc>: -#CHECK: {{.*}} adrp x0, 0x1000 -#CHECK: {{.*}} ldr x0, [x0] +#CHECK: {{.*}} adrp x0, 0x0 +#CHECK: {{.*}} ldr x0, [x0, #0x20] #CHECK: {{.*}} <_test_tls_desc_local>: -#CHECK: {{.*}} adrp x0, 0x1000 -#CHECK: {{.*}} ldr x0, [x0, #0x8] +#CHECK: {{.*}} adrp x0, 0x0 +#CHECK: {{.*}} ldr x0, [x0, #0x28] diff --git a/test/AArch64/standalone/TLS_IE/IE.test b/test/AArch64/standalone/TLS_IE/IE.test index e5b0050ef..64b7e3285 100644 --- a/test/AArch64/standalone/TLS_IE/IE.test +++ b/test/AArch64/standalone/TLS_IE/IE.test @@ -8,9 +8,9 @@ RUN: %clang %clangopts -target aarch64 %p/Inputs/f.c -c -o %t3.o RUN: %link %linkopts -static -march aarch64 %t2.o %t3.o -z max-page-size=0x1000 -o %t2.out CHECK: _test_tls_IE -CHECK: b0000000 adrp -CHECK: f9400000 ldr +CHECK: adrp x0, 0x0 +CHECK: ldr x0, [x0, #0x10] CHECK: _test_tls_IE_local -CHECK: d2a00000 movz -CHECK: f2800280 movk +CHECK: movz x0, #0x0 +CHECK: movk x0, #0x14 diff --git a/test/Common/standalone/TLS/OnlyTBSS/Inputs/script.t b/test/Common/standalone/TLS/OnlyTBSS/Inputs/script.t new file mode 100644 index 000000000..acd7b1c74 --- /dev/null +++ b/test/Common/standalone/TLS/OnlyTBSS/Inputs/script.t @@ -0,0 +1,14 @@ +MEMORY +{ + RAM (rw) : ORIGIN = 10000, LENGTH = 5000 +} + +SECTIONS { + .foo : { *(.text.foo) } > RAM + .empty : {} > RAM + tbss : { *(.tbss*) } > RAM + .empty : {} > RAM + .main : { *(.text.main) } > RAM + output_data : { BYTE(0x0) *(.data*) } > RAM + /DISCARD/ : { *(.riscv.attributes) } +} diff --git a/test/Common/standalone/TLS/OnlyTBSS/Inputs/scripttbssnewregion.t b/test/Common/standalone/TLS/OnlyTBSS/Inputs/scripttbssnewregion.t new file mode 100644 index 000000000..64b4d9472 --- /dev/null +++ b/test/Common/standalone/TLS/OnlyTBSS/Inputs/scripttbssnewregion.t @@ -0,0 +1,16 @@ +MEMORY +{ + RAM (rw) : ORIGIN = 10000, LENGTH = 5000 + ROM (rw) : ORIGIN = 20000, LENGTH = 5000 +} + +SECTIONS { + .foo : { *(.text.foo) } > RAM + .empty : {} > RAM + tdata : { *(.tdata*) } > ROM + tbss : { *(.tbss*) } > ROM + .empty : {} > ROM + .main : { *(.text.main) } > ROM + output_data : { BYTE(0x0) *(.data*) } > ROM + /DISCARD/ : { *(.riscv.attributes) } +} diff --git a/test/Common/standalone/TLS/OnlyTBSS/Inputs/tls.c b/test/Common/standalone/TLS/OnlyTBSS/Inputs/tls.c new file mode 100644 index 000000000..8f1ada3b4 --- /dev/null +++ b/test/Common/standalone/TLS/OnlyTBSS/Inputs/tls.c @@ -0,0 +1,4 @@ +__thread int b = 0; +int data = 100; +int foo() { return 0; } +int main() { return 0; } diff --git a/test/Common/standalone/TLS/OnlyTBSS/OnlyTBSS.test b/test/Common/standalone/TLS/OnlyTBSS/OnlyTBSS.test new file mode 100644 index 000000000..7c86e3d51 --- /dev/null +++ b/test/Common/standalone/TLS/OnlyTBSS/OnlyTBSS.test @@ -0,0 +1,14 @@ +UNSUPPORTED: ndk-build +#---OnlyTBSS.test--------------------------- Executable -----------------# +#BEGIN_COMMENT +# This tests that using TBSS only does not create an empty segment +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -c %p/Inputs/tls.c -o %t1.1.o -fdata-sections -ftls-model=local-exec -fPIE +RUN: %link %linkopts %t1.1.o -T %p/Inputs/script.t -o %t.out --defsym __aeabi_read_tp=0 +RUN: %readelf -l -W %t.out | %filecheck %s -check-prefix=EMPTYLOAD +RUN: %link %linkopts %t1.1.o -T %p/Inputs/scripttbssnewregion.t -o %t.out --defsym __aeabi_read_tp=0 +RUN: %readelf -l -W %t.out | %filecheck %s -check-prefix=EMPTYLOAD +#END_TEST + +#EMPTYLOAD-NOT: LOAD {{.*}} {{.*}} {{.*}} 0x{{[0]+}} 0x{{[0]+}} {{.*}} diff --git a/test/Hexagon/TLS/headers/headers.test b/test/Hexagon/TLS/headers/headers.test index 70168775b..55259ce95 100644 --- a/test/Hexagon/TLS/headers/headers.test +++ b/test/Hexagon/TLS/headers/headers.test @@ -29,12 +29,10 @@ RUN: %readelf -l -S -s -W %t6.out | %filecheck %s --check-prefix="TBSSDATA" #ALL: 00000008 4 TLS GLOBAL DEFAULT {{[0-9]}} b #TBSSTDATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00004 RW 0x1000 #TBSSTDATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00008 R 0x8 -#TBSS: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} R E 0x1000 #TBSS: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00000 0x00008 R 0x8 #TDATADATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00008 0x00008 RW 0x1000 #TDATADATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00008 R 0x8 #TDATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00004 RW 0x1000 #TDATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00008 R 0x8 -#TBSSDATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00004 RW 0x1000 #TBSSDATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00000 0x00008 R 0x8 diff --git a/test/Hexagon/linux/TLS/headers/headers.test b/test/Hexagon/linux/TLS/headers/headers.test index c329fa075..51fded6ff 100644 --- a/test/Hexagon/linux/TLS/headers/headers.test +++ b/test/Hexagon/linux/TLS/headers/headers.test @@ -33,12 +33,10 @@ RUN: %readelf -l -S -s -W %t6.out | %filecheck %s --check-prefix="TBSSDATA" #ALL: 00000008 4 TLS GLOBAL DEFAULT {{[0-9]}} b #TBSSTDATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00004 RW 0x10000 #TBSSTDATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00008 R 0x8 -#TBSS: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} R E 0x10000 #TBSS: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00000 0x00008 R 0x8 #TDATADATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00008 0x00008 RW 0x10000 #TDATADATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00008 R 0x8 #TDATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00004 RW 0x10000 #TDATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00008 R 0x8 -#TBSSDATA: LOAD {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00004 0x00004 RW 0x10000 #TBSSDATA: TLS {{[x0-9a-z]+}} {{[x0-9a-z]+}} {{[x0-9a-z]+}} 0x00000 0x00008 R 0x8