IT技术博客大学习 共学习 共进步

更简单的重现PHP Core的调用栈

风雪之隅 2011-12-11 16:05:24 浏览 3,041 次

以前, 我曾经介绍过如何通过PHP的Core文件获取信息:如何调试PHP的Core之获取基本信息, 对于调用参数这块, 当时介绍的获取方法比较复杂.

于是今天我为PHP 5.4的.gdbinit做了一个改进, 以后如果你遇到了PHP 5.4的core, 那么就可以简单的得到PHP 5.4发生Core时, 包括参数的函数调用栈的信息.

假设对于如下的脚本:

<?php class Test {} function a($i) {    b(new Test, 2.3432, "reader");}function b($i) {    c(array(1,2,3));}function c($i) {    d(TRUE);}function d($i) {    $fp = fopen("/tmp/1.php", "r");    e($fp);} function e($i) {    sleep(1000);} a();

使用后台运行以后, PHP5.4会sleep在e函数的sleep中, 这时, 如果我们使用gdb attach上去,

gdb --pid= xxx //使用ps获得后台运行脚本的pid

然后, source PHP源代码下面的.gdbinit:

(gdb) source php54-src/.gdbini

然后, 让我们尝试调用下zbacktrace, 看看什么结果:

(gdb) zbacktrace[0x2a95dac5e0] sleep(1000) /tmp/1.php:21[0x2a95dac4c0] e(resource(#5)) /tmp/1.php:17[0x2a95dac3f0] d(true) /tmp/1.php:13[0x2a95dac300] c(array(3)[0x2a95de7db0]) /tmp/1.php:10[0x2a95dac1c0] b(object[0x2a95de7840], 2.343200, "reader") /tmp/1.php:7[0x2a95dac0e8] a() /tmp/1.php:2

恩, 对于array和object, 因为我们为了保持不要乱屏, 所以没有展开, 不过, 如果我们要查看这个array具体是什么元素, 可以这样做, 注意到上面的:array(3)[0x2a95de7db0]:

(gdb) print ((zval *)0x2a95de7db0)$4 = (struct _zval_struct *) 0x2a95de7db0(gdb) printzv $4[0x2a95de7db0] (refcount=2) array(3): {    0 => [0x2a95de79d0] (refcount=1) long: 1    1 => [0x2a95de7b80] (refcount=1) long: 2    2 => [0x2a95de7c98] (refcount=1) long: 3  

类似的, 对于object, 注意到上面的: object[0x2a95de7840]

(gdb) print ((zval *)0x2a95de7840)$5 = (struct _zval_struct *) 0x2a95de7840(gdb) printzv $5[0x2a95de7840] (refcount=2) object(Test) #1"no properties found

要注意的一点是, 对于object, 如果你是在调式Core文件, 而不是attach到一个运行的进程上, 那么上面的尝试会得到一个错误:

(gdb) printzv $5[0x2a95de7840] (refcount=2) objectYou can't do that without a process to debug

不过, 即使这样, 我们还是有办法, 只不过就比较麻烦了.在NTS下面:

(gdb) p ((zval *)0x2a95de7840)->value.obj.handle$6 = 1//注意, 下面用到了这个$6的值:1(gdb)  p (zend_object*) executor_globals->objects_store.object_buckets[1].bucket.obj.object$7 = (struct _zend_object *) 0x2a95de3ec0(gdb)  p $9->ce->name$8 = 0x2a95e200b0 "Test

呵呵, 怎么样, 有了这些信息, 分析Core的原因, 是不是就更简单了呢? enjoy~

最后, 还是要提醒下: PHP 5.4还处于开发阶段, 在最终release之前, 任何新特性都可能被调整或者更改. 如果大家有任何建议, 也欢迎反馈, 帮助我们使得PHP变得更好.

建议继续学习

  1. 调试工具之GDB (阅读 14,701)
  2. gdb的基本工作原理是什么? (阅读 11,522)
  3. 深入理解Nginx之调试优化技巧 (阅读 8,103)
  4. 使用gdb调试运行时的程序小技巧 (阅读 7,123)
  5. GDB中应该知道的几个调试方法 (阅读 6,482)
  6. 使用GDB调试多进程程序 (阅读 6,241)
  7. 又一个PHP低概率Core的分析(PHP内存管理) (阅读 4,260)
  8. GDB常用指令说明 (阅读 3,983)
  9. 怎样用core文件调试你的linux程序? (阅读 3,884)
  10. GDB的两个技巧 (阅读 3,684)