You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
348 lines
11 KiB
348 lines
11 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// 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__
|