ntdll: Add small assembly wrappers for snooping instead of saving/restoring the entire context.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a75e3f734d
commit
143143ad00
|
@ -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__ */
|
||||
|
||||
|
|
Loading…
Reference in New Issue