Commit 143143ad authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Add small assembly wrappers for snooping instead of saving/restoring the entire context.

parent a75e3f73
......@@ -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__ */
......
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