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

时间:2015-06-05 10:28:34

标签: php gdb

我正在尝试使用GDB通过控制台调试php脚本,但我无法设置断点。这就是我所做的。 我已经用这个内容创建了一个脚本:

<?php
echo "1";
echo "1";
echo "1";
echo "1";
echo "1";
echo "1";
echo "1";

这是我调试它的临终关键

# gdb php -d CANCELLAMI.php 
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...

warning: /root/CANCELLAMI.php is not a directory.
Reading symbols from /usr/bin/php...(no debugging symbols found)...done.

现在我在gdb中,我在第2行放了一个断点。

(gdb) break CANCELLAMI.php:2
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (CANCELLAMI.php:2) pending.

但如果我运行CANCELLAMI脚本

(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]

执行整个脚本。

3 个答案:

答案 0 :(得分:9)

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

  1. 使用configure --enable-debug编译PHP。
  2. 找到一个脚本不调用的方便的PHP函数。比如说,hebrevc(或quotemetaspl_autoload_extensions - 具有创造性,PHP拥有大量功能)。添加要触发的呼叫。
  3. 接下来,启动gdb并在zif_hebrevc上放置一个断点。如果您阅读PHP源代码,您会发现
    1. PHP_FUNCTION(hebrevc)
    2. #define PHP_FUNCTION ZEND_FUNCTION
    3. define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
    4. #define ZEND_FN(name) zif_##name
    5. #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)
  4. 所有这一切都会导致zif_hebrevc(或zif_quotemetazif_spl_autoload_extensions)。

    您可能希望source /path/to/the/php/source/checkout/.gdbinit这也是可选的,但没有它就很难使用PHP。此文件为您提供zbacktraceprintzvprint_ht等命令。此.gdbinit的最佳文档是source

    最后,http://lxr.php.net/是您浏览PHP源代码的朋友。

    gdb start

答案 1 :(得分:3)

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

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

现在,如果您对解释器有足够的了解,可以通过这种方式调试脚本。您可以单步执行解释程序并了解它正在执行的操作。我以前做过这件事 - 这是可行的,但不是很愉快。如果你试图找到某个特定脚本触发的解释器中的错误,那么它真的很值得。

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

答案 2 :(得分:0)

如果您想了解例如类型转换的工作原理,可以在execute_ex()函数中设置断点。一个接一个地执行操作。以下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;

诀窍是在适当的时候介入。