Module: wine Branch: master Commit: 143143ad00631d97c860fcb6a558b9b02e63e648 URL: http://source.winehq.org/git/wine.git/?a=commit;h=143143ad00631d97c860fcb6a5...
Author: Alexandre Julliard julliard@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@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__ */