I'm trying to write trampolines for x86 and amd64 so that a given function invocation is immediately vectored to an address stored at a known memory location (the purpose is to ensure the first target address lives within a given DLL (windows)).
The following code is attempting to use _fn
as a memory location (or group of them) to start actual target addresses:
(*_fn[IDX])(); // rough equivalent in C
.globl _asmfn
_asmfn:
jmp *_fn+8*IDX(%rip)
The IDX
is intended to be constructed using some CPP macros to provide a range of embedded DLL vectors each uniquely mapped to a slot in the _fn
array of function pointers.
This works in a simple test program, but when I actually put it into a shared library (for the moment testing on OSX), I get a bus error when attempting to vector to the _asmfn code:
Invalid memory access of location 0x10aa1f320 rip=0x10aa1f320
The final target of this code is Windows, though I haven't tried it there yet (I figured I could at least prove out the assembly in a test case on OSX/intel first). Is the amd64 jump at least nominally correct, or have I missed something?
A good reference on trampolines on amd64.
EDIT
The jump does work properly on windows 7 (finally got a chance to test). However, I'm still curious to know why it is failing on OSX. The bus error is caused by a KERN_PROTECTION_FAILURE, which would appear to indicate that OS protections are preventing execution of that code. The target address is allocated memory (it's a trampoline generated by libffi), but I believe it to be properly marked as executable memory. If it's an executable memory issue, that would explain why my standalone test code works (the callback trampoline is compiled, not allocated).