|
|
//----------------------------------------------------------------------------
//
// Process abstraction.
//
// Copyright (C) Microsoft Corporation, 2001-2002.
//
//----------------------------------------------------------------------------
#ifndef __PROCESS_HPP__
#define __PROCESS_HPP__
// In the kernel debugger there is a virtual process representing
// kernel space. It has an artificial handle and threads
// representing each processor in the machine.
// A similar scheme is used in user dump files where real
// handles don't exist.
// With multiple systems there may be multiple kernel spaces,
// so the system user ID is added to the base fake ID to
// create a unique virtual process ID.
#define VIRTUAL_PROCESS_ID_BASE 0xf0f0f0f0
#define VIRTUAL_PROCESS_HANDLE(Id) ((HANDLE)(ULONG_PTR)(Id))
enum COR_DLL { // These enumerants are ordered to
// allow mscorwks/svr to override
// mscoree as the "known" COR image
// by value comparison.
COR_DLL_INVALID, COR_DLL_EE, COR_DLL_WKS, COR_DLL_SVR, };
//----------------------------------------------------------------------------
//
// Thread and process information is much different bewteen
// user and kernel debugging. The structures exist and are
// as common as possible to enable common code.
//
// In user debugging process and thread info track the system
// processes and threads being debugged.
//
// In kernel debugging there is only one process that represents
// kernel space. There is one thread per processor, each
// representing that processor's thread state.
//
//----------------------------------------------------------------------------
#define ENG_PROC_ATTACHED 0x00000001
#define ENG_PROC_CREATED 0x00000002
#define ENG_PROC_EXAMINED 0x00000004
#define ENG_PROC_ATTACH_EXISTING 0x00000008
// Currently the only system process specially marked is CSR.
#define ENG_PROC_SYSTEM 0x00000010
#define ENG_PROC_NO_SUSPEND_RESUME 0x00000020
#define ENG_PROC_NO_INITIAL_BREAK 0x00000040
#define ENG_PROC_RESUME_AT_ATTACH 0x00000080
#define ENG_PROC_ANY_ATTACH (ENG_PROC_ATTACHED | ENG_PROC_EXAMINED)
#define ENG_PROC_ANY_EXAMINE (ENG_PROC_EXAMINED | ENG_PROC_ATTACH_EXISTING)
// Handle must be closed when deleted.
// This flag applies to both processes and threads.
#define ENG_PROC_THREAD_CLOSE_HANDLE 0x80000000
// The debugger set the trace flag when deferring
// breakpoint work on the last event for this thread.
#define ENG_THREAD_DEFER_BP_TRACE 0x00000001
// Processes which were created or attached but that
// have not yet generated events yet.
typedef struct _PENDING_PROCESS { ULONG64 Handle; // Initial thread information is only valid for creations.
ULONG64 InitialThreadHandle; ULONG Id; ULONG InitialThreadId; ULONG Flags; ULONG Options; struct _PENDING_PROCESS* Next; } PENDING_PROCESS;
struct IMPLICIT_THREAD_SAVE { ULONG64 Value; BOOL Default; ThreadInfo* Thread; };
struct OUT_OF_PROC_FUNC_TABLE_DLL { OUT_OF_PROC_FUNC_TABLE_DLL* Next; ULONG64 Handle; // Name data follows.
};
//----------------------------------------------------------------------------
//
// ProcCorDataAccessServices.
//
//----------------------------------------------------------------------------
class ProcCorDataAccessServices : public ICorDataAccessServices { public: ProcCorDataAccessServices(void); // IUnknown.
STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ); STDMETHOD_(ULONG, AddRef)( THIS ); STDMETHOD_(ULONG, Release)( THIS );
// ICorDataAccessServices.
virtual HRESULT STDMETHODCALLTYPE GetMachineType( /* [out] */ ULONG32 *machine); virtual HRESULT STDMETHODCALLTYPE GetPointerSize( /* [out] */ ULONG32 *size); virtual HRESULT STDMETHODCALLTYPE GetImageBase( /* [string][in] */ LPCWSTR name, /* [out] */ CORDATA_ADDRESS *base); virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CORDATA_ADDRESS address, /* [length_is][size_is][out] */ PBYTE buffer, /* [in] */ ULONG32 request, /* [optional][out] */ ULONG32 *done); virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CORDATA_ADDRESS address, /* [size_is][in] */ PBYTE buffer, /* [in] */ ULONG32 request, /* [optional][out] */ ULONG32 *done); virtual HRESULT STDMETHODCALLTYPE GetTlsValue( /* [in] */ ULONG32 index, /* [out] */ CORDATA_ADDRESS* value); virtual HRESULT STDMETHODCALLTYPE SetTlsValue( /* [in] */ ULONG32 index, /* [in] */ CORDATA_ADDRESS value); virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadId( /* [out] */ ULONG32* threadId); virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ULONG32 threadId, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [out, size_is(contextSize)] */ PBYTE context); virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ ULONG32 threadId, /* [in] */ ULONG32 contextSize, /* [in, size_is(contextSize)] */ PBYTE context);
ProcessInfo* m_Process; };
//----------------------------------------------------------------------------
//
// ProcessInfo.
//
//----------------------------------------------------------------------------
class ProcessInfo { public: ProcessInfo(TargetInfo* Target, ULONG SystemId, HANDLE SymHandle, ULONG64 SysHandle, ULONG Flags, ULONG Options); ~ProcessInfo(void);
TargetInfo* m_Target; ProcessInfo* m_Next; ULONG m_NumImages; ULONG m_NumUnloadedModules; ImageInfo* m_ImageHead; ImageInfo* m_ExecutableImage; ImageInfo* m_SynthesizedImage; ULONG m_NumThreads; ThreadInfo* m_ThreadHead; ThreadInfo* m_CurrentThread; ULONG m_UserId; ULONG m_SystemId; ULONG m_Exited:1; ULONG m_ModulesLoaded:1; ULONG m_InitialBreakDone:1; ULONG m_InitialBreak:1; ULONG m_InitialBreakWx86:1; ULONG64 m_DataOffset; // For kernel mode and dumps the process handle is
// a virtual handle for the kernel/dump process.
// dbghelp still uses HANDLE as the process handle
// type even though we may want to pass in 64-bit
// process handles when remote debugging. Keep
// a cut-down version of the handle for normal
// use but also keep the full handle around in
// case it's needed.
// There is also another purpose for the two handles:
// as dbghelp has no notion of systems we need to
// keep all handles from all systems unique. The
// dbghelp handle may be further modified in order
// to preserve uniqueness.
HANDLE m_SymHandle; ULONG64 m_SysHandle; ULONG m_Flags; ULONG m_Options; ULONG m_NumBreakpoints; class Breakpoint* m_Breakpoints; class Breakpoint* m_BreakpointsTail; ULONG64 m_DynFuncTableList; OUT_OF_PROC_FUNC_TABLE_DLL* m_OopFuncTableDlls; ULONG64 m_RtlUnloadList; ULONG64 m_ImplicitThreadData; BOOL m_ImplicitThreadDataIsDefault; ThreadInfo* m_ImplicitThreadDataThread;
ImageInfo* m_CorImage; COR_DLL m_CorImageType; HMODULE m_CorDebugDll; ICorDataAccess* m_CorAccess; ProcCorDataAccessServices m_CorServices; VirtualMemoryCache m_VirtualCache;
ThreadInfo* FindThreadByUserId(ULONG Id); ThreadInfo* FindThreadBySystemId(ULONG Id); ThreadInfo* FindThreadByHandle(ULONG64 Handle); void InsertThread(ThreadInfo* Thread); void RemoveThread(ThreadInfo* Thread); HRESULT CreateVirtualThreads(ULONG StartId, ULONG Threads);
ImageInfo* FindImageByIndex(ULONG Index); ImageInfo* FindImageByOffset(ULONG64 Offset, BOOL AllowSynth); ImageInfo* FindImageByName(PCSTR Name, ULONG NameChars, INAME Which, BOOL AllowSynth);
BOOL GetOffsetFromMod(PCSTR String, PULONG64 Offset); void InsertImage(ImageInfo* Image); void RemoveImage(ImageInfo* Image); BOOL DeleteImageByName(PCSTR Name, INAME Which); BOOL DeleteImageByBase(ULONG64 Base); void DeleteImagesBelowOffset(ULONG64 Offset); void DeleteImages(void); HRESULT AddImage(PMODULE_INFO_ENTRY ModEntry, BOOL ForceSymbolLoad, ImageInfo** ImageAdded); void SynthesizeSymbols(void); void VerifyKernel32Version(void); BOOL DeleteExitedInfos(void); void PrepareForExecution(void);
void OutputThreadInfo(ThreadInfo* Match, BOOL Verbose);
HRESULT AddOopFuncTableDll(PWSTR Dll, ULONG64 Handle); void ClearOopFuncTableDlls(void); OUT_OF_PROC_FUNC_TABLE_DLL* FindOopFuncTableDll(PWSTR Dll);
HRESULT LoadCorDebugDll(void); HRESULT IsCorCode(ULONG64 Native); HRESULT ConvertNativeToIlOffset(ULONG64 Native, PULONG64 ImageBase, PULONG32 MethodToken, PULONG32 MethodOffs); HRESULT GetCorSymbol(ULONG64 Native, PSTR Buffer, ULONG BufferChars, PULONG64 Displacement); ICorDataStackWalk* StartCorStack(ULONG32 CorThreadId); void FlushCorState(void) { if (m_CorDebugDll) { m_CorAccess->Flush(); } } HRESULT Terminate(void); HRESULT Detach(void); HRESULT Abandon(void);
void ResetImplicitData(void) { m_ImplicitThreadData = 0; m_ImplicitThreadDataIsDefault = TRUE; m_ImplicitThreadDataThread = NULL; } void SaveImplicitThread(IMPLICIT_THREAD_SAVE* Save) { Save->Value = m_ImplicitThreadData; Save->Default = m_ImplicitThreadDataIsDefault; Save->Thread = m_ImplicitThreadDataThread; } void RestoreImplicitThread(IMPLICIT_THREAD_SAVE* Save) { m_ImplicitThreadData = Save->Value; m_ImplicitThreadDataIsDefault = Save->Default; m_ImplicitThreadDataThread = Save->Thread; } HRESULT GetImplicitThreadData(ThreadInfo* Thread, PULONG64 Offset); HRESULT GetImplicitThreadDataTeb(ThreadInfo* Thread, PULONG64 Offset); HRESULT SetImplicitThreadData(ThreadInfo* Thread, ULONG64 Offset, BOOL Verbose); HRESULT ReadImplicitThreadInfoPointer(ThreadInfo* Thread, ULONG Offset, PULONG64 Ptr);
void MarkExited(void) { m_Exited = TRUE; g_EngDefer |= ENG_DEFER_DELETE_EXITED; }
PSTR GetExecutableImageName(void) { return m_ExecutableImage ? m_ExecutableImage->m_ImagePath : (m_ImageHead != NULL ? m_ImageHead->m_ImagePath : "?NoImage?"); } };
ProcessInfo* FindAnyProcessByUserId(ULONG Id);
void ParseProcessCmds(void);
HRESULT TerminateProcesses(void); HRESULT DetachProcesses(void);
enum { SEP_TERMINATE, SEP_DETACH, SEP_ABANDON, };
HRESULT SeparateCurrentProcess(ULONG Mode, PSTR Description);
#endif // #ifndef __PROCESS_HPP__
|