跳转到主要内容

trepanxpy是Trepan家族中的x-python的类似GDB的调试器

项目描述

摘要

这是一个专注于Python字节码的类似GDB的调试器。据我所知,这是唯一专门针对Python字节码的调试器。

然而,为了做到这一点,您需要使用底层的x-python:用Python编写的Python解释器。

此项目基于之前名为trepan3k的Python 3调试器。

示例

demo

下面我们将尝试分析上面的内容。

我们将使用我们的调试器调用一个最大公约数程序gcd.py。源代码位于test/example/gcd.py

在本节中,我们将介绍一些在Python调试器中不常见的有趣调试命令

  • stepi来单步执行字节码指令
  • set loglevel来显示x-python的"info"级别的日志跟踪。
  • info stack来显示当前的评估堆栈
$ trepan-xpy test/example/gcd.py 3 5
 Running x-python test/example/gcd.py with ('3', '5')
 (test/example/gcd.py:10): <module>
 -> 2 """
 (trepan-xpy)
 

上面的代码在运行第一条指令之前就停止了。在2之前的->图标表示我们正在停止调用新的帧。

(trepan-xpy) step
(test/example/gcd.py:2): <module>
-- 2 """Greatest Common Divisor"""
@ 0: LOAD_CONST 'Greatest Common Divisor'

好的,现在我们在第一条指令LOAD_CONST之前停止,这条指令将把一个常量加载到评估堆栈上。图标从-> 2变为-- 2,表示我们位于第2行的行号边界。

我们即将执行的Python构造是设置程序的文档字符串。让我们看看它是如何实现的。

首先我们看到变量__doc__,它最终将包含文档字符串,还没有被设置。

在这里我们看到第一部分是将这个常量加载到评估栈上。

为了更好地看到执行过程,我们将发出set loglevel命令,这将显示我们按步执行时的指令。

trepan3k一样,trepan-xpy在调试器中有详细的格式化帮助。让我们获取set loglevel命令的帮助。

(trepan-xpy) help set loglevel
set loglevel [ on | off | debug | info ]

Show loglevel PyVM logger messages. Initially logtracing is off.

However running set loglevel will turn it on and set the log level to debug.
So it's the same thing as set loglevel debug.

If you want the less verbose messages, use info. And to turn off, (except
critical errors), use off.

Examples:

     set loglevel         # turns x-python on info logging messages
     set loglevel info    # same as above
     set loglevel debug   # turn on info and debug logging messages
     set loglevel off     # turn off all logging messages except critical ones


现在我们来设置它

(trepan-xpy) set loglevel
(trepan-xpy)

一个相当独特的命令,你不会在大多数Python调试器中找到,但在低级调试器中可以找到的是stepi,它可以执行指令。让我们使用它

(trepan-xpy) stepi
(test/example/gcd.py:2 @2): <module>
.. 2 """Greatest Common Divisor"""
@ 2: STORE_NAME 'Greatest Common Divisor') __doc__

开头的..表示我们正在一个位于两行之间的指令上。

我们现在使用LOAD_CONST将文档字符串加载到评估栈上,让我们使用info stack查看评估栈。

(trepan-xpy) info stack
0: <class 'str'> 'Greatest Common Divisor'

在这里我们推入了程序的文档字符串,但还没有将其存储在__doc__中。为了看到这一点,可以使用trepan-xpy的自动评估功能:它将自动评估它不认识为调试器命令的字符串。

(trepan-xpy) __doc__ is None
True

让我们执行剩余的指令STORE_NAME来完成构成第一行的指令。

trepan-xpy) stepi
INFO:xpython.vm:L. 10  @  4: LOAD_CONST 0
(test/example/gcd.py:10 @4): <module>
-- 10 import sys
@ 4: LOAD_CONST 0

10 import...之前的--表示我们现在处于一个行边界上。让我们在执行STORE_NAME后查看栈。

(trepan-xpy) info stack
Evaluation stack is empty

为了看到我们将其存储在__doc__中,我们可以运行eval来查看其值

(trepan-xpy) eval __doc__
"Greatest Common Divisor"

(仅输入_doc_等同于在自动评估开启时输入eval __doc__。)

现在让我们执行一个语句(不是指令),来看看模块是如何变得可见的。

(trepan-xpy) step
INFO:xpython.vm:       @  6: LOAD_CONST None
INFO:xpython.vm:       @  8: IMPORT_NAME (0, None) sys
INFO:xpython.vm:       @ 10: STORE_NAME (<module 'sys' (built-in)>)
INFO:xpython.vm:L. 12  @ 12: LOAD_CONST <code object check_args at 0x7f2a0a286f60, file "test/example/gcd.py", line 12>
(test/example/gcd.py:12 @12): <module>
-- 12 def check_args():
@ 12: LOAD_CONST <code object check_args at 0...est/example/gcd.py", line 12>

INFO是由虚拟机解释器发起的。由于执行了set loglevel,解释器的logger日志级别被提高。这反过来又导致调用调试器提供的格式化例程的回调,以很好地着色信息。这就是为什么在这个终端会话中的某些部分被着色。在x-python中,你可以获取相同的信息,只是没有着色。

要注意的一件事是操作符后面的值和括号中的值,就像在STORE NAME之后。将这一行与Python的disxdis版本中的静态反汇编相比。

10 STORE_NAME                1 (sys)

在静态反汇编器中,“1”表示代码对象中的名称索引。括号中的值是那个名称的值,在这里索引为1,即sys

然而,在trepan-xpyx-python中,我们省略了名称索引,1,因为那不是很有兴趣。相反,我们显示了动态栈条目或STORE_NAME将要操作的运算符。特别是将要存储在变量sys中的对象是内置模块sys

现在让我们执行另一个语句,来看看函数是如何变得可用的。

trepan-xpy) step
INFO:xpython.vm:       @ 14: LOAD_CONST 'check_args'
INFO:xpython.vm:       @ 16: MAKE_FUNCTION (check_args) Neither defaults, keyword-only args, annotations, nor closures
INFO:xpython.vm:       @ 18: STORE_NAME (<Function check_args at 0x7fdb1d4d49f0>) check_args
INFO:xpython.vm:L. 25  @ 20: LOAD_CONST <code object gcd at 0x7fdb1d55fed0, file "test/example/gcd.py", line 25>
(test/example/gcd.py:25 @20): <module>
-- 25 def gcd(a,b):
@ 20: LOAD_CONST <code object gcd at 0x7fdb1d...est/example/gcd.py", line 25>

动态语言(如Python)和静态编译语言(如C或Java)之间的一个区别是,在编译中没有链接步骤;模块和函数是作为代码执行的一部分导入或创建并链接的。

再次注意操作码后面的值和括号中的值,以及它与静态反汇编的不同。以下是来自pydisasm的第二和第三条指令的示例。

16 MAKE_FUNCTION             0 (Neither defaults, keyword-only args, annotations, nor closures)
18 STORE_NAME                2 (check_args)

同样,名称表的索引被省略,取而代之的是评估栈项。对于MAKE_FUNCTION,显示创建的函数的名称;而对于STORE_NAME,如之前所述,显示要存储的项目(一个函数对象)。

屏幕录制剩余部分显示,除了 step(进入步骤)和 stepi(执行指令)调试命令外,还有一个 next 或步过调试命令,以及一个稍微有些问题的 finish(退出)命令。

我还没有设置断点。

但与我所知的任何其他Python调试器相比,我们可以立即通过值返回,这在屏幕录制中有所展示。

我们只展示了众多调试功能中的一部分。

字节码特定命令

以下是一些在Python调试器中通常找不到的有趣命令,例如 pdb

  • info blocks 允许您查看代码块堆栈
  • set pc <offset> 允许您在框架内设置程序计数器
  • set autopc 在调试器的命令循环REPL运行之前运行 info pc 以显示调试程序的程序计数器。
  • set autostack 在调试器的命令循环REPL运行之前运行 info stack 以显示调试程序的评估堆栈。
  • vmstack {peek | push, pop} - 检查或修改评估堆栈

参见

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源分发

trepanxpy-1.1.1.tar.gz (962.4 kB 查看哈希)

上传时间

构建分发

trepanxpy-1.1.1-py310-none-any.whl (63.7 kB 查看哈希)

上传时间 Python 3.10

trepanxpy-1.1.1-py39-none-any.whl (63.7 kB 查看哈希)

上传时间 Python 3.9

trepanxpy-1.1.1-py38-none-any.whl (63.7 kB 查看哈希)

上传时间 Python 3.8

trepanxpy-1.1.1-py37-none-any.whl (63.7 kB 查看哈希)

上传时间 Python 3.7

trepanxpy-1.1.1-py36-none-any.whl (63.7 kB 查看哈希)

上传时间 Python 3.6

由以下组织支持