Commit e31188d9 authored by Alexandre Julliard's avatar Alexandre Julliard

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.
parent 9f6ff3d5
......@@ -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
......@@ -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
......
......@@ -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))
......
......@@ -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 */
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment