singrdk/base/Windows/singx86/singx86.h

717 lines
17 KiB
C
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
/////////////////////////////////////////////////////////////////////////////
//
// singx86.h - Singularity Debugger Extension common Header.
//
2008-11-17 18:29:00 -05:00
// Copyright Microsoft Corporation. All rights reserved.
2008-03-05 09:52:00 -05:00
//
// For more information, see http://ddkslingshot/webs/debugexw/
//
#pragma warning(disable:4201) // Enable nameless structs and unions.
#include <winlean.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
//
// Define KDEXT_64BIT to make all wdbgexts APIs recognize 64 bit addresses
// It is recommended for extensions to use 64 bit headers from wdbgexts so
// the extensions could support 64 bit targets.
//
// #define KDEXT_64BIT
// #include <wdbgexts.h>
#include <dbgeng.h>
//////////////////////////////////////////////////////////////////////////////
//
// Load the Singularity types exported by halclass.h
//
#define arrayof(a) (sizeof(a)/sizeof(a[0]))
/////////////////////////////////////////////////////////////// Static Assert.
//
// Compile-time (not run-time) assertion. Code will not compile if
// expr is false. Note: there is no non-debug version of this; we
// want this for all builds. The compiler optimizes the code away.
//
template <bool x> struct STATIC_ASSERT_FAILURE;
template <> struct STATIC_ASSERT_FAILURE<true> { };
template <int x> struct static_assert_test { };
#define STATIC_CAT_INNER(x,y) x##y
#define STATIC_CAT(x,y) STATIC_CAT_INNER(x,y)
#define STATIC_ASSERT(condition) \
typedef static_assert_test< \
sizeof(STATIC_ASSERT_FAILURE<(bool)(condition)>)> \
STATIC_CAT(__static_assert_typedef_, __COUNTER__)
//////////////////////////////////////////////////////////////////////////////
//
#define OFFSETOF(s,m) ((uintptr)&(((s *)0)->m))
#define ARRAYOF(a) (sizeof(a)/sizeof(a[0]))
2008-11-17 18:29:00 -05:00
//
// X64 context definitions
//
typedef struct _X64_M128 {
ULONGLONG Low;
LONGLONG High;
} X64_M128, *PX64_M128;
typedef struct _X64_XMM_SAVE_AREA64 {
USHORT ControlWord;
USHORT StatusWord;
UCHAR TagWord;
UCHAR Reserved1;
USHORT ErrorOpcode;
ULONG64 ErrorOffset;
ULONG64 DataOffset;
ULONG MxCsr;
ULONG MxCsr_Mask;
X64_M128 FloatRegisters[8];
X64_M128 XmmRegisters[16];
UCHAR Reserved4[96];
} X64_XMM_SAVE_AREA64, *PX64_XMM_SAVE_AREA64;
typedef struct _X64_CONTEXT {
//
// Register parameter home addresses.
//
ULONG64 P1Home;
ULONG64 P2Home;
ULONG64 P3Home;
ULONG64 P4Home;
ULONG64 P5Home;
ULONG64 P6Home;
//
// Control flags.
//
ULONG ContextFlags;
ULONG MxCsr;
//
// Segment Registers and processor flags.
//
USHORT SegCs;
USHORT SegDs;
USHORT SegEs;
USHORT SegFs;
USHORT SegGs;
USHORT SegSs;
ULONG EFlags;
//
// Debug registers
//
ULONG64 Dr0;
ULONG64 Dr1;
ULONG64 Dr2;
ULONG64 Dr3;
ULONG64 Dr6;
ULONG64 Dr7;
//
// Integer registers.
//
ULONG64 Rax;
ULONG64 Rcx;
ULONG64 Rdx;
ULONG64 Rbx;
ULONG64 Rsp;
ULONG64 Rbp;
ULONG64 Rsi;
ULONG64 Rdi;
ULONG64 R8;
ULONG64 R9;
ULONG64 R10;
ULONG64 R11;
ULONG64 R12;
ULONG64 R13;
ULONG64 R14;
ULONG64 R15;
//
// Program counter.
//
ULONG64 Rip;
//
// Floating point state.
//
union {
X64_XMM_SAVE_AREA64 FltSave;
struct {
X64_M128 Header[2];
X64_M128 Legacy[8];
X64_M128 Xmm0;
X64_M128 Xmm1;
X64_M128 Xmm2;
X64_M128 Xmm3;
X64_M128 Xmm4;
X64_M128 Xmm5;
X64_M128 Xmm6;
X64_M128 Xmm7;
X64_M128 Xmm8;
X64_M128 Xmm9;
X64_M128 Xmm10;
X64_M128 Xmm11;
X64_M128 Xmm12;
X64_M128 Xmm13;
X64_M128 Xmm14;
X64_M128 Xmm15;
};
};
//
// Vector registers.
//
X64_M128 VectorRegister[26];
ULONG64 VectorControl;
//
// Special debug control registers.
//
ULONG64 DebugControl;
ULONG64 LastBranchToRip;
ULONG64 LastBranchFromRip;
ULONG64 LastExceptionToRip;
ULONG64 LastExceptionFromRip;
} X64_CONTEXT, *PX64_CONTEXT;
2008-03-05 09:52:00 -05:00
//
2008-11-17 18:29:00 -05:00
// X86 context definitions
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
#define SIZE_OF_80387_REGISTERS 80
#define X86_MAXIMUM_SUPPORTED_EXTENSION 512
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
typedef struct _X86_FLOATING_SAVE_AREA {
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
BYTE RegisterArea[SIZE_OF_80387_REGISTERS];
DWORD Cr0NpxState;
} X86_FLOATING_SAVE_AREA;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
typedef struct _X86_CONTEXT {
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// The flags values within this flag control the contents of
// a CONTEXT record.
//
// If the context record is used as an input parameter, then
// for each portion of the context record controlled by a flag
// whose value is set, it is assumed that that portion of the
// context record contains valid context. If the context record
// is being used to modify a threads context, then only that
// portion of the threads context will be modified.
//
// If the context record is used as an IN OUT parameter to capture
// the context of a thread, then only those portions of the thread's
// context corresponding to set flags will be returned.
//
// The context record is never used as an OUT only parameter.
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD ContextFlags;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// This section is specified/returned if X86_CONTEXT_DEBUG_REGISTERS is
// set in ContextFlags. Note that X86_CONTEXT_DEBUG_REGISTERS is NOT
// included in X86_CONTEXT_FULL.
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// This section is specified/returned if the
// ContextFlags word contains the flag X86_CONTEXT_FLOATING_POINT.
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
X86_FLOATING_SAVE_AREA FloatSave;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// This section is specified/returned if the
// ContextFlags word contains the flag X86_CONTEXT_SEGMENTS.
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// This section is specified/returned if the
// ContextFlags word contains the flag X86_CONTEXT_INTEGER.
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// This section is specified/returned if the
// ContextFlags word contains the flag X86_CONTEXT_CONTROL.
//
DWORD Ebp;
DWORD Eip;
DWORD SegCs; // MUST BE SANITIZED
DWORD EFlags; // MUST BE SANITIZED
DWORD Esp;
DWORD SegSs;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// This section is specified/returned if the
// ContextFlags word contains the flag X86_CONTEXT_SYSTEM
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD Cr0;
DWORD Cr2;
DWORD Cr3;
DWORD Cr4;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// This section is specified/returned if the ContextFlags word
// contains the flag X86_CONTEXT_EXTENDED_REGISTERS.
// The format and contexts are processor specific
2008-03-05 09:52:00 -05:00
//
2008-11-17 18:29:00 -05:00
BYTE ExtendedRegisters[X86_MAXIMUM_SUPPORTED_EXTENSION];
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
} X86_CONTEXT;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
typedef struct _ARM_CONTEXT {
2008-03-05 09:52:00 -05:00
//
2008-11-17 18:29:00 -05:00
// Control flags.
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD ContextFlags;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// Integer registers
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD R0;
DWORD R1;
DWORD R2;
DWORD R3;
DWORD R4;
DWORD R5;
DWORD R6;
DWORD R7;
DWORD R8;
DWORD R9;
DWORD R10;
DWORD R11;
DWORD R12;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// Control Registers
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
DWORD Sp;
DWORD Lr;
DWORD Pc;
DWORD Cpsr;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
} ARM_CONTEXT;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
//////////////////////////////////////////////////////////////////////////////
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// Declares an extension routine.
#define EXT_DECL(Name) \
extern "C" HRESULT CALLBACK \
Name(PDEBUG_CLIENT client, PCSTR args)
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// Set up and clean up for an extension routine.
#define EXT_ENTER() \
HRESULT status = ExtQuery(client); \
if (status != S_OK) goto Exit; else 0
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
#define EXT_LEAVE() \
Exit: ExtRelease(); return status
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// Safe release and NULL.
#define EXT_RELEASE(Unk) \
((Unk) != NULL ? ((Unk)->Release(), (Unk) = NULL) : NULL)
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// Evaluates a numeric expression from the current args
// and updates the Args location.
// Assumes variables args and status, plus exit label Exit.
#define EXT_ARG(Dst) \
if ((status = ExtEvalU64(&args, &(Dst))) != S_OK) goto Exit; else 0
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
#define EXT_CHECK(expr) \
if ((status = expr) != S_OK) goto Exit; else 0
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// Global variables initialized by query.
extern PDEBUG_ADVANCED g_ExtAdvanced;
extern PDEBUG_CLIENT g_ExtClient;
extern PDEBUG_CONTROL4 g_ExtControl;
extern PDEBUG_DATA_SPACES4 g_ExtData;
extern PDEBUG_REGISTERS2 g_ExtRegisters;
extern PDEBUG_SYMBOLS g_ExtSymbols;
extern PDEBUG_SYSTEM_OBJECTS g_ExtSystem;
// Queries for all debugger interfaces.
HRESULT ExtQuery(PDEBUG_CLIENT Client);
// Cleans up all debugger interfaces.
void ExtRelease(void);
// Normal output.
void __cdecl ExtOut(PCSTR Format, ...);
// Error output.
void __cdecl ExtErr(PCSTR Format, ...);
// Warning output.
void __cdecl ExtWarn(PCSTR Format, ...);
// Verbose output.
void __cdecl ExtVerb(PCSTR Format, ...);
// Evaluates an expression from the given string
// and updates the string pointer. Consumes trailing whitespace.
HRESULT ExtEvalU64(PCSTR* Str, PULONG64 Val);
HRESULT ExtDefPointer(ULONG64 Address, PULONG64 Val);
extern BOOL Connected;
extern ULONG TargetMachine;
HRESULT OnTargetAccessible(PDEBUG_CLIENT Client,
PDEBUG_CONTROL Control);
HRESULT OnGetKnownStructNames(PDEBUG_CLIENT Client,
PSTR Buffer,
PULONG BufferSize);
HRESULT OnGetSingleLineOutput(PDEBUG_CLIENT Client,
ULONG64 Address,
PSTR StructName,
PSTR Buffer,
PULONG BufferSize);
HRESULT OnGetSuppressTypeName(PDEBUG_CLIENT Client,
PSTR StructName);
ULONG64 GetStaticPointer(PCSTR name);
HRESULT FindKernelNameAndInitialize(PDEBUG_CLIENT client);
///////////////////////////////// Remote to Local conversions for structs.
//
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// Metadata structures.
struct StructType
{
struct StructType * next;
struct FieldType * fields;
ULONG fieldCount;
PSTR name;
ULONG64 module;
ULONG type;
ULONG size;
PBYTE temp;
ULONG localSize;
public:
static StructType * registered;
static HRESULT InitializeRegistered();
public:
StructType(PSTR name, ULONG localSize, struct FieldType *fields);
HRESULT Initialize();
HRESULT RemoteOffsetFromLocal(ULONG localOffset, ULONG *remoteOffset);
HRESULT Clear();
HRESULT Read(ULONG64 address, PVOID local);
HRESULT RawAccess(ULONG remoteOffset, PVOID *raw);
HRESULT Update(PVOID local);
HRESULT Flush(ULONG64 address);
};
struct FieldType
{
struct StructType *parent;
PCSTR name;
ULONG localOffset;
ULONG64 module;
ULONG type;
ULONG offset;
ULONG size;
};
// Macros for defining metadata.
#define FIELD(s,f) { NULL, #f, offsetof(s,f), 0, 0, 0, 0 }
#define FIELDEND() { NULL, NULL, 0, 0, 0, 0, 0 }
/////////////////////////////////////////////////////////// Known Structs.
//
struct MmxContext
{
ULONG64 fcw;
ULONG64 fsw;
ULONG64 ftw;
ULONG64 fop;
ULONG64 ip;
ULONG64 cs;
ULONG64 dp;
ULONG64 ds;
ULONG64 mxcsr;
ULONG64 mxcsrmask;
ULONG64 st0;
ULONG64 st1;
ULONG64 st2;
ULONG64 st3;
ULONG64 st4;
ULONG64 st5;
ULONG64 st6;
ULONG64 st7;
};
struct SpillContext
{
// X86 & X64 Registers
ULONG64 ax;
ULONG64 bx;
ULONG64 cx;
ULONG64 dx;
ULONG64 di;
ULONG64 si;
ULONG64 sp; // also used for ARM sp (aka r13)
ULONG64 ip;
ULONG64 bp;
ULONG64 fl;
// X64 Registers
ULONG64 r8;
ULONG64 r9;
ULONG64 r10;
ULONG64 r11;
ULONG64 r12;
ULONG64 r13;
ULONG64 r14;
ULONG64 r15;
// ARM Registers
ULONG64 r0;
ULONG64 r1;
ULONG64 r2;
ULONG64 r3;
ULONG64 r4;
ULONG64 r5;
ULONG64 r6;
ULONG64 r7;
// r8..r12 repeated above.
// r13 is sp
ULONG64 lr; // aka r14
ULONG64 pc; // aka r15
ULONG64 cpsr;
// X86 & X64
struct MmxContext mmx;
};
struct ThreadRecord
{
struct SpillContext spill;
ULONG64 activeStackLimit;
};
extern StructType ThreadRecordStruct;
struct ThreadContext
{
struct ThreadRecord threadRecord;
ULONG64 num;
ULONG64 regs;
ULONG64 prev;
ULONG64 next;
ULONG64 stackBegin;
ULONG64 stackLimit;
ULONG64 processId;
ULONG64 uncaughtFlag;
ULONG64 suspendAlert;
ULONG64 _thread;
ULONG64 processThread;
ULONG64 stackMarkers;
ULONG64 processMarkers;
ULONG64 threadIndex;
ULONG64 processThreadIndex;
ULONG64 gcStates;
};
extern FieldType *ThreadContextFields;
extern StructType *ThreadContextStruct;
struct Thread
{
ULONG64 blocked;
ULONG64 blockedOn;
ULONG64 blockedOnCount;
ULONG64 blockedUntil;
ULONG64 process;
ULONG64 schedulerEntry;
ThreadContext context;
};
extern FieldType *ThreadFields;
extern StructType *ThreadStruct;
struct ThreadEntry
{
ULONG64 queue;
};
extern StructType ThreadEntryStruct;
struct CpuRecord
{
// struct SpillContext spill; unused here
ULONG64 id;
ULONG64 interruptStackBegin;
ULONG64 interruptStackLimit;
struct ThreadRecord bootThread;
};
extern StructType CpuRecordStruct;
struct ProcessorContext
{
struct CpuRecord cpuRecord;
ULONG64 _processor;
ULONG64 exception;
ULONG64 nextProcessorContext;
};
extern StructType ProcessorContextStruct;
struct Processor
{
ULONG64 context;
ULONG64 pic;
ULONG64 timer;
ULONG64 clock;
ULONG64 timerInterrupt;
ULONG64 clockInterrupt;
ULONG64 inInterruptContext;
ULONG64 halted;
ULONG64 NumExceptions;
ULONG64 NumInterrupts;
ULONG64 NumContextSwitches;
ULONG64 interruptCounts;
};
extern StructType ProcessorStruct;
struct String
{
ULONG64 m_stringLength;
ULONG64 m_firstChar;
};
extern FieldType StringFields[];
extern StructType StringStruct;
struct LogEntry
{
ULONG64 _cycleCount;
ULONG64 _cpuId;
ULONG64 _eip;
ULONG64 _threadId;
ULONG64 _processId;
ULONG64 _tag;
ULONG64 _severity;
ULONG64 _strings;
ULONG64 _text;
union
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
ULONG64 _args[6];
struct
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
ULONG64 _arg0;
ULONG64 _arg1;
ULONG64 _arg2;
ULONG64 _arg3;
ULONG64 _arg4;
ULONG64 _arg5;
2008-03-05 09:52:00 -05:00
};
};
2008-11-17 18:29:00 -05:00
};
extern StructType LogEntryStruct;
// The name of the Singularity kernel is 'kernel.*'. However, when performing kernel debugging the
// Microsoft debuggers want to call it 'nt'. Since we want to use the Singx86 debug extension both
// for kernel and non-kernel debugging, we need a way to build the debug extension for each naming
// convention.
// We fix in place, so OnTargetAccessible checks that that sizeof(KERNEL_NAME) exceeds
// sizeof(ALTERNATE_KERNEL_NAME) before it activates the alternate name.
#define KERNEL_NAME "kernel"
#define ALTERNATE_KERNEL_NAME "nt"
#define LEN_KERNEL_NAME (sizeof(KERNEL_NAME) - 1)
#define LEN_ALTERNATE_KERNEL_NAME (sizeof(ALTERNATE_KERNEL_NAME) - 1)
extern BOOL UseAlternateKernelName;
void FixKernelName(char *candidate);
// Resources:
// Turn 'RES_ENTRY(g_pBootInfo, blah)' into 'extern char kernel_g_pBootInfo [];'
#define RES_ENTRY(sym, name) extern char kernel_ ## sym [];
#include "res.inl"
#undef RES_ENTRY
// Turn 'RES_ENTRY(g_pBootInfo, blah)' into 'enum_kernel_g_pBootInfo,'
#define RES_ENTRY(sym, name) enum_kernel_ ## sym,
enum enum_KernelTable {
#include "res.inl"
countKernelTable,
};
#undef RES_ENTRY
extern char *KernelTable[];
HRESULT TraceRead(UINT64 address, void * buffer, ULONG size);
HRESULT TraceReadPointer(int count, UINT64 address, PULONG64 buffer);
2008-03-05 09:52:00 -05:00