zoukankan      html  css  js  c++  java
  • 重现PHP Core的调用栈

     

     
     

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

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

    假设对于如下的脚本:

    1. <?php
    2.  
    3. class Test {
    4. }
    5.  
    6. function a($i) {
    7.     b(new Test, 2.3432, "reader");
    8. }
    9. function b($i) {
    10.     c(array(1,2,3));
    11. }
    12. function c($i) {
    13.     d(TRUE);
    14. }
    15. function d($i) {
    16.     $fp = fopen("/tmp/1.php", "r");
    17.     e($fp);
    18. }
    19.  
    20. function e($i) {
    21.     sleep(1000);
    22. }
    23.  
    24. a();

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

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

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

    1. (gdb) source php54-src/.gdbini

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

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

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

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

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

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

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

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

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

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

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

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

  • 相关阅读:
    kibana 设置登录认证
    elasticsearch
    elasticsearch安装ik
    elasticsearch 安装head
    Docker 数据卷之进阶篇
    link快捷方式
    动作方法中 参数,Json
    spring单元测试
    js之cookie操作
    idea快捷键
  • 原文地址:https://www.cnblogs.com/zengkefu/p/5647402.html
Copyright © 2011-2022 走看看