基于phpx的php 扩展调试

用c写php的扩展不是一件轻松的事情,调试起来更是麻烦。普通的php扩展调试网上可以找到资料。我这里因为要用到c++,因此用了phpx来降低php扩展开发的门槛。

phpx项目地址:https://github.com/swoole/phpx

准备环境

ubuntu16.04, gcc, git, wget

首先从php的官方网站下载需要的php版本的源代码: https://php.net/releases/

我下载的是php-7.0版本的

wget https://www.php.net/distributions/php-7.0.33.tar.gz

下载完成后,解压进入目录,安装一些必要的依赖库。

sudo apt-get install libxml2-dev
./configure --enable-debug
make -j 4
sudo make install

因为我的扩展使用了phpx这个库,所有phpx的编译也需要开启debug模式,编辑cmakelist.txt加入 SET(CMAKE_BUILD_TYPE "Debug")。然后

cmake .
make -j 4
sudo make install

注意:在编译php扩展的时候也要开启调试模式。

使用gdb调试

因为php+phpx这个组合编译出来的扩展没有办法像普通的gdb调试一样,通过行号来打断点调试。因此需要根据函数名来打断点。

比如我的代码中有一个关键的方法名叫做input, 因此可以

nm /usr/local/lib/php/extensions/debug-non-zts-20151012/php_dv.so | grep input

得到以下的查找结果

000000000003a99e T _Z8Dv_inputRN3php6ObjectERNS_4ArgsERNS_7VariantE
00000000000491f8 T _ZN11DataAdaptor5inputESt6vectorIP6PersonSaIS2_EE

_ZN11DataAdaptor5inputESt6vectorIP6PersonSaIS2_EE这个就是可以打断点的函数名啦。

gdb php
break _ZN11DataAdaptor5inputESt6vectorIP6PersonSaIS2_EE
run paintAll.php

就可以看到断点打在了

Breakpoint 1, DataAdaptor::input (this=0x1259de0, 
    allPerson=std::vector of length 2622, capacity 2622 = {...}) at ../DataAdaptor.cc:195
195    void DataAdaptor::input(vector allPerson) {

可以使用layout分割窗口,大致结果如下:

gdb调试窗口

coredump信息的查看

php扩展出错后,也可以生成coredump文件。需要修改limits.conf中的core文件大小,比如设置成unlimited。生成core文件后,执行gdb php core, 然后使用bt即可打印出方法的调用栈,从而分析问题出现的原因。