【发布时间】:2015-06-30 03:05:24
【问题描述】:
我正在用 C 语言为 x86_64 linux 编写 JIT 编译器。
目前的想法是在可执行内存的缓冲区中生成一些字节码(例如,通过 mmap 调用获得)并使用函数指针跳转到它。
我希望能够将多个可执行内存块链接在一起,以便它们可以仅使用本机指令在彼此之间跳转。
理想情况下,指向可执行块的 C 级指针可以作为绝对跳转地址写入另一个块,如下所示:
unsigned char *code_1 = { 0xAB, 0xCD, ... };
void *exec_block_1 = mmap(code1, ... );
write_bytecode(code_1, code_block_1);
...
unsigned char *code_2 = { 0xAB, 0xCD, ... , exec_block_1, ... };
void *exec_block_2 = mmap(code2, ... );
write_bytecode(code_2, exec_block_2); // bytecode contains code_block_1 as a jump
// address so that the code in the second block
// can jump to the code in the first block
但是我发现 x86_64 的局限性在这里是一个很大的障碍。没有办法跳转到 x86_64 中的绝对 64 位地址,因为所有可用的 64 位跳转操作都是相对于指令指针的。这意味着我不能将 C 指针用作生成代码的跳转目标。
是否有解决此问题的方法可以让我按照我所描述的方式将块链接在一起?也许是我不知道的 x86_64 指令?
【问题讨论】:
-
嗯,也许您高估了生成超过 2 GB 代码的需求。 jitter 的好处是你总是可以告诉你需要回退到一个间接跳转,比如
jmp rax。 -
@HansPassant 说得好。目前我的目标只是实现最简单的工作,然后再担心性能。
-
还相关:Handling calls to far away intrinsic functions in a JIT/ re:使用带有提示地址的
mmap分配彼此靠近的块,因此您可以使用直接的call或jmp rel32编码。
标签: assembly compiler-construction x86-64 jit machine-code