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.
This commit is contained in:
parent
9f6ff3d5af
commit
e31188d9da
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue