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