diff --git a/src/core/include/utils/demangle.h b/src/core/include/utils/demangle.h index b12793b66..751b56bd4 100644 --- a/src/core/include/utils/demangle.h +++ b/src/core/include/utils/demangle.h @@ -33,6 +33,6 @@ #include -std::string demangle(const char* name); +std::string demangle(const char* name) noexcept; #endif // __DEMANGLE_H__ diff --git a/src/core/include/utils/get-call-stack.h b/src/core/include/utils/get-call-stack.h index 2481470c2..b54ca1d3d 100644 --- a/src/core/include/utils/get-call-stack.h +++ b/src/core/include/utils/get-call-stack.h @@ -35,9 +35,10 @@ #include /** - * @brief get_call_stack() is a function to get the call stack + * @brief get_call_stack() is a function to get the call stack. + * @attention it must not throw an exception as it is called from OpenFHEException * @return a vector with call stack (demangled function names) */ -std::vector get_call_stack(); +std::vector get_call_stack() noexcept; #endif // __GET_CALL_STACK_H__ diff --git a/src/core/lib/utils/demangle.cpp b/src/core/lib/utils/demangle.cpp index 6be50c5f8..ee476a160 100644 --- a/src/core/lib/utils/demangle.cpp +++ b/src/core/lib/utils/demangle.cpp @@ -34,14 +34,31 @@ #if defined(__clang__) || defined(__GNUC__) #include -std::string demangle(const char* const name) { - int status = -1; - std::unique_ptr result{abi::__cxa_demangle(name, NULL, NULL, &status)}; +std::string demangle(const char* const name) noexcept { + // output_buffer must be malloc'ed + size_t output_buffer_size = 512; + auto output_buffer = reinterpret_cast(std::malloc(output_buffer_size)); + int status = -1; - return (status == 0) ? result.get() : (std::string("Can not demangle symbol: ") + name); + char* ptr = abi::__cxa_demangle(name, output_buffer, &output_buffer_size, &status); + std::string result; + if (status == 0 && ptr != nullptr) { + result = ptr; + // If ptr is different from output_buffer, free ptr as it points to the newly allocated (realloc) buffer + if (ptr != output_buffer) + std::free(ptr); + else + std::free(output_buffer); + } + else { + result = "Cannot demangle symbol: " + std::string(name); + std::free(output_buffer); + } + + return result; } #else -std::string demangle(const char* const name) { +std::string demangle(const char* const name) noexcept { return name; } #endif diff --git a/src/core/lib/utils/get-call-stack.cpp b/src/core/lib/utils/get-call-stack.cpp index 28c049021..e53f5ac07 100644 --- a/src/core/lib/utils/get-call-stack.cpp +++ b/src/core/lib/utils/get-call-stack.cpp @@ -31,7 +31,7 @@ #include "utils/get-call-stack.h" #if defined(__linux__) && defined(__GNUC__) -// clang-format off + // clang-format off #include "utils/demangle.h" #include @@ -43,7 +43,7 @@ namespace { enum { MAX_BACKTRACE_ADDRESSES = 512 }; } -static bool stringEmpty(const std::string& str) { +static bool stringEmpty(const std::string& str) noexcept { if (!str.length()) return true; @@ -56,18 +56,21 @@ static bool stringEmpty(const std::string& str) { return true; } -std::vector get_call_stack() { +std::vector get_call_stack() noexcept { void* bt_buffer[MAX_BACKTRACE_ADDRESSES] = {NULL}; const int n = backtrace(bt_buffer, MAX_BACKTRACE_ADDRESSES); if (n < 1) { return std::vector(); } - const std::unique_ptr symbols(backtrace_symbols(bt_buffer, n)); + char** symbols = reinterpret_cast(backtrace_symbols(bt_buffer, n)); + if (symbols == NULL) { + return std::vector(); + } const size_t numSymbols = static_cast(n); - std::vector ret(numSymbols); + std::vector retVec(numSymbols); for (size_t i = 0; i < numSymbols; ++i) { - std::string symbol(symbols.get()[i]); + std::string symbol(symbols[i]); // we need to get rid of anything that doesn't belong to the name // Mangled symbol examples: // ./lib/libOPENFHEcore.so.1(_Z14get_call_stackB5cxx11v+0x35) [0x7f1b5cdb91d5] @@ -81,10 +84,11 @@ std::vector get_call_stack() { size_t newLen = symbol.length() - pos; std::string mangledName(symbol.substr(pos + 1, newLen)); - ret[i] = (stringEmpty(mangledName)) ? symbols.get()[i] : demangle(mangledName.c_str()); + retVec[i] = (stringEmpty(mangledName)) ? symbols[i] : demangle(mangledName.c_str()); } - return ret; + free(symbols); + return retVec; } #else std::vector get_call_stack() {