[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