diff --git a/dCommon/CMakeLists.txt b/dCommon/CMakeLists.txt index 2517c048..8092ec76 100644 --- a/dCommon/CMakeLists.txt +++ b/dCommon/CMakeLists.txt @@ -12,7 +12,7 @@ set(DCOMMON_SOURCES "NiPoint3.cpp" "NiQuaternion.cpp" "SHA512.cpp" - "Type.cpp" + "Demangler.cpp" "ZCompression.cpp" "BrickByBrickFix.cpp" "BinaryPathFinder.cpp" diff --git a/dCommon/Demangler.cpp b/dCommon/Demangler.cpp new file mode 100644 index 00000000..61232169 --- /dev/null +++ b/dCommon/Demangler.cpp @@ -0,0 +1,29 @@ +#include "Demangler.h" +#ifdef __GNUG__ +#include +#include +#include +#include + +std::string Demangler::Demangle(const char* name) { + // some arbitrary value to eliminate the compiler warning + // -4 is not a valid return value for __cxa_demangle so we'll use that. + int status = -4; + + // __cxa_demangle requires that we free the returned char* + std::unique_ptr res{ + abi::__cxa_demangle(name, NULL, NULL, &status), + std::free + }; + + return (status == 0) ? res.get() : ""; +} + +#else // __GNUG__ + +// does nothing if not g++ +std::string Demangler::Demangle(const char* name) { + return name; +} + +#endif // __GNUG__ diff --git a/dCommon/Demangler.h b/dCommon/Demangler.h new file mode 100644 index 00000000..84d66b40 --- /dev/null +++ b/dCommon/Demangler.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace Demangler { + // Given a char* containing a mangled name, return a std::string containing the demangled name. + // If the function fails for any reason, it returns an empty string. + std::string Demangle(const char* name); +} diff --git a/dCommon/Diagnostics.cpp b/dCommon/Diagnostics.cpp index 58d558de..f6c4b4b9 100644 --- a/dCommon/Diagnostics.cpp +++ b/dCommon/Diagnostics.cpp @@ -107,7 +107,7 @@ static void ErrorCallback(void* data, const char* msg, int errnum) { } #endif -#include "Type.h" +#include "Demangler.h" void GenerateDump() { std::string cmd = "sudo gcore " + std::to_string(getpid()); @@ -122,41 +122,43 @@ void CatchUnhandled(int sig) { if (Diagnostics::GetProduceMemoryDump()) { GenerateDump(); } - - void* array[10]; + constexpr uint8_t MaxStackTrace = 32; + void* array[MaxStackTrace]; size_t size; // get void*'s for all entries on the stack - size = backtrace(array, 10); + size = backtrace(array, MaxStackTrace); -#if defined(__GNUG__) and defined(__dynamic) +# if defined(__GNUG__) // Loop through the returned addresses, and get the symbols to be demangled char** strings = backtrace_symbols(array, size); // Print the stack trace for (size_t i = 0; i < size; i++) { - // Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]' and extract the function name + // Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]' + // and extract '_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress' from it to be demangled into a proper name std::string functionName = strings[i]; std::string::size_type start = functionName.find('('); std::string::size_type end = functionName.find('+'); if (start != std::string::npos && end != std::string::npos) { std::string demangled = functionName.substr(start + 1, end - start - 1); - demangled = demangle(functionName.c_str()); + demangled = Demangler::Demangle(demangled.c_str()); - if (demangled.empty()) { - Game::logger->Log("Diagnostics", "[%02zu] %s", i, demangled.c_str()); - } else { - Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str()); + // If the demangled string is not empty, then we can replace the mangled string with the demangled one + if (!demangled.empty()) { + demangled.push_back('('); + demangled += functionName.substr(end); + functionName = demangled; } - } else { - Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str()); } + + Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str()); } -#else +# else // defined(__GNUG__) backtrace_symbols_fd(array, size, STDOUT_FILENO); -#endif +# endif // defined(__GNUG__) FILE* file = fopen(fileName.c_str(), "w+"); if (file != NULL) { @@ -166,7 +168,7 @@ void CatchUnhandled(int sig) { fclose(file); } -#else +#else // __include_backtrace__ struct backtrace_state* state = backtrace_create_state( Diagnostics::GetProcessFileName().c_str(), @@ -177,7 +179,7 @@ void CatchUnhandled(int sig) { struct bt_ctx ctx = { state, 0 }; Bt(state); -#endif +#endif // __include_backtrace__ exit(EXIT_FAILURE); } diff --git a/dCommon/Type.cpp b/dCommon/Type.cpp deleted file mode 100644 index 5cce9d66..00000000 --- a/dCommon/Type.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "Type.h" -#ifdef __GNUG__ -#include -#include -#include - -std::string demangle(const char* name) { - - int status = -4; // some arbitrary value to eliminate the compiler warning - - // enable c++11 by passing the flag -std=c++11 to g++ - std::unique_ptr res{ - abi::__cxa_demangle(name, NULL, NULL, &status), - std::free - }; - - return (status == 0) ? res.get() : name; -} - -#else - -// does nothing if not g++ -std::string demangle(const char* name) { - return name; -} - -#endif diff --git a/dCommon/Type.h b/dCommon/Type.h deleted file mode 100644 index 552bb09f..00000000 --- a/dCommon/Type.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include - -std::string demangle(const char* name); - -template -std::string type(const T& t) { - - return demangle(typeid(t).name()); -}