From e31188d9dac2368e050a693086cb8ad2bbdfb2e2 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 6 Jan 2009 12:51:18 +0100 Subject: [PATCH] winebuild: Improve the calling sequence for register functions. Pass parameters on the stack instead of retrieving them from the code stream; this ensures that the code contains only valid instructions. --- dlls/kernel32/kernel_private.h | 8 ++++---- dlls/ntdll/ntdll_misc.h | 8 ++++---- dlls/ntdll/relay.c | 9 +++++---- tools/winebuild/relay.c | 33 ++++++++++++++++----------------- tools/winebuild/spec32.c | 1 - 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/dlls/kernel32/kernel_private.h b/dlls/kernel32/kernel_private.h index 5ab5b0e6593..b23aedfc13f 100644 --- a/dlls/kernel32/kernel_private.h +++ b/dlls/kernel32/kernel_private.h @@ -148,10 +148,10 @@ extern HANDLE get_BaseNamedObjects_handle(void); #ifdef __i386__ #define DEFINE_REGS_ENTRYPOINT( name, args ) \ __ASM_GLOBAL_FUNC( name, \ - "pushl %eax\n\t" \ - "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" \ - ".long " __ASM_NAME("__regs_") #name "-.\n\t" \ - ".byte 4*" #args ",4*" #args ) + ".byte 0x68\n\t" /* pushl $__regs_func */ \ + ".long " __ASM_NAME("__regs_") #name "-.-11\n\t" \ + ".byte 0x6a," #args "\n\t" /* pushl $args */ \ + "call " __ASM_NAME("__wine_call_from_32_regs")) #endif #endif diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 9d7ba6a8354..d8777bc59db 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -219,10 +219,10 @@ static inline struct ntdll_thread_regs *ntdll_get_thread_regs(void) #ifdef __i386__ #define DEFINE_REGS_ENTRYPOINT( name, args ) \ __ASM_GLOBAL_FUNC( name, \ - "pushl %eax\n\t" \ - "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" \ - ".long " __ASM_NAME("__regs_") #name "-.\n\t" \ - ".byte 4*" #args ",4*" #args ) + ".byte 0x68\n\t" /* pushl $__regs_func */ \ + ".long " __ASM_NAME("__regs_") #name "-.-11\n\t" \ + ".byte 0x6a," #args "\n\t" /* pushl $args */ \ + "call " __ASM_NAME("__wine_call_from_32_regs")) /* FIXME: add support for other CPUs */ #endif diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c index 4fae06e3f0f..d369c16875a 100644 --- a/dlls/ntdll/relay.c +++ b/dlls/ntdll/relay.c @@ -447,16 +447,17 @@ void WINAPI __regs_relay_call_regs( struct relay_descr *descr, unsigned int idx, context->Edx, context->Esi, context->Edi, context->Ebp, context->Esp, context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags ); - assert( orig_func[0] == 0x50 /* pushl %eax */ ); - assert( orig_func[1] == 0xe8 /* call */ ); + assert( orig_func[0] == 0x68 /* pushl func */ ); + assert( orig_func[5] == 0x6a /* pushl args */ ); + assert( orig_func[7] == 0xe8 /* call */ ); } /* now call the real function */ memcpy( args_copy, args, nb_args * sizeof(args[0]) ); - args_copy[nb_args++] = (int)context; /* append context argument */ + args_copy[nb_args++] = (INT_PTR)context; /* append context argument */ - call_entry_point( orig_func + 6 + *(int *)(orig_func + 6), nb_args, args_copy ); + call_entry_point( orig_func + 12 + *(int *)(orig_func + 1), nb_args, args_copy ); if (TRACE_ON(relay)) diff --git a/tools/winebuild/relay.c b/tools/winebuild/relay.c index a1c7970520f..2dfda9800d8 100644 --- a/tools/winebuild/relay.c +++ b/tools/winebuild/relay.c @@ -741,9 +741,10 @@ static void BuildCallTo32CBClient( BOOL isEx ) * * Stack layout: * ... - * (ebp+16) first arg - * (ebp+12) ret addr to user code - * (ebp+8) eax saved by relay code + * (ebp+20) first arg + * (ebp+16) ret addr to user code + * (ebp+12) func to call (relative to relay code ret addr) + * (ebp+8) number of args * (ebp+4) ret addr to relay code * (ebp+0) saved ebp * (ebp-128) buffer area to allow stack frame manipulation @@ -770,17 +771,16 @@ static void BuildCallFrom32Regs(void) output( "\tpushl %%ebp\n" ); output( "\tmovl %%esp,%%ebp\n "); - output( "\tleal -%d(%%esp), %%esp\n", STACK_SPACE + 4 /* for context arg */); + output( "\tleal -%d(%%esp),%%esp\n", STACK_SPACE ); /* Build the context structure */ + output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eax) - STACK_SPACE ); output( "\tpushfl\n" ); output( "\tpopl %%eax\n" ); output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(EFlags) - STACK_SPACE ); output( "\tmovl 0(%%ebp),%%eax\n" ); output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Ebp) - STACK_SPACE ); - output( "\tmovl 8(%%ebp),%%eax\n" ); - output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eax) - STACK_SPACE ); output( "\tmovl %%ebx,%d(%%ebp)\n", CONTEXTOFFSET(Ebx) - STACK_SPACE ); output( "\tmovl %%ecx,%d(%%ebp)\n", CONTEXTOFFSET(Ecx) - STACK_SPACE ); output( "\tmovl %%edx,%d(%%ebp)\n", CONTEXTOFFSET(Edx) - STACK_SPACE ); @@ -805,31 +805,30 @@ static void BuildCallFrom32Regs(void) output( "\tmovl $0x%x,%%eax\n", CONTEXT86_FULL ); output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(ContextFlags) - STACK_SPACE ); - output( "\tmovl 12(%%ebp),%%eax\n" ); /* Get %eip at time of call */ + output( "\tmovl 16(%%ebp),%%eax\n" ); /* Get %eip at time of call */ output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eip) - STACK_SPACE ); /* Transfer the arguments */ - output( "\tmovl 4(%%ebp),%%ebx\n" ); /* get relay code addr */ - output( "\tmovzbl 4(%%ebx),%%ecx\n" ); /* fetch number of args to copy */ - output( "\tsubl %%ecx,%%esp\n" ); + output( "\tmovl 8(%%ebp),%%ecx\n" ); /* fetch number of args to copy */ + output( "\tleal 4(,%%ecx,4),%%edx\n" ); /* add 4 for context arg */ + output( "\tsubl %%edx,%%esp\n" ); output( "\tandl $~15,%%esp\n" ); - output( "\tleal 16(%%ebp),%%esi\n" ); /* get %esp at time of call */ + output( "\tleal 20(%%ebp),%%esi\n" ); /* get %esp at time of call */ output( "\tmovl %%esp,%%edi\n" ); - output( "\tshrl $2,%%ecx\n" ); + output( "\ttest %%ecx,%%ecx\n" ); output( "\tjz 1f\n" ); output( "\tcld\n" ); output( "\trep\n\tmovsl\n" ); /* copy args */ output( "1:\tleal %d(%%ebp),%%eax\n", -STACK_SPACE ); /* get addr of context struct */ output( "\tmovl %%eax,(%%edi)\n" ); /* and pass it as extra arg */ - output( "\tmovzbl 5(%%ebx),%%eax\n" ); /* fetch number of args to remove */ - output( "\tleal 16(%%ebp,%%eax),%%eax\n" ); - output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Esp) - STACK_SPACE ); + output( "\tmovl %%esi,%d(%%ebp)\n", CONTEXTOFFSET(Esp) - STACK_SPACE ); /* Call the entry point */ - output( "\taddl (%%ebx),%%ebx\n" ); - output( "\tcall *%%ebx\n" ); + output( "\tmovl 4(%%ebp),%%eax\n" ); /* get relay code addr */ + output( "\taddl 12(%%ebp),%%eax\n" ); + output( "\tcall *%%eax\n" ); output( "\tleal -%d(%%ebp),%%ecx\n", STACK_SPACE ); /* Restore the context structure */ diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 9cf60c3f15c..20009373ebd 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -137,7 +137,6 @@ static void output_relay_debug( DLLSPEC *spec ) output( "\tpushl %%esp\n" ); if (odp->flags & FLAG_RET64) flags |= 1; - if (odp->type == TYPE_STDCALL) flags |= 2; output( "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) ); if (UsePIC)