How to get pthread pointer from lldb?

One of our customer wanted to implement a custom Python script for async coroutine stack trace.

In this async corotine implementation, the async stack root is stored as TLS slot (my understanding).
They have corresponding async stack scripts working in GDB which logically gets struct pthread * pointer from the thread then index into specific field of struct pthread to get async stack root value for decoding.

In GDB, the pthread pointer seems to be shown in “info thread” while lldb “thread list” does not:

(gdb) info threads
  Id   Target Id                                           Frame
* 1    Thread 0x7fc09f945d00 (LWP 101822) "main"           syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
  2    Thread 0x7fc099200640 (LWP 129015) "main"           syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
  3    Thread 0x7fc098800640 (LWP 129016) "main"           syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
  4    Thread 0x7fc096600640 (LWP 129018) "CPUThreadPool0" syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38

Is pthread pointer exposed by lldb anywhere (or public API)?

Without pthread pointer, the closest I can find is Thread::GetThreadLocalData()/DynamicLoaderPOSIXDYLD::GetThreadLocalData() API. But I tried to use it from all modules in a test application, it always returns LLDB_INVALID_ADDRESS because link_map field from m_loaded_modules is LLDB_INVALID_ADDRESS. Not sure if this is expected.

cc @labath , @clayborg

1 Like

After a big digging, I found DynamicLoaderPOSIXDYLD::GetThreadLocalData() seems to never work on Linux. lldb/test/API/lang/c/tls_globals/ fails on Linux. thread_local or __thread variables can’t be examined on Linux. (It is interesting that GDB11 also fails).

This thread (Access to TLS variables on GNU/Linux - #2 by Jan_Kratochvil) seems to imply the the TLS support is only available in FreeBSD (but I can’t find FreeBSDThread::GetThreadPointer() or any concrete platform implementation of it).

It seems $fs_base virtual register is available both from linux Posix and coredump but lldb ignores it for whatever reason. I did a quick prototype by adding fs_base into GPR register list and it seems to work (both from live and coredump debugging). I assume that’s how GDB reports the pthread * pointer in info threads list.