跳转以获取JIT(x86_64) [英] Jumps for a JIT (x86_64)

查看:192
本文介绍了跳转以获取JIT(x86_64)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用C编写用于x86_64 linux的JIT编译器.

I'm writing a JIT compiler in C for x86_64 linux.

当前的想法是在可执行内存的缓冲区中生成一些字节码(例如,通过mmap调用获得),然后使用函数指针跳转到该字节码.

Currently the idea is to generate some bytecode in a buffer of executable memory (e.g. obtained with an mmap call) and jump to it with a function pointer.

我希望能够将可执行内存的多个块链接在一起,以便它们仅使用本机指令就可以在彼此之间跳转.

I'd like to be able to link multiple blocks of executable memory together such that they can jump between each other using only native instructions.

理想情况下,指向可执行块的C级指针可以写为另一个块,作为绝对跳转地址,如下所示:

Ideally, the C-level pointer to an executable block can be written into another block as an absolute jump address something like this:

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的局限性是一个很大的障碍.由于所有可用的64位跳转操作都相对于指令指针,因此无法跳转到x86_64中的绝对64位地址.这意味着我不能将C指针用作生成代码的跳转目标.

However I'm finding the limitations of x86_64 quite an obstacle here. There's no way to jump to an absolute 64-bit address in x86_64 as all available 64-bit jump operations are relative to the instruction pointer. This means that I can't use the C-pointer as a jump target for generated code.

是否有解决此问题的方法,使我可以按照上述方式将块链接在一起?也许是我不知道的x86_64指令?

Is there a solution to this problem that will allow me to link blocks together in the manner I've described? Perhaps an x86_64 instruction that I'm not aware of?

推荐答案

嗯,我不确定我是否清楚地理解了你的问题,以及那是否是正确的答案.这是实现这一目标的复杂方法:

Hmm I'm not sure if I clearly understood your question and if that a proper answer. it's quite a convoluted way to achieve this:

    ;instr              ; opcodes [op size] (comment)
    call next           ; e8 00 00 00 00 [4] (call to get current location)
next:
    pop rax             ; 58 [1]  (next label address in rax)
    add rax, 12h        ; 48 83 c0 12 [4] (adjust rax to fall on landing label)
    push rax            ; 50 [1]  (push adjusted value)
    mov rax, code_block ; 48 b8 XX XX XX XX XX XX XX XX [10] (load target address)
    push rax            ; 50 [1] (push to ret to code_block)
    ret                 ; c3 [1] (go to code_block)
landing:    
    nop
    nop

e8 00 00 00 00刚好在那里,用于将当前指针放在堆栈顶部.然后代码将rax调整为稍后落在着陆标签上.您需要将XX(在mov rax, code_block中)替换为code block的虚拟地址. ret指令用作调用.呼叫者返回时,代码应落在landing上.

e8 00 00 00 00 is just there to get the current pointer on top of stack. Then the code adjusts rax to fall on landing label later. You'll need to replace the XX (in mov rax, code_block) by the virtual address of code block. The ret instruction is used as a call. When caller returns, the code should fall on landing.

您正在尝试实现这种目标吗?

Is that this kind of thing you're trying to achieve?

这篇关于跳转以获取JIT(x86_64)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆