diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/Debugging/Errors.cpp | 63 | ||||
| -rw-r--r-- | src/common/Debugging/Errors.h | 46 | ||||
| -rw-r--r-- | src/common/Debugging/Windows/WheatyExceptionReport.cpp | 16 |
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); } } |
