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