///////////////////////////////////////////////////////////////////////////// // // singx86.h - Singularity Debugger Extension common Header. // // Copyright (c) Microsoft Corporation. All rights reserved. // // For more information, see http://ddkslingshot/webs/debugexw/ // #pragma warning(disable:4201) // Enable nameless structs and unions. #include #include #include #include #include // // 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 #include ////////////////////////////////////////////////////////////////////////////// // // Load the Singularity types exported by halclass.h // #define arrayof(a) (sizeof(a)/sizeof(a[0])) #include /////////////////////////////////////////////////////////////// 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 struct STATIC_ASSERT_FAILURE; template <> struct STATIC_ASSERT_FAILURE { }; template 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])) //#include #include // ////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus extern "C" { #endif // 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); 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); ///////////////////////////////// Remote to Local conversions for structs. // // Metadata structures. struct StructType { struct StructType * next; struct FieldType * fields; ULONG fieldCount; PCSTR name; ULONG64 module; ULONG type; ULONG size; PBYTE temp; ULONG localSize; public: static StructType * registered; static HRESULT InitializeRegistered(); public: StructType(PCSTR 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 eip; 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 ThreadContext { ULONG64 regs; ULONG64 prev; ULONG64 next; ULONG64 eip; ULONG64 efl; ULONG64 num; ULONG64 err; ULONG64 cr2; ULONG64 eax; ULONG64 ebx; ULONG64 ecx; ULONG64 edx; ULONG64 esp; ULONG64 ebp; ULONG64 esi; ULONG64 edi; ULONG64 stackBegin; ULONG64 stackLimit; ULONG64 processId; ULONG64 uncaughtFlag; ULONG64 suspendAlert; ULONG64 _thread; ULONG64 processThread; ULONG64 stackMarkers; ULONG64 processMarkers; ULONG64 threadIndex; ULONG64 processThreadIndex; ULONG64 gcStates; struct MmxContext mmx; }; 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 FieldType ThreadEntryFields[]; extern StructType ThreadEntryStruct; struct ProcessorContext { ULONG64 threadContext; ULONG64 _processor; ULONG64 exception; ULONG64 schedulerStackBegin; ULONG64 schedulerStackLimit; ULONG64 interruptStackBegin; ULONG64 interruptStackLimit; ULONG64 exceptionStackBegin; ULONG64 exceptionStackLimit; ThreadContext exceptionContext; ThreadContext thirdContext; ULONG64 cpuId; ULONG64 nextProcessorContext; }; extern FieldType ProcessorContextFields[]; extern StructType ProcessorContextStruct; struct Processor { ULONG64 context; ULONG64 nextTimerInterrupt; ULONG64 pic; ULONG64 timer; ULONG64 clock; ULONG64 timerInterrupt; ULONG64 clockInterrupt; ULONG64 inInterruptContext; ULONG64 halted; ULONG64 NumExceptions; ULONG64 NumInterrupts; ULONG64 NumContextSwitches; ULONG64 interruptCounts; }; extern FieldType ProcessorFields[]; 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 FieldType LogEntryFields[]; extern StructType LogEntryStruct; #ifdef __cplusplus } #endif