Added possibility to filter relay traces based on the module that
called the function. Cleaned up a few traces.
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index fb0a60d..668744c 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -57,6 +57,7 @@
static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" );
static WINE_MODREF *cached_modref;
+static WINE_MODREF *current_modref;
static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm );
static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
@@ -114,8 +115,7 @@
if (!(wm = MODULE_FindModule( mod_name )))
{
- WINE_MODREF *user = get_modref( module );
- ERR("module not found for forward '%s' used by '%s'\n", forward, user->filename );
+ ERR("module not found for forward '%s' used by '%s'\n", forward, current_modref->filename );
return NULL;
}
if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
@@ -124,10 +124,9 @@
if (!proc)
{
- WINE_MODREF *user = get_modref( module );
ERR("function not found for forward '%s' used by '%s'."
" If you are using builtin '%s', try using the native one instead.\n",
- forward, user->filename, user->modname );
+ forward, current_modref->filename, current_modref->modname );
}
return proc;
}
@@ -144,7 +143,6 @@
DWORD exp_size, int ordinal )
{
FARPROC proc;
- WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
DWORD *functions = get_rva( module, exports->AddressOfFunctions );
if (ordinal >= exports->NumberOfFunctions)
@@ -162,19 +160,11 @@
if (TRACE_ON(snoop))
{
- /* try to find a name for it */
- int i;
- char *ename = "@";
- DWORD *name = get_rva( module, exports->AddressOfNames );
- if (name) for (i = 0; i < exports->NumberOfNames; i++)
- {
- if (ordinals[i] == ordinal)
- {
- ename = get_rva( module, name[i] );
- break;
- }
- }
- proc = SNOOP_GetProcAddress( module, ename, ordinal, proc );
+ proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal );
+ }
+ if (TRACE_ON(relay) && current_modref)
+ {
+ proc = RELAY_GetProcAddress( module, exports, exp_size, proc, current_modref->modname );
}
return proc;
}
@@ -235,12 +225,12 @@
status = load_dll( name, 0, &wmImp );
if (status)
{
- WINE_MODREF *user = get_modref( module );
if (status == STATUS_NO_SUCH_FILE)
- ERR("Module (file) %s (which is needed by %s) not found\n", name, user->filename);
+ ERR("Module (file) %s (which is needed by %s) not found\n",
+ name, current_modref->filename);
else
ERR("Loading module (file) %s (which is needed by %s) failed (error %ld).\n",
- name, user->filename, status);
+ name, current_modref->filename, status);
return NULL;
}
@@ -266,9 +256,8 @@
ordinal - exports->Base );
if (!thunk_list->u1.Function)
{
- WINE_MODREF *user = get_modref( module );
ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
- name, ordinal, user->filename );
+ name, ordinal, current_modref->filename );
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
}
}
@@ -281,9 +270,8 @@
pe_name->Name, pe_name->Hint );
if (!thunk_list->u1.Function)
{
- WINE_MODREF *user = get_modref( module );
ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n",
- name, pe_name->Name, user->filename );
+ name, pe_name->Name, current_modref->filename );
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
}
}
@@ -304,6 +292,7 @@
{
int i, nb_imports;
IMAGE_IMPORT_DESCRIPTOR *imports;
+ WINE_MODREF *prev;
DWORD size;
if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
@@ -328,11 +317,14 @@
/* load the imported modules. They are automatically
* added to the modref list of the process.
*/
+ prev = current_modref;
+ current_modref = wm;
for (i = 0; i < nb_imports; i++)
{
- if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i] ))) return 1;
+ if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i] ))) break;
}
- return 0;
+ current_modref = prev;
+ return (i < nb_imports);
}
@@ -403,6 +395,7 @@
{
static const char * const typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH",
"THREAD_ATTACH", "THREAD_DETACH" };
+ char mod_name[32];
BOOL retv = TRUE;
DLLENTRYPROC entry = wm->ldr.EntryPoint;
void *module = wm->ldr.BaseAddress;
@@ -412,22 +405,25 @@
if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return TRUE;
if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return TRUE;
- TRACE("(%p (%s),%s,%p) - CALL\n", module, wm->modname, typeName[type], lpReserved );
-
if (TRACE_ON(relay))
- DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p,type=%ld,res=%p)\n",
- GetCurrentThreadId(), entry, module, type, lpReserved );
+ {
+ size_t len = max( strlen(wm->modname), sizeof(mod_name)-1 );
+ memcpy( mod_name, wm->modname, len );
+ mod_name[len] = 0;
+ DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p (%s),type=%ld,res=%p)\n",
+ GetCurrentThreadId(), entry, module, mod_name, type, lpReserved );
+ }
+ else TRACE("(%p (%s),%s,%p) - CALL\n", module, wm->modname, typeName[type], lpReserved );
retv = entry( module, type, lpReserved );
- if (TRACE_ON(relay))
- DPRINTF("%04lx:Ret PE DLL (proc=%p,module=%p,type=%ld,res=%p) retval=%x\n",
- GetCurrentThreadId(), entry, module, type, lpReserved, retv );
-
/* The state of the module list may have changed due to the call
to the dll. We cannot assume that this module has not been
deleted. */
- TRACE("(%p,%s,%p) - RETURN %d\n", module, typeName[type], lpReserved, retv );
+ if (TRACE_ON(relay))
+ DPRINTF("%04lx:Ret PE DLL (proc=%p,module=%p (%s),type=%ld,res=%p) retval=%x\n",
+ GetCurrentThreadId(), entry, module, mod_name, type, lpReserved, retv );
+ else TRACE("(%p,%s,%p) - RETURN %d\n", module, typeName[type], lpReserved, retv );
return retv;
}
@@ -494,9 +490,11 @@
/* Call DLL entry point */
if ( retv )
{
+ WINE_MODREF *prev = current_modref;
+ current_modref = wm;
retv = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved );
- if ( retv )
- wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
+ if (retv) wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
+ current_modref = prev;
}
/* Re-insert MODREF at head of list */
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 3eb22fa..a8aa6df 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -34,6 +34,12 @@
/* module handling */
extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
+extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
+ DWORD exp_size, FARPROC proc, const char *user );
+extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
+ FARPROC origfun, DWORD ordinal );
+extern void RELAY_SetupDLL( const char *module );
+
static inline HANDLE ntdll_get_process_heap(void)
{
HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process;
diff --git a/documentation/samples/config b/documentation/samples/config
index 6baa06c..041b1f8 100644
--- a/documentation/samples/config
+++ b/documentation/samples/config
@@ -207,6 +207,8 @@
[Debug]
;"RelayExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
;"RelayInclude" = "user32.CreateWindowA"
+;"RelayFromExclude" = "user32;x11drv"
+;"RelayFromInclude" = "sol.exe"
;"SnoopExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
;"SpyExclude" = "WM_SIZE;WM_TIMER;"
diff --git a/documentation/wine.conf.man b/documentation/wine.conf.man
index 75ccc50..e53b942 100644
--- a/documentation/wine.conf.man
+++ b/documentation/wine.conf.man
@@ -277,28 +277,40 @@
.br
default: none
.br
-Used to specify which function will be excluded from a relay debuglog.
+Used to specify which functions will be excluded from a relay debug log.
.PP
-.I format: """RelayInclude""=""<message names separated by semicolons>"""
+.I format: """RelayInclude""=""<function or dll.functions separated by semicolons>"""
+.br
+default: include all functions
+.br
+Used to specify which functions will be included in a relay debug log.
+.PP
+.I format: """RelayFromExclude""=""<module names separated by semicolons>"""
.br
default: none
+.br
+Used to specify a set of modules whose calls are excluded from a relay debug log.
+.PP
+.I format: """RelayFromInclude""=""<module names separated by semicolons>"""
+.br
+default: include all modules
.br
-Used to specify which function will be included in relay debuglog.
+Used to specify the set of modules whose calls are included in a relay debug log.
.PP
.I format: """SnoopExclude""=""<message names separated by semicolons>"""
.br
default: none
.br
-Used to specify which function will be included in snoop debuglog.
+Used to specify which functions will be included in snoop debug log.
.PP
.I format: """SnoopInclude""=""<message names separated by semicolons>"""
.br
-default: none
+default: include all functions
.br
-Used to specify which function will be included in snoop debuglog.
+Used to specify which functions will be included in snoop debug log.
.PP
For Relay and Snoop <dllname>.* includes or excludes the whole dll. Exclude
-entries overwrite Include Entries.
+entries overwrite Include entries.
.br
.PP
.B [Tweak.Layout]
diff --git a/include/snoop.h b/include/snoop.h
index d950258..115125a 100644
--- a/include/snoop.h
+++ b/include/snoop.h
@@ -24,7 +24,6 @@
#include "module.h"
extern void SNOOP_RegisterDLL(HMODULE,LPCSTR,DWORD,DWORD);
-extern FARPROC SNOOP_GetProcAddress(HMODULE,LPCSTR,DWORD,FARPROC);
extern void SNOOP16_RegisterDLL(NE_MODULE*,LPCSTR);
extern FARPROC16 SNOOP16_GetProcAddress16(HMODULE16,DWORD,FARPROC16);
extern int SNOOP_ShowDebugmsgSnoop(const char *dll,int ord,const char *fname);
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index 0b93b61..3bcbb1b 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -42,8 +42,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(module);
WINE_DECLARE_DEBUG_CHANNEL(relay);
-extern void RELAY_SetupDLL( const char *module );
-
static HMODULE main_module;
static NTSTATUS last_status; /* use to gather all errors in callback */
diff --git a/relay32/relay386.c b/relay32/relay386.c
index 35f1c2f..9b54308 100644
--- a/relay32/relay386.c
+++ b/relay32/relay386.c
@@ -40,6 +40,9 @@
const char **debug_snoop_excludelist = NULL;
const char **debug_snoop_includelist = NULL;
+static const char **debug_from_relay_excludelist;
+static const char **debug_from_relay_includelist;
+
/***********************************************************************
* build_list
*
@@ -103,6 +106,8 @@
static const WCHAR RelayExcludeW[] = {'R','e','l','a','y','E','x','c','l','u','d','e',0};
static const WCHAR SnoopIncludeW[] = {'S','n','o','o','p','I','n','c','l','u','d','e',0};
static const WCHAR SnoopExcludeW[] = {'S','n','o','o','p','E','x','c','l','u','d','e',0};
+ static const WCHAR RelayFromIncludeW[] = {'R','e','l','a','y','F','r','o','m','I','n','c','l','u','d','e',0};
+ static const WCHAR RelayFromExcludeW[] = {'R','e','l','a','y','F','r','o','m','E','x','c','l','u','d','e',0};
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
@@ -143,6 +148,20 @@
debug_snoop_excludelist = build_list( str );
}
+ RtlInitUnicodeString( &name, RelayFromIncludeW );
+ if (!NtQueryValueKey( hkey, &name, KeyValuePartialInformation, buffer, sizeof(buffer), &count ))
+ {
+ TRACE("RelayFromInclude = %s\n", debugstr_w(str) );
+ debug_from_relay_includelist = build_list( str );
+ }
+
+ RtlInitUnicodeString( &name, RelayFromExcludeW );
+ if (!NtQueryValueKey( hkey, &name, KeyValuePartialInformation, buffer, sizeof(buffer), &count ))
+ {
+ TRACE( "RelayFromExclude = %s\n", debugstr_w(str) );
+ debug_from_relay_excludelist = build_list( str );
+ }
+
NtClose( hkey );
}
@@ -200,6 +219,40 @@
/***********************************************************************
+ * check_relay_from_module
+ *
+ * Check if calls from a given module must be included in the relay output.
+ */
+static BOOL check_relay_from_module( const char *module )
+{
+ const char **listitem;
+ BOOL show;
+
+ if (!debug_from_relay_excludelist && !debug_from_relay_includelist) return TRUE;
+ if (debug_from_relay_excludelist)
+ {
+ show = TRUE;
+ listitem = debug_from_relay_excludelist;
+ }
+ else
+ {
+ show = FALSE;
+ listitem = debug_from_relay_includelist;
+ }
+ for(; *listitem; listitem++)
+ {
+ int len;
+
+ if (!strcasecmp( *listitem, module )) return !show;
+ len = strlen( *listitem );
+ if (!strncasecmp( *listitem, module, len ) && !strcasecmp( module + len, ".dll" ))
+ return !show;
+ }
+ return show;
+}
+
+
+/***********************************************************************
* find_exported_name
*
* Find the name of an exported function.
@@ -548,6 +601,26 @@
/***********************************************************************
+ * RELAY_GetProcAddress
+ *
+ * Return the proc address to use for a given function.
+ */
+FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
+ DWORD exp_size, FARPROC proc, const char *user )
+{
+ DEBUG_ENTRY_POINT *debug = (DEBUG_ENTRY_POINT *)proc;
+ DEBUG_ENTRY_POINT *list = (DEBUG_ENTRY_POINT *)((char *)exports + exp_size);
+
+ if (debug < list || debug >= list + exports->NumberOfFunctions) return proc;
+ if (list + (debug - list) != debug) return proc; /* not a valid address */
+ if (check_relay_from_module( user )) return proc; /* we want to relay it */
+ if (!debug->call) return proc; /* not a normal function */
+ if (debug->call != 0xe8 && debug->call != 0xe9) return proc; /* not a debug thunk at all */
+ return debug->orig;
+}
+
+
+/***********************************************************************
* RELAY_SetupDLL
*
* Setup relay debugging for a built-in dll.
@@ -602,6 +675,12 @@
#else /* __i386__ */
+FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
+ DWORD exp_size, FARPROC proc, const char *user )
+{
+ return proc;
+}
+
void RELAY_SetupDLL( const char *module )
{
}
diff --git a/relay32/snoop.c b/relay32/snoop.c
index b09ce59..c36eb20 100644
--- a/relay32/snoop.c
+++ b/relay32/snoop.c
@@ -62,7 +62,7 @@
/* unreached */
int nrofargs;
FARPROC origfun;
- char *name;
+ const char *name;
} SNOOP_FUN;
typedef struct tagSNOOP_DLL {
@@ -180,8 +180,13 @@
memset((*dll)->funs,0,size);
}
-FARPROC
-SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) {
+FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
+ FARPROC origfun, DWORD ordinal )
+{
+ int i;
+ const char *ename;
+ WORD *ordinals;
+ DWORD *names;
SNOOP_DLL *dll = firstdll;
SNOOP_FUN *fun;
IMAGE_SECTION_HEADER *sec;
@@ -202,14 +207,26 @@
}
if (!dll) /* probably internal */
return origfun;
- if (!SNOOP_ShowDebugmsgSnoop(dll->name,ordinal,name))
+
+ /* try to find a name for it */
+ ename = NULL;
+ names = (DWORD *)((char *)hmod + exports->AddressOfNames);
+ ordinals = (WORD *)((char *)hmod + exports->AddressOfNameOrdinals);
+ if (names) for (i = 0; i < exports->NumberOfNames; i++)
+ {
+ if (ordinals[i] == ordinal)
+ {
+ ename = (char *)hmod + names[i];
+ break;
+ }
+ }
+ if (!SNOOP_ShowDebugmsgSnoop(dll->name,ordinal,ename))
return origfun;
assert(ordinal < dll->nrofordinals);
fun = dll->funs+ordinal;
if (!fun->name)
{
- fun->name = RtlAllocateHeap(ntdll_get_process_heap(),0,strlen(name)+1);
- strcpy( fun->name, name );
+ fun->name = ename;
fun->lcall = 0xe8;
/* NOTE: origreturn struct member MUST come directly after snoopentry */
fun->snoopentry = (char*)SNOOP_Entry-((char*)(&fun->nrofargs));
@@ -330,7 +347,8 @@
context->Eip = (DWORD)fun->origfun;
- DPRINTF("%04lx:CALL %s.%ld: %s(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal,fun->name);
+ if (fun->name) DPRINTF("%04lx:CALL %s.%s(",GetCurrentThreadId(),dll->name,fun->name);
+ else DPRINTF("%04lx:CALL %s.%ld(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal);
if (fun->nrofargs>0) {
max = fun->nrofargs; if (max>16) max=16;
for (i=0;i<max;i++)
@@ -353,6 +371,7 @@
void WINAPI SNOOP_DoReturn( CONTEXT86 *context )
{
SNOOP_RETURNENTRY *ret = (SNOOP_RETURNENTRY*)(context->Eip - 5);
+ SNOOP_FUN *fun = &ret->dll->funs[ret->ordinal];
/* 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
@@ -365,10 +384,13 @@
if (ret->args) {
int i,max;
- DPRINTF("%04lx:RET %s.%ld: %s(",
- GetCurrentThreadId(),
- ret->dll->name,ret->dll->ordbase+ret->ordinal,ret->dll->funs[ret->ordinal].name);
- max = ret->dll->funs[ret->ordinal].nrofargs;
+ if (fun->name)
+ DPRINTF("%04lx:RET %s.%s(", GetCurrentThreadId(), ret->dll->name, fun->name);
+ else
+ DPRINTF("%04lx:RET %s.%ld(", GetCurrentThreadId(),
+ ret->dll->name,ret->dll->ordbase+ret->ordinal);
+
+ max = fun->nrofargs;
if (max>16) max=16;
for (i=0;i<max;i++)
@@ -376,15 +398,23 @@
SNOOP_PrintArg(ret->args[i]);
if (i<max-1) DPRINTF(",");
}
- DPRINTF(") retval = %08lx ret=%08lx\n",
+ DPRINTF(") retval=%08lx ret=%08lx\n",
context->Eax,(DWORD)ret->origreturn );
RtlFreeHeap(ntdll_get_process_heap(),0,ret->args);
ret->args = NULL;
- } else
- DPRINTF("%04lx:RET %s.%ld: %s() retval = %08lx ret=%08lx\n",
+ }
+ else
+ {
+ if (fun->name)
+ DPRINTF("%04lx:RET %s.%s() retval=%08lx ret=%08lx\n",
GetCurrentThreadId(),
- ret->dll->name,ret->dll->ordbase+ret->ordinal,ret->dll->funs[ret->ordinal].name,
+ ret->dll->name, fun->name, context->Eax, (DWORD)ret->origreturn);
+ else
+ DPRINTF("%04lx:RET %s.%ld() retval=%08lx ret=%08lx\n",
+ GetCurrentThreadId(),
+ ret->dll->name,ret->dll->ordbase+ret->ordinal,
context->Eax, (DWORD)ret->origreturn);
+ }
ret->origreturn = NULL; /* mark as empty */
}
@@ -402,7 +432,9 @@
FIXME("snooping works only on i386 for now.\n");
}
-FARPROC SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) {
- return origfun;
+FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
+ FARPROC origfun, DWORD ordinal )
+{
+ return origfun;
}
#endif /* !__i386__ */