adsr / phpspy

low-overhead sampling profiler for PHP 7+
MIT License
1.42k stars 66 forks source link

Support ZTS PHP versions #133

Open senseicoder opened 1 year ago

senseicoder commented 1 year ago

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
adsr commented 1 year ago

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.

sj-i commented 1 year ago

I don't know if anyone finds this useful, but here are a few things I found out while making reli.

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.

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...

adsr commented 1 year ago

Valuable info. Thank you @sj-i !