using external TLS variables with ATfE-22.1.0-Linux-x86_64 compiler fails with a link error #3112

Closed
opened 2026-08-05 11:38:14 -05:00 by peterharperuk · 4 comments
peterharperuk commented 2026-08-05 11:38:14 -05:00 (Migrated from github.com)

I got the compiler ATfE-22.1.0-Linux-x86_64 from here https://github.com/arm/arm-toolchain/releases (also tried ATfE-21.1.1-Linux-x86_64)
It is based on llvm and uses picoclib.
I have a very simple program that uses errno and when I build it I get a link error.

cd pico-sdk
mkdir build
cd build
cmake .. -DPICO_TOOLCHAIN_PATH=/opt/compilers/arm/llvm/ATfE-22.1.0-Linux-x86_64
cd test/pico_clib_interface
make
<blah>
[100%] Linking CXX executable tls_repro.elf
ld.lld: error: /home/peterh/source/pico-sdk1/src/rp2_common/pico_standard_link/script_include/section_default_data.incl:71: unable to move location counter (0x20000318) backward to 0x20000314 for section '.tbss_space'
ld.lld: error: section .tbss_space at 0x20000318 of size 0xfffffffffffffffc exceeds available address space
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [test/pico_clib_interface/CMakeFiles/tls_repro.dir/build.make:1092: test/pico_clib_interface/tls_repro.elf] Error 1
make[1]: *** [CMakeFiles/Makefile2:5139: test/pico_clib_interface/CMakeFiles/tls_repro.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

It seems related to the .tbss_space section. The spacer's arithmetic assumes nothing is allocated between bss_start and the spacer itself, and an unplaced .got breaks that assumption on lld. (Thank claude for that)

Anyway - the fix suggested is to add the following into pico_arm_clang_common.cmake - it's what picolibc.specs does evidently.

foreach(LANG IN ITEMS C CXX)
    set(CMAKE_${LANG}_FLAGS_INIT "${CMAKE_${LANG}_FLAGS_INIT} -ftls-model=local-exec")
endforeach()

Claude seems to think this is related to the following issue - but it's a bit over my head: https://github.com/raspberrypi/pico-sdk/issues/3064

I've pushed the test to a branch. The above fix is currently commented out but it does seem to resolve the problem.

I got the compiler ATfE-22.1.0-Linux-x86_64 from here https://github.com/arm/arm-toolchain/releases (also tried ATfE-21.1.1-Linux-x86_64) It is based on llvm and uses picoclib. I have a very simple program that uses errno and when I build it I get a link error. ``` cd pico-sdk mkdir build cd build cmake .. -DPICO_TOOLCHAIN_PATH=/opt/compilers/arm/llvm/ATfE-22.1.0-Linux-x86_64 cd test/pico_clib_interface make <blah> [100%] Linking CXX executable tls_repro.elf ld.lld: error: /home/peterh/source/pico-sdk1/src/rp2_common/pico_standard_link/script_include/section_default_data.incl:71: unable to move location counter (0x20000318) backward to 0x20000314 for section '.tbss_space' ld.lld: error: section .tbss_space at 0x20000318 of size 0xfffffffffffffffc exceeds available address space clang++: error: linker command failed with exit code 1 (use -v to see invocation) make[2]: *** [test/pico_clib_interface/CMakeFiles/tls_repro.dir/build.make:1092: test/pico_clib_interface/tls_repro.elf] Error 1 make[1]: *** [CMakeFiles/Makefile2:5139: test/pico_clib_interface/CMakeFiles/tls_repro.dir/all] Error 2 make: *** [Makefile:91: all] Error 2 ``` It seems related to the .tbss_space section. The spacer's arithmetic assumes nothing is allocated between __bss_start__ and the spacer itself, and an unplaced .got breaks that assumption on lld. (Thank claude for that) Anyway - the fix suggested is to add the following into pico_arm_clang_common.cmake - it's what picolibc.specs does evidently. ``` foreach(LANG IN ITEMS C CXX) set(CMAKE_${LANG}_FLAGS_INIT "${CMAKE_${LANG}_FLAGS_INIT} -ftls-model=local-exec") endforeach() ``` Claude seems to think this is related to the following issue - but it's a bit over my head: https://github.com/raspberrypi/pico-sdk/issues/3064 I've pushed the test to a branch. The above fix is currently commented out but it does seem to resolve the problem.
Wren6991 commented 2026-08-11 04:34:54 -05:00 (Migrated from github.com)

Was able to reproduce this using your SDK branch and:

cmake -DPICO_TOOLCHAIN_PATH=/opt/arm/ATfE-22.1.0-Linux-x86_64/bin -DPICO_COMPILER=pico_arm_cortex_m33_clang -DPICO_PLATFORM=rp2350-arm-s ..
make -j16 tls_repro

and yes, seems like the location counter has been bumped by four bytes already, so this line tries to move it backward:

    /* workaround RISC-V GNU linker bug with spacer section (otherwise it places .bss over .tbss) */
    .tbss_space (NOLOAD) : {
        . = __bss_start__ + SIZEOF(.tbss);
    } > RAM

I find the location counter semantics slightly mysterious here, but this is fixed by placing the GOT section, as per #3065:

diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl
index d05ee974..6079b5fd 100644
--- a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl
+++ b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl
@@ -39,6 +39,8 @@ SECTIONS
         KEEP(*(.mutex_array))
         PROVIDE_HIDDEN (__mutex_array_end = .);
 
+        *(.got)
+        *(.got.*)
         *(.jcr)
         . = ALIGN(4);
     } > RAM AT> RAM_STORE

I had to look up that flag you mentioned: https://support.arm.com/documentation/107976/21-1-1/Clang-reference/clang-command-line-options/-ftls-model

It sounds like maybe we should be using local-exec anyway, but here it would be a symptomatic fix.

Was able to reproduce this using your SDK branch and: ``` cmake -DPICO_TOOLCHAIN_PATH=/opt/arm/ATfE-22.1.0-Linux-x86_64/bin -DPICO_COMPILER=pico_arm_cortex_m33_clang -DPICO_PLATFORM=rp2350-arm-s .. make -j16 tls_repro ``` and yes, seems like the location counter has been bumped by four bytes already, so this line tries to move it backward: ``` /* workaround RISC-V GNU linker bug with spacer section (otherwise it places .bss over .tbss) */ .tbss_space (NOLOAD) : { . = __bss_start__ + SIZEOF(.tbss); } > RAM ``` I find the location counter semantics slightly mysterious here, but this is fixed by placing the GOT section, as per #3065: ```patch diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl index d05ee974..6079b5fd 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl @@ -39,6 +39,8 @@ SECTIONS KEEP(*(.mutex_array)) PROVIDE_HIDDEN (__mutex_array_end = .); + *(.got) + *(.got.*) *(.jcr) . = ALIGN(4); } > RAM AT> RAM_STORE ``` I had to look up that flag you mentioned: https://support.arm.com/documentation/107976/21-1-1/Clang-reference/clang-command-line-options/-ftls-model It sounds like maybe we should be using `local-exec` anyway, but here it would be a symptomatic fix.
kilograham commented 2026-08-12 19:37:31 -05:00 (Migrated from github.com)

note whilst #3064 fixes this issue (likely) we should be adding local-exec anyway so leaving this open

note whilst #3064 fixes this issue (likely) we should be adding local-exec anyway so leaving this open
Wren6991 commented 2026-08-19 03:04:51 -05:00 (Migrated from github.com)

whilst https://github.com/raspberrypi/pico-sdk/issues/3064 fixes this issue (likely)

It does, I checked. But yeah we should be using tp-relative access for all thread-local storage. I can't think of a reason why not.

> whilst https://github.com/raspberrypi/pico-sdk/issues/3064 fixes this issue (likely) It does, I checked. But yeah we should be using tp-relative access for all thread-local storage. I can't think of a reason why not.
kilograham commented 2026-08-21 16:05:45 -05:00 (Migrated from github.com)

-ftls-model=local-exec now added too

-ftls-model=local-exec now added too
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk#3112
No description provided.