Add safe tracing interface
This commit is contained in:
parent
44ba826f67
commit
e80afd460b
@ -26,6 +26,7 @@ namespace cpptrace {
|
|||||||
|
|
||||||
struct CPPTRACE_EXPORT raw_trace {
|
struct CPPTRACE_EXPORT raw_trace {
|
||||||
std::vector<frame_ptr> frames;
|
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 = 0);
|
||||||
static raw_trace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
static raw_trace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||||
object_trace resolve_object_trace() const;
|
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 = 0);
|
||||||
CPPTRACE_EXPORT stacktrace generate_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
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:
|
// utilities:
|
||||||
CPPTRACE_EXPORT std::string demangle(const std::string& name);
|
CPPTRACE_EXPORT std::string demangle(const std::string& name);
|
||||||
CPPTRACE_EXPORT void absorb_trace_exceptions(bool absorb);
|
CPPTRACE_EXPORT void absorb_trace_exceptions(bool absorb);
|
||||||
|
|||||||
@ -28,6 +28,11 @@
|
|||||||
#define CYAN ESC "36m"
|
#define CYAN ESC "36m"
|
||||||
|
|
||||||
namespace cpptrace {
|
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
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
raw_trace raw_trace::current(std::uint_least32_t skip) {
|
raw_trace raw_trace::current(std::uint_least32_t skip) {
|
||||||
return generate_raw_trace(skip + 1);
|
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
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
object_trace generate_object_trace(std::uint_least32_t skip) {
|
object_trace generate_object_trace(std::uint_least32_t skip) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -14,8 +14,12 @@ namespace detail {
|
|||||||
#else
|
#else
|
||||||
constexpr std::size_t hard_max_frames = 100;
|
constexpr std::size_t hard_max_frames = 100;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
std::vector<frame_ptr> capture_frames(std::size_t skip, std::size_t max_depth);
|
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;
|
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
|
#if IS_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -27,6 +27,12 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
return frames;
|
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);
|
} while(unw_step(&cursor) > 0 && frames.size() < max_depth);
|
||||||
return frames;
|
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) {
|
std::vector<frame_ptr> capture_frames(std::size_t, std::size_t) {
|
||||||
return {};
|
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();
|
frames.shrink_to_fit();
|
||||||
return frames;
|
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;
|
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