TrinityCore
Loading...
Searching...
No Matches
WheatyExceptionReport.h
Go to the documentation of this file.
1#ifndef _WHEATYEXCEPTIONREPORT_
2#define _WHEATYEXCEPTIONREPORT_
3
4#define _NO_CVCONST_H
5
6#include "Define.h"
7#include "Optional.h"
8#include <Windows.h>
9#include <dbghelp.h>
10#include <winnt.h>
11#include <winternl.h>
12#include <compare>
13#include <set>
14#include <stack>
15#include <string>
16#include <cstdio>
17#include <cstdlib>
18
19#define WER_MAX_ARRAY_ELEMENTS_COUNT 10
20#define WER_MAX_NESTING_LEVEL 4
21#define WER_SMALL_BUFFER_SIZE 1024
22#define WER_LARGE_BUFFER_SIZE WER_SMALL_BUFFER_SIZE * 16
23
24enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK
25{
27 btVoid = 1,
28 btChar = 2,
30 btInt = 6,
31 btUInt = 7,
33 btBCD = 9,
34 btBool = 10,
35 btLong = 13,
36 btULong = 14,
38 btDate = 26,
41 btBit = 29,
42 btBSTR = 30,
44
45 // Custom types
46 btStdString = 101
47};
48
62
63enum CpuRegister // Stolen from CVCONST.H in the DIA SDK
64{
66
67 //
68 // Register set for the Intel 80x86 and ix86 processor series
69 //
96
97 //
98 // AMD64 registers
99 //
125
126 // Low byte forms of some standard registers
131
132 // 64-bit regular registers
141
142 // 64-bit integer registers with 8-, 16-, and 32-bit forms (B, W, and D)
151
160
169
178
179 //
180 // Register set for ARM64
181 //
183
184 // General purpose 32-bit integer registers
217
218 // General purpose 64-bit integer registers
252};
253
254char const* const rgBaseType[] =
255{
256 "<user defined>", // btNoType = 0,
257 "void", // btVoid = 1,
258 "char",//char* // btChar = 2,
259 "wchar_t*", // btWChar = 3,
260 "signed char",
261 "unsigned char",
262 "int", // btInt = 6,
263 "unsigned int", // btUInt = 7,
264 "float", // btFloat = 8,
265 "<BCD>", // btBCD = 9,
266 "bool", // btBool = 10,
267 "short",
268 "unsigned short",
269 "long", // btLong = 13,
270 "unsigned long", // btULong = 14,
271 "int8",
272 "int16",
273 "int32",
274 "int64",
275 "int128",
276 "uint8",
277 "uint16",
278 "uint32",
279 "uint64",
280 "uint128",
281 "<currency>", // btCurrency = 25,
282 "<date>", // btDate = 26,
283 "VARIANT", // btVariant = 27,
284 "<complex>", // btComplex = 28,
285 "<bit>", // btBit = 29,
286 "BSTR", // btBSTR = 30,
287 "HRESULT" // btHresult = 31
288};
289
291{
292 SymbolPair(DWORD type, DWORD_PTR offset)
293 {
294 _type = type;
295 _offset = offset;
296 }
297
298 bool operator==(SymbolPair const& other) const = default;
299 std::strong_ordering operator<=>(SymbolPair const& other) const = default;
300
301 DWORD _type;
302 DWORD_PTR _offset;
303};
304typedef std::set<SymbolPair> SymbolPairs;
305
307{
308 SymbolDetail() : Prefix(), Type(), Suffix(), Name(), Value(), Logged(false), HasChildren(false) {}
309
310 bool empty() const
311 {
312 return Value.empty() && !HasChildren;
313 }
314
315 std::string Prefix;
316 std::string Type;
317 std::string Suffix;
318 std::string Name;
319 std::string Value;
320 bool Logged;
322};
323
325{
326 public:
327
334
335 // entry point where control comes on an unhandled exception
336 static LONG WINAPI WheatyUnhandledExceptionFilter(
337 PEXCEPTION_POINTERS pExceptionInfo);
338
339 LONG UnhandledExceptionFilterImpl(PEXCEPTION_POINTERS pExceptionInfo) noexcept;
340
341 static void __cdecl WheatyCrtHandler(wchar_t const* expression, wchar_t const* function, wchar_t const* file, unsigned int line, uintptr_t pReserved);
342
343 void printTracesForAllThreads(bool bWriteVariables);
344 private:
345 // where report info is extracted and generated
346 void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo);
347 void PrintSystemInfo();
348 BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
349 static BOOL _GetWindowsVersionFromWMI(TCHAR* szVersion, DWORD cntMax) noexcept;
350 static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
351
352 // Helper functions
353 static LPCTSTR GetExceptionString(DWORD dwCode);
354 static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len,
355 DWORD& section, DWORD_PTR& offset);
356
357 void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
358
359 static BOOL GetSymbolFromAddress(HANDLE hProcess, DWORD64 Address, ULONG InlineContext, PDWORD64 Displacement, PSYMBOL_INFO Symbol);
360 static BOOL GetSymbolLineFromAddress(HANDLE hProcess, DWORD64 qwAddr, ULONG InlineContext, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line64);
361
368
369 static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID);
370
371 bool FormatSymbolValue(PSYMBOL_INFO, EnumerateSymbolsCallbackContext*);
372
373 void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool &, char const*, char const*, bool, bool);
374
375 static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0);
376
377 BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase) const;
378 static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
379
380 int Log(const TCHAR * format, ...);
381
382 bool StoreSymbol(DWORD type , DWORD_PTR offset);
383 void ClearSymbols();
384
385 static Optional<DWORD_PTR> GetIntegerRegisterValue(PCONTEXT context, ULONG registerId);
386
387 // Variables used by the class
389 static constexpr SIZE_T m_tempPathBufferChars = 0x8000;
390 LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
391 _invalid_parameter_handler m_previousCrtHandler;
394 HANDLE m_process;
396 std::stack<SymbolDetail> m_symbolDetails;
399 typedef NTSTATUS(NTAPI* pRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
400 pRtlGetVersion RtlGetVersion;
401
402 SymbolDetail& PushSymbolDetail();
403 void PopSymbolDetail();
404 void PrintSymbolDetail();
405};
406
407#define INIT_CRASH_HANDLER() \
408 __pragma(warning(push)) \
409 __pragma(warning(disable:4073)) /* C4073: initializers put in library initialization area */ \
410 __pragma(init_seg(lib)) \
411 WheatyExceptionReport g_WheatyExceptionReport; \
412 __pragma(warning(pop))
413
414#endif // _WHEATYEXCEPTIONREPORT_
#define TC_COMMON_API
Definition Define.h:99
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
const size_t bufferSize
Definition RASession.h:28
char const *const rgBaseType[]
std::set< SymbolPair > SymbolPairs
@ CV_ALLREG_VFRAME
@ DataIsUnknown
@ DataIsStaticMember
@ DataIsStaticLocal
@ DataIsObjectPtr
@ DataIsConstant
@ DataIsFileStatic
Definition Log.h:52
WheatyExceptionReport(WheatyExceptionReport &&)=delete
WheatyExceptionReport(WheatyExceptionReport const &)=delete
LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter
_invalid_parameter_handler m_previousCrtHandler
WheatyExceptionReport & operator=(WheatyExceptionReport const &)=delete
WheatyExceptionReport & operator=(WheatyExceptionReport &&)=delete
std::stack< SymbolDetail > m_symbolDetails
std::strong_ordering operator<=>(SymbolPair const &other) const =default
bool operator==(SymbolPair const &other) const =default
SymbolPair(DWORD type, DWORD_PTR offset)