Module: wine Branch: master Commit: 439ce3a3aed17fcb41013e7e3e0271e36e5df321 URL: https://gitlab.winehq.org/wine/wine/-/commit/439ce3a3aed17fcb41013e7e3e0271e...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Nov 9 10:27:07 2023 +0100
rpcrt4: Generate stubless thunks at compile time.
---
dlls/rpcrt4/cproxy.c | 149 ++++++++++++--------------------------------------- dlls/rpcrt4/cpsf.h | 101 ++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 116 deletions(-)
diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index ea0d65db259..2fa064b1730 100644 --- a/dlls/rpcrt4/cproxy.c +++ b/dlls/rpcrt4/cproxy.c @@ -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; }
diff --git a/dlls/rpcrt4/cpsf.h b/dlls/rpcrt4/cpsf.h index 3cfbf77ff66..f8e75849301 100644 --- a/dlls/rpcrt4/cpsf.h +++ b/dlls/rpcrt4/cpsf.h @@ -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 */