如何使用gdb在php脚本中设置断点

如何使用gdb在php脚本中设置断点,php,gdb,Php,Gdb,我试图通过GDB控制台调试php脚本,但我无法设置断点。这就是我所做的。 我创建了一个包含以下内容的脚本: <?php echo "1"; echo "1"; echo "1"; echo "1"; echo "1"; echo "1"; echo "1"; 但是如果我运行这个脚本 (gdb) run CANCELLAMI.php Starting program: /usr/bin/php CANCELLAMI.php [Thread debugging using libthrea

我试图通过GDB控制台调试php脚本,但我无法设置断点。这就是我所做的。 我创建了一个包含以下内容的脚本:

<?php
echo "1";
echo "1";
echo "1";
echo "1";
echo "1";
echo "1";
echo "1";
但是如果我运行这个脚本

(gdb) run CANCELLAMI.php 
Starting program: /usr/bin/php CANCELLAMI.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
11111111[Inferior 1 (process 30216) exited normally]

整个脚本都已执行。

简短回答:如果要调试PHP脚本,请使用


目前,gdb只能真正调试编译语言。它有很多关于可执行文件格式、调试信息格式、如何展开堆栈帧以及类似的低级知识。它所没有的是一种将这些东西与解释器中的更高层结构相关联的方法

现在,如果您对解释器有足够的了解,就可以通过这种方式调试脚本。您可以逐步了解解释器并了解它在做什么。我以前做过这件事——这是可行的,但并不令人愉快。这已经够难了,只有当您试图在解释器中找到由某个特定脚本触发的bug时,才真正值得这么做


偶尔会出现这样的想法,gdb可以调试脚本。这是个好主意,但工作量相当大。据我所知,目前没有人在处理它。

您可以相对轻松地从PHP触发断点:

  • 使用
    configure--enable debug
    编译PHP
  • 找到一个脚本不调用的方便PHP函数。比如说,
    hebrevc
    (或者
    quotemeta
    或者
    spl\u autoload\u扩展
    ——要有创意,PHP有很多功能)。在要触发的位置添加呼叫
  • 接下来,启动gdb并在zif_hebrevc上设置一个断点。如果您阅读PHP源代码,您会发现
  • PHP\u函数(hebrevc)
  • #定义PHP_函数ZEND_函数
  • 定义ZEND_函数(名称)ZEND_命名函数(ZEND_FN(名称))
  • #定义ZEND#FN(名称)zif##name
  • #定义ZEND_命名函数(名称)void name(内部函数参数)
  • 因此,所有这些都导致了
    zif_-hebrevc
    (或
    zif_-quotemeta
    zif_-spl_-autoload_-extensions

    您可能需要
    source/path/to/the/php/source/checkout/.gdbinit
    这也是可选的,但是如果没有它,使用php是非常困难的。此文件提供了诸如
    zbacktrace
    printzv
    print\u ht
    等命令。此
    .gdbinit
    的最佳文档是

    最后,是您的朋友浏览PHP源代码


    如果您想了解(例如)类型转换的工作原理,可以在函数处设置断点。它依次执行一个接一个的操作。以下
    gdb
    会话:

    (gdb) n
    54056  HYBRID_SWITCH() {
    (gdb)
    54383  ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    (gdb)
    54384  HYBRID_BREAK();
    (gdb)
    54524  ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    (gdb)
    54525  HYBRID_BREAK();
    (gdb)
    54243  ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    (gdb)
    54244  HYBRID_BREAK();
    (gdb)
    54415  ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    
    对应于以下脚本:

    <?php sleep(1); echo 0.1 + 0.2;
    

    这个答案有点误导人,因为它让OP感觉到有什么东西或者有一天它可能会起作用。事实上,gdb永远无法调试脚本语言(应该如何调试?),如果您想调试php脚本,就需要使用xdebug。我不认为这有什么误导性。有一段是关于这个想法的,这确实是很多人想到的。例如,这里提到的目标是:将python脚本集成到gdb中,使用gdb调试python脚本是完全不同的事情!我是说,你认为它应该如何工作?gdb应该知道脚本语言在内部是如何工作的吗?gdb应该在每次脚本语言更改时更新吗?你真的认为Stallman先生关心PHP、Python、Perl吗?这不是讨论这个想法的好地方。简短的版本是使用gdb-pythonapi用Python编写扩展(为了实现这一点,将对其进行适当的扩展);并将与口译员一起运送。史泰尔曼的关心根本不包括在这件事里。其实外面没有什么。有一次,我在gdb中为Python脚本编写了一份路线图,其中对如何实现这一特定目标进行了更详细的介绍(但仍然不多)。这是这里的一个项目:。我不能聊天,但如果你发电子邮件,我会回复。相关:
    
    (gdb) n
    54056  HYBRID_SWITCH() {
    (gdb)
    54383  ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    (gdb)
    54384  HYBRID_BREAK();
    (gdb)
    54524  ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    (gdb)
    54525  HYBRID_BREAK();
    (gdb)
    54243  ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    (gdb)
    54244  HYBRID_BREAK();
    (gdb)
    54415  ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
    
    <?php sleep(1); echo 0.1 + 0.2;