Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ target_sources(
src/symbols/symbols_with_libdwarf.cpp
src/symbols/symbols_with_nothing.cpp
src/unwind/unwind_with_dbghelp.cpp
src/unwind/unwind_with_rtlvirtualunwind.cpp
src/unwind/unwind_with_execinfo.cpp
src/unwind/unwind_with_libunwind.cpp
src/unwind/unwind_with_nothing.cpp
Expand Down Expand Up @@ -499,6 +500,10 @@ if(CPPTRACE_UNWIND_WITH_DBGHELP)
target_link_libraries(${target_name} PRIVATE dbghelp)
endif()

if(CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND)
target_compile_definitions(${target_name} PRIVATE CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND)
endif()

if(CPPTRACE_UNWIND_WITH_NOTHING)
target_compile_definitions(${target_name} PRIVATE CPPTRACE_UNWIND_WITH_NOTHING)
endif()
Expand Down
1 change: 1 addition & 0 deletions ci/build-in-all-remaining-configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"CPPTRACE_UNWIND_WITH_EXECINFO",
"CPPTRACE_UNWIND_WITH_WINAPI",
"CPPTRACE_UNWIND_WITH_DBGHELP",
"CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND",
"CPPTRACE_UNWIND_WITH_NOTHING",
]
ALL_SYMBOL_OPTIONS = [
Expand Down
2 changes: 2 additions & 0 deletions ci/test-all-configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def get_c_compiler_counterpart(compiler: str) -> str:
"CPPTRACE_UNWIND_WITH_EXECINFO",
"CPPTRACE_UNWIND_WITH_WINAPI",
"CPPTRACE_UNWIND_WITH_DBGHELP",
"CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND",
"CPPTRACE_UNWIND_WITH_NOTHING",
]
ALL_SYMBOL_OPTIONS = [
Expand Down Expand Up @@ -433,6 +434,7 @@ def run_windows_matrix(compilers: list, shared: bool):
"unwind": [
"CPPTRACE_UNWIND_WITH_WINAPI",
"CPPTRACE_UNWIND_WITH_DBGHELP",
"CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND",
"CPPTRACE_UNWIND_WITH_UNWIND", # Broken on github actions for some reason
#"CPPTRACE_UNWIND_WITH_NOTHING",
],
Expand Down
1 change: 1 addition & 0 deletions cmake/Autoconfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ if(
CPPTRACE_UNWIND_WITH_EXECINFO OR
CPPTRACE_UNWIND_WITH_WINAPI OR
CPPTRACE_UNWIND_WITH_DBGHELP OR
CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND OR
CPPTRACE_UNWIND_WITH_NOTHING
)
)
Expand Down
1 change: 1 addition & 0 deletions cmake/OptionVariables.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ option(CPPTRACE_UNWIND_WITH_LIBUNWIND "" OFF)
option(CPPTRACE_UNWIND_WITH_EXECINFO "" OFF)
option(CPPTRACE_UNWIND_WITH_WINAPI "" OFF)
option(CPPTRACE_UNWIND_WITH_DBGHELP "" OFF)
option(CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND "" OFF)
option(CPPTRACE_UNWIND_WITH_NOTHING "" OFF)

# ---- Demangling Options ----
Expand Down
6 changes: 3 additions & 3 deletions src/from_current.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace detail {
}
}

#if defined(_MSC_VER) && defined(CPPTRACE_UNWIND_WITH_DBGHELP)
#if defined(_MSC_VER) && defined(CPPTRACE_UNWIND_WITH_EXCEPTION_POINTERS)
CPPTRACE_FORCE_NO_INLINE void collect_current_trace(std::size_t skip, EXCEPTION_POINTERS* exception_ptrs) {
try {
#if defined(_M_IX86) || defined(__i386__)
Expand Down Expand Up @@ -376,7 +376,7 @@ CPPTRACE_BEGIN_NAMESPACE
CPPTRACE_FORCE_NO_INLINE
int maybe_collect_trace(EXCEPTION_POINTERS* exception_ptrs, int filter_result) {
if(filter_result == EXCEPTION_EXECUTE_HANDLER) {
#ifdef CPPTRACE_UNWIND_WITH_DBGHELP
#ifdef CPPTRACE_UNWIND_WITH_EXCEPTION_POINTERS
collect_current_trace(1, exception_ptrs);
#else
collect_current_trace(1);
Expand All @@ -388,7 +388,7 @@ CPPTRACE_BEGIN_NAMESPACE
CPPTRACE_FORCE_NO_INLINE
void maybe_collect_trace(EXCEPTION_POINTERS* exception_ptrs, const std::type_info& type_info) {
if(matches_exception(exception_ptrs, type_info)) {
#ifdef CPPTRACE_UNWIND_WITH_DBGHELP
#ifdef CPPTRACE_UNWIND_WITH_EXCEPTION_POINTERS
collect_current_trace(2, exception_ptrs);
#else
collect_current_trace(2);
Expand Down
5 changes: 3 additions & 2 deletions src/unwind/unwind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include <cstddef>
#include <vector>

#ifdef CPPTRACE_UNWIND_WITH_DBGHELP
#if defined(CPPTRACE_UNWIND_WITH_DBGHELP) || defined(CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND)
#define CPPTRACE_UNWIND_WITH_EXCEPTION_POINTERS
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
Expand All @@ -22,7 +23,7 @@ namespace detail {
constexpr std::size_t hard_max_frames = 400;
#endif

#ifdef CPPTRACE_UNWIND_WITH_DBGHELP
#ifdef CPPTRACE_UNWIND_WITH_EXCEPTION_POINTERS
CPPTRACE_FORCE_NO_INLINE
std::vector<frame_ptr> capture_frames(
std::size_t skip,
Expand Down
105 changes: 105 additions & 0 deletions src/unwind/unwind_with_rtlvirtualunwind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#ifdef CPPTRACE_UNWIND_WITH_RTLVIRTUALUNWIND

#include <cpptrace/basic.hpp>
#include "unwind/unwind.hpp"
#include "utils/common.hpp"
#include "utils/utils.hpp"

#include <cstddef>
#include <vector>

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>

#if !defined(_M_X64) && !defined(__x86_64__) && !defined(_M_ARM64) && !defined(__aarch64__)
#error "Cpptrace: RtlVirtualUnwind is only supported on 64-bit Windows"
#endif

namespace {
DWORD64 context_pc(CONTEXT& context) {
#if defined(_M_X64) || defined(__x86_64__)
return context.Rip;
#elif defined(_M_ARM64) || defined(__aarch64__)
return context.Pc;
#endif
}
}

CPPTRACE_BEGIN_NAMESPACE
namespace detail {
CPPTRACE_FORCE_NO_INLINE
std::vector<frame_ptr> capture_frames(
std::size_t skip,
std::size_t max_depth,
EXCEPTION_POINTERS* exception_pointers
) {
CONTEXT context;
ZeroMemory(&context, sizeof(CONTEXT));
if(exception_pointers) {
context = *exception_pointers->ContextRecord;
} else {
skip++; // we're unwinding from the capture_frames frame, skip it
RtlCaptureContext(&context);
}

std::vector<frame_ptr> trace;
while(trace.size() < max_depth) {
DWORD64 image_base;
PRUNTIME_FUNCTION function_entry = RtlLookupFunctionEntry(context_pc(context), &image_base, NULL);
if(!function_entry) {
break;
}
if(skip) {
skip--;
} else {
// Same adjustment as StackWalk64
trace.push_back(to_frame_ptr(context_pc(context)) - 1);
}
#if defined(_M_X64) || defined(__x86_64__)
PVOID handler_data;
DWORD64 establisher_frame;
RtlVirtualUnwind(
UNW_FLAG_NHANDLER,
image_base,
context_pc(context),
function_entry,
&context,
&handler_data,
&establisher_frame,
NULL
);
#elif defined(_M_ARM64) || defined(__aarch64__)
BOOLEAN in_function;
FRAME_POINTERS establisher_frame;
RtlVirtualUnwind(
image_base,
context_pc(context),
function_entry,
&context,
&in_function,
&establisher_frame,
NULL
);
#endif
if(context_pc(context) == 0) {
break;
}
}
return trace;
}

CPPTRACE_FORCE_NO_INLINE
std::size_t safe_capture_frames(frame_ptr*, std::size_t, std::size_t, std::size_t) {
// Can't safe trace with RtlVirtualUnwind
return 0;
}

bool has_safe_unwind() {
return false;
}
}
CPPTRACE_END_NAMESPACE

#endif
Loading