phpspy
phpspy copied to clipboard
Support ZTS PHP versions
Hi,
We build our own PHP binaries for maintenance reason, and ZTS seems a good idea. Is ZTS support a possibility ? We just discovered phpspy thanks to Pyroscope, which need it, and we logically have this error
popen_read_line: No stdout; cmd=objdump -Tt /proc/22313/root//usr/sbin/php7.4-fpm | awk '/ executor_globals$/{print $1; exit}'
get_symbol_offset: Failed
which come from phpspy
cedric@prefnttstb1:~$ sudo ./phpspy --limit=1000 --pid=22312
popen_read_line: No stdout; cmd=objdump -Tt '/proc/22312/root//usr/sbin/php7.4-fpm' | awk '/ executor_globals$/{print $1; exit}'
get_symbol_offset: Failed
Yes it is possible. If anyone wants to take a shot at this, a similar project https://github.com/reliforp/reli-prof supports ZTS. A good starting point is here.
I don't know if anyone finds this useful, but here are a few things I found out while making reli.
- In ZTS we need to resolve symbols in the TLS block to resolve the address of the EG
- You can use libthread_db.so to resolve symbols in the TLS block
- libthread_db.so is a special shared object for debugging programmes using libpthreads
- The following article will give you some hints on how to use libthread_db.so
- https://web.archive.org/web/20220414201926/http://timetobleed.com/notes-about-an-odd-esoteric-yet-incredibly-useful-library-libthread_db/
Maybe libthread_db.so can be used directly when supporting ZTS in phpspy, because it's written in C.
FYI, reli does not use libthread_db.so to resolve symbols in the TLS block. In order to use libthread_db.so, some symbols had to be exported from the tracer side, which was a rather cumbersome task to achieve with reli which uses PHP and FFI. For this reason, reli gave up on a more civilised implementation: it reads the value of the segment register via ptrace to get the thread pointer, reads the symbols for use by libthread_db.so directly from libpthread.so or libc.so, then calculates the base address of the TLS block by itself, and adding it to the resolved TLS symbol address in the PHP binary.
The following links helped me a lot.
- https://www.akkadia.org/drepper/tls.pdf
- https://chao-tic.github.io/blog/2018/12/25/tls
- https://android.googlesource.com/platform/bionic/+/HEAD/docs/elf-tls.md
- https://reviews.llvm.org/D1944
My solution is probably glibc-specific and fragile, but I think it's better than nothing.
If you can get the pid of the target thread, reli can find the address of the EG from the ZTS interpreter and phpspy can specify the address of the EG via a command line option, so maybe we can use them in combination if we wrap them in some scripts.
Reli's ELF parsing code does not yet have file caches of parsed binaries, has not yet been optimised, so the CPU load can be unacceptable depending on usage, though.
If I could get more time, I could improve performance of reli and enhance integration with phpspy. But I do not have much hope in the immediate future...
Valuable info. Thank you @sj-i !