[Python] 发一个看起来没啥用的字节码编辑库

先贴一下 README


Pyasmer 是一个 Python 字节码编辑库。它可以用来修改现有的二进制代码(例如, func.code)。

Pyasmer 可以帮助开发者在 python 代码中执行一些动态地在已有代码中插桩、代理、指令生成,

使用它需要你具备一定的 Python 字节码和 CPython 虚拟机执行机制,你可以从官方文档获取这些知识: https://docs.python.org/3/library/dis.html。Pyasmer 也会提供一些易于使用的接口,降低使用难度。

举个例子:

import sys from pyasmer.asm_instruction import asm_global_var, asm_fast_var
from pyasmer.code_writer import CodeWriter if __name__ == '__main__': _frozen_importlib = sys.modules['_frozen_importlib'] # _find_and_load_unlocked 函数会在 import 模块的时候被调用 _find_and_load_unlocked = getattr(_frozen_importlib, '_find_and_load_unlocked') cw = CodeWriter(_find_and_load_unlocked.__code__)() # 在_find_and_load_unlocked 函数开头添加一个 print ,将要被 import 的模块名称打印出来 # # 更新插入位置到函数开头(第 0 条指令) cw.update_position(offset=0) # None: 忽略返回值 # asm_global_var('print'): 调用的函数为 print # asm_fast_var('name'): 将局部变量`name`传给 print cw.call_function(None, asm_global_var('print'), asm_fast_var('name')) cw.gen_code() # 执行 import 命令 import ast

输出显示有两个模块在 import 命令过程中被引用。

output: ast _ast

目前功能还比较简单,支持插入函数调用、获取属性等功能。

此外支持通过表达式匹配定位要修改的位置,比如:

@asm_viewer
def binary_ops(a, b): return [a + b, a - b, a * b, a / b, a + b] def test_match_binary_op(): cv: CodeViewer = binary_ops.viewer # 匹配到两处 a + b 的位置 binary_add = [x for x in cv.find_snippet_by_expression("a + b", local_vars=["a", "b"])] assert len(binary_add) == 2 # 第 0-2 条指令和第 12-14 条指令 # LOAD_FAST a # LOAD_FAST b # BINARY_ADD assert binary_add == [(0, 2), (12, 14)]

总之,想要更多的功能欢迎来手搓,使用场景请各自脑补,over~~~