Added possibility to filter relay traces based on the module that

called the function. Cleaned up a few traces.
This commit is contained in:
Alexandre Julliard 2003-04-07 23:27:54 +00:00
parent 065ac4de85
commit f130f8099a
8 changed files with 191 additions and 65 deletions

View File

@ -57,6 +57,7 @@ static WINE_EXCEPTION_FILTER(page_fault)
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 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward )
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 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward )
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 @@ static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *expo
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 @@ static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *expo
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, exports, exp_size, proc, ordinal );
}
}
proc = SNOOP_GetProcAddress( module, ename, ordinal, proc );
if (TRACE_ON(relay) && current_modref)
{
proc = RELAY_GetProcAddress( module, exports, exp_size, proc, current_modref->modname );
}
return proc;
}
@ -235,12 +225,12 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
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 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
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 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
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 @@ DWORD PE_fixup_imports( WINE_MODREF *wm )
{
int i, nb_imports;
IMAGE_IMPORT_DESCRIPTOR *imports;
WINE_MODREF *prev;
DWORD size;
if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
@ -328,11 +317,14 @@ DWORD PE_fixup_imports( WINE_MODREF *wm )
/* 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 BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
{
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 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
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 @@ BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
/* 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 */

View File

@ -34,6 +34,12 @@ extern void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *tim
/* 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;

View File

@ -207,6 +207,8 @@ WINE REGISTRY Version 2
[Debug]
;"RelayExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
;"RelayInclude" = "user32.CreateWindowA"
;"RelayFromExclude" = "user32;x11drv"
;"RelayFromInclude" = "sol.exe"
;"SnoopExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
;"SpyExclude" = "WM_SIZE;WM_TIMER;"

View File

@ -277,28 +277,40 @@ default: none
.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 which function will be included in relay debuglog.
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 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]

View File

@ -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);

View File

@ -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 */

View File

@ -40,6 +40,9 @@ const char **debug_relay_includelist = NULL;
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 @@ void RELAY_InitDebugLists(void)
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 @@ void RELAY_InitDebugLists(void)
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 );
}
@ -199,6 +218,40 @@ static BOOL check_relay_include( const char *module, const char *func )
}
/***********************************************************************
* 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
*
@ -547,6 +600,26 @@ static BOOL is_register_entry_point( const BYTE *addr )
}
/***********************************************************************
* 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
*
@ -602,6 +675,12 @@ void RELAY_SetupDLL( const char *module )
#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 )
{
}

View File

@ -62,7 +62,7 @@ typedef struct tagSNOOP_FUN {
/* unreached */
int nrofargs;
FARPROC origfun;
char *name;
const char *name;
} SNOOP_FUN;
typedef struct tagSNOOP_DLL {
@ -180,8 +180,13 @@ SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD ordbase,DWORD nrofordinals) {
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 @@ SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) {
}
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 @@ void WINAPI SNOOP_DoEntry( CONTEXT86 *context )
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_DoEntry( CONTEXT86 *context )
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 @@ void WINAPI SNOOP_DoReturn( CONTEXT86 *context )
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 @@ void WINAPI SNOOP_DoReturn( CONTEXT86 *context )
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 @@ void SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD nrofordinals, DWORD dw) {
FIXME("snooping works only on i386 for now.\n");
}
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 )
{
return origfun;
}
#endif /* !__i386__ */