windows-nt/Source/XPSP1/NT/sdktools/debuggers/ntsd64/target.hpp
2020-09-26 16:20:57 +08:00

1500 lines
47 KiB
C++

//----------------------------------------------------------------------------
//
// Abstraction of target-specific information.
//
// Copyright (C) Microsoft Corporation, 1999-2001.
//
//----------------------------------------------------------------------------
#ifndef __TARGET_HPP__
#define __TARGET_HPP__
extern DBGKD_GET_VERSION64 g_KdVersion;
HRESULT EmulateNtSelDescriptor(class MachineInfo* Machine,
ULONG Selector, PDESCRIPTOR64 Desc);
ULONG NtBuildToSystemVersion(ULONG Build);
ULONG Win9xBuildToSystemVersion(ULONG Build);
void SetTargetSystemVersionAndBuild(ULONG Build, ULONG PlatformId);
PCSTR SystemVersionName(ULONG Sver);
BOOL
GetUserModuleListAddress(
MachineInfo* Machine,
ULONG64 Peb,
BOOL Quiet,
PULONG64 OrderModuleListStart,
PULONG64 FirstEntry
);
BOOL
GetModNameFromLoaderList(
MachineInfo* Machine,
ULONG64 Peb,
ULONG64 ModuleBase,
PSTR NameBuffer,
ULONG BufferSize,
BOOL FullPath
);
void InitSelCache(void);
void
ConvertLoaderEntry32To64(
PKLDR_DATA_TABLE_ENTRY32 b32,
PKLDR_DATA_TABLE_ENTRY64 b64
);
void SetTargetNtCsdVersion(ULONG CsdVersion);
//----------------------------------------------------------------------------
//
// Module list abstraction.
//
//----------------------------------------------------------------------------
// If the image header is paged out the true values for
// certain fields cannot be retrieved. These placeholders
// are used instead.
#define UNKNOWN_CHECKSUM 0xffffffff
#define UNKNOWN_TIMESTAMP 0xfffffffe
typedef struct _MODULE_INFO_ENTRY
{
// NamePtr should include a path if one is available.
// It is the responsibility of callers to find the
// file tail if that's all they care about.
// If UnicodeNamePtr is false NameLength is ignored.
PSTR NamePtr;
ULONG UnicodeNamePtr:1;
ULONG ImageInfoValid:1;
ULONG ImageInfoPartial:1;
ULONG ImageDebugHeader:1;
ULONG Unused:28;
// Length in bytes not including the terminator.
ULONG NameLength;
PSTR ModuleName;
HANDLE File;
ULONG64 Base;
ULONG Size;
ULONG SizeOfCode;
ULONG SizeOfData;
ULONG CheckSum;
ULONG TimeDateStamp;
PVOID DebugHeader;
ULONG SizeOfDebugHeader;
CHAR Buffer[MAX_IMAGE_PATH * sizeof(WCHAR)];
} MODULE_INFO_ENTRY, *PMODULE_INFO_ENTRY;
class ModuleInfo
{
public:
virtual HRESULT Initialize(void) = 0;
virtual HRESULT GetEntry(PMODULE_INFO_ENTRY Entry) = 0;
// Base implementation does nothing.
// Updates the entry image info by reading the
// image header.
void ReadImageHeaderInfo(PMODULE_INFO_ENTRY Entry);
};
class NtModuleInfo : public ModuleInfo
{
public:
virtual HRESULT GetEntry(PMODULE_INFO_ENTRY Entry);
protected:
MachineInfo* m_Machine;
ULONG64 m_Head;
ULONG64 m_Cur;
};
class NtKernelModuleInfo : public NtModuleInfo
{
public:
virtual HRESULT Initialize(void);
};
extern NtKernelModuleInfo g_NtKernelModuleIterator;
class NtUserModuleInfo : public NtModuleInfo
{
public:
virtual HRESULT Initialize(void);
protected:
ULONG64 m_Peb;
};
class NtTargetUserModuleInfo : public NtUserModuleInfo
{
public:
virtual HRESULT Initialize(void);
};
extern NtTargetUserModuleInfo g_NtTargetUserModuleIterator;
class NtWow64UserModuleInfo : public NtUserModuleInfo
{
public:
virtual HRESULT Initialize(void);
private:
HRESULT GetPeb32(PULONG64 Peb32);
};
extern NtWow64UserModuleInfo g_NtWow64UserModuleIterator;
class DebuggerModuleInfo : public ModuleInfo
{
public:
virtual HRESULT Initialize(void);
virtual HRESULT GetEntry(PMODULE_INFO_ENTRY Entry);
private:
PDEBUG_IMAGE_INFO m_Image;
};
extern DebuggerModuleInfo g_DebuggerModuleIterator;
class UnloadedModuleInfo
{
public:
virtual HRESULT Initialize(void) = 0;
virtual HRESULT GetEntry(PSTR Name, PDEBUG_MODULE_PARAMETERS Params) = 0;
};
class NtKernelUnloadedModuleInfo : public UnloadedModuleInfo
{
public:
virtual HRESULT Initialize(void);
virtual HRESULT GetEntry(PSTR Name, PDEBUG_MODULE_PARAMETERS Params);
protected:
ULONG64 m_Base;
ULONG m_Index;
ULONG m_Count;
};
extern NtKernelUnloadedModuleInfo g_NtKernelUnloadedModuleIterator;
class W9xModuleInfo : public ModuleInfo
{
public:
virtual HRESULT Initialize(void);
virtual HRESULT GetEntry(PMODULE_INFO_ENTRY Entry);
protected:
HANDLE m_Snap;
BOOL m_First;
ULONG m_LastId;
};
extern W9xModuleInfo g_W9xModuleIterator;
//----------------------------------------------------------------------------
//
// Target configuration information.
//
//----------------------------------------------------------------------------
#define IS_TARGET_SET() (g_TargetClass != DEBUG_CLASS_UNINITIALIZED)
#define IS_KERNEL_TARGET() (g_TargetClass == DEBUG_CLASS_KERNEL)
#define IS_USER_TARGET() (g_TargetClass == DEBUG_CLASS_USER_WINDOWS)
#define IS_CONN_KERNEL_TARGET() \
(IS_KERNEL_TARGET() && g_TargetClassQualifier == DEBUG_KERNEL_CONNECTION)
#define IS_LOCAL_KERNEL_TARGET() \
(IS_KERNEL_TARGET() && g_TargetClassQualifier == DEBUG_KERNEL_LOCAL)
#define IS_EXDI_KERNEL_TARGET() \
(IS_KERNEL_TARGET() && g_TargetClassQualifier == DEBUG_KERNEL_EXDI_DRIVER)
#define IS_LIVE_USER_TARGET() \
(IS_USER_TARGET() && !IS_DUMP_TARGET())
#define IS_LIVE_KERNEL_TARGET() \
(IS_KERNEL_TARGET() && !IS_DUMP_TARGET())
#define IS_REMOTE_USER_TARGET() \
(IS_USER_TARGET() && \
g_TargetClassQualifier == DEBUG_USER_WINDOWS_PROCESS_SERVER)
#define IS_LOCAL_USER_TARGET() \
(IS_USER_TARGET() && \
g_TargetClassQualifier != DEBUG_USER_WINDOWS_PROCESS_SERVER)
// Local kernels do not need caching. Anything else does.
#define IS_REMOTE_KERNEL_TARGET() \
(IS_LIVE_KERNEL_TARGET() && g_TargetClassQualifier != DEBUG_KERNEL_LOCAL)
// g_TargetMachineType is sometimes set before InitializeMachine
// is called so it can't be used as a direct check for
// initialization. Instead a separate, clean initialization
// variable is used.
// IS_MACHINE_SET == TRUE implies a target is set
// since it isn't possible to determine the machine type
// without knowing the target.
#define IS_MACHINE_SET() g_MachineInitialized
// Checks whether the debuggee is in a state where it
// can be examined. This requires that the debuggee is known
// and paused so that its state is available.
#define IS_MACHINE_ACCESSIBLE() \
(IS_MACHINE_SET() && !IS_RUNNING(g_CmdState) && \
g_CurrentProcess != NULL && g_CurrentProcess->CurrentThread != NULL)
// Further restricts the check to just context state as a
// local kernel session can examine memory and therefore is
// accessible but it does not have a context.
#define IS_CONTEXT_ACCESSIBLE() \
(IS_MACHINE_ACCESSIBLE() && !IS_LOCAL_KERNEL_TARGET())
// Simpler context check for code which may be on the suspend/
// resume path and therefore may be in the middle of initializing
// the variables that IS_CONTEXT_ACCESSIBLE checks. This
// macro just checks whether it's possible to get any
// context information.
#define IS_CONTEXT_POSSIBLE() \
(g_RegContextThread != NULL && !IS_LOCAL_KERNEL_TARGET())
// Dumps and local kernel sessions cannot ever support
// execution so disallow execution commands for them.
#define IS_EXECUTION_POSSIBLE() \
(!(IS_DUMP_TARGET() || IS_LOCAL_KERNEL_TARGET()))
//
// System version is an internal abstraction of build numbers
// and product types. The only requirement is that within
// a specific system family the numbers increase for newer
// systems.
//
// Most of the debugger code is built around NT system versions
// so there's a SystemVersion variable which is always an
// NT system version. The ActualSystemVersion contains the
// true system version which gets mapped into a compatible NT
// system version for SystemVersion.
//
enum
{
SVER_INVALID = 0,
NT_SVER_START = 4 * 1024,
NT_SVER_NT4,
NT_SVER_W2K_RC3,
NT_SVER_W2K,
NT_SVER_W2K_WHISTLER,
NT_SVER_END,
W9X_SVER_START = 8 * 1024,
W9X_SVER_W95,
W9X_SVER_W98,
W9X_SVER_W98SE,
W9X_SVER_WME,
W9X_SVER_END,
XBOX_SVER_START = 12 * 1024,
XBOX_SVER_1,
XBOX_SVER_END,
BIG_SVER_START = 16 * 1024,
BIG_SVER_1,
BIG_SVER_END,
EXDI_SVER_START = 20 * 1024,
EXDI_SVER_1,
EXDI_SVER_END,
NTBD_SVER_START = 24 * 1024,
NTBD_SVER_W2K_WHISTLER,
NTBD_SVER_END,
EFI_SVER_START = 28 * 1024,
EFI_SVER_1,
EFI_SVER_END,
};
// KD version MajorVersion high-byte identifiers.
enum
{
KD_MAJOR_NT,
KD_MAJOR_XBOX,
KD_MAJOR_BIG,
KD_MAJOR_EXDI,
KD_MAJOR_NTBD,
KD_MAJOR_EFI,
KD_MAJOR_COUNT
};
extern ULONG g_SystemVersion;
extern ULONG g_ActualSystemVersion;
extern ULONG g_TargetCheckedBuild;
extern ULONG g_TargetBuildNumber;
extern BOOL g_MachineInitialized;
extern ULONG g_TargetMachineType;
extern ULONG g_TargetExecMachine;
extern ULONG g_TargetPlatformId;
extern char g_TargetServicePackString[MAX_PATH];
extern ULONG g_TargetServicePackNumber;
extern char g_TargetBuildLabName[272];
extern ULONG g_TargetNumberProcessors;
extern ULONG g_TargetClass;
extern ULONG g_TargetClassQualifier;
//----------------------------------------------------------------------------
//
// Convenience routines.
//
//----------------------------------------------------------------------------
extern ULONG g_TmpCount;
#define ReadVirt(Offset, Var) \
(g_Target->ReadVirtual(Offset, &(Var), sizeof(Var), \
&g_TmpCount) == S_OK && g_TmpCount == sizeof(Var))
#define WriteVirt(Offset, Var) \
(g_Target->WriteVirtual(Offset, &(Var), sizeof(Var), \
&g_TmpCount) == S_OK && g_TmpCount == sizeof(Var))
//----------------------------------------------------------------------------
//
// This class abstracts processing of target-class-dependent
// information. g_Target is set to the appropriate implementation
// once the class of target is known.
//
//----------------------------------------------------------------------------
class TargetInfo
{
public:
//
// Pure abstraction methods.
// Unless otherwise indicated, base implementations give
// an error message and return E_UNEXPECTED.
//
virtual HRESULT Initialize(void);
// Base implementation does nothing.
virtual void Uninitialize(void);
// Some targets, such as eXDI, require initialization
// per thread. In eXDI's case, it's calling CoInitialize.
// Base implementations do nothing.
virtual HRESULT ThreadInitialize(void);
virtual void ThreadUninitialize(void);
// Determines the next byte offset and next page offset
// that might have different validity than the given offset.
virtual void NearestDifferentlyValidOffsets(ULONG64 Offset,
PULONG64 NextOffset,
PULONG64 NextPage);
virtual HRESULT ReadVirtual(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtual(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
// Base implementation layers on ReadVirtual.
virtual HRESULT SearchVirtual(
IN ULONG64 Offset,
IN ULONG64 Length,
IN PVOID Pattern,
IN ULONG PatternSize,
IN ULONG PatternGranularity,
OUT PULONG64 MatchOffset
);
// Base implementations just call Read/WriteVirtual.
virtual HRESULT ReadVirtualUncached(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtualUncached(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadPhysical(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WritePhysical(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
// Base implementations just call Read/WritePhysical.
virtual HRESULT ReadPhysicalUncached(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WritePhysicalUncached(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadControl(
IN ULONG Processor,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteControl(
IN ULONG Processor,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadMsr(
IN ULONG Msr,
OUT PULONG64 Value
);
virtual HRESULT WriteMsr(
IN ULONG Msr,
IN ULONG64 Value
);
virtual HRESULT ReadBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT GetProcessorSystemDataOffset(
IN ULONG Processor,
IN ULONG Index,
OUT PULONG64 Offset
);
virtual HRESULT CheckLowMemory(
);
virtual HRESULT ReadHandleData(
IN ULONG64 Handle,
IN ULONG DataType,
OUT OPTIONAL PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG DataSize
);
// Base implementations layer on WriteVirtual/Physical.
virtual HRESULT FillVirtual(
THIS_
IN ULONG64 Start,
IN ULONG Size,
IN PVOID Pattern,
IN ULONG PatternSize,
OUT PULONG Filled
);
virtual HRESULT FillPhysical(
THIS_
IN ULONG64 Start,
IN ULONG Size,
IN PVOID Pattern,
IN ULONG PatternSize,
OUT PULONG Filled
);
virtual HRESULT GetProcessorId
(ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id);
// Base implementation silently fails as many targets do
// not support this.
virtual HRESULT ReadPageFile(ULONG PfIndex, ULONG64 PfOffset,
PVOID Buffer, ULONG Size);
virtual HRESULT GetFunctionTableListHead(void);
virtual PVOID FindDynamicFunctionEntry(MachineInfo* Machine,
ULONG64 Address);
virtual ULONG64 GetDynamicFunctionTableBase(MachineInfo* Machine,
ULONG64 Address);
virtual HRESULT ReadOutOfProcessDynamicFunctionTable(PWSTR Dll,
ULONG64 Table,
PULONG TableSize,
PVOID* TableData);
static PVOID CALLBACK DynamicFunctionTableCallback(HANDLE Process,
ULONG64 Address,
ULONG64 Context);
virtual HRESULT GetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT SetTargetContext(
ULONG64 Thread,
PVOID Context
);
// Retrieves segment register descriptors if they are available
// directly. Invalid descriptors may be returned, indicating
// either segment registers aren't supported or that the
// descriptors must be looked up in descriptor tables.
// Base implementation returns invalid descriptors.
virtual HRESULT GetTargetSegRegDescriptors(ULONG64 Thread,
ULONG Start, ULONG Count,
PDESCRIPTOR64 Descs);
// Base implementations call Read/WriteSpecialRegisters.
virtual HRESULT GetTargetSpecialRegisters
(ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special);
virtual HRESULT SetTargetSpecialRegisters
(ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special);
// Called when the current context state is being
// discarded so that caches can be flushed.
// Base implementation does nothing.
virtual void InvalidateTargetContext(void);
virtual HRESULT GetThreadIdByProcessor(
IN ULONG Processor,
OUT PULONG Id
);
// This method takes both a PTHREAD_INFO and a "handle"
// to make things simpler for the kernel thread-to-processor
// mapping. If Thread is NULL processor must be a processor
// index in kernel mode or a thread handle in user mode.
virtual HRESULT GetThreadInfoDataOffset(PTHREAD_INFO Thread,
ULONG64 ThreadHandle,
PULONG64 Offset);
// In theory this method should take a PPROCESS_INFO.
// Due to the current kernel process and thread structure
// where there's only a kernel process and threads per
// processor such a call would be useless in kernel mode.
// Instead it allows you to either get the process data
// for a thread of that process or get the process data
// from a thread data.
virtual HRESULT GetProcessInfoDataOffset(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetThreadInfoTeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetProcessInfoPeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
// This is on target rather than machine since it has
// both user and kernel variations and the implementations
// don't have much processor-specific code in them.
virtual HRESULT GetSelDescriptor(class MachineInfo* Machine,
ULONG64 Thread, ULONG Selector,
PDESCRIPTOR64 Desc);
virtual HRESULT GetTargetKdVersion(PDBGKD_GET_VERSION64 Version);
virtual HRESULT ReadBugCheckData(PULONG Code, ULONG64 Args[4]);
virtual HRESULT OutputVersion(void);
virtual HRESULT OutputTime(void);
virtual ModuleInfo* GetModuleInfo(BOOL UserMode);
virtual UnloadedModuleInfo* GetUnloadedModuleInfo(void);
// Image can be identified either by its path or base address.
virtual HRESULT GetImageVersionInformation(PCSTR ImagePath,
ULONG64 ImageBase,
PCSTR Item,
PVOID Buffer, ULONG BufferSize,
PULONG VerInfoSize);
virtual HRESULT Reload(PCSTR Args);
virtual HRESULT GetExceptionContext(PCROSS_PLATFORM_CONTEXT Context);
virtual ULONG64 GetCurrentTimeDateN(void);
virtual ULONG64 GetCurrentSystemUpTimeN(void);
virtual ULONG64 GetProcessUpTimeN(ULONG64 Process);
virtual void InitializeWatchTrace(void);
virtual void ProcessWatchTraceEvent(PDBGKD_TRACE_DATA TraceData,
ADDR PcAddr);
virtual HRESULT WaitForEvent(ULONG Flags, ULONG Timeout);
virtual HRESULT RequestBreakIn(void);
virtual HRESULT Reboot(void);
virtual HRESULT InsertCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
virtual HRESULT RemoveCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
// Returns information similar to VirtualQueryEx for
// user-mode targets. Used when writing dump files.
virtual HRESULT QueryMemoryRegion(PULONG64 Handle,
BOOL HandleIsOffset,
PMEMORY_BASIC_INFORMATION64 Info);
// Returns information about the kind of memory the
// given address refers to.
// Base implementation returns rwx with process for
// user-mode and kernel for kernel mode. In other words,
// the least restrictive settings.
virtual HRESULT QueryAddressInformation(ULONG64 Address, ULONG InSpace,
PULONG OutSpace, PULONG OutFlags);
//
// Layered methods. These are usually common code that
// use pure methods to do their work.
//
HRESULT ReadAllVirtual(ULONG64 Address, PVOID Buffer, ULONG BufferSize)
{
HRESULT Status;
ULONG Done;
if ((Status = ReadVirtual(Address, Buffer, BufferSize, &Done)) == S_OK
&& Done != BufferSize)
{
Status = HRESULT_FROM_WIN32(ERROR_READ_FAULT);
}
return Status;
}
HRESULT WriteAllVirtual(ULONG64 Address, PVOID Buffer, ULONG BufferSize)
{
HRESULT Status;
ULONG Done;
if ((Status = WriteVirtual(Address, Buffer, BufferSize, &Done)) == S_OK
&& Done != BufferSize)
{
Status = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
}
return Status;
}
HRESULT ReadAllPhysical(ULONG64 Address, PVOID Buffer, ULONG BufferSize)
{
HRESULT Status;
ULONG Done;
if ((Status = ReadPhysical(Address, Buffer, BufferSize, &Done)) == S_OK
&& Done != BufferSize)
{
Status = HRESULT_FROM_WIN32(ERROR_READ_FAULT);
}
return Status;
}
HRESULT WriteAllPhysical(ULONG64 Address, PVOID Buffer, ULONG BufferSize)
{
HRESULT Status;
ULONG Done;
if ((Status = WritePhysical(Address, Buffer, BufferSize,
&Done)) == S_OK
&& Done != BufferSize)
{
Status = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
}
return Status;
}
HRESULT ReadPointer(MachineInfo* Machine,
ULONG64 Address, PULONG64 PointerValue);
HRESULT WritePointer(MachineInfo* Machine,
ULONG64 Address, ULONG64 PointerValue);
HRESULT ReadListEntry(MachineInfo* Machine,
ULONG64 Address, PLIST_ENTRY64 List);
HRESULT ReadLoaderEntry(MachineInfo* Machine,
ULONG64 Address, PKLDR_DATA_TABLE_ENTRY64 Entry);
HRESULT ReadUnicodeString(MachineInfo* Machine,
ULONG64 Address, PUNICODE_STRING64 String);
HRESULT ReadDirectoryTableBase(PULONG64 DirBase);
HRESULT ReadSharedUserTimeDateN(PULONG64 TimeDate);
HRESULT ReadSharedUserUpTimeN(PULONG64 UpTime);
HRESULT ReadImageVersionInfo(ULONG64 ImageBase,
PCSTR Item,
PVOID Buffer,
ULONG BufferSize,
PULONG VerInfoSize,
PIMAGE_DATA_DIRECTORY ResDataDir);
HRESULT ReadImplicitThreadInfoPointer(ULONG Offset, PULONG64 Ptr);
HRESULT ReadImplicitProcessInfoPointer(ULONG Offset, PULONG64 Ptr);
// Internal routines which provide canonical context input
// and output, applying any necessary conversions before
// or after calling Get/SetTargetContext.
HRESULT GetContext(
ULONG64 Thread,
PCROSS_PLATFORM_CONTEXT Context
);
HRESULT SetContext(
ULONG64 Thread,
PCROSS_PLATFORM_CONTEXT Context
);
// Calls GetTargetKdVersion on g_KdVersion and outputs the content.
void GetKdVersion(void);
// Internal implementations based on user or kernel
// registers and data. Placed here for sharing between
// live and dump sessions rather than using multiple
// inheritance.
HRESULT KdGetThreadInfoDataOffset(PTHREAD_INFO Thread,
ULONG64 ThreadHandle,
PULONG64 Offset);
HRESULT KdGetProcessInfoDataOffset(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
HRESULT KdGetThreadInfoTeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
HRESULT KdGetProcessInfoPeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
HRESULT KdGetSelDescriptor(class MachineInfo* Machine,
ULONG64 Thread, ULONG Selector,
PDESCRIPTOR64 Desc);
};
// Base failure behaviors for when a specific target isn't selected.
extern TargetInfo g_UnexpectedTarget;
extern TargetInfo* g_Target;
//----------------------------------------------------------------------------
//
// LiveKernelTargetInfo.
//
//----------------------------------------------------------------------------
class LiveKernelTargetInfo : public TargetInfo
{
public:
// TargetInfo.
virtual HRESULT Initialize(void);
virtual HRESULT GetProcessorId
(ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id);
virtual HRESULT GetThreadIdByProcessor(
IN ULONG Processor,
OUT PULONG Id
);
virtual HRESULT GetThreadInfoDataOffset(PTHREAD_INFO Thread,
ULONG64 ThreadHandle,
PULONG64 Offset);
virtual HRESULT GetProcessInfoDataOffset(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetThreadInfoTeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetProcessInfoPeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetSelDescriptor(class MachineInfo* Machine,
ULONG64 Thread, ULONG Selector,
PDESCRIPTOR64 Desc);
virtual HRESULT ReadBugCheckData(PULONG Code, ULONG64 Args[4]);
virtual ULONG64 GetCurrentTimeDateN(void);
virtual ULONG64 GetCurrentSystemUpTimeN(void);
// LiveKernelTargetInfo.
// Options are only valid in Initialize.
PCSTR m_ConnectOptions;
};
//----------------------------------------------------------------------------
//
// ConnLiveKernelTargetInfo.
//
//----------------------------------------------------------------------------
class ConnLiveKernelTargetInfo : public LiveKernelTargetInfo
{
public:
// TargetInfo.
virtual HRESULT Initialize(void);
virtual void Uninitialize(void);
virtual HRESULT ReadVirtual(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtual(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT SearchVirtual(
IN ULONG64 Offset,
IN ULONG64 Length,
IN PVOID Pattern,
IN ULONG PatternSize,
IN ULONG PatternGranularity,
OUT PULONG64 MatchOffset
);
virtual HRESULT ReadVirtualUncached(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtualUncached(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadPhysical(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WritePhysical(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadPhysicalUncached(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WritePhysicalUncached(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadControl(
IN ULONG Processor,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteControl(
IN ULONG Processor,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadMsr(
IN ULONG Msr,
OUT PULONG64 Value
);
virtual HRESULT WriteMsr(
IN ULONG Msr,
IN ULONG64 Value
);
virtual HRESULT ReadBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT CheckLowMemory(
);
virtual HRESULT FillVirtual(
THIS_
IN ULONG64 Start,
IN ULONG Size,
IN PVOID Pattern,
IN ULONG PatternSize,
OUT PULONG Filled
);
virtual HRESULT FillPhysical(
THIS_
IN ULONG64 Start,
IN ULONG Size,
IN PVOID Pattern,
IN ULONG PatternSize,
OUT PULONG Filled
);
virtual HRESULT GetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT SetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT GetTargetKdVersion(PDBGKD_GET_VERSION64 Version);
virtual void InitializeWatchTrace(void);
virtual void ProcessWatchTraceEvent(PDBGKD_TRACE_DATA TraceData,
ADDR PcAddr);
virtual HRESULT WaitForEvent(ULONG Flags, ULONG Timeout);
virtual HRESULT RequestBreakIn(void);
virtual HRESULT Reboot(void);
virtual HRESULT InsertCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
virtual HRESULT RemoveCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
virtual HRESULT QueryAddressInformation(ULONG64 Address, ULONG InSpace,
PULONG OutSpace, PULONG OutFlags);
};
extern ConnLiveKernelTargetInfo g_ConnLiveKernelTarget;
//----------------------------------------------------------------------------
//
// LocalLiveKernelTargetInfo.
//
//----------------------------------------------------------------------------
class LocalLiveKernelTargetInfo : public LiveKernelTargetInfo
{
public:
// TargetInfo.
virtual HRESULT Initialize(void);
virtual HRESULT ReadVirtual(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtual(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadPhysical(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WritePhysical(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadControl(
IN ULONG Processor,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteControl(
IN ULONG Processor,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadMsr(
IN ULONG Msr,
OUT PULONG64 Value
);
virtual HRESULT WriteMsr(
IN ULONG Msr,
IN ULONG64 Value
);
virtual HRESULT ReadBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT CheckLowMemory(
);
virtual HRESULT GetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT SetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT GetTargetKdVersion(PDBGKD_GET_VERSION64 Version);
virtual HRESULT WaitForEvent(ULONG Flags, ULONG Timeout);
};
extern LocalLiveKernelTargetInfo g_LocalLiveKernelTarget;
//----------------------------------------------------------------------------
//
// ExdiLiveKernelTargetInfo.
//
//----------------------------------------------------------------------------
class ExdiNotifyRunChange : public IeXdiClientNotifyRunChg
{
public:
HRESULT Initialize(void);
void Uninitialize(void);
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
);
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
// IeXdiClientNotifyRunChg.
STDMETHOD(NotifyRunStateChange)(RUN_STATUS_TYPE ersCurrent,
HALT_REASON_TYPE ehrCurrent,
ADDRESS_TYPE CurrentExecAddress,
DWORD dwExceptionCode);
// ExdiNotifyRunChange.
HANDLE m_Event;
HALT_REASON_TYPE m_HaltReason;
ADDRESS_TYPE m_ExecAddress;
ULONG m_ExceptionCode;
};
typedef union _EXDI_CONTEXT
{
CONTEXT_X86 X86Context;
CONTEXT_X86_64 Amd64Context;
} EXDI_CONTEXT, *PEXDI_CONTEXT;
enum EXDI_KD_SUPPORT
{
EXDI_KD_NONE,
EXDI_KD_IOCTL,
EXDI_KD_GS_PCR
};
class ExdiLiveKernelTargetInfo : public LiveKernelTargetInfo
{
public:
// TargetInfo.
virtual HRESULT Initialize(void);
virtual void Uninitialize(void);
virtual HRESULT ThreadInitialize(void);
virtual void ThreadUninitialize(void);
virtual HRESULT ReadVirtual(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtual(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadPhysical(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WritePhysical(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadControl(
IN ULONG Processor,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteControl(
IN ULONG Processor,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteIo(
IN ULONG InterfaceType,
IN ULONG BusNumber,
IN ULONG AddressSpace,
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadMsr(
IN ULONG Msr,
OUT PULONG64 Value
);
virtual HRESULT WriteMsr(
IN ULONG Msr,
IN ULONG64 Value
);
virtual HRESULT ReadBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteBusData(
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN ULONG Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT GetProcessorSystemDataOffset(
IN ULONG Processor,
IN ULONG Index,
OUT PULONG64 Offset
);
virtual HRESULT CheckLowMemory(
);
virtual HRESULT GetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT SetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT GetTargetSegRegDescriptors(ULONG64 Thread,
ULONG Start, ULONG Count,
PDESCRIPTOR64 Descs);
virtual HRESULT GetTargetSpecialRegisters
(ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special);
virtual HRESULT SetTargetSpecialRegisters
(ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special);
virtual void InvalidateTargetContext(void);
virtual HRESULT GetTargetKdVersion(PDBGKD_GET_VERSION64 Version);
virtual HRESULT WaitForEvent(ULONG Flags, ULONG Timeout);
virtual HRESULT RequestBreakIn(void);
virtual HRESULT Reboot(void);
virtual HRESULT InsertCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
virtual HRESULT RemoveCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
// ExdiLiveKernelTargetInfo.
IeXdiServer* m_Server;
IUnknown* m_Context;
ULONG m_ContextValid;
EXDI_CONTEXT m_ContextData;
GLOBAL_TARGET_INFO_STRUCT m_GlobalInfo;
EXDI_KD_SUPPORT m_KdSupport;
BOOL m_ForceX86;
ULONG m_ExpectedMachine;
CBP_KIND m_CodeBpType;
ExdiNotifyRunChange m_RunChange;
};
extern ExdiLiveKernelTargetInfo g_ExdiLiveKernelTarget;
//----------------------------------------------------------------------------
//
// UserTargetInfo.
//
//----------------------------------------------------------------------------
class UserTargetInfo : public TargetInfo
{
public:
// TargetInfo.
virtual HRESULT Initialize(void);
virtual void Uninitialize(void);
virtual HRESULT ReadVirtualUncached(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtualUncached(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
virtual HRESULT ReadHandleData(
IN ULONG64 Handle,
IN ULONG DataType,
OUT OPTIONAL PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG DataSize
);
virtual HRESULT GetProcessorId
(ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id);
virtual HRESULT GetFunctionTableListHead(void);
virtual HRESULT ReadOutOfProcessDynamicFunctionTable(PWSTR Dll,
ULONG64 Table,
PULONG TableSize,
PVOID* TableData);
virtual HRESULT GetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT SetTargetContext(
ULONG64 Thread,
PVOID Context
);
virtual HRESULT GetThreadInfoDataOffset(PTHREAD_INFO Thread,
ULONG64 ThreadHandle,
PULONG64 Offset);
virtual HRESULT GetProcessInfoDataOffset(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetThreadInfoTeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetProcessInfoPeb(PTHREAD_INFO Thread,
ULONG Processor,
ULONG64 ThreadData,
PULONG64 Offset);
virtual HRESULT GetSelDescriptor(class MachineInfo* Machine,
ULONG64 Thread, ULONG Selector,
PDESCRIPTOR64 Desc);
virtual HRESULT GetImageVersionInformation(PCSTR ImagePath,
ULONG64 ImageBase,
PCSTR Item,
PVOID Buffer, ULONG BufferSize,
PULONG VerInfoSize);
virtual ULONG64 GetCurrentTimeDateN(void);
virtual ULONG64 GetCurrentSystemUpTimeN(void);
virtual ULONG64 GetProcessUpTimeN(ULONG64 Process);
virtual void InitializeWatchTrace(void);
virtual void ProcessWatchTraceEvent(PDBGKD_TRACE_DATA TraceData,
ADDR PcAddr);
virtual HRESULT WaitForEvent(ULONG Flags, ULONG Timeout);
virtual HRESULT RequestBreakIn(void);
virtual HRESULT InsertCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
virtual HRESULT RemoveCodeBreakpoint(PPROCESS_INFO Process,
class MachineInfo* Machine,
PADDR Addr,
PUCHAR StorageSpace);
virtual HRESULT QueryMemoryRegion(PULONG64 Handle,
BOOL HandleIsOffset,
PMEMORY_BASIC_INFORMATION64 Info);
IUserDebugServices* m_Services;
ULONG m_ServiceFlags;
};
class LocalUserTargetInfo : public UserTargetInfo
{
public:
// TargetInfo.
virtual HRESULT ReadVirtual(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtual(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
};
extern LocalUserTargetInfo g_LocalUserTarget;
class RemoteUserTargetInfo : public UserTargetInfo
{
public:
// TargetInfo.
virtual HRESULT ReadVirtual(
IN ULONG64 Offset,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesRead
);
virtual HRESULT WriteVirtual(
IN ULONG64 Offset,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BytesWritten
);
};
extern RemoteUserTargetInfo g_RemoteUserTarget;
//----------------------------------------------------------------------------
//
// DumpTargetInfo hierarchy is in dump.hpp.
//
//----------------------------------------------------------------------------
#endif // #ifndef __TARGET_HPP__