Add safe tracing interface
This commit is contained in:
parent
44ba826f67
commit
e80afd460b
@ -26,6 +26,7 @@ namespace cpptrace {
|
||||
|
||||
struct CPPTRACE_EXPORT raw_trace {
|
||||
std::vector<frame_ptr> frames;
|
||||
static raw_trace from_buffer(frame_ptr* buffer, std::size_t size);
|
||||
static raw_trace current(std::uint_least32_t skip = 0);
|
||||
static raw_trace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
object_trace resolve_object_trace() const;
|
||||
@ -124,6 +125,18 @@ namespace cpptrace {
|
||||
CPPTRACE_EXPORT stacktrace generate_trace(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_EXPORT stacktrace generate_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
|
||||
CPPTRACE_EXPORT std::size_t safe_generate_raw_trace(
|
||||
frame_ptr* buffer,
|
||||
std::size_t size,
|
||||
std::uint_least32_t skip = 0
|
||||
);
|
||||
CPPTRACE_EXPORT std::size_t safe_generate_raw_trace(
|
||||
frame_ptr* buffer,
|
||||
std::size_t size,
|
||||
std::uint_least32_t skip,
|
||||
std::uint_least32_t max_depth
|
||||
);
|
||||
|
||||
// utilities:
|
||||
CPPTRACE_EXPORT std::string demangle(const std::string& name);
|
||||
CPPTRACE_EXPORT void absorb_trace_exceptions(bool absorb);
|
||||
|
||||
@ -28,6 +28,11 @@
|
||||
#define CYAN ESC "36m"
|
||||
|
||||
namespace cpptrace {
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
raw_trace raw_trace::from_buffer(frame_ptr* buffer, std::size_t size) {
|
||||
return raw_trace{std::vector<cpptrace::frame_ptr>(buffer, buffer + size)};
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
raw_trace raw_trace::current(std::uint_least32_t skip) {
|
||||
return generate_raw_trace(skip + 1);
|
||||
@ -263,6 +268,21 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_generate_raw_trace(frame_ptr* buffer, std::size_t size, std::uint_least32_t skip) {
|
||||
return detail::safe_capture_frames(buffer, size, skip + 1, UINT_LEAST32_MAX);
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_generate_raw_trace(
|
||||
frame_ptr* buffer,
|
||||
std::size_t size,
|
||||
std::uint_least32_t skip,
|
||||
std::uint_least32_t max_depth
|
||||
) {
|
||||
return detail::safe_capture_frames(buffer, size, skip + 1, max_depth);
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
object_trace generate_object_trace(std::uint_least32_t skip) {
|
||||
try {
|
||||
|
||||
@ -14,8 +14,12 @@ namespace detail {
|
||||
#else
|
||||
constexpr std::size_t hard_max_frames = 100;
|
||||
#endif
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::vector<frame_ptr> capture_frames(std::size_t skip, std::size_t max_depth);
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_capture_frames(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -152,6 +152,12 @@ namespace detail {
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_capture_frames(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth) {
|
||||
// Can't safe trace with dbghelp
|
||||
return 0;
|
||||
}
|
||||
#if IS_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@ -27,6 +27,12 @@ namespace detail {
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_capture_frames(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth) {
|
||||
// Can't safe trace with execinfo
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -36,6 +36,41 @@ namespace detail {
|
||||
} while(unw_step(&cursor) > 0 && frames.size() < max_depth);
|
||||
return frames;
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_capture_frames(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth) {
|
||||
// some code duplication, but whatever
|
||||
skip++;
|
||||
std::vector<frame_ptr> frames;
|
||||
unw_context_t context;
|
||||
unw_cursor_t cursor;
|
||||
// thread and signal-safe https://www.nongnu.org/libunwind/man/unw_getcontext(3).html
|
||||
unw_getcontext(&context);
|
||||
// thread and signal-safe https://www.nongnu.org/libunwind/man/unw_init_local(3).html
|
||||
unw_init_local(&cursor, &context);
|
||||
size_t i = 0;
|
||||
while(i < size && i < max_depth) {
|
||||
unw_word_t pc;
|
||||
unw_word_t sp;
|
||||
// thread and signal-safe https://www.nongnu.org/libunwind/man/unw_get_reg(3).html
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &pc);
|
||||
unw_get_reg(&cursor, UNW_REG_SP, &sp);
|
||||
if(skip) {
|
||||
skip--;
|
||||
} else {
|
||||
// pc is the instruction after the `call`, adjust back to the previous instruction
|
||||
// just a cast, signal safe
|
||||
buffer[i] = to_frame_ptr(pc) - 1;
|
||||
i++;
|
||||
}
|
||||
// thread and signal-safe as long as the cursor is in the local address space, which it is
|
||||
// https://www.nongnu.org/libunwind/man/unw_step(3).html
|
||||
if(unw_step(&cursor) <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,11 @@ namespace detail {
|
||||
std::vector<frame_ptr> capture_frames(std::size_t, std::size_t) {
|
||||
return {};
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_capture_frames(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +62,12 @@ namespace detail {
|
||||
frames.shrink_to_fit();
|
||||
return frames;
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_capture_frames(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth) {
|
||||
// Can't safe trace with _Unwind
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,6 +37,12 @@ namespace detail {
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::size_t safe_capture_frames(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth) {
|
||||
// Can't safe trace with winapi
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user