如何完全反汇编 Python 源代码
How to fully disassemble Python source
我一直在使用 dis
库反汇编一些 Python 源代码,但我发现这不会递归到函数或 类:
import dis
source_py = "test.py"
with open(source_py) as f_source:
source_code = f_source.read()
byte_code = compile(source_code, source_py, "exec")
dis.dis(byte_code)
我只看到条目,例如:
54 456 LOAD_CONST 63 (<code object foo at 022C9458, file "test.py", line 54>)
459 MAKE_FUNCTION 0
462 STORE_NAME 20 (foo)
如果源文件有一个函数foo()
,我显然可以在源文件中添加如下内容:
dis.dis(foo)
如果不更改源文件并执行它,我不知道该怎么做。我希望能够从编译的 byte_code
中提取相关字节并将它们传递给 dis.dis()
.
def sub_byte_code(byte_code, function_or_class_name):
sub_byte_code = xxxxxx
dis.dis(sub_byte_code)
我考虑过包装源代码并按如下方式执行 dis.dis()
但我不想执行脚本:
source_code_dis = "import dis\n%s\ndis.dis(foo)\n" % (source_code)
exec(source_code_dis)
调用它是否有技巧?例如dis.dis(byte_code, recurse=True)
将文件作为模块导入并对该模块调用 dis.dis()
。
import dis
import test
dis.dis(test)
您也可以从命令行执行此操作:
python -m dis test.py
For a module, it disassembles all functions.
编辑:从python 3.7 开始,dis.dis
是递归的。
迟到的答案,但我很乐意在需要时找到它。如果要完全反汇编具有函数 的脚本而不导入它 ,则必须实现问题中提到的 sub_byte_code 函数。这是通过扫描 byte_code.co_consts 找到 types.CodeType 个文字来完成的。
下面完成问题的脚本:
import dis
import types
source_py = "test.py"
with open(source_py) as f_source:
source_code = f_source.read()
byte_code = compile(source_code, source_py, "exec")
dis.dis(byte_code)
for x in byte_code.co_consts:
if isinstance(x, types.CodeType):
sub_byte_code = x
func_name = sub_byte_code.co_name
print('\nDisassembly of %s:' % func_name)
dis.dis(sub_byte_code)
结果会是这样的:
1 0 LOAD_CONST 0 (<code object foo at 0x02CB99C0, file "test.py", line 1>)
2 LOAD_CONST 1 ('foo')
4 MAKE_FUNCTION 0
6 STORE_NAME 0 (foo)
4 8 LOAD_NAME 0 (foo)
10 LOAD_CONST 2 (42)
12 CALL_FUNCTION 1
14 STORE_NAME 1 (x)
16 LOAD_CONST 3 (None)
18 RETURN_VALUE
Disassembly of foo:
2 0 LOAD_FAST 0 (n)
2 UNARY_NEGATIVE
4 RETURN_VALUE
编辑:从 python 3.7 开始,dis.dis 反汇编函数并递归执行此操作。 dis.dis 有一个 depth
附加参数来控制要反汇编的函数定义的深度。
我一直在使用 dis
库反汇编一些 Python 源代码,但我发现这不会递归到函数或 类:
import dis
source_py = "test.py"
with open(source_py) as f_source:
source_code = f_source.read()
byte_code = compile(source_code, source_py, "exec")
dis.dis(byte_code)
我只看到条目,例如:
54 456 LOAD_CONST 63 (<code object foo at 022C9458, file "test.py", line 54>)
459 MAKE_FUNCTION 0
462 STORE_NAME 20 (foo)
如果源文件有一个函数foo()
,我显然可以在源文件中添加如下内容:
dis.dis(foo)
如果不更改源文件并执行它,我不知道该怎么做。我希望能够从编译的 byte_code
中提取相关字节并将它们传递给 dis.dis()
.
def sub_byte_code(byte_code, function_or_class_name):
sub_byte_code = xxxxxx
dis.dis(sub_byte_code)
我考虑过包装源代码并按如下方式执行 dis.dis()
但我不想执行脚本:
source_code_dis = "import dis\n%s\ndis.dis(foo)\n" % (source_code)
exec(source_code_dis)
调用它是否有技巧?例如dis.dis(byte_code, recurse=True)
将文件作为模块导入并对该模块调用 dis.dis()
。
import dis
import test
dis.dis(test)
您也可以从命令行执行此操作:
python -m dis test.py
For a module, it disassembles all functions.
编辑:从python 3.7 开始,dis.dis
是递归的。
迟到的答案,但我很乐意在需要时找到它。如果要完全反汇编具有函数 的脚本而不导入它 ,则必须实现问题中提到的 sub_byte_code 函数。这是通过扫描 byte_code.co_consts 找到 types.CodeType 个文字来完成的。
下面完成问题的脚本:
import dis
import types
source_py = "test.py"
with open(source_py) as f_source:
source_code = f_source.read()
byte_code = compile(source_code, source_py, "exec")
dis.dis(byte_code)
for x in byte_code.co_consts:
if isinstance(x, types.CodeType):
sub_byte_code = x
func_name = sub_byte_code.co_name
print('\nDisassembly of %s:' % func_name)
dis.dis(sub_byte_code)
结果会是这样的:
1 0 LOAD_CONST 0 (<code object foo at 0x02CB99C0, file "test.py", line 1>)
2 LOAD_CONST 1 ('foo')
4 MAKE_FUNCTION 0
6 STORE_NAME 0 (foo)
4 8 LOAD_NAME 0 (foo)
10 LOAD_CONST 2 (42)
12 CALL_FUNCTION 1
14 STORE_NAME 1 (x)
16 LOAD_CONST 3 (None)
18 RETURN_VALUE
Disassembly of foo:
2 0 LOAD_FAST 0 (n)
2 UNARY_NEGATIVE
4 RETURN_VALUE
编辑:从 python 3.7 开始,dis.dis 反汇编函数并递归执行此操作。 dis.dis 有一个 depth
附加参数来控制要反汇编的函数定义的深度。