Files
yttrium-virtio-gpu/NetKVM/DebugTools/NetKVMDumpParser/NetKVMDumpParser.cpp
T
2010-02-21 15:34:12 +02:00

837 lines
22 KiB
C++

/**********************************************************************
* Copyright (c) 2008 Red Hat, Inc.
*
* File: NetKVMDumpParser.cpp
*
* This file contains dump parsing logic
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
**********************************************************************/
#include "stdafx.h"
#include "NetKVMDumpParser.h"
#include "..\..\Common\DebugData.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define DEBUG_SYMBOLS_IF IDebugSymbols2
#define PRINT(fmt, ...) printf("[%s]: "##fmt##"\n", __FUNCTION__, __VA_ARGS__);
//#define PRINT(fmt, ...) { CString __s; __s.Format(TEXT("[%s]: ")##TEXT(fmt)##TEXT("\n"), TEXT(__FUNCTION__), __VA_ARGS__); OutputDebugString(__s.GetBuffer()); }
CString ErrorToString(HRESULT hr)
{
CString s;
LPTSTR lpMessageBuffer;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
(LPTSTR) &lpMessageBuffer,
0,
NULL ))
{
s = lpMessageBuffer;
LocalFree(lpMessageBuffer);
}
else
{
s.Format("[Error %lu]", hr);
}
return s;
}
static const LPCSTR OpNames[] = {
"PowerOff ",
"PowerOn ",
"SysPause ",
"SysResume ",
"InternalSendPause ",
"InternalReceivePause ",
"InternalSendResume ",
"InternalReceiveResume",
"SysReset ",
"Halt ",
"ConnectIndication ",
"DPC ",
"Send ",
"SendNBLRequest ",
"SendPacketRequest ",
"SendPacketMapped ",
"SubmittedPacket ",
"BufferSent ",
"BufferReceivedStat ",
"BufferReturned ",
"SendComplete ",
"TxProcess ",
"PacketReceived ",
"OidRequest ",
"PnpEvent ",
};
static CString HistoryOperationName(ULONG op)
{
CString s;
if (op < sizeof(OpNames)/ sizeof(OpNames[0]))
s = OpNames[op];
else
s.Format("##%d", op);
return s;
}
typedef struct _tagNamedFlag
{
ULONG64 flag;
LPCSTR name;
}tNamedFlag;
typedef struct _tagNamedValue
{
ULONG64 value;
LPCSTR name;
}tNamedValue;
#define STRINGER(x) #x
#define VALUE(v) { v, STRINGER(##v) }
#define ENDTABLE { 0, NULL }
const tNamedValue SessionStatusValues[] =
{
VALUE(DEBUG_SESSION_ACTIVE),
VALUE(DEBUG_SESSION_END_SESSION_ACTIVE_TERMINATE),
VALUE(DEBUG_SESSION_END_SESSION_ACTIVE_DETACH),
VALUE(DEBUG_SESSION_END_SESSION_PASSIVE),
VALUE(DEBUG_SESSION_END),
VALUE(DEBUG_SESSION_REBOOT),
VALUE(DEBUG_SESSION_HIBERNATE),
VALUE(DEBUG_SESSION_FAILURE),
ENDTABLE
};
const tNamedValue DebuggeeStateValues[] =
{
VALUE(DEBUG_CDS_ALL),
VALUE(DEBUG_CDS_REGISTERS),
VALUE(DEBUG_CDS_DATA),
ENDTABLE
};
const tNamedValue DebuggeeStateArgValues[] =
{
VALUE(DEBUG_DATA_SPACE_VIRTUAL),
VALUE(DEBUG_DATA_SPACE_PHYSICAL),
VALUE(DEBUG_DATA_SPACE_CONTROL),
VALUE(DEBUG_DATA_SPACE_IO),
VALUE(DEBUG_DATA_SPACE_MSR),
VALUE(DEBUG_DATA_SPACE_BUS_DATA),
VALUE(DEBUG_DATA_SPACE_DEBUGGER_DATA),
VALUE(DEBUG_DATA_SPACE_COUNT),
ENDTABLE
};
const tNamedFlag EngineStateFlags[] =
{
VALUE(DEBUG_CES_ALL),
VALUE(DEBUG_CES_CURRENT_THREAD),
VALUE(DEBUG_CES_EFFECTIVE_PROCESSOR),
VALUE(DEBUG_CES_BREAKPOINTS),
VALUE(DEBUG_CES_CODE_LEVEL),
VALUE(DEBUG_CES_EXECUTION_STATUS),
VALUE(DEBUG_CES_ENGINE_OPTIONS),
VALUE(DEBUG_CES_LOG_FILE),
VALUE(DEBUG_CES_RADIX),
VALUE(DEBUG_CES_EVENT_FILTERS),
VALUE(DEBUG_CES_PROCESS_OPTIONS),
VALUE(DEBUG_CES_EXTENSIONS),
VALUE(DEBUG_CES_SYSTEMS),
VALUE(DEBUG_CES_ASSEMBLY_OPTIONS),
VALUE(DEBUG_CES_EXPRESSION_SYNTAX),
VALUE(DEBUG_CES_TEXT_REPLACEMENTS),
ENDTABLE
};
const tNamedFlag SymbolStateFlags[] =
{
VALUE(DEBUG_CSS_ALL),
VALUE(DEBUG_CSS_LOADS),
VALUE(DEBUG_CSS_UNLOADS),
VALUE(DEBUG_CSS_SCOPE),
VALUE(DEBUG_CSS_PATHS),
VALUE(DEBUG_CSS_SYMBOL_OPTIONS),
VALUE(DEBUG_CSS_TYPE_OPTIONS),
ENDTABLE
};
const tNamedValue EngineExecutionStatus[] =
{
VALUE(DEBUG_STATUS_NO_CHANGE),
VALUE(DEBUG_STATUS_GO),
VALUE(DEBUG_STATUS_GO_HANDLED),
VALUE(DEBUG_STATUS_GO_NOT_HANDLED),
VALUE(DEBUG_STATUS_STEP_OVER),
VALUE(DEBUG_STATUS_STEP_INTO),
VALUE(DEBUG_STATUS_BREAK),
VALUE(DEBUG_STATUS_NO_DEBUGGEE),
VALUE(DEBUG_STATUS_STEP_BRANCH),
VALUE(DEBUG_STATUS_IGNORE_EVENT),
VALUE(DEBUG_STATUS_RESTART_REQUESTED),
VALUE(DEBUG_STATUS_REVERSE_GO),
VALUE(DEBUG_STATUS_REVERSE_STEP_BRANCH),
VALUE(DEBUG_STATUS_REVERSE_STEP_OVER),
VALUE(DEBUG_STATUS_REVERSE_STEP_INTO),
ENDTABLE
};
const tNamedFlag EngineExecutionStatusFlags[] =
{
VALUE(DEBUG_STATUS_INSIDE_WAIT),
VALUE(DEBUG_STATUS_WAIT_TIMEOUT),
ENDTABLE
};
const tNamedFlag ModuleFlags[] =
{
VALUE(DEBUG_MODULE_LOADED),
VALUE(DEBUG_MODULE_UNLOADED),
VALUE(DEBUG_MODULE_USER_MODE),
VALUE(DEBUG_MODULE_EXPLICIT),
VALUE(DEBUG_MODULE_SECONDARY),
VALUE(DEBUG_MODULE_SYNTHETIC),
VALUE(DEBUG_MODULE_SYM_BAD_CHECKSUM),
ENDTABLE
};
const tNamedValue SymbolTypeValues[] =
{
VALUE(DEBUG_SYMTYPE_NONE),
VALUE(DEBUG_SYMTYPE_COFF),
VALUE(DEBUG_SYMTYPE_CODEVIEW),
VALUE(DEBUG_SYMTYPE_PDB),
VALUE(DEBUG_SYMTYPE_EXPORT),
VALUE(DEBUG_SYMTYPE_DEFERRED),
VALUE(DEBUG_SYMTYPE_SYM),
VALUE(DEBUG_SYMTYPE_DIA),
ENDTABLE
};
const tNamedFlag SymbolOptionsFlags[] =
{
VALUE(SYMOPT_CASE_INSENSITIVE),
VALUE(SYMOPT_UNDNAME),
VALUE(SYMOPT_DEFERRED_LOADS),
VALUE(SYMOPT_NO_CPP),
VALUE(SYMOPT_LOAD_LINES),
VALUE(SYMOPT_OMAP_FIND_NEAREST),
VALUE(SYMOPT_LOAD_ANYTHING),
VALUE(SYMOPT_IGNORE_CVREC),
VALUE(SYMOPT_NO_UNQUALIFIED_LOADS),
VALUE(SYMOPT_FAIL_CRITICAL_ERRORS),
VALUE(SYMOPT_EXACT_SYMBOLS),
VALUE(SYMOPT_ALLOW_ABSOLUTE_SYMBOLS),
VALUE(SYMOPT_IGNORE_NT_SYMPATH),
VALUE(SYMOPT_INCLUDE_32BIT_MODULES),
VALUE(SYMOPT_PUBLICS_ONLY),
VALUE(SYMOPT_NO_PUBLICS),
VALUE(SYMOPT_AUTO_PUBLICS),
VALUE(SYMOPT_NO_IMAGE_SEARCH),
VALUE(SYMOPT_SECURE),
VALUE(SYMOPT_NO_PROMPTS),
VALUE(SYMOPT_OVERWRITE),
VALUE(SYMOPT_IGNORE_IMAGEDIR),
VALUE(SYMOPT_FLAT_DIRECTORY),
VALUE(SYMOPT_FAVOR_COMPRESSED),
VALUE(SYMOPT_ALLOW_ZERO_ADDRESS),
VALUE(SYMOPT_DISABLE_SYMSRV_AUTODETECT),
VALUE(SYMOPT_DEBUG),
ENDTABLE
};
class tDumpParser : public DebugBaseEventCallbacks, public IDebugOutputCallbacks
{
public:
tDumpParser() : refCount(0), Client(NULL), Control(NULL), DataSpaces(NULL), DebugSymbols(NULL)
{
HRESULT hr;
hr = DebugCreate(__uuidof(IDebugClient), (void **)&Client);
if (Client) hr = Client->QueryInterface(__uuidof(IDebugControl), (void **)&Control);
if (Client) hr = Client->QueryInterface(__uuidof(IDebugDataSpaces3), (void **)&DataSpaces);
if (Client) hr = Client->QueryInterface(__uuidof(DEBUG_SYMBOLS_IF), (void **)&DebugSymbols);
}
~tDumpParser()
{
ULONG ul = 0;
if (DebugSymbols) DebugSymbols->Release();
if (Control) Control->Release();
if (DataSpaces) DataSpaces->Release();
if (Client) ul = Client->Release();
PRINT("finished (%d)", ul);
}
BOOL LoadFile(TCHAR *filename)
{
HRESULT hr = S_FALSE;
if (Client && Control && DataSpaces)
{
hr = Client->SetEventCallbacks(this);
if (S_OK == hr) hr = Client->SetOutputCallbacks(this);
DebugSymbols->AddSymbolOptions(SYMOPT_DEBUG);
//DebugSymbols->RemoveSymbolOptions(SYMOPT_DEFERRED_LOADS);
DebugSymbols->AppendSymbolPath(".");
//DebugSymbols->AppendSymbolPath("D:\\SVN\\Qumranet\\drivers\\Logs\\2009-4\\Install\\Vista\\x86");
}
else
{
CString sMessage = TEXT("Error: Not all required interaces are up\n");
if (!Client) sMessage += TEXT("Client interface is not initialized\n");
if (!Control) sMessage += TEXT("Control interface is not initialized\n");
if (!DataSpaces) sMessage += TEXT("Data interface is not initialized\n");
PRINT("%s", sMessage.GetBuffer());
}
if (hr == S_OK)
{
hr = Client->OpenDumpFile(filename);
}
if (hr == S_OK) Control->WaitForEvent(0, INFINITE);
return hr == S_OK;
}
void ProcessDumpFile();
void FindOurTaggedCrashData();
void CheckLoadedSymbols();
void ParseCrashData(tBugCheckStaticDataHeader *ph, ULONG64 databuffer, ULONG bytesRead);
typedef enum _tageSystemProperty {espSymbolPath, espSystemVersion } eSystemProperty;
CString GetProperty(eSystemProperty Prop);
protected:
CString Parse(ULONG64 val, const tNamedValue *pt)
{
CString s;
while (pt->name) { if (pt->value == val) { s = pt->name; break; } pt++; }
if (s.IsEmpty()) s.Format(TEXT("Unknown value 0x%I64X"), val);
return s;
}
CString Parse(ULONG64 val, const tNamedFlag *pt)
{
CString s;
while (pt->name && val)
{
if ((pt->flag & val) == pt->flag)
{
val &= ~pt->flag;
if (!s.IsEmpty()) s += ' ';
s += pt->name;
}
pt++;
}
if (val)
{
CString sv;
sv.Format(TEXT("0x%X"), val);
if (!s.IsEmpty()) s += ' ';
s += sv;
}
return s;
}
protected:
STDMETHOD_(ULONG, AddRef)(
THIS
) { return ++refCount; }
STDMETHOD_(ULONG, Release)(
THIS
) { return --refCount; }
STDMETHOD(QueryInterface)(
THIS_
__in REFIID InterfaceId,
__out PVOID* Interface
)
{
*Interface = NULL;
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
IsEqualIID(InterfaceId, __uuidof(IDebugEventCallbacks)))
{
*Interface = (IDebugEventCallbacks *)this;
}
else if (IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
{
*Interface = (IDebugOutputCallbacks *)this;
}
if (*Interface) AddRef();
return (*Interface) ? S_OK : E_NOINTERFACE;
}
STDMETHOD(GetInterestMask)(
THIS_
__out PULONG Mask
)
{
*Mask =
DEBUG_EVENT_BREAKPOINT |
DEBUG_EVENT_EXCEPTION |
DEBUG_EVENT_LOAD_MODULE |
DEBUG_EVENT_UNLOAD_MODULE |
DEBUG_EVENT_SYSTEM_ERROR |
DEBUG_EVENT_SESSION_STATUS |
DEBUG_EVENT_CHANGE_DEBUGGEE_STATE |
DEBUG_EVENT_CHANGE_ENGINE_STATE |
DEBUG_EVENT_CHANGE_SYMBOL_STATE ;
return S_OK;
}
STDMETHOD(Breakpoint)(
THIS_
__in PDEBUG_BREAKPOINT Bp
)
{
PRINT("");
return DEBUG_STATUS_BREAK;
}
STDMETHOD(Exception)(
THIS_
__in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance
)
{
PRINT("");
return DEBUG_STATUS_NO_CHANGE;
}
STDMETHOD(LoadModule)(
THIS_
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in PCSTR ModuleName,
__in PCSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
)
{
PRINT("%s", ImageName);
return DEBUG_STATUS_NO_CHANGE;
}
STDMETHOD(UnloadModule)(
THIS_
__in PCSTR ImageBaseName,
__in ULONG64 BaseOffset
)
{
PRINT("%s", ImageBaseName);
return DEBUG_STATUS_NO_CHANGE;
}
STDMETHOD(SystemError)(
THIS_
__in ULONG Error,
__in ULONG Level
)
{
PRINT("%s");
return DEBUG_STATUS_NO_CHANGE;
}
STDMETHOD(SessionStatus)(
THIS_
__in ULONG Status
)
{
CString s = Parse(Status, SessionStatusValues);
PRINT("%s", s.GetBuffer());
return DEBUG_STATUS_NO_CHANGE;
}
STDMETHOD(ChangeDebuggeeState)(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
CString sf = Parse(Flags, DebuggeeStateValues);
CString sarg;
if (Flags == DEBUG_CDS_DATA) sarg = Parse(Argument, DebuggeeStateArgValues);
else sarg.Format(TEXT("0x%I64X"), Argument);
PRINT("%s(%s)", sf.GetBuffer(), sarg.GetBuffer());
return DEBUG_STATUS_NO_CHANGE;
return S_OK;
}
STDMETHOD(ChangeEngineState)(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
CString s = Parse(Flags, EngineStateFlags);
CString sArg;
if (Flags == DEBUG_CES_EXECUTION_STATUS)
{
CString sWait = Parse(Argument & ~DEBUG_STATUS_MASK, EngineExecutionStatusFlags);
sArg = Parse(Argument & DEBUG_STATUS_MASK, EngineExecutionStatus);
sArg += ' ';
sArg += sWait;
}
else
sArg.Format(TEXT("arg 0x%I64X"), Argument);
PRINT("%s(%s)", s.GetBuffer(), sArg.GetBuffer());
if (Flags == DEBUG_CES_EXECUTION_STATUS && (Argument & DEBUG_STATUS_MASK) == DEBUG_STATUS_BREAK
&& !(Argument & ~DEBUG_STATUS_MASK))
{
ProcessDumpFile();
}
return S_OK;
}
STDMETHOD(ChangeSymbolState)(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
CString s = Parse(Flags, SymbolStateFlags);
PRINT("%s(arg 0x%I64X)", s.GetBuffer(), Argument);
return S_OK;
}
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS_
__in ULONG Mask,
__in PCSTR Text
)
{
//printf("%s", Text);
//OutputDebugString(Text);
return S_OK;
}
ULONG refCount;
IDebugClient *Client;
IDebugControl *Control;
IDebugDataSpaces3 *DataSpaces;
DEBUG_SYMBOLS_IF *DebugSymbols;
};
#define CHECK_INTERFACE(xf) { \
xf *p; HRESULT hr = Client->QueryInterface(__uuidof(xf), (void **)&p); \
PRINT("Interface " TEXT(STRINGER(xf)) TEXT(" %spresent"), p ? "" : "NOT "); \
if (p) p->Release(); }
static void ParseHistoryEntry(LONGLONG basetime, tBugCheckHistoryDataEntry *phist, LONG Index)
{
if (!phist)
{
PRINT("Op Ctx Time Params");
}
else if (phist[Index].Context)
{
LONGLONG diffInt = (basetime - phist[Index].TimeStamp.QuadPart) / 10;
CString sOp = HistoryOperationName(phist[Index].operation);
#if (PARANDIS_DEBUG_HISTORY_DATA_VERSION == 0)
PRINT("%s %I64X [-%09I64d] x%08X x%08X x%08X %I64X", sOp.GetBuffer(), phist[Index].Context, diffInt, phist[Index].lParam2, phist[Index].lParam3, phist[Index].lParam4, phist[Index].pParam1 );
#elif (PARANDIS_DEBUG_HISTORY_DATA_VERSION == 1)
PRINT("CPU[%d] IRQL[%d] %s %I64X [-%09I64d] x%08X x%08X x%08X %I64X", phist[Index].uProcessor, phist[Index].uIRQL, sOp.GetBuffer(), phist[Index].Context, diffInt, phist[Index].lParam2, phist[Index].lParam3, phist[Index].lParam4, phist[Index].pParam1 );
#endif
}
}
void tDumpParser::ParseCrashData(tBugCheckStaticDataHeader *ph, ULONG64 databuffer, ULONG bytesRead)
{
UINT i;
for (i = 0; i < ph->ulMaxContexts; ++i)
{
tBugCheckPerNicDataContent_V0 *pndc = (tBugCheckPerNicDataContent_V0 *)(ph->PerNicData - databuffer + (PUCHAR)ph);
pndc += i;
if (pndc->Context)
{
LONGLONG diffInt = (ph->qCrashTime.QuadPart - pndc->LastInterruptTimeStamp.QuadPart) / 10;
LONGLONG diffTx = (ph->qCrashTime.QuadPart - pndc->LastTxCompletionTimeStamp.QuadPart) / 10;
PRINT("Context %I64X:", pndc->Context);
PRINT("\tLastInterrupt %I64d us before crash", diffInt);
PRINT("\tLast Tx complete %I64d us before crash", diffTx);
PRINT("\tWaiting %d packets, %d free buffers", pndc->nofPacketsToComplete, pndc->nofReadyTxBuffers);
}
}
tBugCheckStaticDataContent_V0 *pd = (tBugCheckStaticDataContent_V0 *)(ph->DataArea - databuffer + (PUCHAR)ph);
tBugCheckHistoryDataEntry *phist = (tBugCheckHistoryDataEntry *)(pd->HistoryData - databuffer + (PUCHAR)ph);
PRINT("History: version %d, %d entries of %d, current at %d", pd->HistoryDataVersion, pd->SizeOfHistory, pd->SizeOfHistoryEntry, pd->CurrentHistoryIndex);
LONG Index = pd->CurrentHistoryIndex % pd->SizeOfHistory;
LONG EndIndex = Index;
ParseHistoryEntry(NULL, NULL, 0);
for (; Index < (LONG)pd->SizeOfHistory; Index++)
{
ParseHistoryEntry(ph->qCrashTime.QuadPart, phist, Index);
}
for (Index = 0; Index < EndIndex; Index++)
{
ParseHistoryEntry(ph->qCrashTime.QuadPart, phist, Index);
}
}
void tDumpParser::FindOurTaggedCrashData()
{
ULONG64 h;
if (S_OK == DataSpaces->StartEnumTagged(&h))
{
UCHAR ourBuffer[16];
ULONG size;
GUID guid;
while (S_OK == DataSpaces->GetNextTagged(h, &guid, &size))
{
WCHAR string[64];
StringFromGUID2(guid, string, sizeof(string)/sizeof(string[0]));
//PRINT("Found %S(size %d)", string, size);
if (IsEqualGUID(ParaNdis_CrashGuid, guid))
{
PRINT("Found NetKVM GUID");
if (S_OK == DataSpaces->ReadTagged(&guid, 0, ourBuffer, size, &size))
{
if (size >= sizeof(tBugCheckDataLocation))
{
tBugCheckDataLocation *bcdl = (tBugCheckDataLocation *)ourBuffer;
PRINT("Found NetKVM data at %I64X, size %d", bcdl->Address, bcdl->Size);
ULONG bufferSize= (ULONG)bcdl->Size;
ULONG bytesRead;
PVOID databuffer = malloc(bufferSize);
if (databuffer)
{
if (S_OK == DataSpaces->ReadVirtual(bcdl->Address, databuffer, bufferSize, &bytesRead))
{
tBugCheckStaticDataHeader *ph = (tBugCheckStaticDataHeader *)databuffer;
PRINT("Retrieved %d bytes of data", bytesRead);
if (bytesRead >= sizeof(tBugCheckStaticDataHeader))
{
PRINT("Versions: status data %d, pre-NIC data %d, ptr size %d, %d contexts, crash time %I64X",
ph->StaticDataVersion, ph->PerNicDataVersion, ph->SizeOfPointer, ph->ulMaxContexts, ph->qCrashTime);
PRINT("Per-NIC data at %I64X, Static data at %I64X(%d bytes)", ph->PerNicData, ph->DataArea, ph->DataAreaSize);
ParseCrashData(ph, bcdl->Address, bytesRead);
}
}
free(databuffer);
}
}
}
break;
}
}
DataSpaces->EndEnumTagged(h);
}
}
static BOOL GetModuleName(ULONG Which, ULONG64 Base, DEBUG_SYMBOLS_IF *DebugSymbols, CString& s)
{
HRESULT hr;
ULONG bufsize = 1024;
char *buf = (char *)malloc(bufsize);
*buf = 0;
hr = DebugSymbols->GetModuleNameString(
Which,
DEBUG_ANY_ID,
Base,
buf,
bufsize,
NULL);
s = buf;
free(buf);
return S_OK == hr;
}
static BOOL TryMatchingSymbols(DEBUG_SYMBOLS_IF *DebugSymbols, PCSTR name)
{
UINT n = 0;
CString s;
s.Format("%s!*", name);
ULONG64 matchHandle;
if (S_OK == DebugSymbols->StartSymbolMatch(s.GetBuffer(), &matchHandle))
{
ULONG size = 1024;
char *buf = (char *)malloc(size);
*buf = 0;
while (S_OK == DebugSymbols->GetNextSymbolMatch(
matchHandle, buf, size, NULL, NULL))
{
n++;
break;
}
DebugSymbols->EndSymbolMatch(matchHandle);
free(buf);
}
return n != 0;
}
void tDumpParser::CheckLoadedSymbols()
{
ULONG index;
ULONG bufferSize = 2048, bufferUsage;
UNREFERENCED_PARAMETER(bufferUsage);
ULONG64 Base;
char *buffer = (char *)malloc(bufferSize);
DEBUG_MODULE_PARAMETERS ModuleParams;
PCSTR name = "netkvm";
HRESULT hr = DebugSymbols->GetModuleByModuleName(name, 0, &index, &Base);
if (S_OK == hr)
{
CString s;
PRINT("Found %s at %I64X", name, Base);
if (GetModuleName(DEBUG_MODNAME_MODULE, Base, DebugSymbols, s))
PRINT("\tModule Name:%s", s.GetBuffer());
if (GetModuleName(DEBUG_MODNAME_IMAGE, Base, DebugSymbols, s))
PRINT("\tImage Name:%s", s.GetBuffer());
if (GetModuleName(DEBUG_MODNAME_SYMBOL_FILE, Base, DebugSymbols, s))
PRINT("\tSymbol file:%s", s.GetBuffer());
#if 0
{
// this does not retrive information, produces error D0000147
hr = DebugSymbols->GetModuleVersionInformation(
index, Base, "\\", buffer, bufferSize, &bufferUsage);
if (S_OK == hr)
{
VS_FIXEDFILEINFO *ffi = (VS_FIXEDFILEINFO *)buffer;
PRINT("File version:%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
}
else
{
CString sError = ErrorToString(hr & 0xffff);
PRINT("Error %08X loading symbols: %s", hr, sError.GetBuffer());
}
// this does not improve clearness of loading
// gives the wrong OK status when the PDB is not loaded
CString sLoadFor = s;
PRINT("Trying to load symbols for %s...", sLoadFor);
hr = DebugSymbols->Reload(sLoadFor);
if (S_OK == hr)
{
PRINT("Symbols for %s loaded successfully", name);
if (GetModuleName(DEBUG_MODNAME_SYMBOL_FILE, Base, DebugSymbols, s))
PRINT("\tSymbol file:%s", s.GetBuffer());
}
else
{
CString sError = ErrorToString(hr);
PRINT("Error %08X loading symbols: %s", hr, sError.GetBuffer());
}
}
#endif
BOOL bLoaded = 0 != TryMatchingSymbols(DebugSymbols, name);
PRINT("Symbols for %s %sLOADED", name, bLoaded ? "" : "NOT ");
if (S_OK == DebugSymbols->GetModuleParameters(1, &Base, 0, &ModuleParams))
{
CString sSymbolType = Parse(ModuleParams.SymbolType, SymbolTypeValues);
CString sFlags = Parse(ModuleParams.Flags, ModuleFlags);
PRINT("Symbol Type %s, Flags %s", sSymbolType.GetBuffer(), sFlags.GetBuffer());
// timestamp from 1.1.1970
__time32_t timestamp = ModuleParams.TimeDateStamp;
tm *timer = _gmtime32(&timestamp);
strftime(buffer, bufferSize, "%d %b %Y %H:%M:%S UTC", timer);
//PRINT("Checksum: %X", ModuleParams.Checksum);
PRINT("Time Stamp: %s(%X)", buffer, ModuleParams.TimeDateStamp);
}
}
free(buffer);
}
void ExtractKernelLog(IDebugDataSpaces3 *DataSpaces)
{
// does not work
ULONG SizeUsed;
ULONG64 KdBufferAddr = 0, KdSizeAddr = 0;
HRESULT hr = DataSpaces->ReadDebuggerData(
DEBUG_DATA_KdPrintCircularBufferPtrAddr,
&KdBufferAddr,
sizeof(KdBufferAddr),
&SizeUsed);
if (S_OK == hr) hr = DataSpaces->ReadDebuggerData(
DEBUG_DATA_KdPrintBufferSizeAddr,
&KdSizeAddr,
sizeof(KdSizeAddr),
&SizeUsed);
if (S_OK == hr) hr = DataSpaces->ReadDebuggerData(
DEBUG_DATA_KdPrintBufferSizeAddr,
&KdSizeAddr,
sizeof(KdSizeAddr),
&SizeUsed);
}
void tDumpParser::ProcessDumpFile()
{
ULONG SymbolOptions;
CString s;
if (S_OK == DebugSymbols->GetSymbolOptions(&SymbolOptions))
{
s = Parse(SymbolOptions, SymbolOptionsFlags);
PRINT("Symbol options %s", s.GetBuffer());
}
s = GetProperty(espSymbolPath);
PRINT("Symbol path:%s", s.GetBuffer());
s = GetProperty(espSystemVersion);
PRINT("System version:%s", s.GetBuffer());
FindOurTaggedCrashData();
CheckLoadedSymbols();
//ExtractKernelLog();
}
CString tDumpParser::GetProperty(eSystemProperty Prop)
{
CString s;
switch (Prop)
{
case espSymbolPath:
if (DebugSymbols)
{
ULONG maxlen = 1024, len;
char *buf = (char *)malloc(maxlen);
*buf = 0;
DebugSymbols->GetSymbolPath(buf, maxlen, &len);
s = buf;
free(buf);
}
break;
case espSystemVersion:
if (Control)
{
ULONG platform, major, minor, sp, buildsize = 128, buildused, procs = 0;
char *buf = (char *)malloc(buildsize);
*buf = 0;
BOOL Is64 = Control->IsPointer64Bit() == S_OK;
CString sSP;
Control->GetNumberProcessors(&procs);
Control->GetSystemVersion(&platform, &major, &minor, NULL, 0, NULL, &sp, buf, buildsize, &buildused);
if (sp) sSP.Format("(SP%d.%d)", sp >> 8, sp & 0xff);
s.Format("(%X)%d%s%s,%s,%d CPU",
major, minor, sSP.GetBuffer(), Is64 ? "(64-bit)" : "", buf, procs);
free(buf);
}
break;
default:
break;
}
return s;
}
int ParseDumpFile(int argc, TCHAR* argv[])
{
if (1)
{
tDumpParser Parser;
if (argc == 2)
{
if (!Parser.LoadFile(argv[1])) PRINT("Failed to load dump file %s", argv[1]);
}
}
else
{
PRINT("%s", SessionStatusValues[0].name);
}
return 0;
}