使用 gdb 7 对调试 Python 程序的支持需要啥?

Posted

技术标签:

【中文标题】使用 gdb 7 对调试 Python 程序的支持需要啥?【英文标题】:What is needed to use gdb 7's support for debugging Python programs?使用 gdb 7 对调试 Python 程序的支持需要什么? 【发布时间】:2013-01-30 20:59:41 【问题描述】:

我想使用 gdb 7 的支持来调试 Python“劣质进程”。

我需要什么才能做到这一点?

例如:

低级 Python 的配置脚本需要使用哪些标志运行?

低级 Python 进程是否必须是 Python 2.7 或更高版本(我看到那是提交 Python 源代码树中的 gdb 支持的部分时)?还是只有 gdb 进程本身需要 Python 2.7?

需要安装哪些文件可能并非所有发行版都打包?例如,在 packages.ubuntu.com 上我没有得到任何关于 python-gdb.py 的点击,我认为这是需要的。

了解特定发行版的需求会非常方便。我对 Ubuntu 和 Centos 的需求特别感兴趣。

【问题讨论】:

您确定您对此功能的解释正确吗? GDB 7 添加了对在 python 中扩展 GDB 本身的支持,但我不知道能够使用它来调试 python 程序(除了调试解释器本身)。这就是 pdb 的用途,我想。 是的,很确定。严格来说,我的问题是关于 使用 gdb 中的特性来提供调试 Python 程序(或 Python 本身)的特性的 Python 特性:wiki.python.org/moin/DebuggingWithGdb -- 例如有 py-up 和 py-down 命令可以在 Python 堆栈中移动,有一个 py-bt 命令来打印 Python 堆栈,还有一个 py-print 命令来打印绑定到 Python 名称的值。对于跨越 C / Python 边界的问题似乎特别有用,但我也有兴趣尝试使用核心转储来调试生产中发生的纯 Python 问题。 【参考方案1】:

Python 似乎需要使用 --with-pydebug 编译(在 Ubuntu 12.04 上,包 python-dbg 包含一个合适的 Python 可执行文件,本身称为 python-dbg)。劣质的 Python 不需要是 Python 2.7 -- 2.6 可以成功加载 2.7 gdb 扩展(请参阅下面的调试会话)。至少在 Ubuntu 12.04 上,已安装的定义 gdb 扩展的文件称为 libpython.py,而不是 python-gdb.py(出于某种原因,构建 Python 会产生一个包含这两个文件的构建目录——它们是相同的)。

但是,我认为目前无法使用生产核心文件进行调试:看起来 Python 劣质进程的 gdb 扩展试图获取在生产二进制文件中得到优化的变量(例如,f PyEval_EvalFrameEx 中的变量)。似乎 Linux / gdb 和 Python 还没有达到在 Illumos 上实现 javascript 的出色水平,Bryan Cantrill 在这里报告说能够以这种方式调试生产核心转储:

http://www.infoq.com/presentations/Debugging-Production-Systems

这是 Ubuntu 12.04 上的调试会话,显示 gdb 使用 Python 2.7 的 gdb 扩展运行 Python 2.6 次等进程来调试段错误。首先是导致段错误的代码:

~/Downloads/Python-2.6.4$ cat ~/bin/dumpcore.py
class Foo:

    def bar(self):
        from ctypes import string_at
        string_at(0xDEADBEEF) # this code will cause Python to segfault


def main():
    f = Foo()
    f.someattr = 42
    f.someotherattr = 'one':1, 'two':2L, 'three':[(), (None,), (None, None)]
    f.bar()


if __name__ == "__main__":
    main()

和调试会话:

~/Downloads/Python-2.6.4$ gdb --args ./python ~/bin/dumpcore.py
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/>...
Reading symbols from /home/john/Downloads/Python-2.6.4/python...done.
(gdb) run
Starting program: /home/john/Downloads/Python-2.6.4/python /home/john/bin/dumpcore.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x0000000000468d67 in PyString_FromString (str=0xdeadbeef <Address 0xdeadbeef out of bounds>) at Objects/stringobject.c:116
116             size = strlen(str);
(gdb) py-bt
Undefined command: "py-bt".  Try "help".
(gdb) python
>import sys
>sys.path.insert(0, "/home/john/Downloads/Python-2.7/Tools/gdb")
>import libpython
>(gdb) py-bt
#10 Frame 0x8f0f90, for file /home/john/Downloads/Python-2.6.4/Lib/ctypes/__init__.py, line 496, in string_at (ptr=3735928559, size=-1)
    return _string_at(ptr, size)
#14 Frame 0x8ebf90, for file /home/john/bin/dumpcore.py, line 5, in bar (self=<Foo(someattr=42, someotherattr='three': [(), (None,), (None, None)], 'two': 2L, 'one': 1) at remote 0x7ffff6e03240>, string_at=<function at remote 0x7ffff6e1c990>)
        string_at(0xDEADBEEF) # this code will cause Python to segfault
#17 Frame 0x8ebd80, for file /home/john/bin/dumpcore.py, line 12, in main (f=<Foo(someattr=42, someotherattr='three': [(), (None,), (None, None)], 'two': 2L, 'one': 1) at remote 0x7ffff6e03240>)
    f.bar()
#20 Frame 0x8eb680, for file /home/john/bin/dumpcore.py, line 16, in <module> ()
    main()
(gdb) 

【讨论】:

【参考方案2】:

对于 Centos 6,您只需:

yum install gdb python-debuginfo
debuginfo-install python

然后您可以通过简单地使用 gdb 附加到正在运行的 python 进程来调试它们:

gdb python [process id]

连接后,只需输入:

py-bt

【讨论】:

以上是关于使用 gdb 7 对调试 Python 程序的支持需要啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 gdb 调试运行中的 Python 进程

使用 GDB 调试多进程程序

使用GDB调试多进程

通过 GDB 调试 DMD 生成程序

Gdb调试多进程程序

如何将 python 包安装到 GDB/clion2017.1 中的嵌入式 python