On 09/13/2017 12:22 PM, Pedro Alves wrote: > On 09/07/2017 12:34 PM, Pedro Alves wrote: >> On 09/06/2017 10:03 PM, Zack Weinberg wrote: >> >>> So, changes to both gdb and libthread_db seem to be required here. I >>> do think that _in principle_ it ought to be possible to use >>> libthread_db to retrieve the address of thread-local data even if the >>> inferior is not linked with libpthread; glibc has quite a few >>> thread-specific variables (errno most prominent, of course, but also >>> h_errno, _res, etc), and so might any library which can be used from >>> both single- and multithreaded programs. >>> >>> This is really not code I feel comfortable hacking up, though, and >>> it's probably more of a project than I have time for, in any case. >> >> Sounds like a promising approach though. I'd like to see this path >> explored a bit more. I'll keep this in my TODO, even though it's >> not likely to bubble up very soon. Thanks for the discussion/ideas! > > So I played with this a bit more on the plane back from Cauldron, > to try to see if we'd hit some major roadblock. I also chatted > with Carlos a bit about this back at the Cauldron, and seemingly > there's no major reason this can't be made to work, > TLS-internals-wise. > > Seems like that it's mainly a case of moving libthread_db.so-related > symbols from libpthread.so elsewhere. More below. > > I hacked libthread_db.so to disable the nptl_version check, so that > it always successfully loads with non-threaded programs. And then > I tweaked GDB enough to make it actually reach libthread_db.so's > td_thr_tls_get_addr in that scenario too. That's when I hit > another snag: the symbols that libthread_db.so needs which describe > the necessary offsets of internal data structures for getting at the > TLS blocks are also in libpthread.so... In particular, the first > we stumble on is "_thread_db_link_map_l_tls_modid". I made GDB > print the symbol lookups to make it easier to debug. Vis: > > (gdb) p errno > ps_pglobal_lookup: name="__stack_user" => PS_NOSYM > warning: Cannot find user-level thread for LWP 31772: generic error > ps_pglobal_lookup: name="_thread_db_link_map_l_tls_modid" => PS_NOSYM > Cannot find thread-local storage for process 31772, shared library /lib64/libc.so.6: > operation not applicable to > > The lookup is coming from here: > > (top-gdb) bt > #0 ps_pglobal_lookup (ph=0x1f65fe0, obj=0x7fffe58f93ae "libpthread.so.0", name=0x7fffe58f9e48 "_thread_db_link_map_l_tls_modid", sym_addr=0x7fffffffc428) at src/gdb/proc-service.c:115 > #1 0x00007fffe58f88a8 in td_mod_lookup (ps=, mod=mod@entry=0x7fffe58f93ae "libpthread.so.0", idx=, sym_addr=sym_addr@entry=0x7fffffffc428) > at td_symbol_list.c:48 > #2 0x00007fffe58f8f45 in _td_locate_field (ta=ta@entry=0x1f84df0, desc=desc@entry=0x1f84fbc, descriptor_name=descriptor_name@entry=43, idx=idx@entry=0x0, > address=address@entry=0x7fffffffc458) at fetch-value.c:54 > #3 0x00007fffe58f8ff0 in _td_fetch_value (ta=0x1f84df0, desc=0x1f84fbc, descriptor_name=descriptor_name@entry=43, idx=idx@entry=0x0, address=0x7ffff7ff7658, > result=result@entry=0x7fffffffc498) at fetch-value.c:94 > #4 0x00007fffe58f8ddf in td_thr_tls_get_addr (th=0x7fffffffc4e0, map_address=, offset=16, address=0x7fffffffc4f8) at td_thr_tls_get_addr.c:31 > ... > > So we'd need to move that symbol (and maybe others) to one of ld.so/libc.so > instead. AFAICT, those magic symbols are described in nptl_db/structs.def. > I haven't looked enough to figure out what ends up expanding those macros > in libpthread.so. This is where I stopped. > > I'm attaching the gdb and libthread_db.so patches I used, both against current > master in their respective projects. See comments within the patches. > I've also pushed the gdb patch to a "users/palves/tls-nonthreaded" branch. > (I don't think I have write access to glibc's git.) I played some more with this tonight, and got it working. I found that libpthread.so gets the symbols from structs.def via this bit in pthread_create.c: ~~~ /* Information for libthread_db. */ #include "../nptl_db/db_info.c" ~~~ So I added the same thing to elf/dl-tls.c (because TLS stuff), with a tweak to structs.def to make it skip some symbols. Compared to the other version, I also defined nptl_version so that libthread_db.so's version check works. And I made td_ta_map_lwp2thr return the initial thread's fake descriptor when __stack_used isn't found, so that gdb gets back a descriptor instead of an error. I haven't tried running glibc's testsuite, nor gdb's. But, with: GLIBC=/home/pedro/src/glibc/build/ gcc \ -Wl,-rpath=${GLIBC}:${GLIBC}/math:${GLIBC}/elf:${GLIBC}/dlfcn:${GLIBC}/nss:${GLIBC}/nis:${GLIBC}/rt:${GLIBC}/resolv:${GLIBC}/crypt:${GLIBC}/nptl:${GLIBC}/dfp \ -Wl,--dynamic-linker=${GLIBC}/elf/ld.so \ -g -O0 \ errno.c -o errno $ gdb -ex "set debug libthread-db 1" \ -ex "set auto-load safe-path /home/pedro/src/glibc/build/nptl_db/" \ -ex "set libthread-db-search-path /home/pedro/src/glibc/build/nptl_db/" \ ~/tmp/errno I get: ... Temporary breakpoint 1, main () at errno.c:6 6 errno = 2; (gdb) p errno $1 = 0 (gdb) n 7 return errno; (gdb) p errno $2 = 2 (gdb) p &errno $3 = (int *) 0x7ffff7ff36c0 So WDYT? Do you think there's a chance we could get something like this merged? Thanks, Pedro Alves