From 592774d813b2c7b92583bf5d3b0b38d2ffa5e4c9 Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+wintersolstice8@users.noreply.github.com> Date: Tue, 11 Mar 2025 15:57:24 -0600 Subject: [PATCH 1/3] [core] [linux] [ext] Upgrade backward.hpp Upgrades backward.hpp to https://github.com/bombela/backward-cpp/commit/94718085efa256fb25a311a46b5948ee0d95890a --- ext/backward/backward.hpp | 96 +++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/ext/backward/backward.hpp b/ext/backward/backward.hpp index cc45350d5a0..2342b180c15 100644 --- a/ext/backward/backward.hpp +++ b/ext/backward/backward.hpp @@ -221,6 +221,13 @@ #include #include #include +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#include +#undef _GNU_SOURCE +#else +#include +#endif #if BACKWARD_HAS_BFD == 1 // NOTE: defining PACKAGE{,_VERSION} is required before including @@ -233,13 +240,6 @@ #define PACKAGE_VERSION #endif #include -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#include -#undef _GNU_SOURCE -#else -#include -#endif #endif #if BACKWARD_HAS_DW == 1 @@ -254,13 +254,6 @@ #include #include #include -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#include -#undef _GNU_SOURCE -#else -#include -#endif #endif #if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) @@ -734,6 +727,7 @@ template class StackTraceImpl { } size_t thread_id() const { return 0; } void skip_n_firsts(size_t) {} + void *const *begin() const { return nullptr; } }; class StackTraceImplBase { @@ -817,7 +811,12 @@ template class Unwinder { _index = -1; _depth = depth; _Unwind_Backtrace(&this->backtrace_trampoline, this); - return static_cast(_index); + if (_index == -1) { + // _Unwind_Backtrace has failed to obtain any backtraces + return 0; + } else { + return static_cast(_index); + } } private: @@ -934,7 +933,7 @@ class StackTraceImpl : public StackTraceImplHolder { // the rest if (context()) { - [[maybe_unused]] ucontext_t *uctx = reinterpret_cast(context()); + ucontext_t *uctx = reinterpret_cast(context()); #ifdef REG_RIP // x86_64 if (uctx->uc_mcontext.gregs[REG_RIP] == reinterpret_cast(error_addr())) { @@ -955,7 +954,7 @@ class StackTraceImpl : public StackTraceImplHolder { reinterpret_cast(uctx->uc_mcontext.gregs[REG_EIP]); ++index; ctx = *reinterpret_cast(uctx); -#elif defined(__arm__) +#elif defined(__arm__) // clang libunwind/arm // libunwind uses its own context type for ARM unwinding. // Copy the registers from the signal handler's context so we can // unwind @@ -986,6 +985,24 @@ class StackTraceImpl : public StackTraceImplHolder { } _stacktrace[index] = reinterpret_cast(ctx.regs[UNW_ARM_R15]); ++index; +#elif defined(__aarch64__) // gcc libunwind/arm64 + unw_getcontext(&ctx); + // If the IP is the same as the crash address we have a bad function + // dereference The caller's address is pointed to by the link pointer, so + // we dereference that value and set it to be the next frame's IP. + if (uctx->uc_mcontext.pc == reinterpret_cast<__uint64_t>(error_addr())) { + uctx->uc_mcontext.pc = uctx->uc_mcontext.regs[UNW_TDEP_IP]; + } + + // 29 general purpose registers + for (int i = UNW_AARCH64_X0; i <= UNW_AARCH64_X28; i++) { + ctx.uc_mcontext.regs[i] = uctx->uc_mcontext.regs[i]; + } + ctx.uc_mcontext.sp = uctx->uc_mcontext.sp; + ctx.uc_mcontext.pc = uctx->uc_mcontext.pc; + ctx.uc_mcontext.fault_address = uctx->uc_mcontext.fault_address; + _stacktrace[index] = reinterpret_cast(ctx.uc_mcontext.pc); + ++index; #elif defined(__APPLE__) && defined(__x86_64__) unw_getcontext(&ctx); // OS X's implementation of libunwind uses its own context object @@ -1639,9 +1656,9 @@ class TraceResolverLinuxImpl return r; // damned, that's a stripped file that you got there! } - r->handle = std::move(bfd_handle); - r->symtab = std::move(symtab); - r->dynamic_symtab = std::move(dynamic_symtab); + r->handle = move(bfd_handle); + r->symtab = move(symtab); + r->dynamic_symtab = move(dynamic_symtab); return r; } @@ -3621,10 +3638,12 @@ template <> class TraceResolverImpl symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME; SymSetOptions(symOptions); EnumProcessModules(process, &module_handles[0], - module_handles.size() * sizeof(HMODULE), &cbNeeded); + static_cast(module_handles.size() * sizeof(HMODULE)), + &cbNeeded); module_handles.resize(cbNeeded / sizeof(HMODULE)); EnumProcessModules(process, &module_handles[0], - module_handles.size() * sizeof(HMODULE), &cbNeeded); + static_cast(module_handles.size() * sizeof(HMODULE)), + &cbNeeded); std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process)); void *base = modules[0].base_address; @@ -3808,11 +3827,18 @@ class SourceFile { } #endif + // Allow adding to paths gotten from BACKWARD_CXX_SOURCE_PREFIXES after loading the + // library; this can be useful when the library is loaded when the locations are unknown + // Warning: Because this edits the static paths variable, it is *not* intrinsiclly thread safe + static void add_paths_to_env_variable_impl(const std::string & to_add) { + get_mutable_paths_from_env_variable().push_back(to_add); + } + private: details::handle > _file; - std::vector get_paths_from_env_variable_impl() { + static std::vector get_paths_from_env_variable_impl() { std::vector paths; const char *prefixes_str = std::getenv("BACKWARD_CXX_SOURCE_PREFIXES"); if (prefixes_str && prefixes_str[0]) { @@ -3821,9 +3847,13 @@ class SourceFile { return paths; } - const std::vector &get_paths_from_env_variable() { - static std::vector paths = get_paths_from_env_variable_impl(); - return paths; + static std::vector &get_mutable_paths_from_env_variable() { + static volatile std::vector paths = get_paths_from_env_variable_impl(); + return const_cast&>(paths); + } + + static const std::vector &get_paths_from_env_variable() { + return get_mutable_paths_from_env_variable(); } #ifdef BACKWARD_ATLEAST_CXX11 @@ -3991,10 +4021,12 @@ class Printer { bool object; int inliner_context_size; int trace_context_size; + bool reverse; Printer() : snippet(true), color_mode(ColorMode::automatic), address(false), - object(false), inliner_context_size(5), trace_context_size(7) {} + object(false), inliner_context_size(5), trace_context_size(7), + reverse(true) {} template FILE *print(ST &st, FILE *fp = stderr) { cfile_streambuf obuf(fp); @@ -4041,8 +4073,14 @@ class Printer { void print_stacktrace(ST &st, std::ostream &os, Colorize &colorize) { print_header(os, st.thread_id()); _resolver.load_stacktrace(st); - for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) { - print_trace(os, _resolver.resolve(st[trace_idx - 1]), colorize); + if ( reverse ) { + for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) { + print_trace(os, _resolver.resolve(st[trace_idx - 1]), colorize); + } + } else { + for (size_t trace_idx = 0; trace_idx < st.size(); ++trace_idx) { + print_trace(os, _resolver.resolve(st[trace_idx]), colorize); + } } } From e8f63a648fde9634efdc1c14cb8ab88c905f4d1f Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+wintersolstice8@users.noreply.github.com> Date: Tue, 11 Mar 2025 16:03:20 -0600 Subject: [PATCH 2/3] [core] [linux] Use default call stack depth on crash backtraces --- ext/backward/backward.hpp | 16 ++++++++-------- src/common/debug_linux.cpp | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/backward/backward.hpp b/ext/backward/backward.hpp index 2342b180c15..0e35520c5ba 100644 --- a/ext/backward/backward.hpp +++ b/ext/backward/backward.hpp @@ -1656,9 +1656,9 @@ class TraceResolverLinuxImpl return r; // damned, that's a stripped file that you got there! } - r->handle = move(bfd_handle); - r->symtab = move(symtab); - r->dynamic_symtab = move(dynamic_symtab); + r->handle = std::move(bfd_handle); + r->symtab = std::move(symtab); + r->dynamic_symtab = std::move(dynamic_symtab); return r; } @@ -2471,8 +2471,8 @@ class TraceResolverLinuxImpl // If we have a valid elf handle, return the new elf handle // and file handle and discard the original ones if (debuglink_elf) { - elf_handle = move(debuglink_elf); - file_handle = move(debuglink_file); + elf_handle = std::move(debuglink_elf); + file_handle = std::move(debuglink_file); } } } @@ -2494,9 +2494,9 @@ class TraceResolverLinuxImpl dwarf_handle.reset(dwarf_debug); - r.file_handle = move(file_handle); - r.elf_handle = move(elf_handle); - r.dwarf_handle = move(dwarf_handle); + r.file_handle = std::move(file_handle); + r.elf_handle = std::move(elf_handle); + r.dwarf_handle = std::move(dwarf_handle); return r; } diff --git a/src/common/debug_linux.cpp b/src/common/debug_linux.cpp index a67ed0d3638..6b83f52926d 100644 --- a/src/common/debug_linux.cpp +++ b/src/common/debug_linux.cpp @@ -46,7 +46,7 @@ void dumpBacktrace(int signal) backward::StackTrace trace; backward::Printer printer; - trace.load_here(10); + trace.load_here(); printer.object = true; printer.color_mode = backward::ColorMode::always; From 87c964270705875dca28a7194d6876007bc87192 Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+wintersolstice8@users.noreply.github.com> Date: Tue, 11 Mar 2025 16:35:22 -0600 Subject: [PATCH 3/3] [core] Print info when crash command is likely optimized out --- src/common/utils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/utils.cpp b/src/common/utils.cpp index dfb9b566891..7e250f1caf4 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -897,6 +897,10 @@ bool definitelyLessThan(float a, float b) void crash() { +#ifndef _DEBUG + ShowInfo("crash command is likely optimized out in release mode."); +#endif + int* volatile ptr = nullptr; // cppcheck-suppress nullPointer *ptr = 0xDEAD;