Alexandre Julliard : ntdll: Add small assembly wrappers for snooping instead of saving/ restoring the entire context.
Alexandre Julliard
julliard at winehq.org
Thu Jul 20 16:20:35 CDT 2017
Module: wine
Branch: master
Commit: 143143ad00631d97c860fcb6a558b9b02e63e648
URL: http://source.winehq.org/git/wine.git/?a=commit;h=143143ad00631d97c860fcb6a558b9b02e63e648
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Jul 20 16:18:45 2017 +0200
ntdll: Add small assembly wrappers for snooping instead of saving/restoring the entire context.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/relay.c | 101 +++++++++++++++++++++++++++--------------------------
1 file changed, 51 insertions(+), 50 deletions(-)
diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c
index db21872..9ffe28a 100644
--- a/dlls/ntdll/relay.c
+++ b/dlls/ntdll/relay.c
@@ -840,9 +840,6 @@ typedef struct
{
/* code part */
BYTE lcall; /* 0xe8 call snoopentry (relative) */
- /* NOTE: If you move snoopentry OR nrofargs fix the relative offset
- * calculation!
- */
DWORD snoopentry; /* SNOOP_Entry relative */
/* unreached */
int nrofargs;
@@ -863,15 +860,12 @@ typedef struct
{
/* code part */
BYTE lcall; /* 0xe8 call snoopret relative*/
- /* NOTE: If you move snoopret OR origreturn fix the relative offset
- * calculation!
- */
DWORD snoopret; /* SNOOP_Ret relative */
/* unreached */
FARPROC origreturn;
SNOOP_DLL *dll;
DWORD ordinal;
- DWORD origESP;
+ void **origESP;
DWORD *args; /* saved args across a stdcall */
} SNOOP_RETURNENTRY;
@@ -1025,8 +1019,7 @@ FARPROC SNOOP_GetProcAddress( HMODULE hmod, const IMAGE_EXPORT_DIRECTORY *export
{
fun->name = ename;
fun->lcall = 0xe8;
- /* NOTE: origreturn struct member MUST come directly after snoopentry */
- fun->snoopentry = (char*)SNOOP_Entry-((char*)(&fun->nrofargs));
+ fun->snoopentry = (char *)SNOOP_Entry - (char *)(&fun->snoopentry + 1);
fun->origfun = origfun;
fun->nrofargs = -1;
}
@@ -1070,29 +1063,19 @@ static void SNOOP_PrintArg(DWORD x)
__ENDTRY
}
-#define CALLER1REF (*(DWORD*)context->Esp)
-
-void WINAPI __regs_SNOOP_Entry( CONTEXT *context )
+void WINAPI __regs_SNOOP_Entry( void **stack )
{
- DWORD ordinal=0,entry = context->Eip - 5;
- SNOOP_DLL *dll = firstdll;
- SNOOP_FUN *fun = NULL;
+ SNOOP_DLL *dll;
+ SNOOP_FUN *fun = (SNOOP_FUN *)((char *)stack[0] - 5);
SNOOP_RETURNENTRIES **rets = &firstrets;
SNOOP_RETURNENTRY *ret;
int i=0, max;
- while (dll) {
- if ( ((char*)entry>=(char*)dll->funs) &&
- ((char*)entry<=(char*)(dll->funs+dll->nrofordinals))
- ) {
- fun = (SNOOP_FUN*)entry;
- ordinal = fun-dll->funs;
- break;
- }
- dll=dll->next;
- }
+ for (dll = firstdll; dll; dll = dll->next )
+ if (fun >= dll->funs && fun < dll->funs + dll->nrofordinals) break;
+
if (!dll) {
- FIXME("entrypoint 0x%08x not found\n",entry);
+ FIXME("entrypoint %p not found\n", fun);
return; /* oops */
}
/* guess cdecl ... */
@@ -1102,7 +1085,7 @@ void WINAPI __regs_SNOOP_Entry( CONTEXT *context )
* which has (for xxxxxxxx up to 255 the opcode "83 C4 xx".
* (after that 81 C2 xx xx xx xx)
*/
- LPBYTE reteip = (LPBYTE)CALLER1REF;
+ LPBYTE reteip = stack[1];
if (reteip) {
if ((reteip[0]==0x83)&&(reteip[1]==0xc4))
@@ -1128,33 +1111,31 @@ void WINAPI __regs_SNOOP_Entry( CONTEXT *context )
PAGE_EXECUTE_READWRITE);
if (!addr) return;
*rets = addr;
- memset(*rets,0,4096);
i = 0; /* entry 0 is free */
}
ret = &((*rets)->entry[i]);
ret->lcall = 0xe8;
- /* NOTE: origreturn struct member MUST come directly after snoopret */
- ret->snoopret = ((char*)SNOOP_Return)-(char*)(&ret->origreturn);
- ret->origreturn = (FARPROC)CALLER1REF;
- CALLER1REF = (DWORD)&ret->lcall;
+ ret->snoopret = (char *)SNOOP_Return - (char *)(&ret->snoopret + 1);
+ ret->origreturn = stack[1];
+ stack[1] = &ret->lcall;
ret->dll = dll;
ret->args = NULL;
- ret->ordinal = ordinal;
- ret->origESP = context->Esp;
+ ret->ordinal = fun - dll->funs;
+ ret->origESP = stack;
- context->Eip = (DWORD)fun->origfun;
+ stack[0] = fun->origfun;
if (!TRACE_ON(snoop)) return;
if (TRACE_ON(timestamp))
print_timestamp();
if (fun->name) DPRINTF("%04x:CALL %s.%s(",GetCurrentThreadId(),dll->name,fun->name);
- else DPRINTF("%04x:CALL %s.%d(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal);
+ else DPRINTF("%04x:CALL %s.%d(",GetCurrentThreadId(),dll->name,dll->ordbase+ret->ordinal);
if (fun->nrofargs>0) {
max = fun->nrofargs; if (max>16) max=16;
for (i=0;i<max;i++)
{
- SNOOP_PrintArg(*(DWORD*)(context->Esp + 4 + sizeof(DWORD)*i));
+ SNOOP_PrintArg( (DWORD)stack[i + 2] );
if (i<fun->nrofargs-1) DPRINTF(",");
}
if (max!=fun->nrofargs)
@@ -1163,16 +1144,16 @@ void WINAPI __regs_SNOOP_Entry( CONTEXT *context )
DPRINTF("<unknown, check return>");
ret->args = RtlAllocateHeap(GetProcessHeap(),
0,16*sizeof(DWORD));
- memcpy(ret->args,(LPBYTE)(context->Esp + 4),sizeof(DWORD)*16);
+ memcpy(ret->args, stack + 2, sizeof(DWORD)*16);
}
DPRINTF(") ret=%08x\n",(DWORD)ret->origreturn);
}
-
-void WINAPI __regs_SNOOP_Return( CONTEXT *context )
+void WINAPI __regs_SNOOP_Return( void **stack )
{
- SNOOP_RETURNENTRY *ret = (SNOOP_RETURNENTRY*)(context->Eip - 5);
+ SNOOP_RETURNENTRY *ret = (SNOOP_RETURNENTRY*)((char *)stack[0] - 5);
SNOOP_FUN *fun = &ret->dll->funs[ret->ordinal];
+ DWORD retval = (DWORD)stack[-1]; /* get saved %eax from the stack */
/* We haven't found out the nrofargs yet. If we called a cdecl
* function it is too late anyway and we can just set '0' (which
@@ -1180,8 +1161,8 @@ void WINAPI __regs_SNOOP_Return( CONTEXT *context )
* If stdcall -> everything ok.
*/
if (ret->dll->funs[ret->ordinal].nrofargs<0)
- ret->dll->funs[ret->ordinal].nrofargs=(context->Esp - ret->origESP-4)/4;
- context->Eip = (DWORD)ret->origreturn;
+ ret->dll->funs[ret->ordinal].nrofargs = stack - ret->origESP - 1;
+ stack[0] = ret->origreturn;
if (!TRACE_ON(snoop)) {
ret->origreturn = NULL; /* mark as empty */
@@ -1207,8 +1188,7 @@ void WINAPI __regs_SNOOP_Return( CONTEXT *context )
SNOOP_PrintArg(ret->args[i]);
if (i<max-1) DPRINTF(",");
}
- DPRINTF(") retval=%08x ret=%08x\n",
- context->Eax,(DWORD)ret->origreturn );
+ DPRINTF(") retval=%08x ret=%08x\n", retval, (DWORD)ret->origreturn );
RtlFreeHeap(GetProcessHeap(),0,ret->args);
ret->args = NULL;
}
@@ -1217,19 +1197,40 @@ void WINAPI __regs_SNOOP_Return( CONTEXT *context )
if (fun->name)
DPRINTF("%04x:RET %s.%s() retval=%08x ret=%08x\n",
GetCurrentThreadId(),
- ret->dll->name, fun->name, context->Eax, (DWORD)ret->origreturn);
+ ret->dll->name, fun->name, retval, (DWORD)ret->origreturn);
else
DPRINTF("%04x:RET %s.%d() retval=%08x ret=%08x\n",
GetCurrentThreadId(),
ret->dll->name,ret->dll->ordbase+ret->ordinal,
- context->Eax, (DWORD)ret->origreturn);
+ retval, (DWORD)ret->origreturn);
}
ret->origreturn = NULL; /* mark as empty */
}
-/* assembly wrappers that save the context */
-DEFINE_REGS_ENTRYPOINT( SNOOP_Entry, 0 )
-DEFINE_REGS_ENTRYPOINT( SNOOP_Return, 0 )
+/* small wrappers that save registers and get the stack pointer */
+#define SNOOP_WRAPPER(name) \
+ __ASM_STDCALL_FUNC( name, 0, \
+ "pushl %eax\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
+ "pushl %ecx\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
+ "pushl %edx\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
+ "leal 12(%esp),%eax\n\t" \
+ "pushl %eax\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
+ "call " __ASM_NAME("__regs_" #name) __ASM_STDCALL(4) "\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") \
+ "popl %edx\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") \
+ "popl %ecx\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") \
+ "popl %eax\n\t" \
+ __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") \
+ "ret" )
+
+SNOOP_WRAPPER( SNOOP_Entry )
+SNOOP_WRAPPER( SNOOP_Return )
#else /* __i386__ */
More information about the wine-cvs
mailing list