diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a43dc8..80c859a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ project(Arbutils) # Enable all warnings, and make them error when occurring. add_compile_options(-Wall -Wextra -Werror) +# Include debug symbols in all builds +add_compile_options(-g -gfull -g3) # We like new stuff, so set the c++ standard to c++20. set(CMAKE_CXX_STANDARD 20) @@ -43,7 +45,7 @@ endif (WINDOWS) set(LINKS) if (NOT WINDOWS) - set(LINKS ${LINKS} -lbfd -ldl) + set(LINKS ${LINKS} -ldw) endif() # If we want to link the C and C++ library statically, link those as well. if (STATICC) diff --git a/src/Exception.hpp b/src/Exception.hpp index 563051b..983d09e 100644 --- a/src/Exception.hpp +++ b/src/Exception.hpp @@ -6,7 +6,7 @@ #include #include #if !WINDOWS -#define BACKWARD_HAS_BFD 1 +#define BACKWARD_HAS_DW 1 #include "../extern/backward.hpp" #endif @@ -19,7 +19,7 @@ namespace ArbUt { public: explicit Exception(const std::string& msg) : std::logic_error(msg) { #if !WINDOWS - _stack.load_here(9); + _stack.load_here(32); #endif } @@ -43,33 +43,20 @@ namespace ArbUt { backward::TraceResolver tr; tr.load_stacktrace(_stack); std::stringstream ss; - for (size_t i = 3; i < _stack.size() && i < depth + 3; ++i) { + ss << "Stacktrace with depth " << depth << ": " << std::endl; + bool foundExceptionClass = false; + size_t framesAppended = -1; + for (size_t i = 0; i < _stack.size(); ++i) { backward::ResolvedTrace trace = tr.resolve(_stack[i]); if (trace.source.filename.empty()) { - auto objectName = - (strrchr(trace.object_filename.c_str(), '/') ? strrchr(trace.object_filename.c_str(), '/') + 1 - : trace.object_filename.c_str()); - auto function = trace.object_function; - if (function.length() > 70) { - function = function.substr(0, 67); - function += "..."; - } - ss << objectName; - if (include_addr) { - ss << "[" << trace.addr << "]"; - } - ss << " " << function << std::endl; - + AppendNoSourceStack(ss, trace, include_addr); } else { - auto fileName = - (strrchr(trace.source.filename.c_str(), '/') ? strrchr(trace.source.filename.c_str(), '/') + 1 - : trace.source.filename.c_str()); - auto function = trace.object_function; - if (function.length() > 70) { - function = function.substr(0, 67); - function += "..."; + AppendSourceStack(ss, trace, foundExceptionClass); + if (foundExceptionClass){ + framesAppended++; + if (framesAppended >= depth) + break; } - ss << fileName << "[" << trace.source.line << "] " << function << std::endl; } } return ss.str(); @@ -77,6 +64,42 @@ namespace ArbUt { return "Stack trace not available on Windows."; #endif } + + private: + static void AppendNoSourceStack(std::stringstream& ss, const backward::ResolvedTrace& trace, + bool include_addr) { + auto objectName = + (strrchr(trace.object_filename.c_str(), '/') ? strrchr(trace.object_filename.c_str(), '/') + 1 + : trace.object_filename.c_str()); + auto function = trace.object_function; + if (function.length() > 70) { + function = function.substr(0, 67); + function += "..."; + } + ss << objectName; + if (include_addr) { + ss << "[" << trace.addr << "]"; + } + ss << " " << function << std::endl; + } + static void AppendSourceStack(std::stringstream& ss, const backward::ResolvedTrace& trace, bool& foundExceptionClass) { + auto fileName = + (strrchr(trace.source.filename.c_str(), '/') ? strrchr(trace.source.filename.c_str(), '/') + 1 + : trace.source.filename.c_str()); + if (strcmp(fileName, "Exception.hpp") == 0) { + foundExceptionClass = true; + return; + } else if (!foundExceptionClass) { + return; + } + + auto function = trace.object_function; + if (function.length() > 70) { + function = function.substr(0, 67); + function += "..."; + } + ss << fileName << "[" << trace.source.line << "] " << function << std::endl; + } }; } diff --git a/tests/ExceptionTests.cpp b/tests/ExceptionTests.cpp index 729e93e..acec35a 100644 --- a/tests/ExceptionTests.cpp +++ b/tests/ExceptionTests.cpp @@ -3,15 +3,19 @@ #include "../src/Exception.hpp" using namespace ArbUt; +#ifndef WINDOWS +__attribute__((optnone)) +#endif +static void Thrower(){ + throw ArbUt::Exception("foobar"); +} + TEST_CASE("Throw exception get stack trace") { try { - throw ArbUt::Exception("foobar"); + Thrower(); } catch (const ArbUt::Exception& e) { -#ifndef NDEBUG - REQUIRE(e.GetStacktrace(1) == "ExceptionTests.cpp[8] ____C_A_T_C_H____T_E_S_T____0()\n"); -#else - REQUIRE(e.GetStacktrace(1, false) == "ArbutilsTests Catch::RunContext::runTest(Catch::TestCase const&)\n"); -#endif + REQUIRE(e.GetStacktrace(1) == "Stacktrace with depth 1: \n" + "ExceptionTests.cpp[10] Thrower()\n"); } }