使用gdb調試工具上手調試php和swoole源碼

swoole做爲php的核心項目,php和swoole都具備必定的研究價值,因爲是c語言編寫的項目,要上手進行調試,那麼最好用的調試工具就是gdb了php

這個gdb調試工具功能強大,支持的選項也是很是多,下面就總結出來經常使用的命令html

編譯源碼添加調試信息

在編譯時把調試信息編譯進生成的二進制文件中,須要給gcc編譯器加上-g參數,好比編譯php的Makefile中是這樣的 linux

加上 -g參數就已經有調試信息了,-O0是關閉gcc的優化,這個gcc優化後會在調試時丟失一部分調試信息,因此通常建議關閉

這樣在gdb裏面就能夠隨時查看當前執行到源碼的那個地方了,可以顯著提高調試的效率c++

查看源碼

使用 gdb php開始啓動gdb調試php命令行程序

使用list命令,默認會定位到main方法所在的第一行被執行的代碼,能夠看到定位到了1186行,使用info line指令能夠查看上面定位到的代碼所在的文件是"sapi/cli/php_cli.c"shell

在understand中打開php源碼進行驗證 segmentfault

由於是在linux下運行的,因此這個"PHP_CLI_WIN32_NO_CONSOLE"宏是不存在,第一行代碼是走到1186行的else分支是ok的,這就說明了gdb list命令默認是定位到main方法的了

斷點操做

打斷點

使用b命令,或者全名break命令能夠在任意函數開始位置進行斷點,好比c/c++的入口函數main處斷點,只需執行下面的命令就能夠了api

b main
複製代碼

操做效果以下 swoole

這樣斷點就加好了,運行php時就會在main方法處觸發這個斷點了

查看已有斷點

使用命令info b或者info break就能夠查看目前全部的斷點了,效果以下 函數

sapi/cli/php_cli.c:1284處再加個斷點

效果以下: 工具

能夠看到斷點已經成功加上了

刪除斷點

使用命令delete breakpoints 斷點編號就能夠刪除斷點了,這個能夠自行研究

其它斷點操做

這個斷點操做的命令還有很是多,可使用命令help breakpoints查看完整的斷點相關的命令清單

流程控制

使用r命令或者run命令就是啓動這個被調試的php程序了,好比調試這個php命令:php test.php

<?php
// test.php
$a = '1';
echo $a;
複製代碼

上面這個命令是帶了參數 test.php因此,在gdb裏運行時也能夠把這個參數帶上,對應的gdb命令以下

run test.php
複製代碼

查看操做效果:

能夠看到成功命中了設置在1195行的斷點,這個說明在gdb裏啓動php成功了

獲取調試信息

獲取反彙編代碼-layout模式

使用命令layout asm能夠查看當前斷點所處位置的反彙編代碼,這個在高級分析時會常常用到,效果以下:

命令 layout src能夠切換到源碼視圖,這個視圖查看源碼很是方便
結合使用layout asm能夠實時對比彙編代碼和c代碼,有利於快速對比分析 使用這個 ctrl + x + a命令能夠退出這個layout模式

獲取反彙編代碼-普通模式

上面使用layout模式查看彙編代碼,可是會打開新窗口,若是隻想查看當前斷點下面幾行彙編,可使用更快的diaplay命令,好比查看斷點下的10行反彙編代碼使用命令display/10i $pc,查看效果以下:

可是這個display每次斷點都會輸出,可使用undisplay命令進行刪除

獲取變量值

在gdb中能夠很方便的使用p命令或者print命令來獲取當前斷點所處的上下文的變量的值

而後在這個1342處進行斷點,在1337處複製了一段字符串給ini_entries, 因此1342處ini_entries確定有值了

而後使用命令p ini_entries查看ini_entries變量中的值

操做效果以下

成功的獲取到了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
<?php
go(function () {
    $a = '1';
    echo $a;
});
echo '2';
複製代碼

好比在建立協程核心函數處斷點

b zif_swoole_coroutine_create
複製代碼

而後帶swoole擴展運行: run -dextension=swoole.so go.php

操做效果以下

能夠看到程序已經在swoole的swoole_coroutine_create成功斷點了

而後就可使用gdb對swoole進行調試了

同時也能夠看到斷點時斷在了swoole-src/swoole_coroutine_util.cc:415行,能夠在understand中核對代碼是否一致

能夠看到在understand中代碼位置是ok的,這樣就能夠在gdb裏調試,在understand裏閱讀源代碼了😃

參考資料

  1. PHP 7底層設計與源碼實現 (Web開發技術叢書)
  2. PHP7內核剖析
  3. Useful_commands_gdb
  4. 【Swoole源碼研究】深刻理解Swoole協程實現
  5. Understand

一些注意的點

使用c命令或者continue命令可讓程序執行到下一個斷點處

調試帶宏的函數,須要把宏展開獲取完整的函數名,才能下斷點

編譯swoole擴展時須要附加上調試信息,經過參數--enable-debug實現

cd swoole-src
phpize
./configure --enable-debug
複製代碼
相關文章
相關標籤/搜索