This is the mail archive of the
libffi-discuss@sourceware.org
mailing list for the libffi project.
libffi stdcall patch/trampolines
- From: Timothy Wall <twalljava at dev dot java dot net>
- To: Anthony Green <green at redhat dot com>
- Cc: libffi-discuss at sourceware dot org
- Date: Thu, 31 Jan 2008 21:44:31 -0500
- Subject: libffi stdcall patch/trampolines
Anthony,
I was looking over the incorporation of my patch and have a few
comments w/r/t the trampoline initialization. The displacement value
(__dis) must be the offset from the instruction immediately after the
jump instruction to the called function. In the first case, the
offset happens to correspond to FFI_TRAMPOLINE_SIZE (10 prior to my
patch), but using that constant is misleading since you're not
actually trying to offset to the end of the trampoline but rather to
the instruction after "jmp __fun" (which just happens to be at the
end of the trampoline). If the trampoline size is defined to be the
bigger value required for a stdcall trampoline, the offset is going
to be incorrect.
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
*(unsigned char*) &__tramp[0] = 0xb8; \
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
*(unsigned char *) &__tramp[5] = 0xe9; \
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
})
The distinction is much more critical here, where the target
instruction is *not* at the end of the trampoline, but at the same 10-
byte offset as the previous template. The trampoline itself is bigger.
#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned int __dis = __fun - ((unsigned int) __tramp +
FFI_TRAMPOLINE_SIZE);
\
unsigned short __size = (unsigned short)(SIZE); \
*(unsigned char*) &__tramp[0] = 0xb8; \
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
*(unsigned char *) &__tramp[5] = 0xe8; \
*(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
*(unsigned char *) &__tramp[10] = 0xc2; \
*(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
})