gdb 调试PHP
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:
$a = "AAA";
$b = "BBB";
test("phpor");
function test($name) {
$m = "MMM";
$n = "NNN";
sleep(1);
echo$name;
}
|
1
2
3
4
5
6
7
8
9
10
|
<?php
$a = "AAA";
$b = "BBB";
test("phpor");
function test($name) {
$m = "MMM";
$n = "NNN";
sleep(1);
echo$name;
}
|
gdb 调试命令:
———————–
gdb php
set args a.php
break sleep
r
…
———————–
1. print_cvs 打印当前执行环境中已编译的PHP变量, 如:
Compiled variables count: 3
0 = name
[0x9543f7c] (refcount=2) string(5): "phpor"
1 = m
[0x9543f98] (refcount=1) string(3): "MMM"
2 = n
[0x9543fb4] (refcount=1) string(3): "NNN"
(gdb)
|
1
2
3
4
5
6
7
8
9
|
(gdb) print_cvs
Compiled variables count: 3
0 = name
[0x9543f7c] (refcount=2) string(5): "phpor"
1 = m
[0x9543f98] (refcount=1) string(3): "MMM"
2 = n
[0x9543fb4] (refcount=1) string(3): "NNN"
(gdb)
|
2. printzv 打印指定的PHP变量, 需要指定地址, 如:
(gdb) printzv 0x9543f98
[0x9543f98] (refcount=1) string(3): “MMM”
(gdb)
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)
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的已编译变量
使用方法:
———————
(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)
———————
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变量
____executor_globals
set $p = $eg.current_execute_data.CVs
set $c = $eg.current_execute_data.op_array.last_var
set $v = $eg.current_execute_data.op_array.vars
set $i = 0
set $name = $arg0
#printf "search php var: %s c:%d\n", $name, $c
while $i < $c
#printf "name: %s\n", $name
set $n = $v[$i].name
# use strcmp but ==
if strcmp($n, $name) == 0
if $p[$i] != 0
printzv *$p[$i]
# use loop_break but break
loop_break
end
end
#printf "i %d, %s\n", $i, $v[$i].name
set $i = $i + 1
end
if $i == $c
printf "no found var named: %s\n", $name
end
end
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
define print_pval
____executor_globals
set $p = $eg.current_execute_data.CVs
set $c = $eg.current_execute_data.op_array.last_var
set $v = $eg.current_execute_data.op_array.vars
set $i = 0
set $name = $arg0
#printf "search php var: %s c:%d\n", $name, $c
while $i < $c
#printf "name: %s\n", $name
set $n = $v[$i].name
# use strcmp but ==
if strcmp($n, $name) == 0
if $p[$i] != 0
printzv *$p[$i]
# use loop_break but break
loop_break
end
end
#printf "i %d, %s\n", $i, $v[$i].name
set $i = $i + 1
end
if $i == $c
printf "no found var named: %s\n", $name
end
end
|
gdb 调试PHP的更多相关文章
- GDB调试命令小结
1.启动调试 前置条件:编译生成执行码时带上 -g,如果使用Makefile,通过给CFLAGS指定-g选项,否则调试时没有符号信息.gdb program //最常用的用gdb启动程序,开始调试的方 ...
- GDB调试汇编堆栈过程分析
GDB调试汇编堆栈过程分析 分析过程 这是我的C源文件:click here 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb ...
- gdb调试器的使用
想要使用gdb调试程序的话,首先需要gcc -g main.c -o test 然后运行gdb test对程序进行调试 l (小写的l,是list的首字母),用以列出程序 回车 是运行上一个命令 ...
- 20145212——GDB调试汇编堆栈过程分析
GDB调试汇编堆栈过程分析 测试代码 #include <stdio.h> short val = 1; int vv = 2; int g(int xxx) { return xxx + ...
- gdb调试PHP扩展错误
有时候,使用PHP的第三方扩展之后,可能会发生一些错误,这个时候,可能就需要更底层的方式追踪调试程序发生错误的地方和原因,熟悉linux下C编程的肯定不陌生gdb 首先,使用ulimit -c命令,查 ...
- gdb调试汇编堆栈过程的学习
gdb调试汇编堆栈过程的学习 以下为C源文件 使用gcc - g code.c -o code -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 进入之 ...
- gdb调试
·代码(实验楼中的代码,改了部分数值)命名为test.c int g(int x) { return x + 7; } int f(int x) { return g(x); } int main(v ...
- 20145223《信息安全系统设计基础》 GDB调试汇编堆栈过程分析
20145223<信息安全系统设计基础> GDB调试汇编堆栈过程分析 分析的c语言源码 生成汇编代码--命令:gcc -g example.c -o example -m32 进入gdb调 ...
- GDB调试汇编堆栈
GDB调试汇编堆栈 分析过程 C语言源代码 int g(int x) { return x+6; } int f(int x) { return g(x+1); } int main(void) { ...
- 赵文豪 GDB调试汇编堆栈过程分析
GDB调试汇编堆栈过程分析 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 使用gdb调 ...
随机推荐
- ng 双向数据绑定
1.方向1:model->View模型数据绑定到视图 绑定的方式:①双花括号 ②常见的ng指令(ngRepeat ngIf ngShow....) 效果:数据一旦绑定到视图上,随着数据的修改,视 ...
- HashMap(HashSet)的实现
0. HashMap(TreeMAP).HashSet.HashTable 的关系 HashMap 的底层则维护着 Node<K, V>[] table; 一个一维数组用于快速访问(只在初 ...
- 【ACM非算法部分】STL汇总
stackqueuepriority_queuemapsetpair ====================================== stack:(栈) 包含:#include<s ...
- Oracle 13c OEM 安装手册
1 安装准备工作 以下包已Redhat 为准,其他版的操作系统以官方手册为准. 1.1 Oracle Management Service 依赖如下包 glibc-comm ...
- 洛谷 2680 (NOIp2015) 运输计划
题目:https://www.luogu.org/problemnew/show/P2680 因为是最长的时间最短,所以二分! 离线LCA可以知道路径长度.每次只看超过二分值的路径. 原本的想法是遍历 ...
- 题目1534:数组中第K小的数字 ——二分
http://ac.jobdu.com/problem.php?pid=1534 给定两个整型数组A和B.我们将A和B中的元素两两相加可以得到数组C.譬如A为[1,2],B为[3,4].那么由A和B中 ...
- DELPHI中使用UNIDAC连接ORACLE数据库
DELPHI中使用UNIDAC连接ORACLE数据库 最近在DELPHI中使用到UNIDAC连接到oracle数据库,这样可以不要安装oracle客户端,比较方便使用:所以简单学习了一下,主要是用 ...
- Linux盘符漂移问题
Linux管理多块磁盘时(以sata盘为例),会按磁盘加载的顺序依次给磁盘命名为/dev/sda, /dev/sdb... 这种命名规则就会导致,一块磁盘在发生热插拔或系统重启后,盘符可能发生变化,会 ...
- ffmpeg超详细综合教程——摄像头直播
本文的示例将实现:读取PC摄像头视频数据并以RTMP协议发送为直播流.示例包含了1.ffmpeg的libavdevice的使用2.视频解码.编码.推流的基本流程具有较强的综合性.要使用libavdev ...
- thinkphp中的验证码的实现
1.php端生成验证码函数 public function verify(){ // 验证码 import("@.Util.Image"); Image::buildImageVe ...