php扩展开发之GDB调试
俗话说的好"磨刀不误砍柴工",我们在开发扩展的时候,会像写C语言代码一样,经常会遇到程序core掉了.然而PHP脚本中常用的调试方式"echo,print_r,var_dump"却不能给我们什么大的帮助.今天我们就看看如何利用GDB来调试我们的php扩展程序?
为了方便我们使用gdb调试,最好在编译php程序的时候,把configure工具的”–enable-debug”参数启用,默认它是禁用的,因为它会产生很多方便我们调试的信息(注意在生产环境不要启用它,它会降低一部分php的性能).今天会主要说一下利用gdb进行断点调试,利用core文件调试已经不少的教程,所以我就不想再多做这些重复工作了.
前面的文章大家都看到如果声明一个php扩展函数,例如PHP_FUNCTION(count),这里如果我们直接利用cout函数来做断点,可能我们捕捉不到(这里我用了count做例子,但大家不要自己扩展里面这么做,因为count已经是php内建的扩展函数了,这样会引起不必要的问题).因为zend为了避免我们写的函数和C系统函数或这其他类库重名所以这里使用了PHP_FUNCTION宏进行声明,那么这个宏是什么样子哪?
#define PHP_FUNCTION ZEND_FUNCTION #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION( ZEND_FN(name) ) #define ZEND_FN(name) zif_##name #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)
上面我们提到的提到的”PHP_FUNCTION(count)“最终的展开结果是”void zif_count(int ht, zval *return_value, zval **return_value_ptr,zval *this_ptr, int return_value_used TSRMLS_DC)“,因此如果我们直接断点count可能就不会有结果的,这里我们需要用zif_count来断点就会捕捉到了.
如果我们使用的是一个第三方的扩展,我们不是很清楚里面有那些函数,或者修改过函数的前缀,已经不再是”zif”了.那么我们怎么获得我们需要的函数信息那?
我们可以使用nm工具来查看动态链接库里面的函数信息,就那我们上一篇那个交换2个数字的函数扩展为例子,看看如果使用nm吧.
nm king.so //下面信息为nm摘取的部分信息 0000000000000e80 T zif_confirm_king_compiled 0000000000000f10 T zif_king_author 0000000000000fd0 T zif_king_call_system_func 0000000000000f30 T zif_king_exchange_number 0000000000000e60 T zm_activate_king 0000000000000e70 T zm_deactivate_king 0000000000001190 T zm_info_king 0000000000000e50 T zm_shutdown_king 0000000000000e40 T zm_startup_king
具体的信息如下图:
看一下我们的扩展是否加入到php解释器中去那
php -m|grep king //king
如果看到了”king”说明我们的扩展已经ok了,现在就做开始做gdb调试吧
cd /home/king/web_project/test/ext_king gdb php b zif_king_exchange_number //Make breakpoint pending on future shared library load? (y or [n]) //这里用于这动态链接中,所以在我们php中是找不到这符号的,所以点y即可 //运行我们的php测试脚本 run ./exchange.php //后面就是正常的gdb调试了
如此我们就可以清楚看到程序是怎么执行,更方便我们开发扩展程序.
如果我们有php程序core掉的文件,那么我们可以利用core文件进行调试.
gdb php -c core #后面的可以和正常的gdb调试core文件一样,不过php提供了一个.gdbinit的帮助脚本,这个脚本在你下载的源文件的根目录下面,下面source的路径自行替换 source ~/download/php-5.6.10/.gdbinit zbacktrace
如果你需要更多.gdbinit脚本信息请自行google,或者去鸟哥的博客看看.
参考资料:
近期评论