Add frame_ptr alias
This commit is contained in:
parent
7929d239bd
commit
4c1c42c61d
@ -22,8 +22,10 @@ namespace cpptrace {
|
||||
struct object_trace;
|
||||
struct stacktrace;
|
||||
|
||||
using frame_ptr = std::uintptr_t;
|
||||
|
||||
struct CPPTRACE_EXPORT raw_trace {
|
||||
std::vector<std::uintptr_t> frames;
|
||||
std::vector<frame_ptr> frames;
|
||||
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;
|
||||
@ -31,8 +33,8 @@ namespace cpptrace {
|
||||
void clear();
|
||||
bool empty() const noexcept;
|
||||
|
||||
using iterator = std::vector<std::uintptr_t>::iterator;
|
||||
using const_iterator = std::vector<std::uintptr_t>::const_iterator;
|
||||
using iterator = std::vector<frame_ptr>::iterator;
|
||||
using const_iterator = std::vector<frame_ptr>::const_iterator;
|
||||
inline iterator begin() noexcept { return frames.begin(); }
|
||||
inline iterator end() noexcept { return frames.end(); }
|
||||
inline const_iterator begin() const noexcept { return frames.begin(); }
|
||||
@ -44,8 +46,8 @@ namespace cpptrace {
|
||||
struct CPPTRACE_EXPORT object_frame {
|
||||
std::string obj_path;
|
||||
std::string symbol;
|
||||
std::uintptr_t raw_address = 0;
|
||||
std::uintptr_t obj_address = 0;
|
||||
frame_ptr raw_address = 0;
|
||||
frame_ptr obj_address = 0;
|
||||
};
|
||||
|
||||
struct CPPTRACE_EXPORT object_trace {
|
||||
@ -67,7 +69,7 @@ namespace cpptrace {
|
||||
};
|
||||
|
||||
struct CPPTRACE_EXPORT stacktrace_frame {
|
||||
std::uintptr_t address;
|
||||
frame_ptr address;
|
||||
std::uint_least32_t line; // TODO: This should use UINT_LEAST32_MAX as a sentinel
|
||||
std::uint_least32_t column; // UINT_LEAST32_MAX if not present
|
||||
std::string filename;
|
||||
|
||||
@ -111,7 +111,7 @@ namespace cpptrace {
|
||||
stream
|
||||
<< std::hex
|
||||
<< "0x"
|
||||
<< std::setw(2 * sizeof(std::uintptr_t))
|
||||
<< std::setw(2 * sizeof(frame_ptr))
|
||||
<< std::setfill('0')
|
||||
<< frame.address
|
||||
<< std::dec
|
||||
@ -178,14 +178,14 @@ namespace cpptrace {
|
||||
<< " ";
|
||||
if(frame.is_inline) {
|
||||
stream
|
||||
<< std::setw(2 * sizeof(std::uintptr_t) + 2)
|
||||
<< std::setw(2 * sizeof(frame_ptr) + 2)
|
||||
<< "(inlined)";
|
||||
} else {
|
||||
stream
|
||||
<< std::hex
|
||||
<< blue
|
||||
<< "0x"
|
||||
<< std::setw(2 * sizeof(std::uintptr_t))
|
||||
<< std::setw(2 * sizeof(frame_ptr))
|
||||
<< std::setfill('0')
|
||||
<< frame.address
|
||||
<< std::dec
|
||||
@ -295,7 +295,7 @@ namespace cpptrace {
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
stacktrace generate_trace(std::uint32_t skip, std::uint_least32_t max_depth) {
|
||||
try {
|
||||
std::vector<std::uintptr_t> frames = detail::capture_frames(skip + 1, max_depth);
|
||||
std::vector<frame_ptr> frames = detail::capture_frames(skip + 1, max_depth);
|
||||
std::vector<stacktrace_frame> trace = detail::resolve_frames(frames);
|
||||
for(auto& frame : trace) {
|
||||
frame.symbol = detail::demangle(frame.symbol);
|
||||
|
||||
@ -62,11 +62,11 @@ namespace detail {
|
||||
}
|
||||
#endif
|
||||
// aladdr queries are needed to get pre-ASLR addresses and targets to run addr2line on
|
||||
inline std::vector<object_frame> get_frames_object_info(const std::vector<std::uintptr_t>& addrs) {
|
||||
inline std::vector<object_frame> get_frames_object_info(const std::vector<frame_ptr>& addrs) {
|
||||
// reference: https://github.com/bminor/glibc/blob/master/debug/backtracesyms.c
|
||||
std::vector<object_frame> frames;
|
||||
frames.reserve(addrs.size());
|
||||
for(const std::uintptr_t addr : addrs) {
|
||||
for(const frame_ptr addr : addrs) {
|
||||
Dl_info info;
|
||||
object_frame frame;
|
||||
frame.raw_address = addr;
|
||||
@ -122,11 +122,11 @@ namespace detail {
|
||||
}
|
||||
|
||||
// aladdr queries are needed to get pre-ASLR addresses and targets to run addr2line on
|
||||
inline std::vector<object_frame> get_frames_object_info(const std::vector<std::uintptr_t>& addrs) {
|
||||
inline std::vector<object_frame> get_frames_object_info(const std::vector<frame_ptr>& addrs) {
|
||||
// reference: https://github.com/bminor/glibc/blob/master/debug/backtracesyms.c
|
||||
std::vector<object_frame> frames;
|
||||
frames.reserve(addrs.size());
|
||||
for(const std::uintptr_t addr : addrs) {
|
||||
for(const frame_ptr addr : addrs) {
|
||||
object_frame frame;
|
||||
frame.raw_address = addr;
|
||||
HMODULE handle;
|
||||
|
||||
@ -352,8 +352,8 @@ namespace detail {
|
||||
return static_cast<unsigned long long>(t);
|
||||
}
|
||||
template<typename T>
|
||||
std::uintptr_t to_uintptr(T t) {
|
||||
return static_cast<std::uintptr_t>(t);
|
||||
frame_ptr to_frame_ptr(T t) {
|
||||
return static_cast<frame_ptr>(t);
|
||||
}
|
||||
|
||||
// A way to cast to U without "warning: useless cast to type"
|
||||
|
||||
@ -32,7 +32,7 @@ namespace detail {
|
||||
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
||||
namespace libbacktrace {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames);
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
||||
@ -42,7 +42,7 @@ namespace detail {
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
||||
namespace libdl {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames);
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
||||
@ -52,18 +52,18 @@ namespace detail {
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
||||
namespace dbghelp {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames);
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
||||
namespace nothing {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<object_frame>& frames);
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames);
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<object_frame>& frames);
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames);
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ namespace detail {
|
||||
|| defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP) \
|
||||
|| defined(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE)
|
||||
// actually need to go backwards to a void*
|
||||
std::vector<std::uintptr_t> raw_frames(frames.size());
|
||||
std::vector<frame_ptr> raw_frames(frames.size());
|
||||
for(std::size_t i = 0; i < frames.size(); i++) {
|
||||
raw_frames[i] = frames[i].raw_address;
|
||||
}
|
||||
@ -110,7 +110,7 @@ namespace detail {
|
||||
return trace;
|
||||
}
|
||||
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames) {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
|
||||
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) \
|
||||
|| defined(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
|
||||
auto dlframes = get_frames_object_info(frames);
|
||||
|
||||
@ -325,7 +325,7 @@ namespace dbghelp {
|
||||
std::recursive_mutex dbghelp_lock;
|
||||
|
||||
// TODO: Handle backtrace_pcinfo calling the callback multiple times on inlined functions
|
||||
stacktrace_frame resolve_frame(HANDLE proc, std::uintptr_t addr) {
|
||||
stacktrace_frame resolve_frame(HANDLE proc, frame_ptr addr) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(dbghelp_lock); // all dbghelp functions are not thread safe
|
||||
alignas(SYMBOL_INFO) char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||||
SYMBOL_INFO* symbol = (SYMBOL_INFO*)buffer;
|
||||
@ -390,7 +390,7 @@ namespace dbghelp {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames) {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(dbghelp_lock); // all dbghelp functions are not thread safe
|
||||
std::vector<stacktrace_frame> trace;
|
||||
trace.reserve(frames.size());
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace libdl {
|
||||
stacktrace_frame resolve_frame(const std::uintptr_t addr) {
|
||||
stacktrace_frame resolve_frame(const frame_ptr addr) {
|
||||
Dl_info info;
|
||||
if(dladdr(reinterpret_cast<void*>(addr), &info)) { // thread-safe
|
||||
return {
|
||||
@ -33,7 +33,7 @@ namespace libdl {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames) {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
|
||||
std::vector<stacktrace_frame> trace;
|
||||
trace.reserve(frames.size());
|
||||
for(const auto frame : frames) {
|
||||
|
||||
@ -55,7 +55,7 @@ namespace libbacktrace {
|
||||
}
|
||||
|
||||
// TODO: Handle backtrace_pcinfo calling the callback multiple times on inlined functions
|
||||
stacktrace_frame resolve_frame(const std::uintptr_t addr) {
|
||||
stacktrace_frame resolve_frame(const frame_ptr addr) {
|
||||
try {
|
||||
stacktrace_frame frame;
|
||||
frame.column = UINT_LEAST32_MAX;
|
||||
@ -85,7 +85,7 @@ namespace libbacktrace {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames) {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
|
||||
std::vector<stacktrace_frame> trace;
|
||||
trace.reserve(frames.size());
|
||||
for(const auto frame : frames) {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace nothing {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<std::uintptr_t>& frames) {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
|
||||
return std::vector<stacktrace_frame>(frames.size(), null_frame);
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ namespace detail {
|
||||
constexpr std::size_t hard_max_frames = 100;
|
||||
#endif
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::vector<std::uintptr_t> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ namespace detail {
|
||||
#pragma warning(disable: 4740) // warning C4740: flow in or out of inline asm code suppresses global optimization
|
||||
#endif
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::vector<std::uintptr_t> 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) {
|
||||
skip++;
|
||||
// https://jpassing.com/2008/03/12/walking-the-stack-of-the-current-thread/
|
||||
|
||||
@ -94,7 +94,7 @@ namespace detail {
|
||||
#error "Cpptrace: StackWalk64 not supported for this platform yet"
|
||||
#endif
|
||||
|
||||
std::vector<std::uintptr_t> trace;
|
||||
std::vector<frame_ptr> trace;
|
||||
|
||||
// Dbghelp is is single-threaded, so acquire a lock.
|
||||
static std::mutex mutex;
|
||||
@ -138,7 +138,7 @@ namespace detail {
|
||||
// On x86/x64/arm, as far as I can tell, the frame return address is always one after the call
|
||||
// So we just decrement to get the pc back inside the `call` / `bl`
|
||||
// This is done with _Unwind too but conditionally based on info from _Unwind_GetIPInfo.
|
||||
trace.push_back(to_uintptr(frame.AddrPC.Offset) - 1);
|
||||
trace.push_back(to_frame_ptr(frame.AddrPC.Offset) - 1);
|
||||
}
|
||||
} else {
|
||||
// base
|
||||
|
||||
@ -13,17 +13,17 @@
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::vector<std::uintptr_t> 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) {
|
||||
skip++;
|
||||
std::vector<void*> addrs(std::min(hard_max_frames, skip + max_depth), nullptr);
|
||||
const int n_frames = backtrace(addrs.data(), static_cast<int>(addrs.size())); // thread safe
|
||||
// I hate the copy here but it's the only way that isn't UB
|
||||
std::vector<std::uintptr_t> frames(n_frames - skip, 0);
|
||||
std::vector<frame_ptr> frames(n_frames - skip, 0);
|
||||
for(int i = skip; i < n_frames; i++) {
|
||||
// On x86/x64/arm, as far as I can tell, the frame return address is always one after the call
|
||||
// So we just decrement to get the pc back inside the `call` / `bl`
|
||||
// This is done with _Unwind too but conditionally based on info from _Unwind_GetIPInfo.
|
||||
frames[i - skip] = reinterpret_cast<std::uintptr_t>(addrs[i]) - 1;
|
||||
frames[i - skip] = reinterpret_cast<frame_ptr>(addrs[i]) - 1;
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
std::vector<std::uintptr_t> capture_frames(std::size_t, std::size_t) {
|
||||
std::vector<frame_ptr> capture_frames(std::size_t, std::size_t) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,14 +17,14 @@ namespace detail {
|
||||
struct unwind_state {
|
||||
std::size_t skip;
|
||||
std::size_t count;
|
||||
std::vector<std::uintptr_t>& vec;
|
||||
std::vector<frame_ptr>& vec;
|
||||
};
|
||||
|
||||
_Unwind_Reason_Code unwind_callback(_Unwind_Context* context, void* arg) {
|
||||
unwind_state& state = *static_cast<unwind_state*>(arg);
|
||||
if(state.skip) {
|
||||
state.skip--;
|
||||
if(_Unwind_GetIP(context) == std::uintptr_t(0)) {
|
||||
if(_Unwind_GetIP(context) == frame_ptr(0)) {
|
||||
return _URC_END_OF_STACK;
|
||||
} else {
|
||||
return _URC_NO_REASON;
|
||||
@ -36,11 +36,11 @@ namespace detail {
|
||||
"Somehow cpptrace::detail::unwind_callback is overflowing a vector"
|
||||
);
|
||||
int is_before_instruction = 0;
|
||||
std::uintptr_t ip = _Unwind_GetIPInfo(context, &is_before_instruction);
|
||||
if(!is_before_instruction && ip != std::uintptr_t(0)) {
|
||||
frame_ptr ip = _Unwind_GetIPInfo(context, &is_before_instruction);
|
||||
if(!is_before_instruction && ip != frame_ptr(0)) {
|
||||
ip--;
|
||||
}
|
||||
if (ip == std::uintptr_t(0)) {
|
||||
if (ip == frame_ptr(0)) {
|
||||
return _URC_END_OF_STACK;
|
||||
} else {
|
||||
// TODO: push_back?...
|
||||
@ -54,8 +54,8 @@ namespace detail {
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::vector<std::uintptr_t> capture_frames(std::size_t skip, std::size_t max_depth) {
|
||||
std::vector<std::uintptr_t> frames(std::min(hard_max_frames, max_depth), 0);
|
||||
std::vector<frame_ptr> capture_frames(std::size_t skip, std::size_t max_depth) {
|
||||
std::vector<frame_ptr> frames(std::min(hard_max_frames, max_depth), 0);
|
||||
unwind_state state{skip + 1, 0, frames};
|
||||
_Unwind_Backtrace(unwind_callback, &state); // presumably thread-safe
|
||||
frames.resize(state.count);
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
std::vector<std::uintptr_t> 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) {
|
||||
std::vector<void*> addrs(std::min(hard_max_frames, max_depth), nullptr);
|
||||
int n_frames = CaptureStackBackTrace(
|
||||
static_cast<ULONG>(skip + 1),
|
||||
@ -28,12 +28,12 @@ namespace detail {
|
||||
NULL
|
||||
);
|
||||
// I hate the copy here but it's the only way that isn't UB
|
||||
std::vector<std::uintptr_t> frames(n_frames, 0);
|
||||
std::vector<frame_ptr> frames(n_frames, 0);
|
||||
for(std::size_t i = 0; i < n_frames; i++) {
|
||||
// On x86/x64/arm, as far as I can tell, the frame return address is always one after the call
|
||||
// So we just decrement to get the pc back inside the `call` / `bl`
|
||||
// This is done with _Unwind too but conditionally based on info from _Unwind_GetIPInfo.
|
||||
frames[i] = reinterpret_cast<std::uintptr_t>(addrs[i]) - 1;
|
||||
frames[i] = reinterpret_cast<frame_ptr>(addrs[i]) - 1;
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user