717 lines
17 KiB
C++
717 lines
17 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// singx86.h - Singularity Debugger Extension common Header.
|
|
//
|
|
// Copyright Microsoft Corporation. All rights reserved.
|
|
//
|
|
// 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]))
|
|
|
|
//
|
|
// 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;
|
|
|
|
|
|
//
|
|
// X86 context definitions
|
|
//
|
|
|
|
|
|
#define SIZE_OF_80387_REGISTERS 80
|
|
#define X86_MAXIMUM_SUPPORTED_EXTENSION 512
|
|
|
|
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;
|
|
|
|
typedef struct _X86_CONTEXT {
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
DWORD ContextFlags;
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
DWORD Dr0;
|
|
DWORD Dr1;
|
|
DWORD Dr2;
|
|
DWORD Dr3;
|
|
DWORD Dr6;
|
|
DWORD Dr7;
|
|
|
|
//
|
|
// This section is specified/returned if the
|
|
// ContextFlags word contains the flag X86_CONTEXT_FLOATING_POINT.
|
|
//
|
|
|
|
X86_FLOATING_SAVE_AREA FloatSave;
|
|
|
|
//
|
|
// This section is specified/returned if the
|
|
// ContextFlags word contains the flag X86_CONTEXT_SEGMENTS.
|
|
//
|
|
|
|
DWORD SegGs;
|
|
DWORD SegFs;
|
|
DWORD SegEs;
|
|
DWORD SegDs;
|
|
|
|
//
|
|
// This section is specified/returned if the
|
|
// ContextFlags word contains the flag X86_CONTEXT_INTEGER.
|
|
//
|
|
|
|
DWORD Edi;
|
|
DWORD Esi;
|
|
DWORD Ebx;
|
|
DWORD Edx;
|
|
DWORD Ecx;
|
|
DWORD Eax;
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
// This section is specified/returned if the
|
|
// ContextFlags word contains the flag X86_CONTEXT_SYSTEM
|
|
//
|
|
|
|
DWORD Cr0;
|
|
DWORD Cr2;
|
|
DWORD Cr3;
|
|
DWORD Cr4;
|
|
|
|
//
|
|
// This section is specified/returned if the ContextFlags word
|
|
// contains the flag X86_CONTEXT_EXTENDED_REGISTERS.
|
|
// The format and contexts are processor specific
|
|
//
|
|
|
|
BYTE ExtendedRegisters[X86_MAXIMUM_SUPPORTED_EXTENSION];
|
|
|
|
} X86_CONTEXT;
|
|
|
|
typedef struct _ARM_CONTEXT {
|
|
|
|
//
|
|
// Control flags.
|
|
//
|
|
|
|
DWORD ContextFlags;
|
|
|
|
//
|
|
// Integer registers
|
|
//
|
|
|
|
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;
|
|
|
|
//
|
|
// Control Registers
|
|
//
|
|
|
|
DWORD Sp;
|
|
DWORD Lr;
|
|
DWORD Pc;
|
|
DWORD Cpsr;
|
|
|
|
} ARM_CONTEXT;
|
|
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Declares an extension routine.
|
|
#define EXT_DECL(Name) \
|
|
extern "C" HRESULT CALLBACK \
|
|
Name(PDEBUG_CLIENT client, PCSTR args)
|
|
|
|
// Set up and clean up for an extension routine.
|
|
#define EXT_ENTER() \
|
|
HRESULT status = ExtQuery(client); \
|
|
if (status != S_OK) goto Exit; else 0
|
|
|
|
#define EXT_LEAVE() \
|
|
Exit: ExtRelease(); return status
|
|
|
|
// Safe release and NULL.
|
|
#define EXT_RELEASE(Unk) \
|
|
((Unk) != NULL ? ((Unk)->Release(), (Unk) = NULL) : NULL)
|
|
|
|
// 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
|
|
|
|
#define EXT_CHECK(expr) \
|
|
if ((status = expr) != S_OK) goto Exit; else 0
|
|
|
|
// 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.
|
|
//
|
|
|
|
// 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
|
|
{
|
|
ULONG64 _args[6];
|
|
struct
|
|
{
|
|
ULONG64 _arg0;
|
|
ULONG64 _arg1;
|
|
ULONG64 _arg2;
|
|
ULONG64 _arg3;
|
|
ULONG64 _arg4;
|
|
ULONG64 _arg5;
|
|
};
|
|
};
|
|
};
|
|
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);
|
|
|
|
|