|
|
//----------------------------------------------------------------------------
//
// Generic failure analysis framework.
//
// Copyright (C) Microsoft Corporation, 2001.
//
//----------------------------------------------------------------------------
#ifndef __ANALYZE_H__
#define __ANALYZE_H__
#define E_FAILURE_FOLLOWUP_INFO_NOT_FOUND 0x80100001
#define E_FAILURE_BAD_STACK 0x80100002
#define E_FAILURE_ZEROED_STACK 0x80100003
#define E_FAILURE_WRONG_SYMBOLS 0x80100004
#define E_FAILURE_CORRUPT_MODULE_LIST 0x80100005
#define MAX_STACK_FRAMES 50
typedef enum FOLLOW_ADDRESS { FollowYes, FollowSkip, FollowStop } FOLLOW_ADDRESS;
typedef enum FlpClasses { FlpIgnore = 0, FlpOSInternalRoutine, // followups marked as last_ (ignore routines)
FlpOSRoutine, // nt!* or maybe_ followup
FlpOSFilterDrv, // fsfilter!, scsiport! etc.
FlpUnknownDrv, FlpSpecific, // bugcheck or other source tells us exactly what
// the failure is.
MaxFlpClass } FlpClasses;
typedef struct _FOLLOWUP_DESCS { ULONG64 InstructionOffset; CHAR Owner[100]; } FOLLOWUP_DESCS, *PFOLLOWUP_DESCS;
typedef struct _FLR_LOOKUP_TABLE { DEBUG_FLR_PARAM_TYPE Data; PSTR String; } FLR_LOOKUP_TABLE, *PFLR_LOOKUP_TABLE;
extern FLR_LOOKUP_TABLE FlrLookupTable[];
struct ModuleParams { ModuleParams(PCSTR ModName) { m_Name = ModName; m_Valid = FALSE; }
ULONG64 GetBase(void) { return Update() == S_OK ? m_Base : 0; } ULONG GetSize(void) { return Update() == S_OK ? m_Size : 0; } BOOL Contains(ULONG64 Address) { if (Update() == S_OK) { return Address >= m_Base && Address < m_Base + m_Size; }
return FALSE; }
private: HRESULT Update(void);
PCSTR m_Name; BOOL m_Valid; ULONG64 m_Base; ULONG m_Size; };
LONG FaExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo );
BOOL FaGetSymbol( ULONG64 Address, PCHAR Name, PULONG64 Disp, ULONG NameSize );
BOOL FaIsFunctionAddr( ULONG64 IP, PSTR FuncName );
BOOL FaGetFollowupInfo( IN OPTIONAL ULONG64 Addr, IN OPTIONAL PSTR SymbolName, OUT OPTIONAL PCHAR Owner, ULONG OwnerSize );
BOOL FaShowFollowUp( PCHAR Name );
ULONG64 FaGetImplicitStackOffset( void );
LPSTR TimeToStr( ULONG TimeDateStamp, BOOL DateOnly );
//----------------------------------------------------------------------------
//
// DebugFailureAnalysis.
//
//----------------------------------------------------------------------------
class DebugFailureAnalysis : public IDebugFailureAnalysis { public: DebugFailureAnalysis(void); ~DebugFailureAnalysis(void);
//
// IDebugFailureAnalysis.
//
STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ); STDMETHOD_(ULONG, AddRef)( THIS ); STDMETHOD_(ULONG, Release)( THIS );
STDMETHOD_(ULONG, GetFailureClass)(void); STDMETHOD_(DEBUG_FAILURE_TYPE, GetFailureType)(void); STDMETHOD_(ULONG, GetFailureCode)(void); STDMETHOD_(FA_ENTRY*, Get)(FA_TAG Tag); STDMETHOD_(FA_ENTRY*, GetNext)(FA_ENTRY* Entry, FA_TAG Tag, FA_TAG TagMask); STDMETHOD_(FA_ENTRY*, GetString)(FA_TAG Tag, PSTR Str, ULONG MaxSize); STDMETHOD_(FA_ENTRY*, GetBuffer)(FA_TAG Tag, PVOID Buf, ULONG Size); STDMETHOD_(FA_ENTRY*, GetUlong)(FA_TAG Tag, PULONG Value); STDMETHOD_(FA_ENTRY*, GetUlong64)(FA_TAG Tag, PULONG64 Value); STDMETHOD_(FA_ENTRY*, NextEntry)(FA_ENTRY* Entry);
//
// DebugFailureAnalysis.
//
virtual DEBUG_POOL_REGION GetPoolForAddress(ULONG64 Addr) = 0; virtual PCSTR DescribeAddress(ULONG64 Address) = 0; virtual FOLLOW_ADDRESS IsPotentialFollowupAddress(ULONG64 Address) = 0; virtual FOLLOW_ADDRESS IsFollowupContext(ULONG64 Address1, ULONG64 Address2, ULONG64 Address3) = 0;
virtual FlpClasses GetFollowupClass(ULONG64 Address, PCSTR Module, PCSTR Routine) = 0; virtual BOOL CheckForCorruptionInHTE(ULONG64 hTableEntry,PCHAR Owner, ULONG OwnerSize) = 0; virtual BOOL IsManualBreakin(PDEBUG_STACK_FRAME Stk, ULONG Frames) = 0;
void SetFailureClass(ULONG Class) { m_FailureClass = Class; } void SetFailureType(DEBUG_FAILURE_TYPE Type) { m_FailureType = Type; } void SetFailureCode(ULONG Code) { m_FailureCode = Code; }
ULONG GetProcessingFlags(void) { return m_ProcessingFlags; } void SetProcessingFlags(ULONG Flags) { m_ProcessingFlags = Flags; }
void Output(); void OutputEntry(FA_ENTRY* Entry); void OutputEntryParam(DEBUG_FLR_PARAM_TYPE Type); BOOL AddCorruptModules(void); void GenerateBucketId(void); void DbFindBucketInfo(void); void AnalyzeStack(void); void FindFollowupOnRawStack(ULONG64 StackBase, PFOLLOWUP_DESCS PossibleFollowups, FlpClasses *BestClassFollowUp); BOOL GetTriageInfoFromStack(PDEBUG_STACK_FRAME Stack, ULONG Frames, ULONG64 Instruction, PFOLLOWUP_DESCS PossibleFollowups, FlpClasses *BestClassFollowUp); void SetSymbolNameAndModule(void); HRESULT CheckModuleSymbols(PSTR ModName, PSTR ShowName); void ProcessInformation(void); BOOL ProcessInformationPass(void);
FA_ENTRY* Set(FA_TAG Tag, ULONG Size); FA_ENTRY* SetString(FA_TAG Tag, PSTR Str); FA_ENTRY* SetStrings(FA_TAG Tag, ULONG Count, PSTR* Strs); FA_ENTRY* SetBuffer(FA_TAG Tag, PVOID Buf, ULONG Size); FA_ENTRY* SetUlong(FA_TAG Tag, ULONG Value) { FA_ENTRY* Entry = SetBuffer(Tag, &Value, sizeof(Value)); return Entry; } FA_ENTRY* SetUlong64(FA_TAG Tag, ULONG64 Value) { FA_ENTRY* Entry = SetBuffer(Tag, &Value, sizeof(Value)); return Entry; } FA_ENTRY* SetUlong64s(FA_TAG Tag, ULONG Count, PULONG64 Values) { FA_ENTRY* Entry = SetBuffer(Tag, Values, Count * sizeof(*Values)); return Entry; }
FA_ENTRY* Add(FA_TAG Tag, ULONG Size);
ULONG Delete(FA_TAG Tag, FA_TAG TagMask); void Empty(void); BOOL IsEmpty(void) { return m_DataUsed == 0; }
BOOL ValidEntry(FA_ENTRY* Entry) { return (PUCHAR)Entry >= m_Data && (ULONG)((PUCHAR)Entry - m_Data) < m_DataUsed; }
protected: ULONG m_Refs; ULONG m_FailureClass; DEBUG_FAILURE_TYPE m_FailureType; ULONG m_FailureCode; ULONG m_ProcessingFlags;
PUCHAR m_Data; ULONG m_DataLen; ULONG m_DataUsed;
FOLLOWUP_DESCS PossibleFollowups[MaxFlpClass]; FlpClasses BestClassFollowUp;
void PackData(PUCHAR Dst, ULONG Len) { PUCHAR Src = Dst + Len; memmove(Dst, Src, m_DataUsed - (ULONG)(Src - m_Data)); m_DataUsed -= Len; } FA_ENTRY* AllocateEntry(ULONG FullSize); };
class KernelDebugFailureAnalysis : public DebugFailureAnalysis { public: KernelDebugFailureAnalysis(void);
virtual DEBUG_POOL_REGION GetPoolForAddress(ULONG64 Addr); virtual PCSTR DescribeAddress(ULONG64 Address); virtual FOLLOW_ADDRESS IsPotentialFollowupAddress(ULONG64 Address); virtual FOLLOW_ADDRESS IsFollowupContext(ULONG64 Address1, ULONG64 Address2, ULONG64 Address3); virtual FlpClasses GetFollowupClass(ULONG64 Address, PCSTR Module, PCSTR Routine); virtual BOOL CheckForCorruptionInHTE(ULONG64 hTableEntry,PCHAR Owner, ULONG OwnerSize); virtual BOOL IsManualBreakin(PDEBUG_STACK_FRAME Stk, ULONG Frames);
BOOL AddCorruptingPool(ULONG64 Pool); ModuleParams m_KernelModule; };
class UserDebugFailureAnalysis : public DebugFailureAnalysis { public: UserDebugFailureAnalysis(void);
virtual DEBUG_POOL_REGION GetPoolForAddress(ULONG64 Addr); virtual PCSTR DescribeAddress(ULONG64 Address); virtual FOLLOW_ADDRESS IsPotentialFollowupAddress(ULONG64 Address); virtual FOLLOW_ADDRESS IsFollowupContext(ULONG64 Address1, ULONG64 Address2, ULONG64 Address3); virtual FlpClasses GetFollowupClass(ULONG64 Address, PCSTR Module, PCSTR Routine); virtual BOOL CheckForCorruptionInHTE(ULONG64 hTableEntry,PCHAR Owner, ULONG OwnerSize); virtual BOOL IsManualBreakin(PDEBUG_STACK_FRAME Stk, ULONG Frames) { return FALSE; }
ModuleParams m_NtDllModule; ModuleParams m_Kernel32Module; ModuleParams m_Advapi32Module; };
#endif // #ifndef __ANALYZE_H__
|