aboutsummaryrefslogtreecommitdiff
path: root/src/common/Debugging/WheatyExceptionReport.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/Debugging/WheatyExceptionReport.h')
-rw-r--r--src/common/Debugging/WheatyExceptionReport.h210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/common/Debugging/WheatyExceptionReport.h b/src/common/Debugging/WheatyExceptionReport.h
new file mode 100644
index 00000000000..8c2479d5232
--- /dev/null
+++ b/src/common/Debugging/WheatyExceptionReport.h
@@ -0,0 +1,210 @@
+#ifndef _WHEATYEXCEPTIONREPORT_
+#define _WHEATYEXCEPTIONREPORT_
+
+#if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__)
+
+#include <dbghelp.h>
+#include <set>
+#include <stdlib.h>
+#include <stack>
+#include <mutex>
+#define countof _countof
+
+#define WER_MAX_ARRAY_ELEMENTS_COUNT 10
+#define WER_MAX_NESTING_LEVEL 5
+#define WER_LARGE_BUFFER_SIZE 1024 * 128
+
+enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK
+{
+ btNoType = 0,
+ btVoid = 1,
+ btChar = 2,
+ btWChar = 3,
+ btInt = 6,
+ btUInt = 7,
+ btFloat = 8,
+ btBCD = 9,
+ btBool = 10,
+ btLong = 13,
+ btULong = 14,
+ btCurrency = 25,
+ btDate = 26,
+ btVariant = 27,
+ btComplex = 28,
+ btBit = 29,
+ btBSTR = 30,
+ btHresult = 31,
+
+ // Custom types
+ btStdString = 101
+};
+
+enum DataKind // Stolen from CVCONST.H in the DIA 2.0 SDK
+{
+ DataIsUnknown,
+ DataIsLocal,
+ DataIsStaticLocal,
+ DataIsParam,
+ DataIsObjectPtr,
+ DataIsFileStatic,
+ DataIsGlobal,
+ DataIsMember,
+ DataIsStaticMember,
+ DataIsConstant
+};
+
+const char* const rgBaseType[] =
+{
+ "<user defined>", // btNoType = 0,
+ "void", // btVoid = 1,
+ "char",//char* // btChar = 2,
+ "wchar_t*", // btWChar = 3,
+ "signed char",
+ "unsigned char",
+ "int", // btInt = 6,
+ "unsigned int", // btUInt = 7,
+ "float", // btFloat = 8,
+ "<BCD>", // btBCD = 9,
+ "bool", // btBool = 10,
+ "short",
+ "unsigned short",
+ "long", // btLong = 13,
+ "unsigned long", // btULong = 14,
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "int128",
+ "uint8",
+ "uint16",
+ "uint32",
+ "uint64",
+ "uint128",
+ "<currency>", // btCurrency = 25,
+ "<date>", // btDate = 26,
+ "VARIANT", // btVariant = 27,
+ "<complex>", // btComplex = 28,
+ "<bit>", // btBit = 29,
+ "BSTR", // btBSTR = 30,
+ "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;
+
+struct SymbolDetail
+{
+ SymbolDetail() : Prefix(), Type(), Suffix(), Name(), Value(), Logged(false), HasChildren(false) {}
+
+ std::string ToString()
+ {
+ Logged = true;
+ std::string formatted = Prefix + Type + Suffix;
+ if (!Name.empty())
+ {
+ if (!formatted.empty())
+ formatted += " ";
+ formatted += Name;
+ }
+ if (!Value.empty())
+ formatted += " = " + Value;
+ return formatted;
+ }
+
+ bool empty() const
+ {
+ return Value.empty() && !HasChildren;
+ }
+
+ std::string Prefix;
+ std::string Type;
+ std::string Suffix;
+ std::string Name;
+ std::string Value;
+ bool Logged;
+ bool HasChildren;
+};
+
+class WheatyExceptionReport
+{
+ public:
+
+ WheatyExceptionReport();
+ ~WheatyExceptionReport();
+
+ // entry point where control comes on an unhandled exception
+ static LONG WINAPI WheatyUnhandledExceptionFilter(
+ PEXCEPTION_POINTERS pExceptionInfo);
+
+ static void printTracesForAllThreads(bool);
+ private:
+ // where report info is extracted and generated
+ static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo);
+ static void PrintSystemInfo();
+ static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
+ static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
+
+ // Helper functions
+ static LPTSTR GetExceptionString(DWORD dwCode);
+ static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len,
+ DWORD& section, DWORD_PTR& offset);
+
+ static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
+
+ static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID);
+
+ static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *, char * pszBuffer, unsigned cbBuffer);
+
+ static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, const char*, char*, bool, bool);
+
+ static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0);
+
+ static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
+ static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
+
+ static int __cdecl _tprintf(const TCHAR * format, ...);
+ static int __cdecl stackprintf(const TCHAR * format, va_list argptr);
+ static int __cdecl heapprintf(const TCHAR * format, va_list argptr);
+
+ 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];
+ static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
+ static HANDLE m_hReportFile;
+ static HANDLE m_hDumpFile;
+ static HANDLE m_hProcess;
+ static SymbolPairs symbols;
+ static std::stack<SymbolDetail> symbolDetails;
+ static bool stackOverflowException;
+ static bool alreadyCrashed;
+ static std::mutex alreadyCrashedLock;
+
+ static char* PushSymbolDetail(char* pszCurrBuffer);
+ static char* PopSymbolDetail(char* pszCurrBuffer);
+ static char* PrintSymbolDetail(char* pszCurrBuffer);
+
+};
+
+extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class
+#endif // _WIN32
+#endif // _WHEATYEXCEPTIONREPORT_
+