Store the list of loaded dlls in the server, and generate debug events
internally.
This commit is contained in:
parent
5fb54566d2
commit
05f0b71bb3
@ -4,7 +4,7 @@
|
||||
#include "module.h"
|
||||
#include "windef.h"
|
||||
|
||||
WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR libname, DWORD flags, DWORD *err);
|
||||
WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR libname, DWORD flags);
|
||||
HINSTANCE16 ELFDLL_LoadModule16(LPCSTR libname);
|
||||
void ELFDLL_UnloadLibrary(WINE_MODREF *wm);
|
||||
|
||||
|
@ -157,7 +157,6 @@ typedef struct _wine_modref
|
||||
#define WINE_MODREF_PROCESS_ATTACHED 0x00000004
|
||||
#define WINE_MODREF_LOAD_AS_DATAFILE 0x00000010
|
||||
#define WINE_MODREF_DONT_RESOLVE_REFS 0x00000020
|
||||
#define WINE_MODREF_DEBUG_EVENT_SENT 0x00000040
|
||||
#define WINE_MODREF_MARKER 0x80000000
|
||||
|
||||
|
||||
@ -182,7 +181,6 @@ extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
|
||||
extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved );
|
||||
extern void MODULE_DllThreadAttach( LPVOID lpReserved );
|
||||
extern void MODULE_DllThreadDetach( LPVOID lpReserved );
|
||||
extern void MODULE_SendLoadDLLEvents( void );
|
||||
extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags );
|
||||
extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm );
|
||||
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
|
||||
@ -235,7 +233,7 @@ extern void NE_DllProcessAttach( HMODULE16 hModule );
|
||||
HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD size );
|
||||
|
||||
/* relay32/builtin.c */
|
||||
extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags, DWORD *err);
|
||||
extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags);
|
||||
extern HMODULE16 BUILTIN32_LoadExeModule(void);
|
||||
extern void BUILTIN32_UnloadLibrary(WINE_MODREF *wm);
|
||||
|
||||
|
@ -25,7 +25,7 @@ extern BOOL PE_EnumResourceLanguagesA(HMODULE,LPCSTR,LPCSTR,ENUMRESLANGPROCA,LON
|
||||
extern BOOL PE_EnumResourceLanguagesW(HMODULE,LPCWSTR,LPCWSTR,ENUMRESLANGPROCW,LONG);
|
||||
extern HRSRC PE_FindResourceExW(struct _wine_modref*,LPCWSTR,LPCWSTR,WORD);
|
||||
extern DWORD PE_SizeofResource(HMODULE,HRSRC);
|
||||
extern struct _wine_modref *PE_LoadLibraryExA(LPCSTR, DWORD, DWORD *);
|
||||
extern struct _wine_modref *PE_LoadLibraryExA(LPCSTR, DWORD);
|
||||
extern void PE_UnloadLibrary(struct _wine_modref *);
|
||||
extern HGLOBAL PE_LoadResource(struct _wine_modref *wm,HRSRC);
|
||||
extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, WORD *version );
|
||||
@ -64,7 +64,7 @@ typedef struct {
|
||||
ELF_STDCALL_STUB *stubs;
|
||||
} ELF_MODREF;
|
||||
|
||||
extern struct _wine_modref *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, DWORD *err);
|
||||
extern struct _wine_modref *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags);
|
||||
extern void ELF_UnloadLibrary(struct _wine_modref *);
|
||||
extern FARPROC ELF_FindExportedFunction(struct _wine_modref *wm, LPCSTR funcName);
|
||||
|
||||
|
@ -170,8 +170,6 @@ extern void PROCESS_WalkProcess( void );
|
||||
|
||||
/* scheduler/debugger.c */
|
||||
extern DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEXT *ctx );
|
||||
extern DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name );
|
||||
extern DWORD DEBUG_SendUnloadDLLEvent( HMODULE module );
|
||||
|
||||
static inline PDB * WINE_UNUSED PROCESS_Current(void)
|
||||
{
|
||||
|
@ -271,13 +271,22 @@ struct resume_thread_request
|
||||
};
|
||||
|
||||
|
||||
/* Debugger support: freeze / unfreeze */
|
||||
struct debugger_request
|
||||
/* Notify the server that a dll has been loaded */
|
||||
struct load_dll_request
|
||||
{
|
||||
IN int op; /* operation type */
|
||||
IN int handle; /* file handle */
|
||||
IN void* base; /* base address */
|
||||
IN int dbg_offset; /* debug info offset */
|
||||
IN int dbg_size; /* debug info size */
|
||||
IN void* name; /* ptr to ptr to name (in process addr space) */
|
||||
};
|
||||
|
||||
enum debugger_op { DEBUGGER_FREEZE_ALL, DEBUGGER_UNFREEZE_ALL };
|
||||
|
||||
/* Notify the server that a dll is being unloaded */
|
||||
struct unload_dll_request
|
||||
{
|
||||
IN void* base; /* base address */
|
||||
};
|
||||
|
||||
|
||||
/* Queue an APC for a thread */
|
||||
@ -1101,7 +1110,8 @@ enum request
|
||||
REQ_SET_THREAD_INFO,
|
||||
REQ_SUSPEND_THREAD,
|
||||
REQ_RESUME_THREAD,
|
||||
REQ_DEBUGGER,
|
||||
REQ_LOAD_DLL,
|
||||
REQ_UNLOAD_DLL,
|
||||
REQ_QUEUE_APC,
|
||||
REQ_GET_APCS,
|
||||
REQ_CLOSE_HANDLE,
|
||||
@ -1186,7 +1196,7 @@ enum request
|
||||
REQ_NB_REQUESTS
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 1
|
||||
#define SERVER_PROTOCOL_VERSION 2
|
||||
|
||||
/* ### make_requests end ### */
|
||||
/* Everything above this line is generated automatically by tools/make_requests */
|
||||
@ -1250,7 +1260,6 @@ static inline void server_strcpyAtoW( WCHAR *dst, const char *src )
|
||||
extern int CLIENT_InitServer(void);
|
||||
extern int CLIENT_BootDone( int debug_level );
|
||||
extern int CLIENT_IsBootThread(void);
|
||||
extern int CLIENT_DebuggerRequest( int op );
|
||||
extern int CLIENT_InitThread(void);
|
||||
#endif /* __WINE_SERVER__ */
|
||||
|
||||
|
@ -102,7 +102,7 @@ static WINE_MODREF *ELF_CreateDummyModule( LPCSTR libname, LPCSTR modname )
|
||||
return wm;
|
||||
}
|
||||
|
||||
WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, DWORD *err)
|
||||
WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags)
|
||||
{
|
||||
WINE_MODREF *wm;
|
||||
char *modname,*s,*t,*x;
|
||||
@ -146,7 +146,7 @@ WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, DWORD *err)
|
||||
dlhandle = ELFDLL_dlopen(t,RTLD_NOW);
|
||||
if (!dlhandle) {
|
||||
HeapFree( GetProcessHeap(), 0, t );
|
||||
*err = ERROR_FILE_NOT_FOUND;
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -154,7 +154,6 @@ WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, DWORD *err)
|
||||
wm->binfmt.elf.dlhandle = dlhandle;
|
||||
|
||||
SNOOP_RegisterDLL(wm->module,libname,STUBSIZE/sizeof(ELF_STDCALL_STUB));
|
||||
*err = 0;
|
||||
return wm;
|
||||
}
|
||||
|
||||
@ -271,7 +270,7 @@ void ELF_UnloadLibrary(WINE_MODREF *wm)
|
||||
|
||||
#else
|
||||
|
||||
WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, DWORD *err)
|
||||
WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ static HMODULE16 ELFDLL_CreateNEModule(NE_MODULE *ne_image, DWORD size)
|
||||
*
|
||||
* Implementation of elf-dll loading for PE modules
|
||||
*/
|
||||
WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags)
|
||||
{
|
||||
LPVOID dlhandle;
|
||||
struct elfdll_image *image;
|
||||
@ -302,7 +302,7 @@ WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
if(!dlhandle)
|
||||
{
|
||||
WARN("Could not load %s (%s)\n", soname, dlerror());
|
||||
*err = ERROR_FILE_NOT_FOUND;
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -314,7 +314,7 @@ WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
{
|
||||
ERR("Could not get elfdll image descriptor %s (%s)\n", soname, dlerror());
|
||||
dlclose(dlhandle);
|
||||
*err = ERROR_BAD_FORMAT;
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -324,7 +324,7 @@ WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
{
|
||||
ERR("Could not create win16 dummy module for %s\n", path);
|
||||
dlclose(dlhandle);
|
||||
*err = ERROR_OUTOFMEMORY;
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -336,13 +336,11 @@ WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
ERR("Could not create WINE_MODREF for %s\n", path);
|
||||
GLOBAL_FreeBlock((HGLOBAL16)hmod16);
|
||||
dlclose(dlhandle);
|
||||
*err = ERROR_OUTOFMEMORY;
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dump_exports(image->pe_module_start);
|
||||
|
||||
*err = 0;
|
||||
return wm;
|
||||
}
|
||||
|
||||
@ -374,9 +372,9 @@ HINSTANCE16 ELFDLL_LoadModule16(LPCSTR libname)
|
||||
* Just put stubs in here.
|
||||
*/
|
||||
|
||||
WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR libname, DWORD flags, DWORD *err)
|
||||
WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR libname, DWORD flags)
|
||||
{
|
||||
*err = ERROR_FILE_NOT_FOUND;
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,10 @@
|
||||
#include "callback.h"
|
||||
#include "loadorder.h"
|
||||
#include "elfdll.h"
|
||||
#include "server.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(module)
|
||||
DECLARE_DEBUG_CHANNEL(win32)
|
||||
DEFAULT_DEBUG_CHANNEL(module);
|
||||
DECLARE_DEBUG_CHANNEL(win32);
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE_WalkModref
|
||||
@ -328,29 +329,6 @@ BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE_SendLoadDLLEvents
|
||||
*
|
||||
* Sends DEBUG_DLL_LOAD events for all outstanding modules.
|
||||
*
|
||||
* NOTE: Assumes that the process critical section is held!
|
||||
*
|
||||
*/
|
||||
void MODULE_SendLoadDLLEvents( void )
|
||||
{
|
||||
WINE_MODREF *wm;
|
||||
|
||||
for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
|
||||
{
|
||||
if ( wm->type != MODULE32_PE ) continue;
|
||||
if ( wm == PROCESS_Current()->exe_modref ) continue;
|
||||
if ( wm->flags & WINE_MODREF_DEBUG_EVENT_SENT ) continue;
|
||||
|
||||
DEBUG_SendLoadDLLEvent( -1 /*FIXME*/, wm->module, &wm->modname );
|
||||
wm->flags |= WINE_MODREF_DEBUG_EVENT_SENT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MODULE_CreateDummyModule
|
||||
@ -1352,8 +1330,6 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
||||
wm = MODULE_LoadLibraryExA( libname, hfile, flags );
|
||||
if ( wm )
|
||||
{
|
||||
MODULE_SendLoadDLLEvents();
|
||||
|
||||
if ( !MODULE_DllProcessAttach( wm, NULL ) )
|
||||
{
|
||||
WARN_(module)("Attach failed for module '%s', \n", libname);
|
||||
@ -1381,7 +1357,7 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
||||
*/
|
||||
WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
|
||||
{
|
||||
DWORD err;
|
||||
DWORD err = GetLastError();
|
||||
WINE_MODREF *pwm;
|
||||
int i;
|
||||
module_loadorder_t *plo;
|
||||
@ -1402,26 +1378,27 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
|
||||
|
||||
for(i = 0; i < MODULE_LOADORDER_NTYPES; i++)
|
||||
{
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
switch(plo->loadorder[i])
|
||||
{
|
||||
case MODULE_LOADORDER_DLL:
|
||||
TRACE("Trying native dll '%s'\n", libname);
|
||||
pwm = PE_LoadLibraryExA(libname, flags, &err);
|
||||
pwm = PE_LoadLibraryExA(libname, flags);
|
||||
break;
|
||||
|
||||
case MODULE_LOADORDER_ELFDLL:
|
||||
TRACE("Trying elfdll '%s'\n", libname);
|
||||
pwm = ELFDLL_LoadLibraryExA(libname, flags, &err);
|
||||
pwm = ELFDLL_LoadLibraryExA(libname, flags);
|
||||
break;
|
||||
|
||||
case MODULE_LOADORDER_SO:
|
||||
TRACE("Trying so-library '%s'\n", libname);
|
||||
pwm = ELF_LoadLibraryExA(libname, flags, &err);
|
||||
pwm = ELF_LoadLibraryExA(libname, flags);
|
||||
break;
|
||||
|
||||
case MODULE_LOADORDER_BI:
|
||||
TRACE("Trying built-in '%s'\n", libname);
|
||||
pwm = BUILTIN32_LoadLibraryExA(libname, flags, &err);
|
||||
pwm = BUILTIN32_LoadLibraryExA(libname, flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1443,16 +1420,15 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
|
||||
pwm->refCount++;
|
||||
|
||||
LeaveCriticalSection(&PROCESS_Current()->crit_section);
|
||||
|
||||
SetLastError( err ); /* restore last error */
|
||||
return pwm;
|
||||
}
|
||||
|
||||
if(err != ERROR_FILE_NOT_FOUND)
|
||||
if(GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||
break;
|
||||
}
|
||||
|
||||
WARN("Failed to load module '%s'; error=0x%08lx, \n", libname, err);
|
||||
SetLastError(err);
|
||||
WARN("Failed to load module '%s'; error=0x%08lx, \n", libname, GetLastError());
|
||||
LeaveCriticalSection(&PROCESS_Current()->crit_section);
|
||||
return NULL;
|
||||
}
|
||||
@ -1610,8 +1586,11 @@ BOOL MODULE_FreeLibrary( WINE_MODREF *wm )
|
||||
/* Call process detach notifications */
|
||||
if ( PROCESS_Current()->free_lib_count <= 1 )
|
||||
{
|
||||
struct unload_dll_request *req = get_req_buffer();
|
||||
|
||||
MODULE_DllProcessDetach( FALSE, NULL );
|
||||
DEBUG_SendUnloadDLLEvent( wm->module );
|
||||
req->base = (void *)wm->module;
|
||||
server_call_noerr( REQ_UNLOAD_DLL );
|
||||
}
|
||||
|
||||
TRACE("END\n");
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "global.h"
|
||||
#include "task.h"
|
||||
#include "snoop.h"
|
||||
#include "server.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(win32)
|
||||
@ -886,8 +887,9 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule,
|
||||
* The PE Library Loader frontend.
|
||||
* FIXME: handle the flags.
|
||||
*/
|
||||
WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags, DWORD *err)
|
||||
WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
|
||||
{
|
||||
struct load_dll_request *req = get_req_buffer();
|
||||
HMODULE hModule32;
|
||||
HMODULE16 hModule16;
|
||||
NE_MODULE *pModule;
|
||||
@ -898,33 +900,26 @@ WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags, DWORD *err)
|
||||
|
||||
/* Search for and open PE file */
|
||||
if ( SearchPathA( NULL, name, ".DLL",
|
||||
sizeof(filename), filename, NULL ) == 0 )
|
||||
{
|
||||
*err = ERROR_FILE_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
sizeof(filename), filename, NULL ) == 0 ) return NULL;
|
||||
|
||||
hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, 0, -1 );
|
||||
if ( hFile == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
*err = ERROR_FILE_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
if ( hFile == INVALID_HANDLE_VALUE ) return NULL;
|
||||
|
||||
/* Load PE module */
|
||||
hModule32 = PE_LoadImage( hFile, filename, &version );
|
||||
CloseHandle( hFile );
|
||||
if (!hModule32)
|
||||
{
|
||||
*err = ERROR_OUTOFMEMORY; /* Not entirely right, but good enough */
|
||||
CloseHandle( hFile );
|
||||
SetLastError( ERROR_OUTOFMEMORY ); /* Not entirely right, but good enough */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create 16-bit dummy module */
|
||||
if ((hModule16 = MODULE_CreateDummyModule( filename, version )) < 32)
|
||||
{
|
||||
*err = (DWORD)hModule16; /* This should give the correct error */
|
||||
CloseHandle( hFile );
|
||||
SetLastError( (DWORD)hModule16 ); /* This should give the correct error */
|
||||
return NULL;
|
||||
}
|
||||
pModule = (NE_MODULE *)GlobalLock16( hModule16 );
|
||||
@ -936,14 +931,20 @@ WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags, DWORD *err)
|
||||
{
|
||||
ERR( "can't load %s\n", filename );
|
||||
FreeLibrary16( hModule16 );
|
||||
*err = ERROR_OUTOFMEMORY;
|
||||
CloseHandle( hFile );
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (wm->binfmt.pe.pe_export)
|
||||
SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions);
|
||||
|
||||
*err = 0;
|
||||
req->handle = hFile;
|
||||
req->base = (void *)hModule32;
|
||||
req->dbg_offset = 0;
|
||||
req->dbg_size = 0;
|
||||
req->name = &wm->modname;
|
||||
server_call_noerr( REQ_LOAD_DLL );
|
||||
CloseHandle( hFile );
|
||||
return wm;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "main.h"
|
||||
#include "snoop.h"
|
||||
#include "winerror.h"
|
||||
#include "server.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(module);
|
||||
@ -331,8 +332,9 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
|
||||
* Partly copied from the original PE_ version.
|
||||
*
|
||||
*/
|
||||
WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
|
||||
{
|
||||
struct load_dll_request *req = get_req_buffer();
|
||||
HMODULE16 hModule16;
|
||||
NE_MODULE *pModule;
|
||||
WINE_MODREF *wm;
|
||||
@ -352,25 +354,21 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
|
||||
if (i == nb_dlls)
|
||||
{
|
||||
*err = ERROR_FILE_NOT_FOUND;
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Load built-in module */
|
||||
if (!dll_modules[i])
|
||||
{
|
||||
if (!(dll_modules[i] = BUILTIN32_DoLoadImage( builtin_dlls[i] )))
|
||||
{
|
||||
*err = ERROR_FILE_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
if (!(dll_modules[i] = BUILTIN32_DoLoadImage( builtin_dlls[i] ))) return NULL;
|
||||
}
|
||||
else BUILTIN32_WarnSecondInstance( builtin_dlls[i]->name );
|
||||
|
||||
/* Create 16-bit dummy module */
|
||||
if ((hModule16 = MODULE_CreateDummyModule( dllname, 0 )) < 32)
|
||||
{
|
||||
*err = (DWORD)hModule16;
|
||||
SetLastError( (DWORD)hModule16 );
|
||||
return NULL; /* FIXME: Should unload the builtin module */
|
||||
}
|
||||
|
||||
@ -383,14 +381,19 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err)
|
||||
{
|
||||
ERR( "can't load %s\n", path );
|
||||
FreeLibrary16( hModule16 ); /* FIXME: Should unload the builtin module */
|
||||
*err = ERROR_OUTOFMEMORY;
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (wm->binfmt.pe.pe_export)
|
||||
SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions);
|
||||
|
||||
*err = 0;
|
||||
req->handle = -1;
|
||||
req->base = (void *)pModule->module32;
|
||||
req->dbg_offset = 0;
|
||||
req->dbg_size = 0;
|
||||
req->name = &wm->modname;
|
||||
server_call_noerr( REQ_LOAD_DLL );
|
||||
return wm;
|
||||
}
|
||||
|
||||
|
@ -505,15 +505,3 @@ int CLIENT_IsBootThread(void)
|
||||
{
|
||||
return (GetCurrentThreadId() == (DWORD)boot_thread_id);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CLIENT_DebuggerRequest
|
||||
*
|
||||
* Send a debugger support request. Return 0 if OK.
|
||||
*/
|
||||
int CLIENT_DebuggerRequest( int op )
|
||||
{
|
||||
struct debugger_request *req = get_req_buffer();
|
||||
req->op = op;
|
||||
return server_call( REQ_DEBUGGER );
|
||||
}
|
||||
|
@ -40,43 +40,6 @@ DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEX
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* DEBUG_SendLoadDLLEvent
|
||||
*
|
||||
* Send an LOAD_DLL_DEBUG_EVENT event to the current process debugger.
|
||||
*/
|
||||
DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name )
|
||||
{
|
||||
struct send_debug_event_request *req = get_req_buffer();
|
||||
|
||||
req->event.code = LOAD_DLL_DEBUG_EVENT;
|
||||
req->event.info.load_dll.handle = file;
|
||||
req->event.info.load_dll.base = (void *)module;
|
||||
req->event.info.load_dll.dbg_offset = 0; /* FIXME */
|
||||
req->event.info.load_dll.dbg_size = 0; /* FIXME */
|
||||
req->event.info.load_dll.name = name;
|
||||
req->event.info.load_dll.unicode = 0;
|
||||
server_call_noerr( REQ_SEND_DEBUG_EVENT );
|
||||
return req->status;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* DEBUG_SendUnloadDLLEvent
|
||||
*
|
||||
* Send an UNLOAD_DLL_DEBUG_EVENT event to the current process debugger.
|
||||
*/
|
||||
DWORD DEBUG_SendUnloadDLLEvent( HMODULE module )
|
||||
{
|
||||
struct send_debug_event_request *req = get_req_buffer();
|
||||
|
||||
req->event.code = UNLOAD_DLL_DEBUG_EVENT;
|
||||
req->event.info.unload_dll.base = (void *)module;
|
||||
server_call_noerr( REQ_SEND_DEBUG_EVENT );
|
||||
return req->status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* WaitForDebugEvent (KERNEL32.720)
|
||||
*
|
||||
|
@ -458,14 +458,6 @@ void PROCESS_Start(void)
|
||||
server_call( REQ_INIT_PROCESS_DONE );
|
||||
debugged = req->debugged;
|
||||
|
||||
/* Send all required start-up debugger events */
|
||||
if (type == PROC_WIN32 && debugged)
|
||||
{
|
||||
EnterCriticalSection( &pdb->crit_section );
|
||||
MODULE_SendLoadDLLEvents();
|
||||
LeaveCriticalSection( &pdb->crit_section );
|
||||
}
|
||||
|
||||
if ( (pdb->flags & PDB32_CONSOLE_PROC) || (pdb->flags & PDB32_DOS_PROC) )
|
||||
AllocConsole();
|
||||
|
||||
|
@ -84,72 +84,85 @@ static const struct object_ops debug_ctx_ops =
|
||||
|
||||
|
||||
/* initialise the fields that do not need to be filled by the client */
|
||||
static int fill_debug_event( struct thread *debugger, struct thread *thread,
|
||||
struct debug_event *event )
|
||||
static int fill_debug_event( struct debug_event *event, void *arg )
|
||||
{
|
||||
struct process *debugger = event->debugger->process;
|
||||
struct process *process;
|
||||
struct thread *thread;
|
||||
struct process_dll *dll;
|
||||
int handle;
|
||||
|
||||
/* some events need special handling */
|
||||
switch(event->data.code)
|
||||
{
|
||||
case CREATE_THREAD_DEBUG_EVENT:
|
||||
if ((event->data.info.create_thread.handle = alloc_handle( debugger->process, thread,
|
||||
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
|
||||
THREAD_ALL_ACCESS, FALSE )) == -1)
|
||||
thread = arg;
|
||||
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
|
||||
if ((handle = alloc_handle( debugger, thread, THREAD_ALL_ACCESS, FALSE )) == -1)
|
||||
return 0;
|
||||
event->data.info.create_thread.teb = thread->teb;
|
||||
event->data.info.create_thread.start = thread->entry;
|
||||
event->data.info.create_thread.handle = handle;
|
||||
event->data.info.create_thread.teb = thread->teb;
|
||||
event->data.info.create_thread.start = thread->entry;
|
||||
break;
|
||||
case CREATE_PROCESS_DEBUG_EVENT:
|
||||
if ((handle = alloc_handle( debugger->process, thread->process,
|
||||
/* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
|
||||
PROCESS_ALL_ACCESS, FALSE )) == -1)
|
||||
process = arg;
|
||||
thread = process->thread_list;
|
||||
/* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
|
||||
if ((handle = alloc_handle( debugger, process, PROCESS_ALL_ACCESS, FALSE )) == -1)
|
||||
return 0;
|
||||
event->data.info.create_process.process = handle;
|
||||
|
||||
if ((handle = alloc_handle( debugger->process, thread,
|
||||
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
|
||||
THREAD_ALL_ACCESS, FALSE )) == -1)
|
||||
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
|
||||
if ((handle = alloc_handle( debugger, thread, THREAD_ALL_ACCESS, FALSE )) == -1)
|
||||
{
|
||||
close_handle( debugger->process, event->data.info.create_process.process );
|
||||
close_handle( debugger, event->data.info.create_process.process );
|
||||
return 0;
|
||||
}
|
||||
event->data.info.create_process.thread = handle;
|
||||
|
||||
handle = -1;
|
||||
if (thread->process->exe_file &&
|
||||
((handle = alloc_handle( debugger->process, thread->process->exe_file,
|
||||
/* the doc says write access too, but this doesn't seem a good idea */
|
||||
GENERIC_READ, FALSE )) == -1))
|
||||
if (process->exe.file &&
|
||||
/* the doc says write access too, but this doesn't seem a good idea */
|
||||
((handle = alloc_handle( debugger, process->exe.file, GENERIC_READ, FALSE )) == -1))
|
||||
{
|
||||
close_handle( debugger->process, event->data.info.create_process.process );
|
||||
close_handle( debugger->process, event->data.info.create_process.thread );
|
||||
close_handle( debugger, event->data.info.create_process.process );
|
||||
close_handle( debugger, event->data.info.create_process.thread );
|
||||
return 0;
|
||||
}
|
||||
event->data.info.create_process.file = handle;
|
||||
event->data.info.create_process.teb = thread->teb;
|
||||
event->data.info.create_process.base = thread->process->module;
|
||||
event->data.info.create_process.base = process->exe.base;
|
||||
event->data.info.create_process.start = thread->entry;
|
||||
event->data.info.create_process.dbg_offset = 0;
|
||||
event->data.info.create_process.dbg_size = 0;
|
||||
event->data.info.create_process.dbg_offset = process->exe.dbg_offset;
|
||||
event->data.info.create_process.dbg_size = process->exe.dbg_size;
|
||||
event->data.info.create_process.name = 0;
|
||||
event->data.info.create_process.unicode = 0;
|
||||
break;
|
||||
case LOAD_DLL_DEBUG_EVENT:
|
||||
if ((handle = event->data.info.load_dll.handle) != -1)
|
||||
{
|
||||
if ((handle = duplicate_handle( thread->process, handle, debugger->process,
|
||||
GENERIC_READ, FALSE, 0 )) == -1)
|
||||
return 0;
|
||||
event->data.info.load_dll.handle = handle;
|
||||
}
|
||||
dll = arg;
|
||||
handle = -1;
|
||||
if (dll->file &&
|
||||
(handle = alloc_handle( debugger, dll->file, GENERIC_READ, FALSE )) == -1)
|
||||
return 0;
|
||||
event->data.info.load_dll.handle = handle;
|
||||
event->data.info.load_dll.base = dll->base;
|
||||
event->data.info.load_dll.dbg_offset = dll->dbg_offset;
|
||||
event->data.info.load_dll.dbg_size = dll->dbg_size;
|
||||
event->data.info.load_dll.name = dll->name;
|
||||
event->data.info.load_dll.unicode = 0;
|
||||
break;
|
||||
case EXIT_PROCESS_DEBUG_EVENT:
|
||||
process = arg;
|
||||
event->data.info.exit.exit_code = process->exit_code;
|
||||
break;
|
||||
case EXIT_THREAD_DEBUG_EVENT:
|
||||
thread = arg;
|
||||
event->data.info.exit.exit_code = thread->exit_code;
|
||||
break;
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
case UNLOAD_DLL_DEBUG_EVENT:
|
||||
event->data.info.unload_dll.base = arg;
|
||||
break;
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
case OUTPUT_DEBUG_STRING_EVENT:
|
||||
case RIP_EVENT:
|
||||
break;
|
||||
@ -333,7 +346,6 @@ static int continue_debug_event( struct process *process, struct thread *thread,
|
||||
{
|
||||
if (event == debug_ctx->to_send) goto error;
|
||||
if (event->sender == thread) break;
|
||||
event = event->next;
|
||||
}
|
||||
if (!event) goto error;
|
||||
|
||||
@ -351,7 +363,7 @@ static int continue_debug_event( struct process *process, struct thread *thread,
|
||||
}
|
||||
|
||||
/* queue a debug event for a debugger */
|
||||
static struct debug_event *queue_debug_event( struct thread *thread, int code,
|
||||
static struct debug_event *queue_debug_event( struct thread *thread, int code, void *arg,
|
||||
debug_event_t *data )
|
||||
{
|
||||
struct thread *debugger = thread->process->debugger;
|
||||
@ -372,7 +384,7 @@ static struct debug_event *queue_debug_event( struct thread *thread, int code,
|
||||
if (data) memcpy( &event->data, data, sizeof(event->data) );
|
||||
event->data.code = code;
|
||||
|
||||
if (!fill_debug_event( debugger, thread, event ))
|
||||
if (!fill_debug_event( event, arg ))
|
||||
{
|
||||
event->data.code = -1; /* make sure we don't attempt to close handles */
|
||||
release_object( event );
|
||||
@ -385,15 +397,35 @@ static struct debug_event *queue_debug_event( struct thread *thread, int code,
|
||||
}
|
||||
|
||||
/* generate a debug event from inside the server and queue it */
|
||||
void generate_debug_event( struct thread *thread, int code )
|
||||
void generate_debug_event( struct thread *thread, int code, void *arg )
|
||||
{
|
||||
if (thread->process->debugger)
|
||||
{
|
||||
struct debug_event *event = queue_debug_event( thread, code, NULL );
|
||||
struct debug_event *event = queue_debug_event( thread, code, arg, NULL );
|
||||
if (event) release_object( event );
|
||||
}
|
||||
}
|
||||
|
||||
/* generate all startup events of a given process */
|
||||
void generate_startup_debug_events( struct process *process )
|
||||
{
|
||||
struct process_dll *dll;
|
||||
struct thread *thread = process->thread_list;
|
||||
|
||||
/* generate creation events */
|
||||
generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT, process );
|
||||
while ((thread = thread->next))
|
||||
generate_debug_event( thread, CREATE_THREAD_DEBUG_EVENT, thread );
|
||||
|
||||
/* generate dll events (in loading order, i.e. reverse list order) */
|
||||
for (dll = &process->exe; dll->next; dll = dll->next);
|
||||
while (dll != &process->exe)
|
||||
{
|
||||
generate_debug_event( process->thread_list, LOAD_DLL_DEBUG_EVENT, dll );
|
||||
dll = dll->prev;
|
||||
}
|
||||
}
|
||||
|
||||
/* return a pointer to the context in case the thread is inside an exception event */
|
||||
CONTEXT *get_debug_context( struct thread *thread )
|
||||
{
|
||||
@ -487,10 +519,8 @@ DECL_HANDLER(debug_process)
|
||||
if (!process) return;
|
||||
if (debugger_attach( process, current ))
|
||||
{
|
||||
struct thread *thread = process->thread_list;
|
||||
generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT );
|
||||
while ((thread = thread->next)) generate_debug_event( thread, CREATE_THREAD_DEBUG_EVENT );
|
||||
/* FIXME: load dll + breakpoint exception events */
|
||||
generate_startup_debug_events( process );
|
||||
/* FIXME: breakpoint exception event */
|
||||
}
|
||||
release_object( process );
|
||||
}
|
||||
@ -507,7 +537,8 @@ DECL_HANDLER(send_debug_event)
|
||||
return;
|
||||
}
|
||||
req->status = 0;
|
||||
if (current->process->debugger && ((event = queue_debug_event( current, code, &req->event ))))
|
||||
if (current->process->debugger && ((event = queue_debug_event( current, code,
|
||||
NULL, &req->event ))))
|
||||
{
|
||||
/* wait for continue_debug_event */
|
||||
struct object *obj = &event->obj;
|
||||
|
@ -154,7 +154,8 @@ extern int free_console( struct process *process );
|
||||
/* debugger functions */
|
||||
|
||||
extern int debugger_attach( struct process *process, struct thread *debugger );
|
||||
extern void generate_debug_event( struct thread *thread, int code );
|
||||
extern void generate_debug_event( struct thread *thread, int code, void *arg );
|
||||
extern void generate_startup_debug_events( struct process *process );
|
||||
extern void debug_exit_thread( struct thread *thread );
|
||||
extern CONTEXT *get_debug_context( struct thread *thread );
|
||||
|
||||
|
111
server/process.c
111
server/process.c
@ -143,7 +143,6 @@ struct thread *create_process( int fd, struct process *parent,
|
||||
process->prev = NULL;
|
||||
process->thread_list = NULL;
|
||||
process->debugger = NULL;
|
||||
process->exe_file = NULL;
|
||||
process->handles = NULL;
|
||||
process->exit_code = STILL_ACTIVE;
|
||||
process->running_threads = 0;
|
||||
@ -157,6 +156,11 @@ struct thread *create_process( int fd, struct process *parent,
|
||||
process->info = NULL;
|
||||
process->ldt_copy = NULL;
|
||||
process->ldt_flags = NULL;
|
||||
process->exe.next = NULL;
|
||||
process->exe.prev = NULL;
|
||||
process->exe.file = NULL;
|
||||
process->exe.dbg_offset = 0;
|
||||
process->exe.dbg_size = 0;
|
||||
gettimeofday( &process->start_time, NULL );
|
||||
if ((process->next = first_process) != NULL) process->next->prev = process;
|
||||
first_process = process;
|
||||
@ -176,7 +180,7 @@ struct thread *create_process( int fd, struct process *parent,
|
||||
/* retrieve the main exe file */
|
||||
if (process->info->exe_file != -1)
|
||||
{
|
||||
if (!(process->exe_file = get_file_obj( parent, process->info->exe_file,
|
||||
if (!(process->exe.file = get_file_obj( parent, process->info->exe_file,
|
||||
GENERIC_READ ))) goto error;
|
||||
process->info->exe_file = -1;
|
||||
}
|
||||
@ -225,7 +229,7 @@ static void process_destroy( struct object *obj )
|
||||
else first_process = process->next;
|
||||
if (process->info) free( process->info );
|
||||
if (process->init_event) release_object( process->init_event );
|
||||
if (process->exe_file) release_object( process->exe_file );
|
||||
if (process->exe.file) release_object( process->exe.file );
|
||||
}
|
||||
|
||||
/* dump a process on stdout for debugging purposes */
|
||||
@ -263,17 +267,68 @@ struct process *get_process_from_handle( int handle, unsigned int access )
|
||||
access, &process_ops );
|
||||
}
|
||||
|
||||
/* add a dll to a process list */
|
||||
static struct process_dll *process_load_dll( struct process *process, struct file *file,
|
||||
void *base )
|
||||
{
|
||||
struct process_dll *dll;
|
||||
|
||||
/* make sure we don't already have one with the same base address */
|
||||
for (dll = process->exe.next; dll; dll = dll->next) if (dll->base == base)
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((dll = mem_alloc( sizeof(*dll) )))
|
||||
{
|
||||
dll->prev = &process->exe;
|
||||
dll->file = NULL;
|
||||
dll->base = base;
|
||||
if (file) dll->file = (struct file *)grab_object( file );
|
||||
if ((dll->next = process->exe.next)) dll->next->prev = dll;
|
||||
process->exe.next = dll;
|
||||
}
|
||||
return dll;
|
||||
}
|
||||
|
||||
/* remove a dll from a process list */
|
||||
static void process_unload_dll( struct process *process, void *base )
|
||||
{
|
||||
struct process_dll *dll;
|
||||
|
||||
for (dll = process->exe.next; dll; dll = dll->next)
|
||||
{
|
||||
if (dll->base == base)
|
||||
{
|
||||
if (dll->file) release_object( dll->file );
|
||||
if (dll->next) dll->next->prev = dll->prev;
|
||||
if (dll->prev) dll->prev->next = dll->next;
|
||||
free( dll );
|
||||
generate_debug_event( current, UNLOAD_DLL_DEBUG_EVENT, base );
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
}
|
||||
|
||||
/* a process has been killed (i.e. its last thread died) */
|
||||
static void process_killed( struct process *process, int exit_code )
|
||||
static void process_killed( struct process *process )
|
||||
{
|
||||
assert( !process->thread_list );
|
||||
process->exit_code = exit_code;
|
||||
gettimeofday( &process->end_time, NULL );
|
||||
release_object( process->handles );
|
||||
process->handles = NULL;
|
||||
free_console( process );
|
||||
if (process->exe_file) release_object( process->exe_file );
|
||||
process->exe_file = NULL;
|
||||
while (process->exe.next)
|
||||
{
|
||||
struct process_dll *dll = process->exe.next;
|
||||
process->exe.next = dll->next;
|
||||
if (dll->file) release_object( dll->file );
|
||||
free( dll );
|
||||
}
|
||||
if (process->exe.file) release_object( process->exe.file );
|
||||
process->exe.file = NULL;
|
||||
wake_up( &process->obj, 0 );
|
||||
if (!--running_processes)
|
||||
{
|
||||
@ -308,8 +363,11 @@ void remove_process_thread( struct process *process, struct thread *thread )
|
||||
if (!--process->running_threads)
|
||||
{
|
||||
/* we have removed the last running thread, exit the process */
|
||||
process_killed( process, thread->exit_code );
|
||||
process->exit_code = thread->exit_code;
|
||||
generate_debug_event( thread, EXIT_PROCESS_DEBUG_EVENT, process );
|
||||
process_killed( process );
|
||||
}
|
||||
else generate_debug_event( thread, EXIT_THREAD_DEBUG_EVENT, thread );
|
||||
release_object( thread );
|
||||
}
|
||||
|
||||
@ -580,8 +638,8 @@ DECL_HANDLER(init_process)
|
||||
req->cmd_show = info->cmd_show;
|
||||
req->env_ptr = info->env_ptr;
|
||||
strcpy( req->cmdline, info->cmdline );
|
||||
if (current->process->exe_file)
|
||||
req->exe_file = alloc_handle( current->process, current->process->exe_file,
|
||||
if (current->process->exe.file)
|
||||
req->exe_file = alloc_handle( current->process, current->process->exe.file,
|
||||
GENERIC_READ, 0 );
|
||||
free( info );
|
||||
}
|
||||
@ -595,9 +653,9 @@ DECL_HANDLER(init_process_done)
|
||||
fatal_protocol_error( current, "init_process_done: no event\n" );
|
||||
return;
|
||||
}
|
||||
current->entry = req->entry;
|
||||
process->module = req->module;
|
||||
generate_debug_event( current, CREATE_PROCESS_DEBUG_EVENT );
|
||||
current->entry = req->entry;
|
||||
process->exe.base = req->module;
|
||||
generate_startup_debug_events( current->process );
|
||||
set_event( process->init_event );
|
||||
release_object( process->init_event );
|
||||
process->init_event = NULL;
|
||||
@ -678,3 +736,30 @@ DECL_HANDLER(write_process_memory)
|
||||
release_object( process );
|
||||
}
|
||||
}
|
||||
|
||||
/* notify the server that a dll has been loaded */
|
||||
DECL_HANDLER(load_dll)
|
||||
{
|
||||
struct process_dll *dll;
|
||||
struct file *file = NULL;
|
||||
|
||||
if ((req->handle != -1) &&
|
||||
!(file = get_file_obj( current->process, req->handle, GENERIC_READ ))) return;
|
||||
|
||||
if ((dll = process_load_dll( current->process, file, req->base )))
|
||||
{
|
||||
dll->dbg_offset = req->dbg_offset;
|
||||
dll->dbg_size = req->dbg_size;
|
||||
dll->name = req->name;
|
||||
/* only generate event if initialization is done */
|
||||
if (!current->process->init_event)
|
||||
generate_debug_event( current, LOAD_DLL_DEBUG_EVENT, dll );
|
||||
}
|
||||
if (file) release_object( file );
|
||||
}
|
||||
|
||||
/* notify the server that a dll is being unloaded */
|
||||
DECL_HANDLER(unload_dll)
|
||||
{
|
||||
process_unload_dll( current->process, req->base );
|
||||
}
|
||||
|
@ -15,6 +15,17 @@
|
||||
|
||||
/* process structures */
|
||||
|
||||
struct process_dll
|
||||
{
|
||||
struct process_dll *next; /* per-process dll list */
|
||||
struct process_dll *prev;
|
||||
struct file *file; /* dll file */
|
||||
void *base; /* dll base address (in process addr space) */
|
||||
void *name; /* ptr to ptr to name (in process addr space) */
|
||||
int dbg_offset; /* debug info offset */
|
||||
int dbg_size; /* debug info size */
|
||||
};
|
||||
|
||||
struct process
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
@ -22,7 +33,6 @@ struct process
|
||||
struct process *prev;
|
||||
struct thread *thread_list; /* head of the thread list */
|
||||
struct thread *debugger; /* thread debugging this process */
|
||||
struct file *exe_file; /* main exe file */
|
||||
struct object *handles; /* handle entries */
|
||||
int exit_code; /* process exit code */
|
||||
int running_threads; /* number of threads running in this process */
|
||||
@ -35,9 +45,9 @@ struct process
|
||||
struct object *console_in; /* console input */
|
||||
struct object *console_out; /* console output */
|
||||
struct event *init_event; /* event for init done */
|
||||
struct process_dll exe; /* main exe file */
|
||||
void *ldt_copy; /* pointer to LDT copy in client addr space */
|
||||
void *ldt_flags; /* pointer to LDT flags in client addr space */
|
||||
void *module; /* main module base address */
|
||||
struct new_process_request *info; /* startup info (freed after startup) */
|
||||
};
|
||||
|
||||
|
@ -120,15 +120,20 @@ static int attach_thread( struct thread *thread )
|
||||
void detach_thread( struct thread *thread )
|
||||
{
|
||||
if (!thread->unix_pid) return;
|
||||
kill( thread->unix_pid, SIGTERM );
|
||||
if (thread->suspend + thread->process->suspend) continue_thread( thread );
|
||||
if (thread->attached)
|
||||
{
|
||||
wait4_thread( thread, SIGTERM );
|
||||
/* make sure it is stopped */
|
||||
if (!(thread->suspend + thread->process->suspend)) stop_thread( thread );
|
||||
kill( thread->unix_pid, SIGTERM );
|
||||
if (debug_level) fprintf( stderr, "%08x: *detached*\n", (unsigned int)thread );
|
||||
ptrace( PTRACE_DETACH, thread->unix_pid, 1, SIGTERM );
|
||||
thread->attached = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
kill( thread->unix_pid, SIGTERM );
|
||||
if (thread->suspend + thread->process->suspend) continue_thread( thread );
|
||||
}
|
||||
}
|
||||
|
||||
/* stop a thread (at the Unix level) */
|
||||
|
@ -383,18 +383,3 @@ void lock_master_socket( int locked )
|
||||
{
|
||||
set_select_events( &master_socket->obj, locked ? 0 : POLLIN );
|
||||
}
|
||||
|
||||
/* debugger support operations */
|
||||
DECL_HANDLER(debugger)
|
||||
{
|
||||
switch ( req->op )
|
||||
{
|
||||
case DEBUGGER_FREEZE_ALL:
|
||||
suspend_all_threads();
|
||||
break;
|
||||
|
||||
case DEBUGGER_UNFREEZE_ALL:
|
||||
resume_all_threads();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ extern void close_master_socket(void);
|
||||
extern void lock_master_socket( int locked );
|
||||
|
||||
extern void trace_request( enum request req, int fd );
|
||||
extern void trace_kill( struct thread *thread );
|
||||
extern void trace_reply( struct thread *thread );
|
||||
|
||||
/* get the request buffer */
|
||||
@ -85,7 +84,8 @@ DECL_HANDLER(get_thread_info);
|
||||
DECL_HANDLER(set_thread_info);
|
||||
DECL_HANDLER(suspend_thread);
|
||||
DECL_HANDLER(resume_thread);
|
||||
DECL_HANDLER(debugger);
|
||||
DECL_HANDLER(load_dll);
|
||||
DECL_HANDLER(unload_dll);
|
||||
DECL_HANDLER(queue_apc);
|
||||
DECL_HANDLER(get_apcs);
|
||||
DECL_HANDLER(close_handle);
|
||||
@ -189,7 +189,8 @@ static const struct handler {
|
||||
{ (void(*)())req_set_thread_info, sizeof(struct set_thread_info_request) },
|
||||
{ (void(*)())req_suspend_thread, sizeof(struct suspend_thread_request) },
|
||||
{ (void(*)())req_resume_thread, sizeof(struct resume_thread_request) },
|
||||
{ (void(*)())req_debugger, sizeof(struct debugger_request) },
|
||||
{ (void(*)())req_load_dll, sizeof(struct load_dll_request) },
|
||||
{ (void(*)())req_unload_dll, sizeof(struct unload_dll_request) },
|
||||
{ (void(*)())req_queue_apc, sizeof(struct queue_apc_request) },
|
||||
{ (void(*)())req_get_apcs, sizeof(struct get_apcs_request) },
|
||||
{ (void(*)())req_close_handle, sizeof(struct close_handle_request) },
|
||||
|
@ -563,10 +563,9 @@ void kill_thread( struct thread *thread, int exit_code )
|
||||
thread->state = TERMINATED;
|
||||
thread->exit_code = exit_code;
|
||||
if (current == thread) current = NULL;
|
||||
if (debug_level) trace_kill( thread );
|
||||
if (debug_level)
|
||||
fprintf( stderr,"%08x: *killed* exit_code=%d\n", (unsigned int)thread, exit_code );
|
||||
if (thread->wait) end_wait( thread );
|
||||
generate_debug_event( thread, (thread->process->running_threads == 1) ?
|
||||
EXIT_PROCESS_DEBUG_EVENT : EXIT_THREAD_DEBUG_EVENT );
|
||||
debug_exit_thread( thread );
|
||||
abandon_mutexes( thread );
|
||||
remove_process_thread( thread->process, thread );
|
||||
@ -633,7 +632,7 @@ DECL_HANDLER(init_thread)
|
||||
current->entry = req->entry;
|
||||
if (current->suspend + current->process->suspend > 0) stop_thread( current );
|
||||
if (current->process->running_threads > 1)
|
||||
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT );
|
||||
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, current );
|
||||
}
|
||||
|
||||
/* terminate a thread */
|
||||
|
@ -361,9 +361,18 @@ static void dump_resume_thread_reply( const struct resume_thread_request *req )
|
||||
fprintf( stderr, " count=%d", req->count );
|
||||
}
|
||||
|
||||
static void dump_debugger_request( const struct debugger_request *req )
|
||||
static void dump_load_dll_request( const struct load_dll_request *req )
|
||||
{
|
||||
fprintf( stderr, " op=%d", req->op );
|
||||
fprintf( stderr, " handle=%d,", req->handle );
|
||||
fprintf( stderr, " base=%p,", req->base );
|
||||
fprintf( stderr, " dbg_offset=%d,", req->dbg_offset );
|
||||
fprintf( stderr, " dbg_size=%d,", req->dbg_size );
|
||||
fprintf( stderr, " name=%p", req->name );
|
||||
}
|
||||
|
||||
static void dump_unload_dll_request( const struct unload_dll_request *req )
|
||||
{
|
||||
fprintf( stderr, " base=%p", req->base );
|
||||
}
|
||||
|
||||
static void dump_queue_apc_request( const struct queue_apc_request *req )
|
||||
@ -1247,7 +1256,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||
(dump_func)dump_set_thread_info_request,
|
||||
(dump_func)dump_suspend_thread_request,
|
||||
(dump_func)dump_resume_thread_request,
|
||||
(dump_func)dump_debugger_request,
|
||||
(dump_func)dump_load_dll_request,
|
||||
(dump_func)dump_unload_dll_request,
|
||||
(dump_func)dump_queue_apc_request,
|
||||
(dump_func)dump_get_apcs_request,
|
||||
(dump_func)dump_close_handle_request,
|
||||
@ -1349,6 +1359,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||
(dump_func)dump_resume_thread_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_apcs_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_handle_info_reply,
|
||||
@ -1447,7 +1458,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||
"set_thread_info",
|
||||
"suspend_thread",
|
||||
"resume_thread",
|
||||
"debugger",
|
||||
"load_dll",
|
||||
"unload_dll",
|
||||
"queue_apc",
|
||||
"get_apcs",
|
||||
"close_handle",
|
||||
@ -1548,12 +1560,6 @@ void trace_request( enum request req, int fd )
|
||||
else fprintf( stderr, " )\n" );
|
||||
}
|
||||
|
||||
void trace_kill( struct thread *thread )
|
||||
{
|
||||
fprintf( stderr,"%08x: *killed* exit_code=%d\n",
|
||||
(unsigned int)thread, thread->exit_code );
|
||||
}
|
||||
|
||||
void trace_reply( struct thread *thread )
|
||||
{
|
||||
fprintf( stderr, "%08x: %s() = %x",
|
||||
|
Loading…
x
Reference in New Issue
Block a user