我有个这个函数,当它被反汇编时看起来像这样:
def game_on():
def other_function():
print('Statement within a another function')
print("Hello World")
sys.exit()
print("Statement after sys.exit")
8 0 LOAD_CONST 1 (<code object easter_egg at 0x0000000005609C90, file "filename", line 8>)
3 LOAD_CONST 2 ('game_on.<locals>.other_function')
6 MAKE_FUNCTION 0
9 STORE_FAST 0 (other_function)
10 12 LOAD_GLOBAL 0 (print)
15 LOAD_CONST 3 ('Hello World')
18 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
21 POP_TOP
11 22 LOAD_GLOBAL 1 (sys)
25 LOAD_ATTR 2 (exit)
28 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
31 POP_TOP
12 32 LOAD_GLOBAL 0 (print)
35 LOAD_CONST 4 ('second print statement')
38 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
41 POP_TOP
42 LOAD_CONST 5 (None)
45 RETURN_VALUE
有没有一种方法可以修改字节码,使其不打印“Hello world。”就像我想跳过第10行并继续到第11行。
有很多类似检查器和settrace
的材料,但它们不是非常直接。有人对此有什么信息或者能指点我该怎么做吗?
bytecode
库(https://github.com/vstinner/bytecode)。不过看起来你还在使用 Python 3.4,所以你可能需要使用旧版的byteplay
库,可以尝试使用 Serprex 的 3.x 移植版本。 - abarnertCALL_FUNCTION
到print
。由于该print
恰好在一行上,因此很明显偏移量[12,22)
是相关的。作为双重检查,如果您足够了解字节码,可以看到偏移量12将函数推入堆栈,偏移量15将唯一参数推入堆栈,偏移量18调用函数,偏移量21丢弃返回值。因此,您只需使用该范围内的所有字节替换为dis.opmap['NOP']
。然后重新构建代码对象,并将函数对象的__code__
替换为结果,就完成了。 - abarnerttypes.CodeType
的构造函数调用起来很麻烦,所以我不喜欢向任何我不讨厌的人推荐它。 - abarnertbyteplay
和bytecode
文档可能有示例和其他资源的链接。我相信有一些博客文章可以帮助您 - 我可能甚至写过一两篇;我有机会时会检查一下。 - abarnert