gdb 调试php扩展,使用gdb调试工具上手调试php和swoole源码

swoole作为 php 的核心项目,php和swoole都具有一定的研究价值,由于是 c语言 编写的项目,要上手进行调试,那么最好用的调试 工具 就是gdb了

这个gdb调试工具功能强大,支持的选项也是非常多,下面就总结出来常用的命令

编译源码添加调试信息

在编译时把调试信息编译进生成的二进制文件中,需要给gcc编译器加上-g参数,比如编译 php 的Makefile中是这样的

9b9abefe295aa4194dfd5381463e7440.png 加上

-g

参数就已经有调试信息了,-O0是关闭gcc的优化,这个gcc优化后会在调试时丢失一部分调试信息,所以一般建议关闭

这样在gdb里面就可以随时查看当前执行到源码的那个地方了,能够显著提升调试的效率

查看源码

a9956c5db7d1e0c6ad8bddd217aadbdd.png 使用

gdb php

开始启动gdb调试php命令行程序

使用 list 命令,默认会定位到main方法所在的第一行被执行的代码,可以看到定位到了1186行,使用 info line 指令可以查看上面定位到的代码所在的文件是"sapi/cli/php_cli.c"

在understand中打开php源码进行验证

93565955f43b029a6cb4deed25ec46cc.png 因为是在 linux 下运行的,所以这个"PHP_CLI_WIN32_NO_CONSOLE"宏是不存在,第一行代码是走到1186行的else分支是ok的,这就说明了gdb

list

命令默认是定位到main方法的了

断点操作

打断点

使用 b 命令,或者全名 break 命令可以在任意函数开始位置进行断点,比如c/c++的入口函数main处断点,只需执行下面的命令就可以了

b main

复制代码

操作效果如下

34a42ad2720756b7f9b9f6893aef0ed9.png

这样断点就加好了,运行php时就会在main方法处触发这个断点了

查看已有断点

使用命令 info b 或者 info break 就可以查看目前所有的断点了,效果如下

d23d2fdb54bfa5ca381b2fe8027f135a.png

sapi/cli/php_cli.c:1284

处再加个断点

a46f2aa1abdd1cb6b0315b06d74024ad.png

效果如下:

2012b3bd799be1fc79b506a3497fac8f.png

可以看到断点已经成功加上了

删除断点

使用命令 delete breakpoints 断点编号 就可以删除断点了,这个可以自行研究

其它断点操作

这个断点操作的命令还有非常多,可以使用命令 help breakpoints 查看完整的断点相关的命令清单

流程控制

使用 r 命令或者 run 命令就是启动这个被调试的php程序了,比如调试这个php命令:php test.php

// test.php

$a = '1';

echo $a;

复制代码

上面这个命令是带了参数 test.php所以,在gdb里运行时也可以把这个参数带上,对应的gdb命令如下

run test.php

复制代码

查看操作效果:

62a6ae950ecf1269c89ecf577edcdcf0.png

可以看到成功命中了设置在1195行的断点,这个说明在gdb里启动php成功了

获取调试信息

获取反汇编代码-layout模式

使用命令 layout asm 可以查看当前断点所处位置的反汇编代码,这个在高级分析时会经常用到,效果如下:

3743f074d63c23cc4840dcc3c589d9ba.png 命令

layout src

可以切换到源码视图,这个视图查看源码非常方便

4152bb0e81101d3839768de8f59d668e.png 结合使用layout asm可以实时对比汇编代码和c代码,有利于快速对比分析 使用这个

ctrl + x + a

命令可以退出这个layout模式

获取反汇编代码-普通模式

上面使用layout模式查看汇编代码,但是会打开新窗口,如果只想查看当前断点下面几行汇编,可以使用更快的diaplay命令,比如查看断点下的10行反汇编代码使用命令 display/10i $pc ,查看效果如下:

bc7f3de4f860af54defcd167f9db6d5a.png

但是这个display每次断点都会输出,可以使用 undisplay 命令进行删除

获取变量值

在gdb中可以很方便的使用p命令或者print命令来获取当前断点所处的上下文的变量的值

4fdaf615028952bfb0a43be139787a89.png

然后在这个1342处进行断点,在1337处复制了一段字符串给ini_entries, 所以1342处ini_entries肯定有值了

然后使用命令 p ini_entries 查看ini_entries变量中的值

操作效果如下

64a1e129998bfab7cadda6f9ca7509dd.png

成功的获取到了ini_entries变量中的值是字符串 "html_errors=0\nregister_argc_argv=1\nimplicit_flush=1\noutput_buffering=0\nmax_execution_time=0\nmax_input_time=-1\n"

调试swoole

编写swoole协程测试代码

// go.php

go(function () {

$a = '1';

echo $a;

});

echo '2';

复制代码

比如在创建协程核心函数处断点

b zif_swoole_coroutine_create

复制代码

然后带swoole扩展运行: run -dextension=swoole.so go.php

操作效果如下

4ae195a54045c6f14a21122bef9c6205.png

可以看到程序已经在swoole的swoole_coroutine_create成功断点了

然后就可以使用gdb对swoole进行调试了

同时也可以看到断点时断在了swoole-src/swoole_coroutine_util.cc:415行,可以在understand中核对代码是否一致

03a17c2f8274d2e03c4b80cad59cc8cf.png

可以看到在understand中代码位置是ok的,这样就可以在gdb里调试,在understand里阅读源代码了:smiley:

参考资料

一些注意的点

使用c命令或者continue命令可以让程序执行到下一个断点处

调试带宏的函数,需要把宏展开获取完整的函数名,才能下断点

编译swoole扩展时需要附加上调试信息,通过参数 --enable-debug 实现

cd swoole-src

phpize

./configure --enable-debug

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值