使用xhprof测试slim框架的性能时,发现php抛了Segment Fault错误,试着使用gdb查看是什么导致的。
生成coredump文件
要生成php的coredump文件需要对系统进行一些配置,具体查看:Generating core-dump for php5-fpm
使用gdb调试coredump文件
执行gdb命令,因为coredump是php-fpm进程生成的,还需要指定php-fpm的路径,要不查看不了具体的代码执行信息。
$ gdb /usr/local/php5/sbin/php-fpm -c /tmp/core-php-fpm.1567
gdb调试命令
bt
bt命令打印程序执行的堆栈信息
(gdb) bt
#0 _phpi_pop (ht=<value optimized out>, return_value=0x7faf756ace10, return_value_ptr=0x0, this_ptr=<value optimized out>,
return_value_used=<value optimized out>, off_the_end=0) at /home/apps/php-5.6.10/ext/standard/array.c:1879
#1 0x00007faf7d8f3317 in hp_execute_internal (execute_data=0x7faf8991db40, fci=0x0, ret=1) at /home/apps/xhprof-master/extension/xhprof.c:1730
#2 0x0000000000888cc5 in zend_do_fcall_common_helper_SPEC (execute_data=<value optimized out>) at /home/apps/php-5.6.10/Zend/zend_vm_execute.h:560
#3 0x00000000008787d0 in execute_ex (execute_data=0x7faf8991db40) at /home/apps/php-5.6.10/Zend/zend_vm_execute.h:363
#4 0x00007faf7d8f2ca9 in hp_execute_ex (execute_data=0x7faf8991db40) at /home/apps/xhprof-master/extension/xhprof.c:1675
p
p命令用于打印变量信息
(gdb) p *executor_globals->argument_stack
$2 = {top = 0x7faf8991dc38, end = 0x7faf8993d848, prev = 0x0}
f
切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈
# 切换到1层级的栈
(gdb) f 1
#1 0x00007f701d60c317 in hp_execute_internal (execute_data=0x7f702940a858, fci=0x0, ret=1) at /home/apps/xhprof-master/extension/xhprof.c:1730
1730 ((zend_internal_function *) execute_data->function_state.function)->handler(
# 查看当前栈信息
(gdb) info f
Stack level 1, frame at 0x7fff515e2090:
rip = 0x7f701d60c317 in hp_execute_internal (/home/apps/xhprof-master/extension/xhprof.c:1730); saved rip 0x888a15
called by frame at 0x7fff515e2150, caller of frame at 0x7fff515e2040
source language c.
Arglist at 0x7fff515e2038, args: execute_data=0x7f702940a858, fci=0x0, ret=1
Locals at 0x7fff515e2038, Previous frame's sp is 0x7fff515e2090
Saved registers:
rbx at 0x7fff515e2058, rbp at 0x7fff515e2060, r12 at 0x7fff515e2068, r13 at 0x7fff515e2070, r14 at 0x7fff515e2078, r15 at 0x7fff515e2080,
rip at 0x7fff515e2088
info
查看信息
# 打印局部变量信息
info locals
# 打印全局和局部变量信息
info variables
# 打印参数信息
info args
# 打印当前堆栈信息
info f
php脚本调试命令
使用php脚本调试命令,需要引入php源码中的脚本文件.gdbinit。
(gdb) source /home/apps/php-5.6.10/.gdbinit
zbacktrace
zbacktrace可以打印php的堆栈信息,不同于bt只打印c的堆栈信息。
(gdb) zbacktrace
[0x7faf8991db40] array_shift(array(2)[0x7faf756acc88]) /var/www/html/php-framework-benchmark/slim-2.6/vendor/slim/slim/Slim/Slim.php:441
[0x7faf8991da18] Slim\Slim->mapRoute(array(2)[0x7faf897a0590]) /var/www/html/php-framework-benchmark/slim-2.6/vendor/slim/slim/Slim/Slim.php:473
[0x7faf8991d910] Slim\Slim->get("/hello/index", object[0x7faf897a0510]) /var/www/html/php-framework-benchmark/slim-2.6/index.php:18
print_cvs
print_cvs打印当前执行命令下的所有php变量
printzv
打印zval变量信息,可指定zval的指针地址,如zbacktrace返回的函数参数地址
(gdb) printzv 0x7faf756acc88
[0x7faf756acc88] (refcount=2,is_ref) array(2): {
0 => [0x7faf8979ee40] (refcount=4) string(12): "/hello/index"
1 => [0x7faf897a0510] (refcount=3) objectYou can't do that without a process to debug.
print_ht
print_ht是用打印zval变量信息
print_htptr
print_htptr是用打印zval指针指向的变量信息
print_htstr
print_htstr用于打印string构成的Hashtable变量信息
print_ft
print_ft用于打印function table (HashTable)
zmemcheck
zmemcheck用于显示当前的内在分配状态信息
php全局对象executor_globals
php源码用有个用EG宏表示的全局对象executor_globals,它包含了php所有相关的执行信息,如当前执行的op_array,传递参数和函数名等信息。源码中的EG(v)实际是调用executor_globals->v。executor_globals包含的变量有很多,可以用命令:
p executor_globals
打印出来查看。
下面是比较重要的几个变量:
argument_stack : 传递给当前调用函数的参数堆栈,可以查看参数信息
current_execute_data : 当前执行的命令信息,如当前执行函数信息,op_array,op_code等
prev_execute_data :前一执行命令信息,相当于调用函数的上级函数
active_op_array : 当前正在执行的op_array
exception : 当前包含的异常信息
查看示例:
## 查看当前执行命令信息
(gdb) p *executor_globals->current_execute_data
$8 = {opline = 0x7faf76376fd0, function_state = {function = 0x1123720, arguments = 0x7faf8991dc30}, op_array = 0x7faf897bf9f8, object = 0x0,
symbol_table = 0x0, prev_execute_data = 0x7faf8991da18, old_error_reporting = 0x0, nested = 0 '\000', original_return_value = 0x0,
current_scope = 0x7faf8991da28, current_called_scope = 0x0, current_this = 0x0, fast_ret = 0x0, delayed_exception = 0x0,
call_slots = 0x7faf8991dc08, call = 0x7faf8991dc08}
## 查看前一执行命令信息,相当于上级调用函数
(gdb) p *executor_globals->current_execute_data->prev_execute_data
$19 = {opline = 0x7faf763781e8, function_state = {function = 0x7faf897bf9f8, arguments = 0x7faf8991dad8}, op_array = 0x7faf897bf020,
object = 0x7faf8978adf0, symbol_table = 0x0, prev_execute_data = 0x7faf8991d910, old_error_reporting = 0x0, nested = 0 '\000',
original_return_value = 0x0, current_scope = 0x7faf897c2d48, current_called_scope = 0x7faf897c2d48, current_this = 0x7faf8978adf0,
fast_ret = 0x7faf897c2d48, delayed_exception = 0x0, call_slots = 0x7faf8991dab0, call = 0x7faf8991dab0}