【问题标题】:How to set breakpoints in a php script using gdb如何使用 gdb 在 php 脚本中设置断点
【发布时间】:2019-09-18 04:45:53
【问题描述】:

我正在尝试通过控制台使用 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]

整个脚本被执行。

【问题讨论】:

标签: php gdb


【解决方案1】:

您可以相对容易地从 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)

所以这一切都会导致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 源代码的朋友。

【讨论】:

    【解决方案2】:

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


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

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

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

    【讨论】:

    • 答案有点误导,因为它让 OP 感觉有些东西 或者它总有一天会起作用。事实上,gdb 永远无法调试脚本语言(应该如何调试?),如果要调试 php 脚本,则需要使用 xdebug。
    • 我不认为这有那么大的误导性。有一段关于这个想法,这确实是很多东西。例如,这里提到它作为一个目标:sourceware.org/gdb/wiki/PythonGdb
    • 将 python 脚本集成到 gdb 和使用 gdb 调试 python 脚本是完全不同的事情!我的意思是,你期望它应该如何工作? gdb 是否应该知道脚本语言在内部是如何工作的?每次脚本语言更改时是否应该更新 gdb?你真的认为 Stallman 先生关心 PHP、Python、Perl 吗?
    • 这里不是讨论这个想法的地方。简短的版本是扩展将使用 gdb Python API 用 Python 编写(将适当扩展以使这成为可能);并将与口​​译员一起运送。 Stallman 根本不关心这件事。
    • 真的没有多少。有一次我在 gdb 中编写了 Python 脚本的路线图,其中详细介绍了如何实现这个特定目标(但仍然不多)。这是这里的子弹之一:sourceware.org/ml/gdb/2010-08/msg00139.html。我不能聊天,但如果你发邮件我会回复的。
    【解决方案3】:

    如果您想了解例如类型转换的工作原理,您可以在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;
    

    诀窍是适时介入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      • 2014-09-22
      • 1970-01-01
      相关资源
      最近更新 更多