singrdk/base/Windows/singx86/diagnose.h

668 lines
19 KiB
C
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
/////////////////////////////////////////////////////////////////////////////
//
// diagnose.h - Definitions for diag.cpp
//
// Copyright Microsoft Corporation. All rights reserved.
//
// Some arbitrary constants to simplify dealing with variable size arrays.
// Some cleanup would be necessary
#define MAX_FIELDS 32
#define MAX_TYPES 1024
#define MAX_FILTERS 8
#define MAX_SOURCES 1024
#define MAX_CONTROLLERS 1024
#define ROUND_UP_TO_POWER2( x, n ) (((x) + ((n)-1)) & ~((n)-1))
#define ROUND_DOWN_TO_POWER2( x, n ) ((x) & ~((n)-1))
extern volatile BOOL BreakOnInternalError;
void inline ERRORBREAK(char * msg)
{
ExtVerb(msg);
#ifdef ISA_IX86
if (BreakOnInternalError) {
__asm int 3;
}
#endif
}
struct FieldEntry;
struct EventTypeEntry;
struct SourceEntry;
struct FieldFilter;
struct ControllerObject;
// Structure to cache information for entry enumeration. The values are retrieved from the
// entry header
struct EntryHeader {
UINT64 address;
int size;
int Flags;
UINT64 timestamp;
int TID;
int Cpu;
int StackSize;
UINT64 StackAddress;
};
struct StringPattern;
#define MAX_STORAGE_FILTERS 256
class EventingEnumerator
{
public:
FieldFilter ** Filters;
int FiltersCount;
StringPattern * SourcePattern;
ULONG64 usedStorages;
ULONG64 StorageHandles[MAX_STORAGE_FILTERS];
EventingEnumerator();
bool virtual ApplyFilters(FieldFilter ** filters, int Count);
bool ApplySourceSelector(StringPattern * sourcePattern);
void ClearStorageFilters(){usedStorages = 0;}
bool AddStorageFilter(ULONG64 storageHandle);
bool MatchStorageHandle(ULONG64 storageHandle);
// System enumeration callout. The function is called twice, one before enumeration of all
// controllers begin, and ones after the last controller has been parsed.
bool virtual SystemCallout(bool finished)
{ return TRUE;}
// Controler enumeration callout. The function is called twice, one before enumeration of sources,
// storages andtypes begin. If override, by returning false, will inform the enumeration
// that wlaking the controller's structures must be skipped for this controller. In that case
// there will be no second call to notify enumeration complete
bool virtual ControllerCallout(ControllerObject *controller, bool finished)
{ usedStorages = 0; return TRUE;}
// Metadata callout. The function is called after all metadata has been loaded in controller
// Return TRUE if also walking entries is needed, false if no walk is further
// necessary on this controller.
bool virtual MedataCallout(ControllerObject *controller);
// Storage enumeration callout. The function is called twice, one before enumeration zones
// inside the storage. If override, by returning false, will inform the enumeration that
// walking the storage's structures must be skipped. In that case there will be no
// second call to notify enumeration complete
bool virtual StorageCallout(UINT64 storageAddress, bool finished);
// Zone enumeration callout. The function is called twice, one before enumeration zones
// inside the storage. If override, by returning false, will inform the enumeration that
// walking the storage's structures must be skipped. In that case there will be no
// second call to notify enumeration complete.
bool virtual ZoneCallout(UINT64 zoneAddress, bool finished)
{ return TRUE;}
// Sources enumeration callout. There are two type of sources:
// a. Sources which log to regular memory storages.
// b. Sources which manages the updates in their's private maner (active sources)
// SourcesCallout is called to enumerate very source inside a controller. This is a leaf
// enumeration point, no other internal structures will follow this callback.
void virtual SourcesCallout(SourceEntry * source){}
// Active sources will go through an enumeration also of the internal elements.
// They respect the same semantics as explained in controller, wrt. overriding the
// function. The second call when entries enumeration is completed does not occur if the
// override explicitely rejected the enumeration by returning false.
bool virtual ActiveSourceCallout(SourceEntry * source, bool finished, ControllerObject *controller)
{ return TRUE;}
// Leaf enumeration point to notify about the presence of a new type that has been read
// from the corrent controller's repository
bool virtual TypeCallout(EventTypeEntry * entryDescriptor);
// Callout for every entry in the storage, as they are parsed. Internally the override
// may also choose to walk the fields inside with a call to the method:
// entryDescriptor->WalkFields(this);
// Otherwise this is also a leaf call, the value of the entry is already loaded
// in the buffer so querying values, properties will assume the right context
bool virtual EntryCallout(EntryHeader *header, EventTypeEntry * entryDescriptor)
{ return TRUE;}
// Callout for active entries. The active entries to not have a the usual ENTRY_HEADER
// that everything else has, because the storage of such events are really the responsibility
// of the source. To also force the enumeration of fields for each entry the following call
// must be made in the override:
// entryDescriptor->WalkFields(this);
bool virtual ActiveEntryCallout(EventTypeEntry * entryDescriptor, BOOL finished)
{ return TRUE;}
// The following callout is to notify about every field in a type / entry that gets enumerated.
// for regular entries these will not be invoked, unless in the EntryCallout or in
// ActiveEntryCallout the entryDescriptor->WalkFields(this) call is done.
bool virtual FieldCallout(EventTypeEntry * entryDescriptor, FieldEntry * fieldDescriptor)
{ return TRUE;}
};
// TODO: redefinition of constants. Must be moved to a common place
#define RECORD_STACK_TRACES 0x0001
#define RECORD_LAYOUT_FLAGS (RECORD_STACK_TRACES)
#define FIELD_TYPE__int8 0x1 // 1
#define FIELD_TYPE__uint8 0x2 // 2
#define FIELD_TYPE__byte 0x2 // 2
#define FIELD_TYPE__int16 0x3 // 3
#define FIELD_TYPE__uint16 0x4 // 4
#define FIELD_TYPE__int32 0x5 // 5
#define FIELD_TYPE__int 0x5 // 5
#define FIELD_TYPE__uint32 0x6 // 6
#define FIELD_TYPE__int64 0x7 // 7
#define FIELD_TYPE__uint64 0x8 // 8
#define FIELD_TYPE__IntPtr 0x9 // 9
#define FIELD_TYPE__UIntPtr 0xa // 10
#define FIELD_TYPE_GENERIC_TYPE 0xff
#define FIELD_TYPE__arrayType 0x8000
#define FIELD_TYPE__string 0x4000
#define FIELD_TYPE__szChar 0x2000
#define FIELD_TYPE_VARIABLE_SIZE (FIELD_TYPE__arrayType | FIELD_TYPE__string | FIELD_TYPE__szChar)
#define FIELD_TYPE_VARIABLE_ANY_STRING (FIELD_TYPE__string | FIELD_TYPE__szChar)
struct ArrayType
{
USHORT Length;
USHORT ItemSize;
UINT Type;
PVOID Buffer;
};
//
// Filtering operations
//
enum PatternMatch{
anywhere = 1,
exact = 2,
begin = 3
};
enum FilterOperation{
all = 0, // no test on value
equal = 1,
less = 2,
greater = 3,
different = 4,
contains = 5 // for strings only
};
struct ControllerObject;
// Utility class for simple string pattern matching
struct StringPattern
{
char * Pattern;
PatternMatch MatchMode;
StringPattern();
~StringPattern();
void Cleanup();
bool IsMatch(char * p);
char * ParseInput(char * arg);
};
struct SymbolicValue {
struct SymbolicValue * Next;
PCHAR Name;
ULONG64 Value;
UCHAR FlagChar;
ULONG64 ParentKey;
SymbolicValue() {
Name = NULL;
Value = 0;
FlagChar = 0;
Next = NULL;
}
~SymbolicValue(){ if (Name) free (Name);}
};
struct EnumType {
UINT64 Key;
int BasicType;
ULONG64 FlagsMask;
struct SymbolicValue * ValuesLists;
int NumFlags;
int PrintWidth;
PCHAR Name;
EnumType()
{
Key = 0;
FlagsMask = 0;
ValuesLists = NULL;
NumFlags = 0;
PrintWidth = 0;
Name = NULL;
}
~EnumType();
void AddSymbolicValue(SymbolicValue * symValue);
int GetFieldPrintWidth();
int PrintValue(int printWidth, int offset);
ULONG64 GetFieldNumericValue(int offset);
PCHAR GetStringSymbol(int offset);
};
struct FieldEntry {
int Offset;
int Type;
int Size;
PCHAR Name;
UINT64 ParentKey;
int ExtendedFieldIndex;
unsigned int PrintWidth;
UINT64 TypeKey;
EnumType * SymType;
ControllerObject * Controller;
FieldEntry();
~FieldEntry();
ULONG64 GetFieldNumericValue();
ULONG64 PrintValue(EventTypeEntry * type);
int GetFieldPrintWidth();
int GetArraySize(void * buffer);
ULONG64 GetFieldNumericValue(void * buffer, int index);
};
//
// Utility class used in searching and filtering of entries in
// either regular or active sources.
//
struct FieldFilter
{
char * FieldNamePattern;
char * StringValuePattern;
INT64 NumericValuePattern;
PatternMatch FieldMatchMode;
FilterOperation Operation;
FieldFilter();
~FieldFilter();
void Cleanup();
FieldFilter(PatternMatch matchMode,
char * fieldPattern,
FilterOperation op,
UINT64 value,
char * strValue);
bool MatchFieldName(char * p);
bool MatchFieldValue(INT64 value);
bool MatchFieldValue(char * value);
char * ParseInput(char * arg);
};
// Simple variable size array implementation
struct VariableArray
{
UINT64 *Array;
int InUse;
int Size;
VariableArray();
~VariableArray();
bool Add(UINT64 value);
private:
bool Extend();
};
struct EventTypeEntry {
UINT64 Key;
int NumFields;
FieldEntry * Fields[MAX_FIELDS];
PCHAR Name;
PCHAR Descriptor;
int size;
int ExtendedFieldsCount;
FieldFilter * filterList[MAX_FILTERS];
FieldEntry * fieldsFilterList[MAX_FILTERS];
int filterCount;
bool FilterApplied;
EventTypeEntry();
~EventTypeEntry();
void AddNewField(FieldEntry * field);
bool TestFilter(FieldFilter * newFilter);
bool ApplyFilter(FieldFilter * newFilter);
void ClearFilters();
bool FilterMatch();
void UpdateFieldsOffsets();
void WalkFields(EventingEnumerator * enumerator);
char * GetExtendedString(int index);
void * GetFieldArray(int index);
void Format(int formatStringIndex, int argIndex);
void PrintDescription();
FieldEntry * GetField(PCHAR name);
int GetFieldIndex(PCHAR name);
void EnumerateEntries(EventingEnumerator * enumerator, UINT64 address, ULONG count);
};
struct SourceEntry {
UINT64 Key;
PCHAR Name;
UINT64 StorageHandle;
ULONG ControlFlags;
//
// For active sources
//
UINT64 EventTypeHandle;
UINT64 DebuggerBufferAddress;
UINT64 Count;
UINT64 EntrySize;
SourceEntry();
~SourceEntry();
void EnumerateEntries(EventingEnumerator * enumerator, ControllerObject *controller);
};
struct ControllerObject {
// Enumeration support local variables and definitions
EventTypeEntry * RegisteredTypes[MAX_TYPES];
int TypesCount;
FieldEntry * RegisteredFieldsTypes[MAX_FIELDS];
SourceEntry * RegisteredSources[MAX_SOURCES];
int SourcesCount;
EnumType * RegisteredEnums[MAX_TYPES];
int EnumCount;
SymbolicValue * RegisteredSymbolicValues[MAX_FIELDS];
UINT64 ControllerHandle;
UINT64 ContextHandle;
UINT64 RepositoryAddress;
UINT64 StorageListHead;
ControllerObject(UINT64 handle,
UINT64 contextHandle,
UINT64 storageAddress,
UINT64 storageListHead);
~ControllerObject();
void FetchMetadata(EventingEnumerator * enumerator);
void WalkEntries(EventingEnumerator * enumerator);
EventTypeEntry * FindType(ULONG64 Key);
UINT64 ReadMemoryHeader(EventingEnumerator * enumerator, UINT64 entryAddress);
char * GetControllerName();
EnumType * FindEnum(ULONG64 Key);
private:
void AddTempField(FieldEntry * field);
void PopulateFields(EventTypeEntry * type);
void AddewType(EventTypeEntry * newType);
SourceEntry * FindSource(ULONG64 Key);
void AddNewSource(SourceEntry * newSource);
void WalkTypes(EventingEnumerator * enumerator);
void WalkSources(EventingEnumerator * enumerator);
void WalkActiveSourcesEntries(EventingEnumerator * enumerator);
void ReadSource(UINT64 entryAddress);
void ReadEventDescriptor(UINT64 entryAddress);
void ReadFieldDescriptor(UINT64 entryAddress, UINT64 parent);
void ReadGenericFieldDescriptor(UINT64 entryAddress, UINT64 parent);
UINT64 ReadMetadataMemoryHeader(EventingEnumerator * enumerator, UINT64 entryAddress);
UINT64 ReadMemoryZone(EventingEnumerator * enumerator, UINT64 zoneAddress);
UINT64 ReadStorage(EventingEnumerator * enumerator, UINT64 storageAddress, bool isRepository);
void AddNewEnum(EnumType * newEnum);
void PopulateFields(EnumType * type);
void AddTempField(SymbolicValue * field);
void ReadEnumDescriptor(UINT64 entryAddress);
void ReadValueDescriptor(UINT64 entryAddress, UINT64 parent);
void FlushTypeArray();
void FlushSourceArray();
};
//
// Generic utility prototypes
//
extern EventTypeEntry * SystemHeaderType;
int GetFieldSize(int type);
char * GetFieldTypeName(int type);
bool MatchPatternString(PatternMatch matchMode, char * p, char* pattern);
char * ReadToken(PCSTR& args);
void FlushTransforms();
void ParseStringFormatTransform(PCSTR & args);
void ParseVisibleFields(PCSTR & args);
void ParseSymbolLookupTransform(PCSTR & args);
#define SKIP_WHITESPACES(arg) \
while (*(arg) == ' ' || *(arg) == '\t') (arg)++;
extern ULONG64 GetValue(PCSTR& args, bool fHex);
HRESULT FindBound(const char *symbol, ULONG64 *ptrval);
HRESULT SetBound(const char *symbol, ULONG64 ptrval);
//
// Classes support for filtering, sorting and content dump
//
class DumpTracing : public EventingEnumerator
{
// High level diagnosis enumeration. Each override will skip walking through actuall entries
public:
bool DumpSummary;
DumpTracing() {CrtEntryIndex = 0; DumpSummary = false;}
// Override callouts
bool virtual TypeCallout(EventTypeEntry * entryDescriptor);
void virtual SourcesCallout(SourceEntry * source);
bool virtual ActiveSourceCallout(SourceEntry * source, bool finished, ControllerObject *controller);
bool virtual ControllerCallout(ControllerObject *controller, bool finished);
bool virtual FieldCallout(EventTypeEntry * entryDescriptor, FieldEntry * fieldDescriptor);
bool virtual EntryCallout(EntryHeader *header, EventTypeEntry * entryDescriptor);
private:
enum Lastprinted {
controller,
type,
source,
activesource
};
int CrtEntryIndex;
Lastprinted LastItem;
int PrintPhase;
int FieldIndex;
};
class DumpType : public EventingEnumerator
{
public:
UINT64 typeHandle;
int printHeader;
UINT64 lastTimeStamp;
int CrtEntryIndex;
DumpType(UINT64 handle);
bool virtual FieldCallout(EventTypeEntry * entryDescriptor, FieldEntry * fieldDescriptor);
bool virtual EntryCallout(EntryHeader *header, EventTypeEntry * entryDescriptor);
bool virtual PrintHeader(EventTypeEntry * entryDescriptor);
bool virtual TypeCallout(EventTypeEntry * entryDescriptor);
bool virtual ActiveEntryCallout(EventTypeEntry * entryDescriptor, BOOL finished);
bool virtual ActiveSourceCallout(SourceEntry * source, bool finished, ControllerObject *controller);
};
class TypeFilterEnumerator : public EventingEnumerator
{
public:
VariableArray * Array;
StringPattern * Pattern;
TypeFilterEnumerator();
~TypeFilterEnumerator();
void SetPattern(StringPattern * pattern);
bool virtual TypeCallout(EventTypeEntry * entryDescriptor);
};
class TypeEntryCollector : public TypeFilterEnumerator
{
public:
char * sortField;
UINT64 crtHandle;
UINT64 TypeHandle;
BOOL GroupByController;
EventingEnumerator *cascadeEnumerator;
ControllerObject * currentController;
static const int FieldsWidth = 3;
TypeEntryCollector(UINT64 typeHandle, char * field);
~TypeEntryCollector();
bool virtual FieldCallout(EventTypeEntry * entryDescriptor, FieldEntry * fieldDescriptor);
bool virtual EntryCallout(EntryHeader *header, EventTypeEntry * entryDescriptor);
bool virtual TypeCallout(EventTypeEntry * entryDescriptor);
bool virtual ControllerCallout(ControllerObject *controller, bool finished);
bool virtual SystemCallout(bool finished);
bool virtual MedataCallout(ControllerObject *controller);
void virtual SourcesCallout(SourceEntry * source);
bool virtual StorageCallout(UINT64 storageAddress, bool finished);
private:
void SortItems();
void WalkItems(EventingEnumerator * enumerator);
};
class SourceCollector : public TypeEntryCollector
{
public:
StringPattern *SourcePattern;
UINT64 storageHandle;
SourceCollector(char * sourceName, char * field);
void virtual SourcesCallout(SourceEntry * source);
bool virtual StorageCallout(UINT64 storageAddress, bool finished);
};
//
// Function support for GC profiling
//
void DumpMemory(PCSTR fname);
void WriteFileRange (int Base, int Size, PCSTR fname);
void WriteCLRProfileFile(PCSTR fname, bool Kernel);
void EnableKernelGCProfiler(ULONG64 MemorySize, bool breakOnRecycle);
void DisableKernelGCProfiler();
void EnableSIPGCProfiler(ULONG64 MemorySize, bool breakOnRecycle);
extern ULONG_PTR MetadataSize;
extern char * MetadataInfo;
class MemoryRagesCollection : public VariableArray {
int DiscardedRanges;
UINT64 PreviousAddress;
UINT64 PreviousSize;
public:
MemoryRagesCollection() : VariableArray(){DiscardedRanges=0; PreviousAddress = 0; PreviousSize = 0;};
void AddRange(UINT64 startRVA, UINT64 rangeSize);
int GetEffectiveRanges(){return GetRangesCount() - DiscardedRanges;}
UINT64 GetStartAddress(int i){return Array[i * 2];}
UINT64 GetRangeSize(int i){return Array[i * 2 + 1];}
int GetRangesCount(){return InUse / 2;}
void CompactItems();
UINT64 GetRVA(UINT64 address);
};
extern ULONG pointerSize;
ULONG_PTR SWITCH_TO_METADATA_CURSOR();
void RESTORE_CURSOR(ULONG_PTR savedCursor);
void WalkTracingDatabase(EventingEnumerator * enumerator, bool typesOnly);
UINT64 GetStackTrace(int index) ;