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 *: 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 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 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. search the system path for `addr2line` at runtime. This is not the default to prevent against path injection attacks.

View File

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

View File

@ -421,7 +421,9 @@ namespace dbghelp {
if(!detail::should_absorb_trace_exceptions()) { if(!detail::should_absorb_trace_exceptions()) {
throw; 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) { if(get_cache_mode() != cache_mode::prioritize_speed) {

View File

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