From 00d6f1c9d103957c97f7bbedf44b31c5ecb1f30f Mon Sep 17 00:00:00 2001 From: Jeremy <51220084+jeremy-rifkin@users.noreply.github.com> Date: Sat, 22 Jul 2023 21:31:31 -0400 Subject: [PATCH] Update how stacktraces are printed, add color, add a demo program, add a screenshot to the readme, and two small fixes to backends --- CMakeLists.txt | 14 ++++++ README.md | 9 ++-- res/screenshot.png | Bin 0 -> 90150 bytes src/cpptrace.cpp | 49 +++++++++++++++++---- src/full/full_trace_with_libbacktrace.cpp | 3 ++ src/platform/cpptrace_common.hpp | 32 ++++++++++++++ src/symbols/symbols_with_addr2line.cpp | 3 ++ test/demo.cpp | 50 ++++++++++++++++++++++ 8 files changed, 149 insertions(+), 11 deletions(-) create mode 100644 res/screenshot.png create mode 100644 test/demo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6dc280a..d69bac9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ option(CPPTRACE_DEMANGLE_WITH_CXXABI "" OFF) option(CPPTRACE_DEMANGLE_WITH_NOTHING "" OFF) option(CPPTRACE_BUILD_TEST "" OFF) +option(CPPTRACE_BUILD_DEMO "" OFF) option(CPPTRACE_BUILD_TEST_RDYNAMIC "" OFF) option(CPPTRACE_BUILD_SPEEDTEST "" OFF) @@ -408,6 +409,19 @@ if(CPPTRACE_BUILD_TEST) endif() endif() +if(CPPTRACE_BUILD_DEMO) + add_executable(demo test/demo.cpp) + target_link_libraries(demo PRIVATE cpptrace) + # Clang has been fast to adopt dwarf 5, other tools (e.g. addr2line from binutils) have not + check_cxx_compiler_flag("-gdwarf-4" HAS_DWARF4) + if(HAS_DWARF4) + target_compile_options(demo PRIVATE "$<$:-gdwarf-4>") + endif() + if(CPPTRACE_BUILD_TEST_RDYNAMIC) + set_property(TARGET demo PROPERTY ENABLE_EXPORTS ON) + endif() +endif() + if(CPPTRACE_BUILD_SPEEDTEST) if(CPPTRACE_BUILD_SPEEDTEST_DWARF4) check_cxx_compiler_flag("-gdwarf-4" HAS_DWARF4) diff --git a/README.md b/README.md index 7295284..62b3e1d 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ Some day C++23's `` will be ubiquitous. And maybe one day the msvc i 🚧 WIP: This library is in beta. 🏗️ +![Screenshot](res/screenshot.png) + ## Table of contents - [Cpptrace](#cpptrace) @@ -187,9 +189,10 @@ General: `100`. Testing: -- `CPPTRACE_BUILD_TEST` -- `CPPTRACE_BUILD_TEST_RDYNAMIC` -- `CPPTRACE_BUILD_SPEEDTEST` +- `CPPTRACE_BUILD_TEST` Build a small test program +- `CPPTRACE_BUILD_DEMO` Build a small demo program +- `CPPTRACE_BUILD_TEST_RDYNAMIC` Use `-rdynamic` when compiling the test program +- `CPPTRACE_BUILD_SPEEDTEST` Build a small speed test program - `CPPTRACE_BUILD_SPEEDTEST_DWARF4` - `CPPTRACE_BUILD_SPEEDTEST_DWARF5` diff --git a/res/screenshot.png b/res/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..27ad81b51c197720189fa3578c34ae9411222a40 GIT binary patch literal 90150 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 #include #include +#include #include #if !(defined(CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE) || defined(CPPTRACE_FULL_TRACE_WITH_STACKTRACE)) @@ -46,23 +47,55 @@ namespace cpptrace { #endif +#define ESC "\033[" +#define RESET ESC "0m" +#define RED ESC "31m" +#define GREEN ESC "32m" +#define YELLOW ESC "33m" +#define BLUE ESC "34m" +#define MAGENTA ESC "35m" +#define CYAN ESC "36m" + namespace cpptrace { void print_trace(std::uint32_t skip) { + enable_virtual_terminal_processing_if_needed(); std::cerr<<"Stack trace (most recent call first):"<"<(trace.size()) - 1); + for(const auto& frame : trace) { std::cerr + << '#' + << std::setw(static_cast(frame_number_width)) + << std::left << counter++ << " " - << frame.filename - << ":" - << frame.line - << (frame.col > 0 ? ":" + std::to_string(frame.col) : "") - << " " + << std::hex + << BLUE + << "0x" + << std::setw(2 * sizeof(uintptr_t)) + << std::setfill('0') + << frame.address + << std::dec + << std::setfill(' ') + << RESET + << " in " + << YELLOW << frame.symbol + << RESET + << " at " + << GREEN + << frame.filename + << RESET + << ":" + << BLUE + << frame.line + << RESET + << (frame.col > 0 ? ":" BLUE + std::to_string(frame.col) + RESET : "") << std::endl; } } diff --git a/src/full/full_trace_with_libbacktrace.cpp b/src/full/full_trace_with_libbacktrace.cpp index c7f6791..2713a42 100644 --- a/src/full/full_trace_with_libbacktrace.cpp +++ b/src/full/full_trace_with_libbacktrace.cpp @@ -28,6 +28,9 @@ namespace cpptrace { trace_data& data = *reinterpret_cast(data_pointer); if(data.skip > 0) { data.skip--; + } else if(address == uintptr_t(-1)) { + // sentinel for libbacktrace, stop tracing + return 1; } else { data.frames.push_back({ address, diff --git a/src/platform/cpptrace_common.hpp b/src/platform/cpptrace_common.hpp index 750e4a1..a744db3 100644 --- a/src/platform/cpptrace_common.hpp +++ b/src/platform/cpptrace_common.hpp @@ -57,6 +57,10 @@ #error "Unsupported compiler" #endif +#if IS_WINDOWS + #include +#endif + // Lightweight std::source_location. struct source_location { // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) @@ -218,6 +222,34 @@ T byteswap(T value) { return byte_swapper{}(value); } +CPPTRACE_MAYBE_UNUSED +inline void enable_virtual_terminal_processing_if_needed() { + // enable colors / ansi processing if necessary + #if IS_WINDOWS + // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#example-of-enabling-virtual-terminal-processing + #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING + constexpr DWORD ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4; + #endif + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD dwMode = 0; + if(hOut == INVALID_HANDLE_VALUE) return; + if(!GetConsoleMode(hOut, &dwMode)) return; + if(dwMode != (dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + if(!SetConsoleMode(hOut, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return; + #endif +} + +CPPTRACE_MAYBE_UNUSED +// NOLINTNEXTLINE(misc-no-recursion) +inline constexpr unsigned n_digits(unsigned value) { + return value < 10 ? 1 : 1 + n_digits(value / 10); +} +static_assert(n_digits(1) == 1, "n_digits utility producing the wrong result"); +static_assert(n_digits(9) == 1, "n_digits utility producing the wrong result"); +static_assert(n_digits(10) == 2, "n_digits utility producing the wrong result"); +static_assert(n_digits(11) == 2, "n_digits utility producing the wrong result"); +static_assert(n_digits(1024) == 4, "n_digits utility producing the wrong result"); + #ifdef _MSC_VER #pragma warning(pop) #endif diff --git a/src/symbols/symbols_with_addr2line.cpp b/src/symbols/symbols_with_addr2line.cpp index db2eca6..e0eac4f 100644 --- a/src/symbols/symbols_with_addr2line.cpp +++ b/src/symbols/symbols_with_addr2line.cpp @@ -291,6 +291,9 @@ namespace cpptrace { std::vector resolve_frames(const std::vector& frames) { // TODO: Refactor better std::vector trace(frames.size(), stacktrace_frame { 0, 0, 0, "", "" }); + for(size_t i = 0; i < frames.size(); i++) { + trace[i].address = reinterpret_cast(frames[i]); + } if(has_addr2line()) { const std::vector dlframes = backtrace_frames(frames); const auto entries = get_addr2line_targets(dlframes, trace); diff --git a/test/demo.cpp b/test/demo.cpp new file mode 100644 index 0000000..1d688ac --- /dev/null +++ b/test/demo.cpp @@ -0,0 +1,50 @@ +#include + +#include +#include +#include +#include + +void trace() { + cpptrace::print_trace(); +} + +int x; + +void foo(int n) { + if(n == 0) { + x = 0; + trace(); + x = 0; + } else { + x = 0; + foo(n - 1); + x = 0; + } +} + +template +void foo(int x, Args... args) { + x = 0; + foo(args...); + x = 0; +} + +void function_two(int, float) { + x = 0; + foo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + x = 0; +} + +void function_one(int) { + x = 0; + function_two(0, 0); + x = 0; +} + +int main() { + x = 0; + function_one(0); + x = 0; +} +