aboutsummaryrefslogtreecommitdiff
path: root/src/common/Debugging
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/Debugging')
-rw-r--r--src/common/Debugging/Errors.cpp63
-rw-r--r--src/common/Debugging/Errors.h46
-rw-r--r--src/common/Debugging/Windows/WheatyExceptionReport.cpp16
3 files changed, 67 insertions, 58 deletions
diff --git a/src/common/Debugging/Errors.cpp b/src/common/Debugging/Errors.cpp
index 162b613e12e..c333aa24ec0 100644
--- a/src/common/Debugging/Errors.cpp
+++ b/src/common/Debugging/Errors.cpp
@@ -17,10 +17,10 @@
#include "Errors.h"
#include "StringFormat.h"
-#include <cstdio>
-#include <cstdlib>
#include <thread>
#include <cstdarg>
+#include <cstdio>
+#include <cstring>
/**
@file Errors.cpp
@@ -33,73 +33,84 @@
terminates the application.
*/
+#if TRINITY_COMPILER == TRINITY_COMPILER_MICROSOFT
+#define Unreachable() (__assume(false))
+#else
+#define Unreachable() (__builtin_unreachable())
+#endif
+
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
#include <Windows.h>
#include <intrin.h>
#define Crash(message) \
ULONG_PTR execeptionArgs[] = { reinterpret_cast<ULONG_PTR>(strdup(message)), reinterpret_cast<ULONG_PTR>(_ReturnAddress()) }; \
- RaiseException(EXCEPTION_ASSERTION_FAILURE, 0, 2, execeptionArgs);
+ RaiseException(EXCEPTION_ASSERTION_FAILURE, 0, 2, execeptionArgs); \
+ Unreachable()
#else
-#include <cstring>
// should be easily accessible in gdb
extern "C" { TC_COMMON_API char const* TrinityAssertionFailedMessage = nullptr; }
#define Crash(message) \
TrinityAssertionFailedMessage = strdup(message); \
*((volatile int*)nullptr) = 0; \
- exit(1);
+ Unreachable()
#endif
namespace
{
- std::string FormatAssertionMessage(char const* format, va_list args)
+ void FormatAssertionMessageTo(std::string& formatted, char const* format, va_list args) noexcept
{
- std::string formatted;
va_list len;
va_copy(len, args);
int32 length = vsnprintf(nullptr, 0, format, len);
va_end(len);
- formatted.resize(length);
- vsnprintf(&formatted[0], length + 1, format, args);
-
- return formatted;
+ std::size_t offset = formatted.length();
+ formatted.resize(offset + length);
+ vsnprintf(&formatted[offset], length + 1, format, args);
}
}
namespace Trinity
{
-
-void Assert(char const* file, int line, char const* function, std::string debugInfo, char const* message)
+void Assert(char const* file, int line, char const* function, char const* message, std::string debugInfo) noexcept
{
- std::string formattedMessage = StringFormat("\n{}:{} in {} ASSERTION FAILED:\n {}\n", file, line, function, message) + debugInfo + '\n';
+ std::string formattedMessage = StringFormat("\n{}:{} in {} ASSERTION FAILED:\n {}\n{}\n", file, line, function, message, debugInfo);
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
Crash(formattedMessage.c_str());
}
-void Assert(char const* file, int line, char const* function, std::string debugInfo, char const* message, char const* format, ...)
+void Assert(char const* file, int line, char const* function, char const* message, std::string debugInfo, char const* format, ...) noexcept
{
va_list args;
va_start(args, format);
- std::string formattedMessage = StringFormat("\n{}:{} in {} ASSERTION FAILED:\n {}\n", file, line, function, message) + FormatAssertionMessage(format, args) + '\n' + debugInfo + '\n';
+ std::string formattedMessage = StringFormat("\n{}:{} in {} ASSERTION FAILED:\n {}\n", file, line, function, message);
+ FormatAssertionMessageTo(formattedMessage, format, args);
va_end(args);
+ formattedMessage.append(1, '\n');
+ formattedMessage.append(debugInfo);
+ formattedMessage.append(1, '\n');
+
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
Crash(formattedMessage.c_str());
}
-void Fatal(char const* file, int line, char const* function, char const* message, ...)
+void Fatal(char const* file, int line, char const* function, char const* message, ...) noexcept
{
va_list args;
va_start(args, message);
- std::string formattedMessage = StringFormat("\n{}:{} in {} FATAL ERROR:\n", file, line, function) + FormatAssertionMessage(message, args) + '\n';
+ std::string formattedMessage = StringFormat("\n{}:{} in {} FATAL ERROR:\n", file, line, function);
+ FormatAssertionMessageTo(formattedMessage, message, args);
va_end(args);
+ formattedMessage.append(1, '\n');
+
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
@@ -107,7 +118,7 @@ void Fatal(char const* file, int line, char const* function, char const* message
Crash(formattedMessage.c_str());
}
-void Error(char const* file, int line, char const* function, char const* message)
+void Error(char const* file, int line, char const* function, char const* message) noexcept
{
std::string formattedMessage = StringFormat("\n{}:{} in {} ERROR:\n {}\n", file, line, function, message);
fprintf(stderr, "%s", formattedMessage.c_str());
@@ -115,13 +126,13 @@ void Error(char const* file, int line, char const* function, char const* message
Crash(formattedMessage.c_str());
}
-void Warning(char const* file, int line, char const* function, char const* message)
+void Warning(char const* file, int line, char const* function, char const* message) noexcept
{
fprintf(stderr, "\n%s:%i in %s WARNING:\n %s\n",
file, line, function, message);
}
-void Abort(char const* file, int line, char const* function)
+void Abort(char const* file, int line, char const* function) noexcept
{
std::string formattedMessage = StringFormat("\n{}:{} in {} ABORTED.\n", file, line, function);
fprintf(stderr, "%s", formattedMessage.c_str());
@@ -129,21 +140,24 @@ void Abort(char const* file, int line, char const* function)
Crash(formattedMessage.c_str());
}
-void Abort(char const* file, int line, char const* function, char const* message, ...)
+void Abort(char const* file, int line, char const* function, char const* message, ...) noexcept
{
va_list args;
va_start(args, message);
- std::string formattedMessage = StringFormat("\n{}:{} in {} ABORTED:\n", file, line, function) + FormatAssertionMessage(message, args) + '\n';
+ std::string formattedMessage = StringFormat("\n{}:{} in {} ABORTED:\n", file, line, function);
+ FormatAssertionMessageTo(formattedMessage, message, args);
va_end(args);
+ formattedMessage.append(1, '\n');
+
fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr);
Crash(formattedMessage.c_str());
}
-void AbortHandler(int sigval)
+void AbortHandler(int sigval) noexcept
{
// nothing useful to log here, no way to pass args
std::string formattedMessage = StringFormat("Caught signal {}\n", sigval);
@@ -151,7 +165,6 @@ void AbortHandler(int sigval)
fflush(stderr);
Crash(formattedMessage.c_str());
}
-
} // namespace Trinity
std::string GetDebugInfo()
diff --git a/src/common/Debugging/Errors.h b/src/common/Debugging/Errors.h
index 8cceacf7e71..913b4898b4f 100644
--- a/src/common/Debugging/Errors.h
+++ b/src/common/Debugging/Errors.h
@@ -21,25 +21,36 @@
#include "Define.h"
#include <string>
+TC_COMMON_API std::string GetDebugInfo();
+
namespace Trinity
{
- [[noreturn]] TC_COMMON_API void Assert(char const* file, int line, char const* function, std::string debugInfo, char const* message);
- [[noreturn]] TC_COMMON_API void Assert(char const* file, int line, char const* function, std::string debugInfo, char const* message, char const* format, ...) ATTR_PRINTF(6, 7);
+ [[noreturn]] TC_COMMON_API void Assert(char const* file, int line, char const* function, char const* message, std::string debugInfo) noexcept;
+ [[noreturn]] TC_COMMON_API void Assert(char const* file, int line, char const* function, char const* message, std::string debugInfo, char const* format, ...) noexcept ATTR_PRINTF(6, 7);
- [[noreturn]] TC_COMMON_API void Fatal(char const* file, int line, char const* function, char const* message, ...) ATTR_PRINTF(4, 5);
+ [[noreturn]] TC_COMMON_API void Fatal(char const* file, int line, char const* function, char const* message, ...) noexcept ATTR_PRINTF(4, 5);
- [[noreturn]] TC_COMMON_API void Error(char const* file, int line, char const* function, char const* message);
+ [[noreturn]] TC_COMMON_API void Error(char const* file, int line, char const* function, char const* message) noexcept;
- [[noreturn]] TC_COMMON_API void Abort(char const* file, int line, char const* function);
- [[noreturn]] TC_COMMON_API void Abort(char const* file, int line, char const* function, char const* message, ...);
+ [[noreturn]] TC_COMMON_API void Abort(char const* file, int line, char const* function) noexcept;
+ [[noreturn]] TC_COMMON_API void Abort(char const* file, int line, char const* function, char const* message, ...) noexcept;
- TC_COMMON_API void Warning(char const* file, int line, char const* function, char const* message);
+ TC_COMMON_API void Warning(char const* file, int line, char const* function, char const* message) noexcept;
- [[noreturn]] TC_COMMON_API void AbortHandler(int sigval);
+ [[noreturn]] TC_COMMON_API void AbortHandler(int sigval) noexcept;
-} // namespace Trinity
+ namespace Impl
+ {
+ template <typename T>
+ inline T* AssertNotNull(T* pointer, char const* file, int line, char const* function, char const* message) noexcept
+ {
+ if (pointer) [[likely]]
+ return pointer;
-TC_COMMON_API std::string GetDebugInfo();
+ Assert(file, line, function, message, ::GetDebugInfo());
+ }
+ }
+} // namespace Trinity
#if TRINITY_COMPILER == TRINITY_COMPILER_MICROSOFT
#define ASSERT_BEGIN __pragma(warning(push)) __pragma(warning(disable: 4127))
@@ -53,8 +64,8 @@ TC_COMMON_API std::string GetDebugInfo();
#define EXCEPTION_ASSERTION_FAILURE 0xC0000420L
#endif
-#define WPAssert(cond, ...) ASSERT_BEGIN do { if (!(cond)) [[unlikely]] Trinity::Assert(__FILE__, __LINE__, __FUNCTION__, GetDebugInfo(), #cond, ##__VA_ARGS__); } while(0) ASSERT_END
-#define WPAssert_NODEBUGINFO(cond, ...) ASSERT_BEGIN do { if (!(cond)) [[unlikely]] Trinity::Assert(__FILE__, __LINE__, __FUNCTION__, "", #cond, ##__VA_ARGS__); } while(0) ASSERT_END
+#define WPAssert(cond, ...) ASSERT_BEGIN do { if (!(cond)) [[unlikely]] Trinity::Assert(__FILE__, __LINE__, __FUNCTION__, #cond, GetDebugInfo(), ##__VA_ARGS__); } while(0) ASSERT_END
+#define WPAssert_NODEBUGINFO(cond, ...) ASSERT_BEGIN do { if (!(cond)) [[unlikely]] Trinity::Assert(__FILE__, __LINE__, __FUNCTION__, #cond, ::GetDebugInfo(), ##__VA_ARGS__); } while(0) ASSERT_END
#define WPFatal(cond, ...) ASSERT_BEGIN do { if (!(cond)) [[unlikely]] Trinity::Fatal(__FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); } while(0) ASSERT_END
#define WPError(cond, msg) ASSERT_BEGIN do { if (!(cond)) [[unlikely]] Trinity::Error(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END
#define WPWarning(cond, msg) ASSERT_BEGIN do { if (!(cond)) [[unlikely]] Trinity::Warning(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END
@@ -64,9 +75,11 @@ TC_COMMON_API std::string GetDebugInfo();
#ifdef PERFORMANCE_PROFILING
#define ASSERT(cond, ...) ((void)0)
#define ASSERT_NODEBUGINFO(cond, ...) ((void)0)
+#define ASSERT_NOTNULL(pointer) (pointer)
#else
#define ASSERT WPAssert
#define ASSERT_NODEBUGINFO WPAssert_NODEBUGINFO
+#define ASSERT_NOTNULL(pointer) Trinity::Impl::AssertNotNull(pointer, __FILE__, __LINE__, __FUNCTION__, #pointer)
#endif
#define ASSERT_WITH_SIDE_EFFECTS WPAssert
@@ -74,13 +87,4 @@ TC_COMMON_API std::string GetDebugInfo();
#define ABORT WPAbort
#define ABORT_MSG WPAbort_MSG
-template <typename T>
-inline T* ASSERT_NOTNULL_IMPL(T* pointer, char const* expr)
-{
- ASSERT(pointer, "%s", expr);
- return pointer;
-}
-
-#define ASSERT_NOTNULL(pointer) ASSERT_NOTNULL_IMPL(pointer, #pointer)
-
#endif
diff --git a/src/common/Debugging/Windows/WheatyExceptionReport.cpp b/src/common/Debugging/Windows/WheatyExceptionReport.cpp
index fd233317268..0c2cf42a682 100644
--- a/src/common/Debugging/Windows/WheatyExceptionReport.cpp
+++ b/src/common/Debugging/Windows/WheatyExceptionReport.cpp
@@ -1824,7 +1824,7 @@ size_t countOverride)
if (basicType == btFloat)
pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "%f", *(PFLOAT)pAddress);
else
- pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%X", *(PDWORD)pAddress);
+ pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%lX", *(PDWORD)pAddress);
}
else if (length == 8)
{
@@ -1834,27 +1834,19 @@ size_t countOverride)
*(double *)pAddress);
}
else
- pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%I64X",
+ pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%llX",
*(DWORD64*)pAddress);
}
else
{
- #if _WIN64
- pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%I64X", (DWORD64)pAddress);
- #else
- pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%X", (DWORD)pAddress);
- #endif
+ pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "%p", pAddress);
}
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
-#if _WIN64
- pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%I64X <Unable to read memory>", (DWORD64)pAddress);
-#else
- pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "0x%X <Unable to read memory>", (DWORD)pAddress);
-#endif
+ pszCurrBuffer += snprintf(pszCurrBuffer, bufferSize, "%p <Unable to read memory>", pAddress);
}
}