[lld] [lldb] [llvm] [AArch64] Support TLS variables in debug info (PR #146572)

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 9 18:37:20 PDT 2026


================
@@ -274,9 +274,17 @@ void DwarfCompileUnit::addLocationAttribute(
     if (!Global && (!Expr || !Expr->isConstant()))
       continue;
 
-    if (Global && Global->isThreadLocal() &&
-        !Asm->getObjFileLowering().supportDebugThreadLocalLocation())
-      continue;
+    if (Global && Global->isThreadLocal()) {
+      // Do not emit TLS location for preemptible TLS variables
+      // (e.g. TLS in shared libraries). The TLS offset cannot be
+      // represented safely in DWARF. In that case let Debugger use
+      // Runtime TLS lookup via DTV (Dynmic thread vector).
+      if (Asm->TM.getTargetTriple().isAArch64() && !Global->isDSOLocal())
----------------
igorkudrin wrote:

The changes here break thread-local variables for the platforms that already support them, like X86. Even if `lldb` or `gdb` cannot find the correct location when a variable in DSO is overridden by a variable with the same name in the application, this should not be the concern of the compiler and should be addressed in the debugger.

```
> cat app.cpp
thread_local int tl_foo = 1;
int get_tl_foo();
int main(int argc, char **argv) {
  int tl_foo_from_dso = get_tl_foo();
  return 0;
}
> cat dso.cpp
thread_local int tl_foo = 99;
int get_tl_foo() { return tl_foo; }
> clang++ -c app.cpp -o app.o -g -fpic
> clang++ -c dso.cpp -o dso.o -g -fpic
> clang++ -shared dso.o -o dso.so
> clang++ app.o ./dso.so -o app.out
> lldb app.out
(lldb) br set -n main
(lldb) run
   3    int main(int argc, char **argv) {
-> 4      int tl_foo_from_dso = get_tl_foo();
   5      return 0;
(lldb) s
   1    thread_local int tl_foo = 99;
-> 2    int get_tl_foo() { return tl_foo; }
(lldb) var -g
(int) ::tl_foo = 99
(lldb) n
(lldb) s
   4      int tl_foo_from_dso = get_tl_foo();
-> 5      return 0;
(lldb) var -g
(int) tl_foo_from_dso = 1
(int) ::tl_foo = 1
```
Yes, when the execution is inside `get_tl_foo()`, the debugger incorrectly prints the variable that is not actually used; as far as I can see, `gdb` does the same, at least version 15.0. 

Now, if you compile the same test with the compiler built with this patch applied, `lldb` cannot find the thread local variables at all:
```
(lldb) var -g
(lldb) expr tl_foo
error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory
```

https://github.com/llvm/llvm-project/pull/146572


More information about the llvm-commits mailing list