Although there exists a technique that works fairly well (considering it's an ugly hack, of course) on x86, doing it natively on the x86_64 is much more complex. Because an unconditional relative jump has a maximum immediate that is a signed 32 bit integer that method won't work for jumping to a heap-allocated memory region on x86_64 (expanded address space). Therefore I have two options,
- 1) Embed an encoded indirect absolute jump to a 64 bit memory region ala: "rex.W jmpq *0x0(%rip); .quad $sym;"
- 2) Embed two encoded instructions: "movabs $sym, %r11; jmp *%r11;"
- 1) Control transfer instructions are all relative to the current instruction pointer, and therefore the immediate will need to be fixed up. The math involved isn't the problem, the instruction offsets are. If I have to extend a call/jmp instruction to use %r11 like above, it will clobber the instructions ahead of it. This can probably be mitigated by disassembling each instruction in a given function, copying each one as per normal, and offsetting the latter instructions to cope. It's ugly, but it may work.
- 2) The stack. Return addresses are stored in the stack frame, and I don't believe that the value encoded is going to be valid once a function is relocated. I don't know what to do here.