A sampling profiler or a memory profiler for PHP written in PHP, which reads information about running PHP VM from outside the process. You can find performance bottlenecks or memory leaks of your scripts without changing the target script or loading extensions.
_tsrm_ls_cache is not an exported symbol in the interpreter, so we usually cannot resolve it from the stripped PHP binary, and therefore cannot find globals like EG or CG.
But I recently noticed that the PHP binary has only small size of the PT_TLS segment as a whole, like 0x13c bytes.
This means that we can search the offset of the actual _tsrm_ls_cache without resolving the symbol by brute forcing the PT_TLS segment. By examining each candidate of the offset by actually trying to resolve EG and see the value of uninitialized_zval and error_zval, and also trying to resolve a global constant like PHP_VERSION, we can assume the candidate is really the offset of _tsrm_ls_cache.
The offset is fixed on each PHP binary, so once we cache the offset on a file, we don't have to do the process multiple times on the same binary.
_tsrm_ls_cache
is not an exported symbol in the interpreter, so we usually cannot resolve it from the stripped PHP binary, and therefore cannot find globals like EG or CG.But I recently noticed that the PHP binary has only small size of the PT_TLS segment as a whole, like 0x13c bytes.
This means that we can search the offset of the actual
_tsrm_ls_cache
without resolving the symbol by brute forcing the PT_TLS segment. By examining each candidate of the offset by actually trying to resolve EG and see the value ofuninitialized_zval
anderror_zval
, and also trying to resolve a global constant likePHP_VERSION
, we can assume the candidate is really the offset of_tsrm_ls_cache
.The offset is fixed on each PHP binary, so once we cache the offset on a file, we don't have to do the process multiple times on the same binary.