This is the DWARF for the first successfully-executed GNU Infinity note, as described here. It’s a reimplementation of the libthread_db function td_ta_map_lwp2thr
.
# Input stack: # 0: lwpid # 1: pid # 2: __stack_user 0: DW_OP_pick 2 2: DW_OP_deref 3: DW_OP_bra libpthread_is_initialized 6: DW_OP_eq 7: DW_OP_bra is_main_thread 10: DW_OP_lit1 # TD_ERR 11: DW_OP_skip to end is_main_thread: 14: DW_OP_drop 15: DW_OP_lit0 # NULL 16: DW_OP_lit0 # TD_OK 17: DW_OP_skip to end libpthread_is_initialized: 20: DW_OP_lit25 # FS 21: DW_OP_GNU_get_thread_area 22: DW_OP_bra get_thread_area_failed 25: DW_OP_rot 26: DW_OP_drop 27: DW_OP_drop 28: DW_OP_lit0 # TD_OK 29: DW_OP_skip to end get_thread_area_failed: 32: DW_OP_drop 33: DW_OP_drop 34: DW_OP_lit1 # TD_ERR # Output stack: # 0: TD_OK or TD_ERR # 1: if TD_OK: handle used to identify thread # else: undefined
This is valid for all CONST_THREAD_AREA
architectures, i.e. arm, aarch64, mips, microblaze, m68k and x86_64. REGISTER
and REGISTER_THREAD_AREA
architectures will differ following libpthread_is_initialized
. x86_64 could theoretically have its own implementation using DW_OP_bregx 0(%fs.base)
but GDB doesn’t know about %fs.base
right now so that’s an optimization for the future.
The __stack_user
on the stack is an automatic argument. Function notes have a list of automatic arguments that are pushed to the stack, currently before the user pushes their arguments but I may rearrange that so that automatic arguments come after. The caller just pushes PID and LWPID and calls the function.
Infinity functions are going to have to be able to call other functions if I’m going to replace td_ta_thr_iter
–which I am. Once that’s in the DW_OP_GNU_get_thread_area
extension will be replaced by some “call Infinity function” extension, with ps_get_thread_area
being a special function provided by the infrastructure. That’s probably the only DWARF extension Infinity will need. I’ll likely replace the PID argument here with a second special function ps_getpid
too. The PID argument works quite naturally here, but it’s required in other places where it’s not so natural.
I don’t have a compiler/assembler for this yet. I got the above code into libpthread.so by embedding a bunch of assembler in one of the C source files. I will write something to generate functions more conveniently and once this done only the INFINITY_EXPORT
lines will exist in glibc’s C sources.