如何在 lldb 中的实时 运行 脚本上转储 PHP 回溯?
How to dump PHP backtrace on live running script in lldb?
我正在玩 LLDB (debugger) 并做了以下实验。
运行 PHP 脚本为:
php -r "sleep(1000);"
或:
php -r "function r(){sleep(1000);}r();"
在另一个控制台上,我直接从 lldb
:
调用 zif_debug_backtrace()
echo 'call (void)zif_debug_backtrace()' | lldb -p $(pgrep -fn php)
以上工作正常,但是进程停止并出现以下警告:
Warning: sleep() expects at most 2 parameters, 1606408648 given in Command line code on line 1
Call Stack:
0.0016 235152 1. {main}() Command line code:0
0.0021 235248 2. sleep(1000) Command line code:1
我不太清楚为什么脚本必须停止以及我需要做什么才能实现透明度(不影响脚本)?
P.S。调用 zif_debug_print_backtrace()
和调用 custom_backtrace()
时发生同样的情况,它显示:Backtrace null function called
。如果有任何改变,我正在使用 xdebug
。
也许我需要调用一个不同的函数,比如 zend_fetch_debug_backtrace
(参见:image dump symtab
)?或者使用正确的论点,如果是,是哪一个?
我只对 lldb
/gdb
解决方案感兴趣,以便打印回溯。
类似的方法适用于 Ruby,例如:
- 运行:
ruby -e 'sleep 1000'
.
- 在另一个终端:
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)
.
我试了一下,发现它是如何工作的:
echo 'call (void)zif_debug_print_backtrace(0)' | lldb -p $(pgrep -fn php)
对于上面的示例,这不会打印任何内容,因为没有回溯。但是当你 运行 这样的脚本时:
php -r "function r(){sleep(1000);}r();"
然后lldb命令会导致PHP进程输出:
#0 r() called at [Command line code:1]
瞧。不幸的是,这也会使脚本崩溃。
它确实适用于 gdb
,但:
echo 'call zif_debug_print_backtrace(0,0,0,0,0)' | gdb -p $(pgrep -fn php)
当分离脚本时继续 运行。 (使用 PHP 5.6.14 (DEBUG) 在 Debian 上测试)
你不能那样调用内部函数,内部函数需要像框架、return 值等等...不要这样做。
有一个 .gdbinit distributed with php, in it there is a function named zbacktrace,您可以将其移植到 lldb。
您可以做的另一件事可能更简单,就是调用生成跟踪的 API 函数,但要正确调用它。
这是 GDB (PHP7):
define ztrace
set $var = malloc(sizeof(zval))
call zend_fetch_debug_backtrace($var, 0, 0, 0)
call php_var_dump($var, 0)
call _zval_ptr_dtor($var, 0, 0)
call free($var)
end
document ztrace
show a debug backtrace
end
对于 LLDB (PHP7):
(lldb) expr zval $var;
(lldb) expr zend_fetch_debug_backtrace(&$var, 0, 0, 0)
(lldb) expr php_var_dump(&$var, 0)
(lldb) expr _zval_ptr_dtor(&$var, 0, 0)
既然你问了,LLDB for PHP5.6 (no-zts):
(lldb) expr zval *$zp = (zval*) malloc(sizeof(zval))
(lldb) expr zend_fetch_debug_backtrace($zp, 0, 0, 0)
(lldb) expr php_var_dump(&$zp, 0)
(lldb) expr _zval_ptr_dtor(&$zp, 0, 0)
(lldb) expr free($zp)
我正在玩 LLDB (debugger) 并做了以下实验。
运行 PHP 脚本为:
php -r "sleep(1000);"
或:
php -r "function r(){sleep(1000);}r();"
在另一个控制台上,我直接从
调用lldb
:zif_debug_backtrace()
echo 'call (void)zif_debug_backtrace()' | lldb -p $(pgrep -fn php)
以上工作正常,但是进程停止并出现以下警告:
Warning: sleep() expects at most 2 parameters, 1606408648 given in Command line code on line 1
Call Stack:
0.0016 235152 1. {main}() Command line code:0
0.0021 235248 2. sleep(1000) Command line code:1
我不太清楚为什么脚本必须停止以及我需要做什么才能实现透明度(不影响脚本)?
P.S。调用 zif_debug_print_backtrace()
和调用 custom_backtrace()
时发生同样的情况,它显示:Backtrace null function called
。如果有任何改变,我正在使用 xdebug
。
也许我需要调用一个不同的函数,比如 zend_fetch_debug_backtrace
(参见:image dump symtab
)?或者使用正确的论点,如果是,是哪一个?
我只对 lldb
/gdb
解决方案感兴趣,以便打印回溯。
类似的方法适用于 Ruby,例如:
- 运行:
ruby -e 'sleep 1000'
. - 在另一个终端:
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)
.
我试了一下,发现它是如何工作的:
echo 'call (void)zif_debug_print_backtrace(0)' | lldb -p $(pgrep -fn php)
对于上面的示例,这不会打印任何内容,因为没有回溯。但是当你 运行 这样的脚本时:
php -r "function r(){sleep(1000);}r();"
然后lldb命令会导致PHP进程输出:
#0 r() called at [Command line code:1]
瞧。不幸的是,这也会使脚本崩溃。
它确实适用于 gdb
,但:
echo 'call zif_debug_print_backtrace(0,0,0,0,0)' | gdb -p $(pgrep -fn php)
当分离脚本时继续 运行。 (使用 PHP 5.6.14 (DEBUG) 在 Debian 上测试)
你不能那样调用内部函数,内部函数需要像框架、return 值等等...不要这样做。
有一个 .gdbinit distributed with php, in it there is a function named zbacktrace,您可以将其移植到 lldb。
您可以做的另一件事可能更简单,就是调用生成跟踪的 API 函数,但要正确调用它。
这是 GDB (PHP7):
define ztrace
set $var = malloc(sizeof(zval))
call zend_fetch_debug_backtrace($var, 0, 0, 0)
call php_var_dump($var, 0)
call _zval_ptr_dtor($var, 0, 0)
call free($var)
end
document ztrace
show a debug backtrace
end
对于 LLDB (PHP7):
(lldb) expr zval $var;
(lldb) expr zend_fetch_debug_backtrace(&$var, 0, 0, 0)
(lldb) expr php_var_dump(&$var, 0)
(lldb) expr _zval_ptr_dtor(&$var, 0, 0)
既然你问了,LLDB for PHP5.6 (no-zts):
(lldb) expr zval *$zp = (zval*) malloc(sizeof(zval))
(lldb) expr zend_fetch_debug_backtrace($zp, 0, 0, 0)
(lldb) expr php_var_dump(&$zp, 0)
(lldb) expr _zval_ptr_dtor(&$zp, 0, 0)
(lldb) expr free($zp)