First working GNU Infinity note

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
      14: DW_OP_drop
      15: DW_OP_lit0   # NULL
      16: DW_OP_lit0   # TD_OK
      17: DW_OP_skip to end
      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
      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 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.