mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
rpcrt4: Generate stubless thunks at compile time.
This commit is contained in:
parent
533823ed2a
commit
439ce3a3ae
2 changed files with 134 additions and 116 deletions
|
@ -82,23 +82,13 @@ __ASM_GLOBAL_FUNC(call_stubless_func,
|
|||
"addl %edx,%esp\n\t"
|
||||
"jmp *%ecx" );
|
||||
|
||||
#include "pshpack1.h"
|
||||
struct thunk
|
||||
{
|
||||
BYTE mov_eax;
|
||||
DWORD index;
|
||||
BYTE jmp;
|
||||
LONG handler;
|
||||
};
|
||||
#include "poppack.h"
|
||||
|
||||
static inline void init_thunk( struct thunk *thunk, unsigned int index )
|
||||
{
|
||||
thunk->mov_eax = 0xb8; /* movl $n,%eax */
|
||||
thunk->index = index;
|
||||
thunk->jmp = 0xe9; /* jmp */
|
||||
thunk->handler = (char *)call_stubless_func - (char *)(&thunk->handler + 1);
|
||||
}
|
||||
#define THUNK_ENTRY_SIZE 12
|
||||
#define THUNK_ENTRY(num) \
|
||||
".balign 4\n\t" \
|
||||
"movl $("#num"),%eax\n\t" \
|
||||
".byte 0xe9\n\t" /* jmp */ \
|
||||
".long " __ASM_NAME("call_stubless_func") "-1f\n" \
|
||||
"1:\n\t"
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
|
@ -128,30 +118,13 @@ __ASM_GLOBAL_FUNC(call_stubless_func,
|
|||
__ASM_CFI(".cfi_adjust_cfa_offset -0x38\n\t")
|
||||
"ret" );
|
||||
|
||||
#include "pshpack1.h"
|
||||
struct thunk
|
||||
{
|
||||
BYTE mov_r10[3];
|
||||
DWORD index;
|
||||
BYTE mov_rax[2];
|
||||
void *call_stubless;
|
||||
BYTE jmp_rax[2];
|
||||
};
|
||||
#include "poppack.h"
|
||||
|
||||
static const struct thunk thunk_template =
|
||||
{
|
||||
{ 0x49, 0xc7, 0xc2 }, 0, /* movq $index,%r10 */
|
||||
{ 0x48, 0xb8 }, 0, /* movq $call_stubless_func,%rax */
|
||||
{ 0xff, 0xe0 } /* jmp *%rax */
|
||||
};
|
||||
|
||||
static inline void init_thunk( struct thunk *thunk, unsigned int index )
|
||||
{
|
||||
*thunk = thunk_template;
|
||||
thunk->index = index;
|
||||
thunk->call_stubless = call_stubless_func;
|
||||
}
|
||||
#define THUNK_ENTRY_SIZE 12
|
||||
#define THUNK_ENTRY(num) \
|
||||
".balign 4\n\t" \
|
||||
"movl $("#num"),%r10d\n\t" \
|
||||
".byte 0xe9\n\t" /* jmp */ \
|
||||
".long " __ASM_NAME("call_stubless_func") "-1f\n" \
|
||||
"1:\n\t"
|
||||
|
||||
#elif defined(__arm__)
|
||||
|
||||
|
@ -180,21 +153,11 @@ __ASM_GLOBAL_FUNC(call_stubless_func,
|
|||
"add sp, #16\n\t"
|
||||
"bx lr" );
|
||||
|
||||
struct thunk
|
||||
{
|
||||
DWORD ldr_ip; /* ldr ip,[pc] */
|
||||
DWORD ldr_pc; /* ldr pc,[pc] */
|
||||
DWORD index;
|
||||
void *func;
|
||||
};
|
||||
|
||||
static inline void init_thunk( struct thunk *thunk, unsigned int index )
|
||||
{
|
||||
thunk->ldr_ip = 0xe59fc000; /* ldr ip,[pc] */
|
||||
thunk->ldr_pc = 0xe59ff000; /* ldr pc,[pc] */
|
||||
thunk->index = index * sizeof(unsigned short);
|
||||
thunk->func = call_stubless_func;
|
||||
}
|
||||
#define THUNK_ENTRY_SIZE 12
|
||||
#define THUNK_ENTRY(num) \
|
||||
"ldr ip,1f\n\t" \
|
||||
"b.w " __ASM_NAME("call_stubless_func") "\n" \
|
||||
"1:\t.long "#num"\n\t"
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
|
@ -225,83 +188,37 @@ __ASM_GLOBAL_FUNC( call_stubless_func,
|
|||
"ldp x29, x30, [sp], #0x90\n\t"
|
||||
"ret" )
|
||||
|
||||
struct thunk
|
||||
{
|
||||
DWORD ldr_index; /* ldr w16, index */
|
||||
DWORD ldr_func; /* ldr x17, func */
|
||||
DWORD br; /* br x17 */
|
||||
DWORD index;
|
||||
void *func;
|
||||
};
|
||||
|
||||
static inline void init_thunk( struct thunk *thunk, unsigned int index )
|
||||
{
|
||||
thunk->ldr_index = 0x18000070; /* ldr w16,index */
|
||||
thunk->ldr_func = 0x58000071; /* ldr x17,func */
|
||||
thunk->br = 0xd61f0220; /* br x17 */
|
||||
thunk->index = index;
|
||||
thunk->func = call_stubless_func;
|
||||
}
|
||||
#define THUNK_ENTRY_SIZE 8
|
||||
#define THUNK_ENTRY(num) \
|
||||
"mov w16,#("#num")\n\t" \
|
||||
"b " __ASM_NAME("call_stubless_func") "\n\t"
|
||||
|
||||
#else /* __i386__ */
|
||||
|
||||
#warning You must implement stubless proxies for your CPU
|
||||
|
||||
struct thunk
|
||||
{
|
||||
DWORD index;
|
||||
};
|
||||
|
||||
static inline void init_thunk( struct thunk *thunk, unsigned int index )
|
||||
{
|
||||
thunk->index = index;
|
||||
}
|
||||
#define THUNK_ENTRY_SIZE 0
|
||||
#define THUNK_ENTRY(num) ""
|
||||
|
||||
#endif /* __i386__ */
|
||||
|
||||
#define BLOCK_SIZE 1024
|
||||
#define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */
|
||||
|
||||
static const struct thunk *method_blocks[MAX_BLOCKS];
|
||||
|
||||
static const struct thunk *allocate_block( unsigned int num )
|
||||
{
|
||||
unsigned int i;
|
||||
struct thunk *prev, *block;
|
||||
DWORD oldprot;
|
||||
|
||||
block = VirtualAlloc( NULL, BLOCK_SIZE * sizeof(*block),
|
||||
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
|
||||
if (!block) return NULL;
|
||||
|
||||
for (i = 0; i < BLOCK_SIZE; i++) init_thunk( &block[i], BLOCK_SIZE * num + i + 3 );
|
||||
VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, &oldprot );
|
||||
prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL );
|
||||
if (prev) /* someone beat us to it */
|
||||
{
|
||||
VirtualFree( block, 0, MEM_RELEASE );
|
||||
block = prev;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
extern void stubless_thunks(void);
|
||||
__ASM_GLOBAL_FUNC( stubless_thunks, ALL_THUNK_ENTRIES )
|
||||
#undef THUNK_ENTRY
|
||||
|
||||
BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num )
|
||||
{
|
||||
const void **entry = (const void **)(vtbl + 1);
|
||||
DWORD i, j;
|
||||
DWORD i;
|
||||
|
||||
if (num - 3 > BLOCK_SIZE * MAX_BLOCKS)
|
||||
if (num >= NB_THUNK_ENTRIES)
|
||||
{
|
||||
FIXME( "%lu methods not supported\n", num );
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++)
|
||||
{
|
||||
const struct thunk *block = method_blocks[i];
|
||||
if (!block && !(block = allocate_block( i ))) return FALSE;
|
||||
for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++, entry++)
|
||||
if (*entry == (LPVOID)-1) *entry = &block[j];
|
||||
}
|
||||
for (i = 0; i < num - 3; i++, entry++)
|
||||
if (*entry == (void *)-1) *entry = (char *)stubless_thunks + i * THUNK_ENTRY_SIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,4 +72,105 @@ BOOL fill_stubless_table(IUnknownVtbl *vtbl, DWORD num) DECLSPEC_HIDDEN;
|
|||
IUnknownVtbl *get_delegating_vtbl(DWORD num_methods) DECLSPEC_HIDDEN;
|
||||
void release_delegating_vtbl(IUnknownVtbl *vtbl) DECLSPEC_HIDDEN;
|
||||
|
||||
#define THUNK_ENTRY_FIRST_BLOCK() \
|
||||
THUNK_ENTRY(3) \
|
||||
THUNK_ENTRY(4) \
|
||||
THUNK_ENTRY(5) \
|
||||
THUNK_ENTRY(6) \
|
||||
THUNK_ENTRY(7) \
|
||||
THUNK_ENTRY(8) \
|
||||
THUNK_ENTRY(9) \
|
||||
THUNK_ENTRY(10) \
|
||||
THUNK_ENTRY(11) \
|
||||
THUNK_ENTRY(12) \
|
||||
THUNK_ENTRY(13) \
|
||||
THUNK_ENTRY(14) \
|
||||
THUNK_ENTRY(15) \
|
||||
THUNK_ENTRY(16) \
|
||||
THUNK_ENTRY(17) \
|
||||
THUNK_ENTRY(18) \
|
||||
THUNK_ENTRY(19) \
|
||||
THUNK_ENTRY(20) \
|
||||
THUNK_ENTRY(21) \
|
||||
THUNK_ENTRY(22) \
|
||||
THUNK_ENTRY(23) \
|
||||
THUNK_ENTRY(24) \
|
||||
THUNK_ENTRY(25) \
|
||||
THUNK_ENTRY(26) \
|
||||
THUNK_ENTRY(27) \
|
||||
THUNK_ENTRY(28) \
|
||||
THUNK_ENTRY(29) \
|
||||
THUNK_ENTRY(30) \
|
||||
THUNK_ENTRY(31)
|
||||
|
||||
#define THUNK_ENTRY_BLOCK(block) \
|
||||
THUNK_ENTRY(32 * (block) + 0) \
|
||||
THUNK_ENTRY(32 * (block) + 1) \
|
||||
THUNK_ENTRY(32 * (block) + 2) \
|
||||
THUNK_ENTRY(32 * (block) + 3) \
|
||||
THUNK_ENTRY(32 * (block) + 4) \
|
||||
THUNK_ENTRY(32 * (block) + 5) \
|
||||
THUNK_ENTRY(32 * (block) + 6) \
|
||||
THUNK_ENTRY(32 * (block) + 7) \
|
||||
THUNK_ENTRY(32 * (block) + 8) \
|
||||
THUNK_ENTRY(32 * (block) + 9) \
|
||||
THUNK_ENTRY(32 * (block) + 10) \
|
||||
THUNK_ENTRY(32 * (block) + 11) \
|
||||
THUNK_ENTRY(32 * (block) + 12) \
|
||||
THUNK_ENTRY(32 * (block) + 13) \
|
||||
THUNK_ENTRY(32 * (block) + 14) \
|
||||
THUNK_ENTRY(32 * (block) + 15) \
|
||||
THUNK_ENTRY(32 * (block) + 16) \
|
||||
THUNK_ENTRY(32 * (block) + 17) \
|
||||
THUNK_ENTRY(32 * (block) + 18) \
|
||||
THUNK_ENTRY(32 * (block) + 19) \
|
||||
THUNK_ENTRY(32 * (block) + 20) \
|
||||
THUNK_ENTRY(32 * (block) + 21) \
|
||||
THUNK_ENTRY(32 * (block) + 22) \
|
||||
THUNK_ENTRY(32 * (block) + 23) \
|
||||
THUNK_ENTRY(32 * (block) + 24) \
|
||||
THUNK_ENTRY(32 * (block) + 25) \
|
||||
THUNK_ENTRY(32 * (block) + 26) \
|
||||
THUNK_ENTRY(32 * (block) + 27) \
|
||||
THUNK_ENTRY(32 * (block) + 28) \
|
||||
THUNK_ENTRY(32 * (block) + 29) \
|
||||
THUNK_ENTRY(32 * (block) + 30) \
|
||||
THUNK_ENTRY(32 * (block) + 31)
|
||||
|
||||
#define ALL_THUNK_ENTRIES \
|
||||
THUNK_ENTRY_FIRST_BLOCK() \
|
||||
THUNK_ENTRY_BLOCK(1) \
|
||||
THUNK_ENTRY_BLOCK(2) \
|
||||
THUNK_ENTRY_BLOCK(3) \
|
||||
THUNK_ENTRY_BLOCK(4) \
|
||||
THUNK_ENTRY_BLOCK(5) \
|
||||
THUNK_ENTRY_BLOCK(6) \
|
||||
THUNK_ENTRY_BLOCK(7) \
|
||||
THUNK_ENTRY_BLOCK(8) \
|
||||
THUNK_ENTRY_BLOCK(9) \
|
||||
THUNK_ENTRY_BLOCK(10) \
|
||||
THUNK_ENTRY_BLOCK(11) \
|
||||
THUNK_ENTRY_BLOCK(12) \
|
||||
THUNK_ENTRY_BLOCK(13) \
|
||||
THUNK_ENTRY_BLOCK(14) \
|
||||
THUNK_ENTRY_BLOCK(15) \
|
||||
THUNK_ENTRY_BLOCK(16) \
|
||||
THUNK_ENTRY_BLOCK(17) \
|
||||
THUNK_ENTRY_BLOCK(18) \
|
||||
THUNK_ENTRY_BLOCK(19) \
|
||||
THUNK_ENTRY_BLOCK(20) \
|
||||
THUNK_ENTRY_BLOCK(21) \
|
||||
THUNK_ENTRY_BLOCK(22) \
|
||||
THUNK_ENTRY_BLOCK(23) \
|
||||
THUNK_ENTRY_BLOCK(24) \
|
||||
THUNK_ENTRY_BLOCK(25) \
|
||||
THUNK_ENTRY_BLOCK(26) \
|
||||
THUNK_ENTRY_BLOCK(27) \
|
||||
THUNK_ENTRY_BLOCK(28) \
|
||||
THUNK_ENTRY_BLOCK(29) \
|
||||
THUNK_ENTRY_BLOCK(30) \
|
||||
THUNK_ENTRY_BLOCK(31)
|
||||
|
||||
#define NB_THUNK_ENTRIES (32 * 32)
|
||||
|
||||
#endif /* __WINE_CPSF_H */
|
||||
|
|
Loading…
Reference in a new issue