Add frame_ptr alias

This commit is contained in:
Jeremy 2023-11-08 21:32:34 -05:00
parent 7929d239bd
commit 4c1c42c61d
No known key found for this signature in database
GPG Key ID: BE03111EB7ED6E2E
16 changed files with 50 additions and 48 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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"

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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());

View File

@ -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) {

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 {};
}
}

View File

@ -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);

View File

@ -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;
}