我试图在python中编写一个简单的JIT,包括将机器代码写入mmap-ed内存然后执行它。
按照此blog post中的说明,双倍功能的目标代码
int multby2(int a) { return 2*a; }
(在我的macOS El Capitan机器上)
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 89 7d fc mov DWORD PTR [rbp-0x4],edi
7: 8b 7d fc mov edi,DWORD PTR [rbp-0x4]
a: c1 e7 01 shl edi,0x1
d: 89 f8 mov eax,edi
f: 5d pop rbp
10: c3 ret
将其写为Python 3字节对象:
MULT_BY_TWO_OBJ = b''.join([
b'\x55', # push rbp
b'\x48\x89\xe5', # mov rbp,rsp
b'\x89\x7d\xfc', # mov DWORD PTR [rbp-0x4],edi
b'\x8b\x7d\xfc', # mov edi,DWORD PTR [rbp-0x4]
b'\xc1\xe7\x01', # shl edi,0x1
b'\x89\xf8', # mov eax,edi
b'\x5d', # pop rbp
b'\xc3', # ret
])
我的程序用于将此机器代码写入mmap-ed缓冲区,然后执行如下:
import mmap
import ctypes
mm_buf = mmap.mmap(
-1, len(MULT_BY_TWO_OBJ),
flags=mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE,
prot=mmap.PROT_WRITE | mmap.PROT_EXEC)
mm_buf.write(MULT_BY_TWO_OBJ)
prototype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
mm_buf_address = ctypes.c_int.from_buffer(mm_buf)
double_func = prototype(mm_buf_address.value)
print(double_func(ctypes.c_int(1)))
mm_buf.close()
运行此程序会导致分段错误:
Segmentation fault: 11
是否可以在Python中执行这样的mmap-ed机器代码? Python中使用mmap
和ctypes
是否有更好的方法?