修改 python pytecode

Modifying python pytecode

首先,我想说我知道您不应该在生产环境中这样做。别担心,这只是为了看看我可以在多大程度上更改 python 代码,而它是 运行.

我有一个接受代码对象的函数 inject_code。它还包含一些我觉得有趣的变量名。这些可以是 fasts 或 names 但我知道它们是什么以及它们的内部 ID。

目前,我正在字节码中搜索 STORE_FASTSTORE_NAME 命令。找到后,我将以下指令添加到字节码中:

LOAD_FAST/NAME   VAR_ID
PRINT_ITEM
PRINT_NEWLINE

我正在使用此代码来执行此操作:

import dis, opcode, struct

def inject_code(code, vars):
    co_code = code.co_code
    new_code = ""
    i = 0
    n = len(co_code)
    fast_name = [opcode.opmap["STORE_NAME"], opcode.opmap["STORE_FAST"]]
    while i < n:
        c = co_code[i]
        op = ord(c)
        i+=1
        arg = ""
        new_opcode = ""
        if op >= opcode.HAVE_ARGUMENT:
            arg = co_code[i:i+2]
            i+=2
            if op in fast_name:
                cur_map = vars[fast_name.index(op)]
                arg_id = struct.unpack("<H", arg)[0]
                if arg_id in cur_map:
                    new_opcode = chr(opcode.opmap[("LOAD_NAME", "LOAD_FAST")[fast_name.index(op)]])+arg
                    new_opcode += chr(opcode.opmap["PRINT_ITEM"])
                    new_opcode += chr(opcode.opmap["PRINT_NEWLINE"])
        new_code += c+arg+new_opcode
    dis.dis(new_code)
    return new_code

变量 vars 遵循以下结构:[NAME_VARIABLE_IDS, FAST_VARIABLE_IDS]

例如:[[0,2],[1,3]]

但是,完成此操作后,大多数跳转操作码的目标都是错误的,因为我插入了一些新的操作码。

如何计算新的跳跃目标?

此外,我应该如何重新对齐字节和行缩进?

如果你想要一种测试代码的简单方法,我可以在这里添加。但是我不确定默认隐藏的语法。

你需要使用字节码汇编器来处理所有这些东西:

https://pypi.python.org/pypi/BytecodeAssembler