gdb 調試PHP

擴展編譯好用,經過php編碼測試報「段錯誤",若是是c語言都是用gdb進行設置,那php擴展要如何進行調試呢?搜索了下,雖然是php擴展可是core是php 的core不是單個so擴展的coredump
這裏使用ulimit -c unlimited來開啓core文件,使用gdb來對core文件進行調試演示一下。
 
root@debian:~/php# php a.php 
段錯誤
root@debian:~/php# ulimit -c unlimited 
root@debian:~/php# php a.php 
段錯誤 (core dumped)
root@debian:~/php# ls
a.php  core
root@debian:~/php# apt-get install gdb
root@debian:~/php# gdb php -c core 
Core was generated by `php a.php'.
Program terminated with signal 11, Segmentation fault.
#0  0xb6a7bfb8 in zif_smtpmail_connect (ht=5, return_value=0xb6f149dc, return_value_ptr=0x0, this_ptr=0x0, return_value_used=1) at /root/php/php-5.4.7/ext/smtpmail/smtpmail.c:281
281             if(strcmp(substring(lastmessage, 1, 3), hen) !=0 || strlen(lastmessage)==0) {
(gdb) 

(gdb) source ./php-5.4.7/.gdbinit 
(gdb) zbacktrace 
[0xb6efb030] smtpmail_connect("smtp.qq.com", "xxxx", "xxx", "xxxx@qq.com", 25) /root/php/a.php:5 

 

PHP的代碼包中提供了一個 .gdbinit 的gdb腳本文件,裏面提供了20多個 gdb 的自定義命令,用於方便PHP的調試,下面舉幾個例子:
測試腳本a.php:php

 

gdb 調試命令:
———————–
gdb php
set args a.php
break sleep
r

———————–express

1. print_cvs 打印當前執行環境中已編譯的PHP變量, 如:函數


2. printzv 打印指定的PHP變量, 須要指定地址, 如:

(gdb) printzv 0x9543f98
[0x9543f98] (refcount=1) string(3): 「MMM」
(gdb)
oop

3. 打印PHP的函數調用棧, 如:
(gdb) zbacktrace
[0x95770a4] sleep(1) /usr/home/junjie2/a.php:11
[0x9576fe0] test(「phpor」) /usr/home/junjie2/a.php:7
(gdb)學習

4. print_ft 打印函數表( HashTable )
(gdb) set $eg = executor_globals
(gdb) print $eg.function_table  
$6 = (HashTable *) 0xa5bd450
(gdb) print_ft $eg.function_table
[0xa5bd450] {
「zend_version\0″ => 「zend_version」
「func_num_args\0″ => 「func_num_args」
「func_get_arg\0″ => 「func_get_arg」
「func_get_args\0″ => 「func_get_args」
「strlen\0″ => 「strlen」
「strcmp\0″ => 「strcmp」
「strncmp\0″ => 「strncmp」
「strcasecmp\0″ => 「strcasecmp」
「strncasecmp\0″ => 「strncasecmp」
「each\0″ => 「each」
測試

學習
1. 經過閱讀 print_cvs 命令的實現,能夠知道能夠經過prev_execute_data來打印上一執行空間的PHP變量,如:
(gdb) printzv *executor_globals.current_execute_data->prev_execute_data->CVs[1]  
[0x9543408] (refcount=1) string(3): 「AAA」
(gdb) printzv *executor_globals.current_execute_data->prev_execute_data->CVs[2]  
[0x95433ec] (refcount=1) string(3): 「BBB」
(gdb)
this

2. 經過 op_array->vars 來找到對應的變量的名字
(gdb) printf 「%s\n」 ,executor_globals.current_execute_data->prev_execute_data->op_array->vars[1].name  
a
(gdb) printf 「%s\n」 ,executor_globals.current_execute_data->prev_execute_data->op_array->vars[2].name  
b
編碼

3. 修改了一下 print_cvs 命令,經過參數來獲取每一個執行空間的PHP的已編譯變量spa


 

使用方法:
———————
(gdb) zbacktrace  #查看PHP的調用棧
[0x8ce2078] sleep(1) /usr/home/junjie2/a.php:9
[0x8ce1fe0] test(「phpor」) /usr/home/junjie2/a.php:5
(gdb) print_cvs #查看當前執行空間中的PHP變量
Compiled variables count: 3
0 = name
[0x8cae3d0] (refcount=2) string(5): 「phpor」
1 = m
[0x8cae93c] (refcount=1) string(3): 「MMM」
2 = n
[0x8cae958] (refcount=1) string(3): 「NNN」
(gdb) print_cvs 2 # 查看指定執行空間中的PHP變量, 這個參數給大了也不要緊,最多打印最外層的PHP變量
Compiled variables count: 2
0 = a
[0x8cae408] (refcount=1) string(3): 「AAA」
1 = b
[0x8cae3ec] (refcount=1) string(3): 「BBB」
(gdb)
———————
3d

4. 有時候須要藉助環境變量,如:
(gdb) print_ft (HashTable *)0xa5bd450
A syntax error in expression, near `’.
(gdb) set $phpor=(HashTable *)0xa5bd450
(gdb) print_ft $phpor
[0xa5bd450] {
「zend_version\0″ => 「zend_version」
「func_num_args\0″ => 「func_num_args」
「func_get_arg\0″ => 「func_get_arg」
「func_get_args\0″ => 「func_get_args」
「strlen\0″ => 「strlen」
「strcmp\0″ => 「strcmp」
「strncmp\0″ => 「strncmp」

 

5. 打印指定的PHP變量

相關文章
相關標籤/搜索