Core/CrashHandler: Add more informations about locals

Handle SymTagData with inner type of SymTagPointerType.
Increase buffer sizes to avoid buffer overflows.
Avoid infinite loops by logging the children of each type only once.
Avoid too deep nesting by adding a max nesting level.
Print the address for arrays instead of just the name.
This commit is contained in:
jackpoz
2014-02-06 22:07:12 +01:00
parent b000fdca70
commit 20a1f4d28e
2 changed files with 79 additions and 8 deletions

View File

@@ -51,6 +51,7 @@ LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter;
HANDLE WheatyExceptionReport::m_hReportFile;
HANDLE WheatyExceptionReport::m_hDumpFile;
HANDLE WheatyExceptionReport::m_hProcess;
SymbolPairs WheatyExceptionReport::symbols;
// Declare global instance of class
WheatyExceptionReport g_WheatyExceptionReport;
@@ -78,6 +79,7 @@ WheatyExceptionReport::~WheatyExceptionReport()
{
if (m_previousFilter)
SetUnhandledExceptionFilter(m_previousFilter);
ClearSymbols();
}
//===========================================================
@@ -498,12 +500,12 @@ PEXCEPTION_POINTERS pExceptionInfo)
WriteStackDetails(&trashableContext, true, NULL);
printTracesForAllThreads(true);
_tprintf(_T("========================\r\n"));
/*_tprintf(_T("========================\r\n"));
_tprintf(_T("Global Variables\r\n"));
SymEnumSymbols(GetCurrentProcess(),
(UINT_PTR)GetModuleHandle(szFaultingModule),
0, EnumerateSymbolsCallback, 0);
0, EnumerateSymbolsCallback, 0);*/
// #endif // X86 Only!
SymCleanup(GetCurrentProcess());
@@ -757,10 +759,11 @@ ULONG /*SymbolSize*/,
PVOID UserContext)
{
char szBuffer[8192];
char szBuffer[1024 * 64];
__try
{
ClearSymbols();
if (FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext,
szBuffer, sizeof(szBuffer)))
_tprintf(_T("\t%s\r\n"), szBuffer);
@@ -862,6 +865,9 @@ char* suffix)
{
bHandled = false;
if (!StoreSymbol(dwTypeIndex, offset))
return pszCurrBuffer;
DWORD typeTag;
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag))
return pszCurrBuffer;
@@ -879,12 +885,16 @@ char* suffix)
if (strlen(suffix) > 0)
pszCurrBuffer += sprintf(pszCurrBuffer, "%s", suffix);
DWORD innerTypeID;
switch (typeTag)
{
case SymTagPointerType:
DWORD innerTypeID;
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
{
#define MAX_NESTING_LEVEL 5
if (nestingLevel >= MAX_NESTING_LEVEL)
break;
pszCurrBuffer += sprintf(pszCurrBuffer, " %s", Name);
BOOL isReference;
SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_IS_REFERENCE, &isReference);
@@ -908,7 +918,7 @@ char* suffix)
LocalFree(pwszTypeName);
}
pszCurrBuffer += sprintf(pszCurrBuffer, "%s = NULL", addressStr);
pszCurrBuffer += sprintf(pszCurrBuffer, "%s = NULL\r\n", addressStr);
bHandled = true;
return pszCurrBuffer;
@@ -921,6 +931,26 @@ char* suffix)
}
}
break;
case SymTagData:
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
{
DWORD innerTypeTag;
if (!SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMTAG, &innerTypeTag))
break;
if (innerTypeTag == SymTagPointerType)
{
pszCurrBuffer += sprintf(pszCurrBuffer, " %s", Name);
pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1,
offset, bHandled, "", "");
}
}
break;
case SymTagBaseType:
break;
case SymTagEnum:
return pszCurrBuffer;
default:
break;
}
@@ -937,7 +967,7 @@ char* suffix)
// TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this.
struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS
{
ULONG MoreChildIds[1024];
ULONG MoreChildIds[1024*2];
FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);}
} children;
@@ -1058,6 +1088,14 @@ PVOID pAddress)
pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X",
*(DWORD64*)pAddress);
}
else
{
#if _WIN64
pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", (DWORD64*)pAddress);
#else
pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", (PDWORD)pAddress);
#endif
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
@@ -1102,7 +1140,7 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase)
//============================================================================
int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
{
TCHAR szBuff[8192];
TCHAR szBuff[1024 * 64];
int retValue;
DWORD cbWritten;
va_list argptr;
@@ -1116,4 +1154,14 @@ int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
return retValue;
}
bool WheatyExceptionReport::StoreSymbol(DWORD type, DWORD_PTR offset)
{
return symbols.insert(SymbolPair(type, offset)).second;
}
void WheatyExceptionReport::ClearSymbols()
{
symbols.clear();
}
#endif // _WIN32

View File

@@ -4,7 +4,7 @@
#if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__)
#include <dbghelp.h>
#include <set>
#if _MSC_VER < 1400
# define countof(array) (sizeof(array) / sizeof(array[0]))
#else
@@ -70,6 +70,25 @@ const char* const rgBaseType[] =
" HRESULT " // btHresult = 31
};
struct SymbolPair
{
SymbolPair(DWORD type, DWORD_PTR offset)
{
_type = type;
_offset = offset;
}
bool operator<(const SymbolPair& other) const
{
return _offset < other._offset ||
(_offset == other._offset && _type < other._type);
}
DWORD _type;
DWORD_PTR _offset;
};
typedef std::set<SymbolPair> SymbolPairs;
class WheatyExceptionReport
{
public:
@@ -108,6 +127,9 @@ class WheatyExceptionReport
static int __cdecl _tprintf(const TCHAR * format, ...);
static bool StoreSymbol(DWORD type , DWORD_PTR offset);
static void ClearSymbols();
// Variables used by the class
static TCHAR m_szLogFileName[MAX_PATH];
static TCHAR m_szDumpFileName[MAX_PATH];
@@ -115,6 +137,7 @@ class WheatyExceptionReport
static HANDLE m_hReportFile;
static HANDLE m_hDumpFile;
static HANDLE m_hProcess;
static SymbolPairs symbols;
};
extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class