python-gdb错误:Python异常<class'runtimeerror'=“”>类型没有目标

时间:2018-10-31 13:16:53

标签: python python-3.x debugging gdb gdb-python

我正在运行python 3.6.6-debug(通过pyenv安装),并且已将关联的libpython.py从cpython/Tools/gdb/libpython.py复制到~/.config/gdb(已检出v3.6.6标记)

在我的.gdbinit中,我有:

source ~/.config/gdb/libpython.py

对于简单的过程,我可以使用py-listpy-bt等,但是目前在py.test下测试的程序为所有python gdb helper命令提供了此错误:

(gdb) py-list
Python Exception <class 'RuntimeError'> Type does not have a target.:
Error occurred in Python command: Type does not have a target.

此错误是什么意思,我该如何解决?

更新

我深入libpython.py来确切地了解py-list / py-bt的工作方式,然后从gdb中手动运行相关的gdb python命令以重现该问题并确切地找出libpython中的位置.py出现问题。在完成下面的调试后,我能够在gdb中获得更详细的回溯:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/git/cpython/Tools/gdb/libpython.py", line 916, in filename
  File "~/git/cpython/Tools/gdb/libpython.py", line 1158, in proxyval
RuntimeError: Type does not have a target.

问题是在libpython.py第1158行触发的,

fields = gdb.lookup_type('PyUnicodeObject').target().fields()

这可以澄清问题:libpython.py获取PyUnicodeObject的Type对象,然后尝试在其上调用target方法,但是PyUnicodeObject的Type对象没有目标 。根据{{​​3}}:

  

—功能:Type.target()

     

返回一个新的gdb.Type对象,该对象表示此类型的目标类型。

     

对于指针类型,目标类型是指向对象的类型。对于数组类型(意味着类似C的数组),目标类型是数组元素的类型。对于函数或方法类型,目标类型是返回值的类型。对于复杂类型,目标类型是元素的类型。对于typedef,目标类型是别名类型。

     

如果类型没有目标,则此方法将引发异常。

这肯定看起来像是个错误,尽管在网上,Python问题跟踪器或python提交历史中的其他任何地方都找不到这个问题的提法。我要在python跟踪器上打开一个问题,看看维护者说了些什么(除非之前有人遇到过这个问题并提交答案)。

我如何调试

配置ptrace以允许不使用sudo进行调试

$ sudo sh -c 'echo 0 > /proc/sys/kernel/yama/ptrace_scope

确定挂起(多处理)程序的父python进程

$ pstree -p -s 22391
systemd(1)───tmux(31719)───bash(5161)───py.test(22391)─┬─py.test(22478)
                                                       ├─py.test(24577)
                                                       ├─py.test(24578)
                                                       ├─python3.6(25427)
                                                       ├─python3.6(25545)
                                                       ├─python3.6(25546)
                                                       ├─python3.6(25547)
                                                       ├─python3.6(27376)───{python3.6}(27393)
                                                       ├─python3.6(30563)───{python3.6}(30580)
                                                       ├─{py.test}(27368)
                                                       ├─{py.test}(30562)
                                                       ├─{py.test}(629)
                                                       └─{py.test}(630)

(我在上面只是猜对了,对我的程序使用任何正在运行的python进程的pid都可以工作)

附加到父流程

$ gdb -p 22391

确定最新的python执行框架并切换到该框架

(gdb) bt 10
#0  0x00007fec7309a5d3 in select () at ../sysdeps/unix/syscall-template.S:84
#1  0x00007fec738692aa in pysleep (secs=50000000) at ./Modules/timemodule.c:1417
#2  0x00007fec738671a3 in time_sleep (self=0x7fec71a00458, obj=0x7fec6cf728b0) at ./Modules/timemodule.c:235
#3  0x00007fec7368513e in _PyCFunction_FastCallDict (func_obj=0x7fec719ff5f8, args=0x7fec406fac08, nargs=1, kwargs=0x0) at Objects/methodobject.c:209
#4  0x00007fec73685535 in _PyCFunction_FastCallKeywords (func=0x7fec719ff5f8, stack=0x7fec406fac08, nargs=1, kwnames=0x0) at Objects/methodobject.c:294
#5  0x00007fec7379ab0d in call_function (pp_stack=0x7ffc37032440, oparg=1, kwnames=0x0) at Python/ceval.c:4830
#6  0x00007fec737927ca in _PyEval_EvalFrameDefault (f=0x7fec406faa58, throwflag=0) at Python/ceval.c:3328
===> #7  0x00007fec7377eb3b in PyEval_EvalFrameEx (f=0x7fec406faa58, throwflag=0) at Python/ceval.c:754
#8  0x00007fec7363a208 in gen_send_ex (gen=0x7fec3d0b88d8, arg=0x0, exc=0, closing=0) at Objects/genobject.c:189
#9  0x00007fec7363bca6 in gen_iternext (gen=0x7fec3d0b88d8) at Objects/genobject.c:563
(More stack frames follow...)
(gdb) frame 7
#7  0x00007fec7377eb3b in PyEval_EvalFrameEx (f=0x7fec406faa58, throwflag=0) at Python/ceval.c:754
754     Python/ceval.c: No such file or directory.

添加python源目录并使用tui enable获取一些上下文

(gdb) dir ~/git/cpython
Source directories searched: /home/calid/git/cpython:$cdir:$cwd
(gdb) tui enable

gdb documentation

启动gdb的交互式python解释器,然后手动输入libpython行以获取当前的python脚本/行号

(gdb) pi
>>> gdbframe = gdb.selected_frame()
>>> f = gdbframe.read_var('f')
>>> pyframe = PyFrameObjectPtr.from_pyobject_ptr(f)
>>> pyframe.filename()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/git/cpython/Tools/gdb/libpython.py", line 916, in filename
  File "~/git/cpython/Tools/gdb/libpython.py", line 1158, in proxyval
RuntimeError: Type does not have a target.

这重现了我在py-listpy-bt上遇到的异常,但是这次我也得到了非常有用的回溯。

默认情况下启用gdb python堆栈跟踪

set python print-stack full

毕竟,对于上述选项,我偶然发现了gdb tui screenshot。设置默认情况下会打开堆栈跟踪打印,这将避免进行所有手动调试的需要。因此,事后看来,我做了 lot 不需要的额外工作:) (尽管我在此过程中学到了很多东西。)

我现在将其添加到我的gdbinit中,以备将来使用。

资源

1 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,尝试过并简单地更改了线路

  

fields = gdb.lookup_type('PyUnicodeObject')。target()。fields()

  

fields = gdb.lookup_type('PyUnicodeObject')。fields()

然后它起作用。