Commit f4e58868 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Make the entire relay entry point routine CPU-specific.

parent 1f47580e
......@@ -320,8 +320,68 @@ static inline void RELAY_PrintArgs( const INT_PTR *args, int nb_args, unsigned i
}
}
extern LONGLONG CDECL call_entry_point( void *func, int nb_args, const INT_PTR *args, int flags );
static void print_timestamp(void)
{
ULONG ticks = NtGetTickCount();
DPRINTF( "%3u.%03u:", ticks / 1000, ticks % 1000 );
}
/***********************************************************************
* relay_trace_entry
*
* stack points to the return address, i.e. the first argument is stack[1].
*/
void * WINAPI relay_trace_entry( struct relay_descr *descr, unsigned int idx, const INT_PTR *stack )
{
WORD ordinal = LOWORD(idx);
BYTE nb_args = LOBYTE(HIWORD(idx));
struct relay_private_data *data = descr->private;
struct relay_entry_point *entry_point = data->entry_points + ordinal;
if (TRACE_ON(relay))
{
if (TRACE_ON(timestamp)) print_timestamp();
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 + 1, nb_args, descr->arg_types[ordinal] );
DPRINTF( ") ret=%08lx\n", stack[0] );
}
return entry_point->orig_func;
}
/***********************************************************************
* relay_trace_exit
*/
void WINAPI relay_trace_exit( struct relay_descr *descr, unsigned int idx,
const INT_PTR *stack, LONGLONG retval )
{
WORD ordinal = LOWORD(idx);
BYTE flags = HIBYTE(HIWORD(idx));
struct relay_private_data *data = descr->private;
struct relay_entry_point *entry_point = data->entry_points + ordinal;
if (!TRACE_ON(relay)) return;
if (TRACE_ON(timestamp)) print_timestamp();
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 );
if (flags & 1) /* 64-bit return value */
DPRINTF( " retval=%08x%08x ret=%08lx\n",
(UINT)(retval >> 32), (UINT)retval, stack[0] );
else
DPRINTF( " retval=%08lx ret=%08lx\n", (UINT_PTR)retval, stack[0] );
}
#ifdef __i386__
extern LONGLONG CDECL call_entry_point( void *func, int nb_args, const INT_PTR *args, int flags );
__ASM_GLOBAL_FUNC( call_entry_point,
"pushl %ebp\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
......@@ -355,7 +415,84 @@ __ASM_GLOBAL_FUNC( call_entry_point,
__ASM_CFI(".cfi_def_cfa %esp,4\n\t")
__ASM_CFI(".cfi_same_value %ebp\n\t")
"ret" )
static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, const INT_PTR *stack )
{
BYTE nb_args = LOBYTE(HIWORD(idx));
BYTE flags = HIBYTE(HIWORD(idx));
void *func = relay_trace_entry( descr, idx, stack );
LONGLONG ret = call_entry_point( func, nb_args, stack + 1, flags );
relay_trace_exit( descr, idx, stack, ret );
return ret;
}
void WINAPI __regs_relay_call_regs( struct relay_descr *descr, unsigned int idx,
unsigned int orig_eax, unsigned int ret_addr,
CONTEXT *context )
{
WORD ordinal = LOWORD(idx);
BYTE nb_args = LOBYTE(HIWORD(idx));
struct relay_private_data *data = descr->private;
struct relay_entry_point *entry_point = data->entry_points + ordinal;
BYTE *orig_func = entry_point->orig_func;
INT_PTR *args = (INT_PTR *)context->Esp;
INT_PTR args_copy[32];
/* restore the context to what it was before the relay thunk */
context->Eax = orig_eax;
context->Eip = ret_addr;
context->Esp += nb_args * sizeof(int);
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( args, nb_args, descr->arg_types[ordinal] );
DPRINTF( ") ret=%08x\n", ret_addr );
DPRINTF( "%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n",
GetCurrentThreadId(), context->Eax, context->Ebx, context->Ecx,
context->Edx, context->Esi, context->Edi, context->Ebp, context->Esp,
context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags );
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_PTR)context; /* append context argument */
call_entry_point( orig_func + 12 + *(int *)(orig_func + 1), nb_args, args_copy, 0 );
if (TRACE_ON(relay))
{
if (entry_point->name)
DPRINTF( "%04x:Ret %s.%s() retval=%08x ret=%08x\n",
GetCurrentThreadId(), data->dllname, entry_point->name,
context->Eax, context->Eip );
else
DPRINTF( "%04x:Ret %s.%u() retval=%08x ret=%08x\n",
GetCurrentThreadId(), data->dllname, data->base + ordinal,
context->Eax, context->Eip );
DPRINTF( "%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n",
GetCurrentThreadId(), context->Eax, context->Ebx, context->Ecx,
context->Edx, context->Esi, context->Edi, context->Ebp, context->Esp,
context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags );
}
}
extern void WINAPI relay_call_regs(void);
DEFINE_REGS_ENTRYPOINT( relay_call_regs, 4 )
#elif defined(__arm__)
extern LONGLONG CDECL call_entry_point( void *func, int nb_args, const INT_PTR *args, int flags );
__ASM_GLOBAL_FUNC( call_entry_point,
".arm\n\t"
"push {r4, r5, LR}\n\t"
......@@ -388,7 +525,25 @@ __ASM_GLOBAL_FUNC( call_entry_point,
"5:\tblx r4\n\t"
"mov SP, r5\n\t"
"pop {r4, r5, PC}" )
#else
static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, const INT_PTR *stack )
{
BYTE nb_args = LOBYTE(HIWORD(idx));
BYTE flags = HIBYTE(HIWORD(idx));
void *func = relay_trace_entry( descr, idx, stack );
LONGLONG ret = call_entry_point( func, nb_args, stack + 1, flags );
relay_trace_exit( descr, idx, stack, ret );
return ret;
}
static void WINAPI relay_call_regs( struct relay_descr *descr, INT_PTR idx, INT_PTR *stack )
{
assert(0); /* should never be called */
}
#elif defined(__x86_64__)
extern LONGLONG CDECL call_entry_point( void *func, int nb_args, const INT_PTR *args, int flags );
__ASM_GLOBAL_FUNC( call_entry_point,
"pushq %rbp\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
......@@ -428,139 +583,25 @@ __ASM_GLOBAL_FUNC( call_entry_point,
__ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
__ASM_CFI(".cfi_same_value %rbp\n\t")
"ret")
#endif
static void print_timestamp(void)
{
ULONG ticks = NtGetTickCount();
DPRINTF( "%3u.%03u:", ticks / 1000, ticks % 1000 );
}
/***********************************************************************
* relay_call
*
* stack points to the return address, i.e. the first argument is stack[1].
*/
static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, const INT_PTR *stack )
{
LONGLONG ret;
WORD ordinal = LOWORD(idx);
BYTE nb_args = LOBYTE(HIWORD(idx));
BYTE flags = HIBYTE(HIWORD(idx));
struct relay_private_data *data = descr->private;
struct relay_entry_point *entry_point = data->entry_points + ordinal;
if (!TRACE_ON(relay))
ret = call_entry_point( entry_point->orig_func, nb_args, stack + 1, flags );
else
{
if (TRACE_ON(timestamp))
print_timestamp();
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 + 1, nb_args, descr->arg_types[ordinal] );
DPRINTF( ") ret=%08lx\n", stack[0] );
ret = call_entry_point( entry_point->orig_func, nb_args, stack + 1, flags );
if (TRACE_ON(timestamp))
print_timestamp();
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 );
if (flags & 1) /* 64-bit return value */
DPRINTF( " retval=%08x%08x ret=%08lx\n",
(UINT)(ret >> 32), (UINT)ret, stack[0] );
else
DPRINTF( " retval=%08lx ret=%08lx\n", (UINT_PTR)ret, stack[0] );
}
void *func = relay_trace_entry( descr, idx, stack );
LONGLONG ret = call_entry_point( func, nb_args, stack + 1, flags );
relay_trace_exit( descr, idx, stack, ret );
return ret;
}
/***********************************************************************
* relay_call_regs
*/
#ifdef __i386__
void WINAPI __regs_relay_call_regs( struct relay_descr *descr, unsigned int idx,
unsigned int orig_eax, unsigned int ret_addr,
CONTEXT *context )
{
WORD ordinal = LOWORD(idx);
BYTE nb_args = LOBYTE(HIWORD(idx));
struct relay_private_data *data = descr->private;
struct relay_entry_point *entry_point = data->entry_points + ordinal;
BYTE *orig_func = entry_point->orig_func;
INT_PTR *args = (INT_PTR *)context->Esp;
INT_PTR args_copy[32];
/* restore the context to what it was before the relay thunk */
context->Eax = orig_eax;
context->Eip = ret_addr;
context->Esp += nb_args * sizeof(int);
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( args, nb_args, descr->arg_types[ordinal] );
DPRINTF( ") ret=%08x\n", ret_addr );
DPRINTF( "%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n",
GetCurrentThreadId(), context->Eax, context->Ebx, context->Ecx,
context->Edx, context->Esi, context->Edi, context->Ebp, context->Esp,
context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags );
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_PTR)context; /* append context argument */
call_entry_point( orig_func + 12 + *(int *)(orig_func + 1), nb_args, args_copy, 0 );
if (TRACE_ON(relay))
{
if (entry_point->name)
DPRINTF( "%04x:Ret %s.%s() retval=%08x ret=%08x\n",
GetCurrentThreadId(), data->dllname, entry_point->name,
context->Eax, context->Eip );
else
DPRINTF( "%04x:Ret %s.%u() retval=%08x ret=%08x\n",
GetCurrentThreadId(), data->dllname, data->base + ordinal,
context->Eax, context->Eip );
DPRINTF( "%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n",
GetCurrentThreadId(), context->Eax, context->Ebx, context->Ecx,
context->Edx, context->Esi, context->Edi, context->Ebp, context->Esp,
context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags );
}
}
extern void WINAPI relay_call_regs(void);
DEFINE_REGS_ENTRYPOINT( relay_call_regs, 4 )
#else /* __i386__ */
void WINAPI relay_call_regs( struct relay_descr *descr, INT_PTR idx, INT_PTR *stack )
static void WINAPI relay_call_regs( struct relay_descr *descr, INT_PTR idx, INT_PTR *stack )
{
assert(0); /* should never be called */
}
#endif /* __i386__ */
#else
#error Not supported on this CPU
#endif
/***********************************************************************
......@@ -645,7 +686,7 @@ void RELAY_SetupDLL( HMODULE module )
}
}
#else /* __i386__ || __x86_64__ */
#else /* __i386__ || __x86_64__ || __arm__ */
FARPROC RELAY_GetProcAddress( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
DWORD exp_size, FARPROC proc, DWORD ordinal, const WCHAR *user )
......@@ -657,7 +698,7 @@ void RELAY_SetupDLL( HMODULE module )
{
}
#endif /* __i386__ || __x86_64__ */
#endif /* __i386__ || __x86_64__ || __arm__ */
/***********************************************************************/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment