Alexandre Julliard : winebuild: Improve the calling sequence for register functions.
Alexandre Julliard
julliard at winehq.org
Tue Jan 6 08:23:11 CST 2009
Module: wine
Branch: master
Commit: e31188d9dac2368e050a693086cb8ad2bbdfb2e2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e31188d9dac2368e050a693086cb8ad2bbdfb2e2
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue Jan 6 12:51:18 2009 +0100
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 5ab5b0e..b23aedf 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 9d7ba6a..d8777bc 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 4fae06e..d369c16 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 a1c7970..2dfda98 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 9cf60c3..2000937 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)
More information about the wine-cvs
mailing list