[PATCH] ntdll: Implement the relay channel for amd64

Maarten Lankhorst m.b.lankhorst at gmail.com
Tue Dec 16 11:33:35 CST 2008


---
 dlls/ntdll/relay.c |  152 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 129 insertions(+), 23 deletions(-)

diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c
index a3031f2..28cef2a 100644
--- a/dlls/ntdll/relay.c
+++ b/dlls/ntdll/relay.c
@@ -38,10 +38,13 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(relay);
 
-#ifdef __i386__
+#if defined(__i386__) || defined(__x86_64__)
 
+#ifdef __i386__
+/* Snoop only channels */
 WINE_DECLARE_DEBUG_CHANNEL(snoop);
 WINE_DECLARE_DEBUG_CHANNEL(seh);
+#endif
 
 struct relay_descr  /* descriptor for a module */
 {
@@ -54,7 +57,7 @@ struct relay_descr  /* descriptor for a module */
     const unsigned int *arg_types;           /* table of argument types for all entry points */
 };
 
-#define RELAY_DESCR_MAGIC  ((void *)0xdeb90001)
+#define RELAY_DESCR_MAGIC  ((void *)0xdeb90001L)
 
 /* private data built at dll load time */
 
@@ -299,27 +302,41 @@ static BOOL check_from_module( const WCHAR **includelist, const WCHAR **excludel
     return show;
 }
 
+#if defined(__i386__) || defined(__x86_64__)
+
 /***********************************************************************
  *           RELAY_PrintArgs
  */
-static inline void RELAY_PrintArgs( const int *args, int nb_args, unsigned int typemask )
+static inline void RELAY_PrintArgs( const long *args, int nb_args, unsigned int typemask )
 {
-    while (nb_args--)
+    int x;
+
+    for (x = 0; x < nb_args; ++x)
     {
-	if ((typemask & 3) && HIWORD(*args))
+#ifdef __x86_64__
+        if (x == 4)
+            /* Skip the return address and 32-byte reserved area */
+            args += 6;
+#endif
+
+        if ((typemask & 3) && HIWORD(*args))
         {
-	    if (typemask & 2)
-                DPRINTF( "%08x %s", *args, debugstr_w((LPCWSTR)*args) );
+            if (typemask & 2)
+                DPRINTF( "%08lx %s", *args, debugstr_w((LPCWSTR)*args) );
             else
-                DPRINTF( "%08x %s", *args, debugstr_a((LPCSTR)*args) );
-	}
-        else DPRINTF( "%08x", *args );
-        if (nb_args) DPRINTF( "," );
-        args++;
+                DPRINTF( "%08lx %s", *args, debugstr_a((LPCSTR)*args) );
+        }
+        else DPRINTF( "%08lx", *args );
+        if (x + 1 < nb_args) DPRINTF( "," );
+        ++args;
         typemask >>= 2;
     }
 }
 
+#endif
+
+#ifdef __i386__
+
 extern LONGLONG call_entry_point( void *func, int nb_args, const int *args );
 __ASM_GLOBAL_FUNC( call_entry_point,
                    "\tpushl %ebp\n"
@@ -455,6 +472,84 @@ void WINAPI __regs_relay_call_from_32_regs( struct relay_descr *descr, unsigned
 extern void WINAPI relay_call_from_32_regs(void);
 DEFINE_REGS_ENTRYPOINT( relay_call_from_32_regs, 16, 16 )
 
+#else
+
+extern long __attribute__((ms_abi)) call_entry_point( void *func, int stack_args, const long *args, const long *lastarg );
+__ASM_GLOBAL_FUNC( call_entry_point,
+                   "\tpushq %rbp\n"
+                   "\tmovq %rsp,%rbp\n"
+
+                   /* Copy all stack arguments to new stack */
+                   "2:\ttest %edx, %edx\n"
+                   "\tjz 1f\n"
+                   "\tpushq (%r9)\n"
+                   "\tsubq $0x8, %r9\n"
+                   "\tsubl $0x1, %edx\n"
+                   "\tjmp 2b\n"
+
+                   "1:\tsubq $0x20, %rsp\n"
+                   "\tpushq %rcx\n"
+                   "\tmovq %r8, %rax\n"
+
+                   /* Restore last four arguments */
+                   "\tmovq 0x0(%rax), %rcx\n"
+                   "\tmovq 0x8(%rax), %rdx\n"
+                   "\tmovq 0x10(%rax), %r8\n"
+                   "\tmovq 0x18(%rax), %r9\n"
+                   "\tpopq %rax\n"
+                   "\tcall *%rax\n"
+                   "\tleaveq\n"
+                   "\tretq\n")
+
+/***********************************************************************
+ *           relay_call_from_64
+ */
+static long WINAPI relay_call_from_64( struct relay_descr *descr, unsigned int idx, const long *stack )
+{
+    long ret;
+    WORD ordinal = LOWORD(idx);
+    BYTE nb_args = LOBYTE(HIWORD(idx));
+/*  BYTE flags   = HIBYTE(HIWORD(idx)); -- not used */
+    struct relay_private_data *data = descr->private;
+    struct relay_entry_point *entry_point = data->entry_points + ordinal;
+
+    int stack_args;
+    if (nb_args > 4)
+        stack_args = nb_args - 4;
+    else
+        stack_args = 0;
+
+    if (stack_args % 2)
+        /* Make sure the stack stays 16-byte aligned! Copy a fake additional parameter */
+        ++stack_args;
+
+    stack += 4;
+
+    if (TRACE_ON(relay))
+    {
+        if (entry_point->name)
+            DPRINTF( "%04x:Call %s.%s(", GetCurrentThreadId(), data->dllname, entry_point->name );
+        else
+            DPRINTF( "%04x:Call %s.%u(", GetCurrentThreadId(), data->dllname, data->base + ordinal );
+        RELAY_PrintArgs( stack, nb_args, descr->arg_types[ordinal] );
+        DPRINTF( ") ret=%08lx\n", stack[5] );
+
+        ret = call_entry_point( entry_point->orig_func, stack_args, stack, stack + stack_args + 9 );
+
+        if (entry_point->name)
+            DPRINTF( "%04x:Ret  %s.%s()", GetCurrentThreadId(), data->dllname, entry_point->name );
+        else
+            DPRINTF( "%04x:Ret  %s.%u()", GetCurrentThreadId(), data->dllname, data->base + ordinal );
+
+        DPRINTF( " retval=%08lx ret=%08lx\n", (long)ret, stack[5] );
+    }
+    else
+        ret = call_entry_point( entry_point->orig_func, stack_args, stack, stack + stack_args + 9 );
+    return ret;
+}
+
+#endif
+
 
 /***********************************************************************
  *           RELAY_GetProcAddress
@@ -502,8 +597,12 @@ void RELAY_SetupDLL( HMODULE module )
                                   (exports->NumberOfFunctions-1) * sizeof(data->entry_points) )))
         return;
 
+#ifdef __i386__
     descr->relay_from_32 = relay_call_from_32;
     descr->relay_from_32_regs = relay_call_from_32_regs;
+#else
+    descr->relay_from_32 = relay_call_from_64;
+#endif
     descr->private = data;
 
     data->module = module;
@@ -538,7 +637,10 @@ void RELAY_SetupDLL( HMODULE module )
     }
 }
 
+#endif
 
+#ifdef __i386__
+/* Snoop support is i386 only for now */
 
 /***********************************************************************/
 /* snoop support */
@@ -743,11 +845,11 @@ FARPROC SNOOP_GetProcAddress( HMODULE hmod, const IMAGE_EXPORT_DIRECTORY *export
     return (FARPROC)&(fun->lcall);
 }
 
-static void SNOOP_PrintArg(DWORD x)
+static void SNOOP_PrintArg(DWORD_PTR x)
 {
     int i,nostring;
 
-    DPRINTF("%08x",x);
+    DPRINTF("%08lx",x);
     if (!HIWORD(x) || TRACE_ON(seh)) return; /* trivial reject to avoid faults */
     __TRY
     {
@@ -780,11 +882,12 @@ static void SNOOP_PrintArg(DWORD x)
     __ENDTRY
 }
 
-#define CALLER1REF (*(DWORD*)context->Esp)
+#define CALLER1REF (*(DWORD_PTR*)context->Esp)
 
-void WINAPI __regs_SNOOP_Entry( CONTEXT86 *context )
+void WINAPI __regs_SNOOP_Entry( CONTEXT *context )
 {
-	DWORD		ordinal=0,entry = context->Eip - 5;
+	DWORD		ordinal=0;
+	DWORD_PTR	entry = context->Eip - 5;
 	SNOOP_DLL	*dll = firstdll;
 	SNOOP_FUN	*fun = NULL;
 	SNOOP_RETURNENTRIES	**rets = &firstrets;
@@ -802,7 +905,7 @@ void WINAPI __regs_SNOOP_Entry( CONTEXT86 *context )
 		dll=dll->next;
 	}
 	if (!dll) {
-		FIXME("entrypoint 0x%08x not found\n",entry);
+		FIXME("entrypoint 0x%08lx not found\n",entry);
 		return; /* oops */
 	}
 	/* guess cdecl ... */
@@ -875,7 +978,7 @@ void WINAPI __regs_SNOOP_Entry( CONTEXT86 *context )
 }
 
 
-void WINAPI __regs_SNOOP_Return( CONTEXT86 *context )
+void WINAPI __regs_SNOOP_Return( CONTEXT *context )
 {
 	SNOOP_RETURNENTRY	*ret = (SNOOP_RETURNENTRY*)(context->Eip - 5);
         SNOOP_FUN *fun = &ret->dll->funs[ret->ordinal];
@@ -931,20 +1034,23 @@ DEFINE_REGS_ENTRYPOINT( SNOOP_Return, 0, 0 )
 
 #else  /* __i386__ */
 
+#ifndef __x86_64__
 FARPROC RELAY_GetProcAddress( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
                               DWORD exp_size, FARPROC proc, DWORD ordinal, const WCHAR *user )
 {
     return proc;
 }
 
-FARPROC SNOOP_GetProcAddress( HMODULE hmod, const IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
-                              FARPROC origfun, DWORD ordinal, const WCHAR *user )
+void RELAY_SetupDLL( HMODULE module )
 {
-    return origfun;
 }
 
-void RELAY_SetupDLL( HMODULE module )
+#endif
+
+FARPROC SNOOP_GetProcAddress( HMODULE hmod, const IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
+                              FARPROC origfun, DWORD ordinal, const WCHAR *user )
 {
+    return origfun;
 }
 
 void SNOOP_SetupDLL( HMODULE hmod )
-- 
1.5.6.5


--------------050209010308020105000602--



More information about the wine-patches mailing list