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.
664 lines
26 KiB
664 lines
26 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// Abstraction of processor-specific information.
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1999-2002.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef __MACHINE_HPP__
|
|
#define __MACHINE_HPP__
|
|
|
|
// These context information states are intended to be shared among
|
|
// processors so they may not all apply to each processor. The important
|
|
// thing is that they are ordered from less information to more.
|
|
// Each state includes all the information from the states that precede it.
|
|
// More states can be inserted anywhere as new processors require them.
|
|
#define MCTX_NONE 0 // No context information.
|
|
#define MCTX_PC 1 // Program counter.
|
|
#define MCTX_DR67_REPORT 2 // X86: DR6,7 control report.
|
|
#define MCTX_REPORT 3 // Control report.
|
|
#define MCTX_CONTEXT 4 // Kernel protocol context information.
|
|
#define MCTX_FULL 5 // All possible information.
|
|
#define MCTX_DIRTY 6 // Dirty context, implies full information.
|
|
|
|
// Constant offset value returned from GetNextOffset to indicate the
|
|
// trace flag should be used.
|
|
#define OFFSET_TRACE ((ULONG64)(LONG64)-1)
|
|
#define OFFSET_TRACE_32 ((ULONG)OFFSET_TRACE)
|
|
|
|
// Distinguished error code for GetVirtualTranslationPhysicalOffsets
|
|
// to indicate that all translations were successful but
|
|
// the page was not present. In this case the LastVal value
|
|
// will contain the page file offset and PfIndex will contain
|
|
// the page file number.
|
|
#define HR_PAGE_IN_PAGE_FILE HRESULT_FROM_NT(STATUS_PAGE_FAULT_PAGING_FILE)
|
|
// Translation could not complete and a page file location
|
|
// for the data could not be determined.
|
|
#define HR_PAGE_NOT_AVAILABLE HRESULT_FROM_NT(STATUS_NO_PAGEFILE)
|
|
|
|
#define MAX_PAGING_FILE_MASK 0xf
|
|
|
|
//
|
|
// Segment register access.
|
|
// Processors which do not support segment registers return
|
|
// zero for the segment register number.
|
|
//
|
|
|
|
enum
|
|
{
|
|
// Descriptor table pseudo-segments. The GDT does
|
|
// not have a specific register number.
|
|
// These pseudo-segments should be first so that
|
|
// index zero is not used for a normal segreg.
|
|
SEGREG_GDT,
|
|
SEGREG_LDT,
|
|
|
|
// Generic segments.
|
|
SEGREG_CODE,
|
|
SEGREG_DATA,
|
|
SEGREG_STACK,
|
|
|
|
// Extended segments.
|
|
SEGREG_ES,
|
|
SEGREG_FS,
|
|
SEGREG_GS,
|
|
|
|
SEGREG_COUNT
|
|
};
|
|
|
|
#define FORM_VM86 0x00000001
|
|
#define FORM_CODE 0x00000002
|
|
#define FORM_SEGREG 0x00000004
|
|
|
|
#define X86_FORM_VM86(Efl) \
|
|
(X86_IS_VM86(Efl) ? FORM_VM86 : 0)
|
|
|
|
#define X86_RPL_MASK 3
|
|
|
|
#define MPTE_FLAG_VALID 0x00000001
|
|
|
|
#define PAGE_ALIGN(Machine, Addr) \
|
|
((Addr) & ~((ULONG64)((Machine)->m_PageSize - 1)))
|
|
#define NEXT_PAGE(Machine, Addr) \
|
|
(((Addr) + (Machine)->m_PageSize) & \
|
|
~((ULONG64)((Machine)->m_PageSize - 1)))
|
|
|
|
typedef struct _ADDR_RANGE
|
|
{
|
|
ULONG64 Base;
|
|
ULONG Size;
|
|
} ADDR_RANGE, *PADDR_RANGE;
|
|
|
|
#define MAX_ALT_ADDR_RANGES 4
|
|
|
|
//
|
|
// InsertBreakpointInstruction flags. These
|
|
// are processor specific.
|
|
//
|
|
|
|
#define IBI_DEFAULT 0x00000000
|
|
|
|
// The low six bits on IA64 indicate which predicate
|
|
// register to use in the break instruction.
|
|
#define IBI_IA64_PRED_MASK 0x0000003f
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Abstract interface for machine information. All possible
|
|
// machine-specific implementations of this interface exist at
|
|
// all times. The effective implementation is selected when
|
|
// SetEffMachine is called. For generic access the abstract
|
|
// interface should be used. In machine-specific code the
|
|
// specific implementation classes can be used.
|
|
//
|
|
// IMPORTANT: Be very careful when using machine-specific header files
|
|
// such as nt<plat>.h. The machine implementation class is
|
|
// compiled for all platforms so the nt<plat>.h file will be the
|
|
// one for the build platform, not necessarily the platform
|
|
// of the machine implementation. ntdbg.h contains many cross-platform
|
|
// types and definitions that can be used to avoid problems.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
extern BOOL g_PrefixSymbols;
|
|
extern BOOL g_ContextChanged;
|
|
|
|
struct RegisterGroup
|
|
{
|
|
// Counted automatically.
|
|
ULONG NumberRegs;
|
|
// Regs is assumed to be non-NULL in all groups.
|
|
// SubRegs and AllExtraDesc may be NULL in any group.
|
|
REGDEF* Regs;
|
|
REGSUBDEF* SubRegs;
|
|
REGALLDESC* AllExtraDesc;
|
|
};
|
|
|
|
// Trace modes used by SetTraceMode/GetTraceMode functions
|
|
typedef enum
|
|
{
|
|
TRACE_NONE,
|
|
TRACE_INSTRUCTION,
|
|
TRACE_TAKEN_BRANCH
|
|
} TRACEMODE;
|
|
|
|
// These enumerants are abstract values but currently
|
|
// only IA64 actually has different page directories
|
|
// so set them up to match the IA64 mapping for convenience.
|
|
enum
|
|
{
|
|
PAGE_DIR_USER,
|
|
PAGE_DIR_SESSION,
|
|
PAGE_DIR_KERNEL = 7,
|
|
PAGE_DIR_COUNT
|
|
};
|
|
|
|
// For machines which only support a single page directory
|
|
// take it from the kernel slot. All will be updated so
|
|
// this is an arbitrary choice.
|
|
#define PAGE_DIR_SINGLE PAGE_DIR_KERNEL
|
|
|
|
// All directories bit mask.
|
|
#define PAGE_DIR_ALL ((1 << PAGE_DIR_COUNT) - 1)
|
|
|
|
// Flags for GetPrefixedSymbolOffset.
|
|
#define GETPREF_VERBOSE 0x00000001
|
|
|
|
#define MAX_REGISTER_GROUPS 8
|
|
|
|
struct CvRegMap
|
|
{
|
|
CV_HREG_e CvReg;
|
|
ULONG Machine;
|
|
};
|
|
|
|
struct ContextSave
|
|
{
|
|
ULONG ContextState;
|
|
BOOL ReadOnly;
|
|
CROSS_PLATFORM_CONTEXT Context;
|
|
CROSS_PLATFORM_KSPECIAL_REGISTERS Special;
|
|
DESCRIPTOR64 SegRegDesc[SEGREG_COUNT];
|
|
};
|
|
|
|
class MachineInfo
|
|
{
|
|
public:
|
|
MachineInfo(TargetInfo* Target);
|
|
virtual ~MachineInfo(void);
|
|
|
|
TargetInfo* m_Target;
|
|
|
|
// Descriptive information.
|
|
PCSTR m_FullName;
|
|
PCSTR m_AbbrevName;
|
|
ULONG m_PageSize;
|
|
ULONG m_PageShift;
|
|
ULONG m_NumExecTypes;
|
|
// First entry must be the actual processor type.
|
|
PULONG m_ExecTypes;
|
|
BOOL m_Ptr64;
|
|
ULONG m_RetRegIndex;
|
|
|
|
// Automatically counted from regs in base initialization.
|
|
ULONG m_NumRegs;
|
|
ULONG m_NumGroups;
|
|
RegisterGroup* m_Groups[MAX_REGISTER_GROUPS];
|
|
ULONG m_AllMask;
|
|
// Collected automatically from groups.
|
|
ULONG m_AllMaskBits;
|
|
ULONG m_MaxDataBreakpoints;
|
|
PCSTR m_SymPrefix;
|
|
// Computed automatically.
|
|
ULONG m_SymPrefixLen;
|
|
|
|
// Size of the canonical context kept in the MachineInfo.
|
|
ULONG m_SizeCanonicalContext;
|
|
// System version of the canonical context. Can be compared
|
|
// against a system version to see if the target provides
|
|
// canonical contexts or not.
|
|
ULONG m_SverCanonicalContext;
|
|
|
|
// Context could be kept per-thread
|
|
// so that several can be around at once for a cache.
|
|
// That would also make the save/restore stuff unnecessary.
|
|
ULONG m_ContextState;
|
|
CROSS_PLATFORM_CONTEXT m_Context;
|
|
CROSS_PLATFORM_KSPECIAL_REGISTERS m_Special;
|
|
|
|
// Segment register descriptors. These will only
|
|
// be valid on processors that support them, otherwise
|
|
// they will be marked invalid.
|
|
DESCRIPTOR64 m_SegRegDesc[SEGREG_COUNT];
|
|
|
|
// Holds the current page directory offsets.
|
|
ULONG64 m_PageDirectories[PAGE_DIR_COUNT];
|
|
BOOL m_Translating;
|
|
|
|
BOOL m_ContextIsReadOnly;
|
|
|
|
USHORT m_MainCodeSeg;
|
|
|
|
ULONG m_CvRegMapSize;
|
|
CvRegMap* m_CvRegMap;
|
|
|
|
virtual HRESULT Initialize(void);
|
|
virtual HRESULT InitializeForProcessor(void);
|
|
|
|
virtual void GetSystemTypeInfo(PSYSTEM_TYPE_INFO Info) = 0;
|
|
virtual void GetDefaultKdData(PKDDEBUGGER_DATA64 KdData) = 0;
|
|
|
|
ULONG CvRegToMachine(CV_HREG_e CvReg);
|
|
|
|
virtual void InitializeContext
|
|
(ULONG64 Pc, PDBGKD_ANY_CONTROL_REPORT ControlReport) = 0;
|
|
HRESULT GetContextState(ULONG State);
|
|
HRESULT SetContext(void);
|
|
// Base implementations use Get/SetThreadContext for
|
|
// any request.
|
|
virtual HRESULT UdGetContextState(ULONG State);
|
|
virtual HRESULT UdSetContext(void);
|
|
virtual HRESULT KdGetContextState(ULONG State) = 0;
|
|
virtual HRESULT KdSetContext(void) = 0;
|
|
// Base implementation sets ContextState to NONE.
|
|
virtual void InvalidateContext(void);
|
|
// Context conversion is version-based rather than size-based
|
|
// as the size is ambiguous in certain cases. For example,
|
|
// ALPHA_CONTEXT and ALPHA_NT5_CONTEXT are the same size
|
|
// so additional information is necessary to distinguish them.
|
|
virtual HRESULT ConvertContextFrom(PCROSS_PLATFORM_CONTEXT Context,
|
|
ULONG FromSver,
|
|
ULONG FromSize, PVOID From) = 0;
|
|
virtual HRESULT ConvertContextTo(PCROSS_PLATFORM_CONTEXT Context,
|
|
ULONG ToSver, ULONG ToSize, PVOID To) = 0;
|
|
virtual void InitializeContextFlags(PCROSS_PLATFORM_CONTEXT Context,
|
|
ULONG Version) = 0;
|
|
virtual HRESULT GetContextFromThreadStack(ULONG64 ThreadBase,
|
|
PCROSS_PLATFORM_CONTEXT Context,
|
|
ULONG64 Stack) = 0;
|
|
virtual HRESULT GetContextFromFiber(ProcessInfo* Process,
|
|
ULONG64 FiberBase,
|
|
PCROSS_PLATFORM_CONTEXT Context,
|
|
BOOL Verbose) = 0;
|
|
virtual HRESULT GetContextFromTrapFrame(ULONG64 TrapBase,
|
|
PCROSS_PLATFORM_CONTEXT Context,
|
|
BOOL Verbose) = 0;
|
|
// Base implementation fails for platforms that don't
|
|
// have task segments.
|
|
virtual HRESULT GetContextFromTaskSegment(ULONG64 TssBase,
|
|
PCROSS_PLATFORM_CONTEXT Context,
|
|
BOOL Verbose);
|
|
virtual void GetScopeFrameFromContext(PCROSS_PLATFORM_CONTEXT Context,
|
|
PDEBUG_STACK_FRAME ScopeFrame) = 0;
|
|
// Base implementation zeros addresses.
|
|
virtual void GetStackDefaultsFromContext(PCROSS_PLATFORM_CONTEXT Context,
|
|
LPADDRESS64 Instr,
|
|
LPADDRESS64 Stack,
|
|
LPADDRESS64 Frame);
|
|
virtual HRESULT GetScopeFrameRegister(ULONG Reg,
|
|
PDEBUG_STACK_FRAME ScopeFrame,
|
|
PULONG64 Value) = 0;
|
|
virtual HRESULT SetScopeFrameRegister(ULONG Reg,
|
|
PDEBUG_STACK_FRAME ScopeFrame,
|
|
ULONG64 Value) = 0;
|
|
|
|
// Base implementation does nothing.
|
|
virtual void SanitizeMemoryContext(PCROSS_PLATFORM_CONTEXT Context);
|
|
|
|
// Base implementations return E_NOTIMPL.
|
|
virtual HRESULT GetExdiContext(IUnknown* Exdi,
|
|
PEXDI_CONTEXT Context,
|
|
EXDI_CONTEXT_TYPE CtxType);
|
|
virtual HRESULT SetExdiContext(IUnknown* Exdi,
|
|
PEXDI_CONTEXT Context,
|
|
EXDI_CONTEXT_TYPE CtxType);
|
|
virtual void ConvertExdiContextFromContext(PCROSS_PLATFORM_CONTEXT Context,
|
|
PEXDI_CONTEXT ExdiContext,
|
|
EXDI_CONTEXT_TYPE CtxType);
|
|
virtual void ConvertExdiContextToContext(PEXDI_CONTEXT ExdiContext,
|
|
EXDI_CONTEXT_TYPE CtxType,
|
|
PCROSS_PLATFORM_CONTEXT Context);
|
|
virtual void ConvertExdiContextToSegDescs(PEXDI_CONTEXT ExdiContext,
|
|
EXDI_CONTEXT_TYPE CtxType,
|
|
ULONG Start, ULONG Count,
|
|
PDESCRIPTOR64 Descs);
|
|
virtual void ConvertExdiContextFromSpecial
|
|
(PCROSS_PLATFORM_KSPECIAL_REGISTERS Special,
|
|
PEXDI_CONTEXT ExdiContext,
|
|
EXDI_CONTEXT_TYPE CtxType);
|
|
virtual void ConvertExdiContextToSpecial
|
|
(PEXDI_CONTEXT ExdiContext,
|
|
EXDI_CONTEXT_TYPE CtxType,
|
|
PCROSS_PLATFORM_KSPECIAL_REGISTERS Special);
|
|
|
|
virtual int GetType(ULONG Reg) = 0;
|
|
virtual HRESULT GetVal(ULONG Reg, REGVAL* Val) = 0;
|
|
virtual HRESULT SetVal(ULONG Reg, REGVAL* Val) = 0;
|
|
|
|
virtual void GetPC(PADDR Address) = 0;
|
|
virtual void SetPC(PADDR Address) = 0;
|
|
virtual void GetFP(PADDR Address) = 0;
|
|
virtual void GetSP(PADDR Address) = 0;
|
|
virtual ULONG64 GetArgReg(void) = 0;
|
|
virtual ULONG64 GetRetReg(void) = 0;
|
|
// Base implementations return zero and FALSE.
|
|
virtual ULONG GetSegRegNum(ULONG SegReg);
|
|
virtual HRESULT GetSegRegDescriptor(ULONG SegReg, PDESCRIPTOR64 Desc);
|
|
|
|
virtual void OutputAll(ULONG Mask, ULONG OutMask) = 0;
|
|
|
|
virtual HRESULT SetAndOutputTrapFrame(ULONG64 TrapBase,
|
|
PCROSS_PLATFORM_CONTEXT Context) = 0;
|
|
// Base implementation fails for platforms that don't
|
|
// have task segments.
|
|
virtual HRESULT SetAndOutputTaskSegment(ULONG64 TssBase,
|
|
PCROSS_PLATFORM_CONTEXT Context,
|
|
BOOL Extended);
|
|
|
|
virtual TRACEMODE GetTraceMode(void) = 0;
|
|
virtual void SetTraceMode(TRACEMODE Mode) = 0;
|
|
|
|
// Returns true if trace mode appropriate to specified execution status
|
|
// (e.g. DEBUG_STATUS_STEP_OVER, DEBUG_STATUS_STEP_INTO,
|
|
// DEBUG_STATUS_STEP_BRANCH...) supported by the machine.
|
|
virtual BOOL IsStepStatusSupported(ULONG Status) = 0;
|
|
|
|
void QuietSetTraceMode(TRACEMODE Mode)
|
|
{
|
|
BOOL ContextChangedOrg = g_ContextChanged;
|
|
SetTraceMode(Mode);
|
|
g_ContextChanged = ContextChangedOrg;
|
|
}
|
|
|
|
// Base implementation does nothing.
|
|
virtual void KdUpdateControlSet
|
|
(PDBGKD_ANY_CONTROL_SET ControlSet);
|
|
|
|
virtual ULONG ExecutingMachine(void) = 0;
|
|
|
|
virtual HRESULT SetPageDirectory(ThreadInfo* Thread,
|
|
ULONG Idx, ULONG64 PageDir,
|
|
PULONG NextIdx) = 0;
|
|
HRESULT SetDefaultPageDirectories(ThreadInfo* Thread, ULONG Mask);
|
|
virtual HRESULT GetVirtualTranslationPhysicalOffsets
|
|
(ThreadInfo* Thread, ULONG64 Virt, PULONG64 Offsets, ULONG OffsetsSize,
|
|
PULONG Levels, PULONG PfIndex, PULONG64 LastVal) = 0;
|
|
virtual HRESULT GetBaseTranslationVirtualOffset(PULONG64 Offset) = 0;
|
|
virtual void DecodePte(ULONG64 Pte, PULONG64 PageFrameNumber,
|
|
PULONG Flags) = 0;
|
|
|
|
virtual void Assemble(ProcessInfo* Process,
|
|
PADDR Addr, PSTR Input) = 0;
|
|
virtual BOOL Disassemble(ProcessInfo* Process,
|
|
PADDR Addr, PSTR Buffer, BOOL EffAddr) = 0;
|
|
|
|
// Creates new Breakpoint object compatible with specific machine
|
|
virtual HRESULT NewBreakpoint(DebugClient* Client,
|
|
ULONG Type,
|
|
ULONG Id,
|
|
Breakpoint** RetBp);
|
|
|
|
virtual BOOL IsBreakpointInstruction(ProcessInfo* Process, PADDR Addr) = 0;
|
|
virtual HRESULT InsertBreakpointInstruction(PUSER_DEBUG_SERVICES Services,
|
|
ULONG64 Process,
|
|
ULONG64 Offset,
|
|
ULONG Flags,
|
|
PUCHAR SaveInstr,
|
|
PULONG64 ChangeStart,
|
|
PULONG ChangeLen) = 0;
|
|
virtual HRESULT RemoveBreakpointInstruction(PUSER_DEBUG_SERVICES Services,
|
|
ULONG64 Process,
|
|
ULONG64 Offset,
|
|
PUCHAR SaveInstr,
|
|
PULONG64 ChangeStart,
|
|
PULONG ChangeLen) = 0;
|
|
virtual void AdjustPCPastBreakpointInstruction(PADDR Addr,
|
|
ULONG BreakType) = 0;
|
|
// Base implementations do nothing for platforms which
|
|
// do not support data breakpoints.
|
|
virtual void InsertThreadDataBreakpoints(void);
|
|
virtual void RemoveThreadDataBreakpoints(void);
|
|
// Base implementation returns EXCEPTION_BRAKEPOINT_ANY
|
|
// for STATUS_BREAKPOINT.
|
|
virtual ULONG IsBreakpointOrStepException(PEXCEPTION_RECORD64 Record,
|
|
ULONG FirstChance,
|
|
PADDR BpAddr,
|
|
PADDR RelAddr);
|
|
|
|
virtual BOOL IsCallDisasm(PCSTR Disasm) = 0;
|
|
virtual BOOL IsReturnDisasm(PCSTR Disasm) = 0;
|
|
virtual BOOL IsSystemCallDisasm(PCSTR Disasm) = 0;
|
|
|
|
virtual BOOL IsDelayInstruction(PADDR Addr) = 0;
|
|
virtual void GetEffectiveAddr(PADDR Addr, PULONG Size) = 0;
|
|
// Some processors, such as IA64, have instructions which
|
|
// switch between instruction sets, thus the machine type
|
|
// of the next offset may be different from the current machine.
|
|
// If the NextAddr is OFFSET_TRACE the NextMachine is ignored.
|
|
virtual void GetNextOffset(ProcessInfo* Process, BOOL StepOver,
|
|
PADDR NextAddr, PULONG NextMachine) = 0;
|
|
// Base implementation returns the value from StackWalk.
|
|
virtual void GetRetAddr(PADDR Addr);
|
|
// Base implementation does nothing for machines which
|
|
// do not have symbol prefixing.
|
|
virtual BOOL GetPrefixedSymbolOffset(ProcessInfo* Process,
|
|
ULONG64 SymOffset,
|
|
ULONG Flags,
|
|
PULONG64 PrefixedSymOffset);
|
|
|
|
virtual void IncrementBySmallestInstruction(PADDR Addr) = 0;
|
|
virtual void DecrementBySmallestInstruction(PADDR Addr) = 0;
|
|
|
|
// Output function entry information for the given entry.
|
|
virtual void OutputFunctionEntry(PVOID RawEntry) = 0;
|
|
// Base implementation returns E_UNEXPECTED.
|
|
virtual HRESULT ReadDynamicFunctionTable(ProcessInfo* Process,
|
|
ULONG64 Table,
|
|
PULONG64 NextTable,
|
|
PULONG64 MinAddress,
|
|
PULONG64 MaxAddress,
|
|
PULONG64 BaseAddress,
|
|
PULONG64 TableData,
|
|
PULONG TableSize,
|
|
PWSTR OutOfProcessDll,
|
|
PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE RawTable);
|
|
// Base implementation returns NULL.
|
|
virtual PVOID FindDynamicFunctionEntry(PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE Table,
|
|
ULONG64 Address,
|
|
PVOID TableData,
|
|
ULONG TableSize);
|
|
// Base implementation returns E_UNEXPECTED.
|
|
virtual HRESULT GetUnwindInfoBounds(ProcessInfo* Process,
|
|
ULONG64 TableBase,
|
|
PVOID RawTableEntries,
|
|
ULONG EntryIndex,
|
|
PULONG64 Start,
|
|
PULONG Size);
|
|
|
|
virtual HRESULT ReadKernelProcessorId
|
|
(ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id) = 0;
|
|
|
|
// Base implementation discards page directory entries.
|
|
virtual void FlushPerExecutionCaches(void);
|
|
|
|
// Base implementation does nothing.
|
|
virtual HRESULT GetAlternateTriageDumpDataRanges(ULONG64 PrcbBase,
|
|
ULONG64 ThreadBase,
|
|
PADDR_RANGE Ranges);
|
|
|
|
// Stack output functions
|
|
virtual void PrintStackFrameAddressesTitle(ULONG Flags);
|
|
virtual void PrintStackFrameAddresses(ULONG Flags,
|
|
PDEBUG_STACK_FRAME StackFrame);
|
|
virtual void PrintStackArgumentsTitle(ULONG Flags);
|
|
virtual void PrintStackArguments(ULONG Flags,
|
|
PDEBUG_STACK_FRAME StackFrame);
|
|
virtual void PrintStackCallSiteTitle(ULONG Flags);
|
|
virtual void PrintStackCallSite(ULONG Flags,
|
|
PDEBUG_STACK_FRAME StackFrame,
|
|
PSYMBOL_INFO SiteSymbol,
|
|
PSTR SymName,
|
|
DWORD64 Displacement);
|
|
virtual void PrintStackNonvolatileRegisters
|
|
(ULONG Flags,
|
|
PDEBUG_STACK_FRAME StackFrame,
|
|
PCROSS_PLATFORM_CONTEXT Context,
|
|
ULONG FrameNum);
|
|
virtual void PrintStackFrameMemoryUsage(PDEBUG_STACK_FRAME CurFrame,
|
|
PDEBUG_STACK_FRAME PrevFrame);
|
|
|
|
//
|
|
// Helpers for convenient value access.
|
|
//
|
|
// Note that the basic methods here do not get the register
|
|
// type as is done in the generic code. All of these methods
|
|
// assume that the proper call is being made for the register.
|
|
// The Get/SetReg methods also only operate on real registers, not
|
|
// subregisters. Use the Get/SetSubReg methods when dealing
|
|
// with subregisters.
|
|
//
|
|
// Alternately, FullGet/SetVal perform all the necessary
|
|
// work for typing and subregisters.
|
|
//
|
|
|
|
USHORT GetReg16(ULONG Reg)
|
|
{
|
|
REGVAL RegVal;
|
|
RegVal.I64 = 0;
|
|
GetVal(Reg, &RegVal);
|
|
return RegVal.I16;
|
|
}
|
|
ULONG GetReg32(ULONG Reg)
|
|
{
|
|
REGVAL RegVal;
|
|
RegVal.I64 = 0;
|
|
GetVal(Reg, &RegVal);
|
|
return RegVal.I32;
|
|
}
|
|
void SetReg32(ULONG Reg, ULONG Val)
|
|
{
|
|
REGVAL RegVal;
|
|
RegVal.Type = REGVAL_INT32;
|
|
RegVal.I64 = (ULONG64)Val;
|
|
SetVal(Reg, &RegVal);
|
|
}
|
|
ULONG64 GetReg64(ULONG Reg)
|
|
{
|
|
REGVAL RegVal;
|
|
RegVal.I64 = 0;
|
|
GetVal(Reg, &RegVal);
|
|
return RegVal.I64;
|
|
}
|
|
HRESULT SetReg64(ULONG Reg, ULONG64 Val)
|
|
{
|
|
REGVAL RegVal;
|
|
RegVal.Type = REGVAL_INT64;
|
|
RegVal.I64 = Val;
|
|
RegVal.Nat = FALSE;
|
|
return SetVal(Reg, &RegVal);
|
|
}
|
|
ULONG GetSubReg32(ULONG SubReg)
|
|
{
|
|
REGVAL RegVal;
|
|
REGSUBDEF* SubDef = RegSubDefFromIndex(SubReg);
|
|
|
|
if (!SubDef)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
RegVal.I64 = 0;
|
|
GetVal(SubDef->FullReg, &RegVal);
|
|
return (ULONG)((RegVal.I64 >> SubDef->Shift) & SubDef->Mask);
|
|
}
|
|
|
|
HRESULT FullGetVal(ULONG Reg, REGVAL* Val);
|
|
ULONG FullGetVal32(ULONG Reg)
|
|
{
|
|
REGVAL RegVal;
|
|
RegVal.I64 = 0;
|
|
FullGetVal(Reg, &RegVal);
|
|
return RegVal.I32;
|
|
}
|
|
ULONG64 FullGetVal64(ULONG Reg)
|
|
{
|
|
REGVAL RegVal;
|
|
RegVal.I64 = 0;
|
|
FullGetVal(Reg, &RegVal);
|
|
return RegVal.I64;
|
|
}
|
|
HRESULT FullSetVal(ULONG Reg, REGVAL* Val);
|
|
HRESULT FullSetVal32(ULONG Reg, ULONG Val)
|
|
{
|
|
REGVAL RegVal;
|
|
ZeroMemory(&RegVal, sizeof(RegVal));
|
|
RegVal.Type = GetType(Reg);
|
|
RegVal.I32 = Val;
|
|
return FullSetVal(Reg, &RegVal);
|
|
}
|
|
HRESULT FullSetVal64(ULONG Reg, ULONG64 Val)
|
|
{
|
|
REGVAL RegVal;
|
|
ZeroMemory(&RegVal, sizeof(RegVal));
|
|
RegVal.Type = GetType(Reg);
|
|
RegVal.I64 = Val;
|
|
return FullSetVal(Reg, &RegVal);
|
|
}
|
|
|
|
// Helper function to initialize an ADDR given a flat
|
|
// offset from a known segment or segment register.
|
|
void FormAddr(ULONG SegOrReg, ULONG64 Off, ULONG Flags,
|
|
PADDR Address);
|
|
|
|
REGSUBDEF* RegSubDefFromIndex(ULONG Index);
|
|
REGDEF* RegDefFromIndex(ULONG Index);
|
|
REGDEF* RegDefFromCount(ULONG Count);
|
|
ULONG RegCountFromIndex(ULONG Index);
|
|
|
|
ContextSave* PushContext(PCROSS_PLATFORM_CONTEXT Context);
|
|
void PopContext(ContextSave* Save);
|
|
|
|
protected:
|
|
TRACEMODE m_TraceMode;
|
|
|
|
// Common helpers for disassembly.
|
|
PCHAR m_Buf, m_BufStart;
|
|
|
|
void BufferHex(ULONG64 Value, ULONG Length, BOOL Signed);
|
|
void BufferInt(ULONG64 Value, ULONG MinLength, BOOL Signed);
|
|
void BufferBlanks(ULONG BufferPos);
|
|
void BufferString(PCSTR String);
|
|
|
|
void PrintMultiPtrTitle(const CHAR* Title, USHORT PtrNum);
|
|
};
|
|
|
|
extern ULONG g_PossibleProcessorTypes[MACHIDX_COUNT];
|
|
|
|
MachineInfo* NewMachineInfo(ULONG Index, ULONG BaseMachineType,
|
|
TargetInfo* Target);
|
|
MachineIndex MachineTypeIndex(ULONG Machine);
|
|
|
|
// g_AllMachines has a NULL at MACHIDX_COUNT to handle errors.
|
|
#define MachineTypeInfo(Target, Machine) \
|
|
(Target)->m_Machines[MachineTypeIndex(Machine)]
|
|
|
|
void CacheReportInstructions(ULONG64 Pc, ULONG Count, PUCHAR Stream);
|
|
|
|
BOOL IsImageMachineType64(DWORD MachineType);
|
|
|
|
extern CHAR g_F0[], g_F1[], g_F2[], g_F3[], g_F4[], g_F5[];
|
|
extern CHAR g_F6[], g_F7[], g_F8[], g_F9[], g_F10[], g_F11[];
|
|
extern CHAR g_F12[], g_F13[], g_F14[], g_F15[], g_F16[], g_F17[];
|
|
extern CHAR g_F18[], g_F19[], g_F20[], g_F21[], g_F22[], g_F23[];
|
|
extern CHAR g_F24[], g_F25[], g_F26[], g_F27[], g_F28[], g_F29[];
|
|
extern CHAR g_F30[], g_F31[];
|
|
|
|
extern CHAR g_R0[], g_R1[], g_R2[], g_R3[], g_R4[], g_R5[];
|
|
extern CHAR g_R6[], g_R7[], g_R8[], g_R9[], g_R10[], g_R11[];
|
|
extern CHAR g_R12[], g_R13[], g_R14[], g_R15[], g_R16[], g_R17[];
|
|
extern CHAR g_R18[], g_R19[], g_R20[], g_R21[], g_R22[], g_R23[];
|
|
extern CHAR g_R24[], g_R25[], g_R26[], g_R27[], g_R28[], g_R29[];
|
|
extern CHAR g_R30[], g_R31[];
|
|
|
|
#endif // #ifndef __MACHINE_HPP__
|