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.
336 lines
9.4 KiB
336 lines
9.4 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// 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__
|