Handle multiple symbol back-ends better

This commit is contained in:
Jeremy 2023-11-15 15:09:08 -05:00
parent fec5324502
commit 79bc580519
No known key found for this signature in database
GPG Key ID: BE03111EB7ED6E2E
4 changed files with 94 additions and 66 deletions

View File

@ -604,6 +604,9 @@ configurable with `CPPTRACE_HARD_MAX_FRAMES`.
*: Requires installation
One back-end should be used. For MinGW `CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF` and `CPPTRACE_GET_SYMBOLS_WITH_DBGHELP` can
be used in conjunction.
Note for addr2line: By default cmake will resolve an absolute path to addr2line to bake into the library. This path can
be configured with `CPPTRACE_ADDR2LINE_PATH`, or `CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH` can be used to have the library
search the system path for `addr2line` at runtime. This is not the default to prevent against path injection attacks.

View File

@ -55,31 +55,43 @@ namespace detail {
*
*/
void apply_trace(
std::vector<stacktrace_frame>& result,
std::vector<stacktrace_frame>&& trace
// Resolver must not support walking inlines
void fill_blanks(
std::vector<stacktrace_frame>& vec,
std::vector<stacktrace_frame> (*resolver)(const std::vector<frame_ptr>&)
) {
for(std::size_t i = 0; i < result.size(); i++) {
if(result[i].address == 0) {
result[i].address = trace[i].address;
std::vector<frame_ptr> addresses;
for(const auto& frame : vec) {
if(frame.symbol.empty() || frame.filename.empty()) {
addresses.push_back(frame.address);
}
if(!result[i].line.has_value()) {
result[i].line = trace[i].line;
}
if(!result[i].column.has_value()) {
result[i].column = trace[i].column;
std::vector<stacktrace_frame> new_frames = resolver(addresses);
std::size_t i = 0;
for(auto& frame : vec) {
if(frame.symbol.empty() || frame.filename.empty()) {
// three cases to handle, either partially overwrite or fully overwrite
if(frame.symbol.empty() && frame.filename.empty()) {
frame = new_frames[i];
} else if(frame.symbol.empty() && !frame.filename.empty()) {
frame.symbol = new_frames[i].symbol;
} else {
ASSERT(!frame.symbol.empty() && frame.filename.empty());
frame.filename = new_frames[i].filename;
frame.line = new_frames[i].line;
frame.column = new_frames[i].column;
}
if(result[i].filename.empty()) {
result[i].filename = std::move(trace[i].filename);
}
if(result[i].symbol.empty()) {
result[i].symbol = std::move(trace[i].symbol);
i++;
}
}
}
std::vector<stacktrace_frame> resolve_frames(const std::vector<object_frame>& frames) {
std::vector<stacktrace_frame> trace(frames.size(), null_frame);
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) && defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
std::vector<stacktrace_frame> trace = libdwarf::resolve_frames(frames);
fill_blanks(trace, dbghelp::resolve_frames);
return trace;
#else
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDL) \
|| defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP) \
|| defined(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE)
@ -90,24 +102,24 @@ namespace detail {
}
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
apply_trace(trace, libdl::resolve_frames(raw_frames));
return libdl::resolve_frames(raw_frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
apply_trace(trace, libdwarf::resolve_frames(frames));
return libdwarf::resolve_frames(frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
apply_trace(trace, dbghelp::resolve_frames(raw_frames));
return dbghelp::resolve_frames(raw_frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
apply_trace(trace, addr2line::resolve_frames(frames));
return addr2line::resolve_frames(frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
apply_trace(trace, libbacktrace::resolve_frames(raw_frames));
return libbacktrace::resolve_frames(raw_frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
apply_trace(trace, nothing::resolve_frames(frames));
return nothing::resolve_frames(frames);
#endif
#endif
return trace;
}
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
@ -115,26 +127,30 @@ namespace detail {
|| defined(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
auto dlframes = get_frames_object_info(frames);
#endif
std::vector<stacktrace_frame> trace(frames.size(), null_frame);
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) && defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
std::vector<stacktrace_frame> trace = libdwarf::resolve_frames(dlframes);
fill_blanks(trace, dbghelp::resolve_frames);
return trace;
#else
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
apply_trace(trace, libdl::resolve_frames(frames));
return libdl::resolve_frames(frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
apply_trace(trace, libdwarf::resolve_frames(dlframes));
return libdwarf::resolve_frames(dlframes);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
apply_trace(trace, dbghelp::resolve_frames(frames));
return dbghelp::resolve_frames(frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
apply_trace(trace, addr2line::resolve_frames(dlframes));
return addr2line::resolve_frames(dlframes);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
apply_trace(trace, libbacktrace::resolve_frames(frames));
return libbacktrace::resolve_frames(frames);
#endif
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
apply_trace(trace, nothing::resolve_frames(frames));
return nothing::resolve_frames(frames);
#endif
#endif
return trace;
}
}
}

View File

@ -421,7 +421,9 @@ namespace dbghelp {
if(!detail::should_absorb_trace_exceptions()) {
throw;
}
trace.push_back(null_frame);
auto entry = null_frame;
entry.address = frame;
trace.push_back(entry);
}
}
if(get_cache_mode() != cache_mode::prioritize_speed) {

View File

@ -881,12 +881,19 @@ namespace libdwarf {
const auto& dlframe = entry.first.get();
auto& frame = entry.second.get();
frame = resolver->resolve_frame(dlframe);
} catch(...) { // NOSONAR
} catch(...) {
if(!should_absorb_trace_exceptions()) {
throw;
}
}
}
} else {
// at least copy the addresses
for(const auto& entry : obj_entry.second) {
const auto& dlframe = entry.first.get();
auto& frame = entry.second.get();
frame.frame.address = dlframe.raw_address;
}
}
if(resolver_object.has_value() && get_cache_mode() == cache_mode::prioritize_speed) {
// .emplace needed, for some reason .insert tries to copy <= gcc 7.2