Handle multiple symbol back-ends better
This commit is contained in:
parent
fec5324502
commit
79bc580519
@ -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.
|
||||||
|
|||||||
@ -55,31 +55,43 @@ 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;
|
|
||||||
}
|
}
|
||||||
if(!result[i].column.has_value()) {
|
std::vector<stacktrace_frame> new_frames = resolver(addresses);
|
||||||
result[i].column = trace[i].column;
|
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()) {
|
i++;
|
||||||
result[i].filename = std::move(trace[i].filename);
|
|
||||||
}
|
|
||||||
if(result[i].symbol.empty()) {
|
|
||||||
result[i].symbol = std::move(trace[i].symbol);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
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) \
|
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDL) \
|
||||||
|| defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP) \
|
|| defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP) \
|
||||||
|| defined(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE)
|
|| defined(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE)
|
||||||
@ -90,24 +102,24 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
||||||
apply_trace(trace, libdl::resolve_frames(raw_frames));
|
return libdl::resolve_frames(raw_frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
||||||
apply_trace(trace, libdwarf::resolve_frames(frames));
|
return libdwarf::resolve_frames(frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
||||||
apply_trace(trace, dbghelp::resolve_frames(raw_frames));
|
return dbghelp::resolve_frames(raw_frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
||||||
apply_trace(trace, addr2line::resolve_frames(frames));
|
return addr2line::resolve_frames(frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
||||||
apply_trace(trace, libbacktrace::resolve_frames(raw_frames));
|
return libbacktrace::resolve_frames(raw_frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
||||||
apply_trace(trace, nothing::resolve_frames(frames));
|
return nothing::resolve_frames(frames);
|
||||||
|
#endif
|
||||||
#endif
|
#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)
|
||||||
|
std::vector<stacktrace_frame> trace = libdwarf::resolve_frames(dlframes);
|
||||||
|
fill_blanks(trace, dbghelp::resolve_frames);
|
||||||
|
return trace;
|
||||||
|
#else
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
||||||
apply_trace(trace, libdl::resolve_frames(frames));
|
return libdl::resolve_frames(frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
||||||
apply_trace(trace, libdwarf::resolve_frames(dlframes));
|
return libdwarf::resolve_frames(dlframes);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
||||||
apply_trace(trace, dbghelp::resolve_frames(frames));
|
return dbghelp::resolve_frames(frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
||||||
apply_trace(trace, addr2line::resolve_frames(dlframes));
|
return addr2line::resolve_frames(dlframes);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
||||||
apply_trace(trace, libbacktrace::resolve_frames(frames));
|
return libbacktrace::resolve_frames(frames);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
||||||
apply_trace(trace, nothing::resolve_frames(frames));
|
return nothing::resolve_frames(frames);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return trace;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user