I'm writing a JIT compiler in C for x86_64 linux.
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.
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
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.
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?
jmp rax
. – Hans Passantmmap
with a hint address, so you can use a directcall
orjmp rel32
encoding. – Peter Cordes