Refactor frame collation from addr2line

This commit is contained in:
Jeremy 2023-09-16 21:54:44 -04:00
parent fdbc69e18e
commit 5e4e842704
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
3 changed files with 40 additions and 43 deletions

View File

@ -6,8 +6,19 @@
#include <memory>
#include <vector>
#include "../platform/object.hpp"
namespace cpptrace {
namespace detail {
using collated_vec = std::vector<
std::pair<std::reference_wrapper<const dlframe>, std::reference_wrapper<stacktrace_frame>>
>;
std::unordered_map<std::string, collated_vec> collate_frames(
const std::vector<dlframe>& frames,
std::vector<stacktrace_frame>& trace
);
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
namespace libbacktrace {
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
@ -38,6 +49,7 @@ namespace detail {
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
}
#endif
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
}
}

View File

@ -7,6 +7,25 @@
namespace cpptrace {
namespace detail {
std::unordered_map<std::string, collated_vec> collate_frames(
const std::vector<dlframe>& frames,
std::vector<stacktrace_frame>& trace
) {
std::unordered_map<std::string, collated_vec> entries;
for(std::size_t i = 0; i < frames.size(); i++) {
const auto& entry = frames[i];
// If libdl fails to find the shared object for a frame, the path will be empty. I've observed this
// on macos when looking up the shared object containing `start`.
if(!entry.obj_path.empty()) {
entries[entry.obj_path].emplace_back(
entry,
trace[i]
);
}
}
return entries;
}
void apply_trace(
std::vector<stacktrace_frame>& result,
std::vector<stacktrace_frame>&& trace

View File

@ -190,45 +190,8 @@ namespace addr2line {
}
#endif
using target_vec = std::vector<std::pair<std::string, std::reference_wrapper<stacktrace_frame>>>;
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
std::unordered_map<std::string, target_vec> get_addr2line_targets(
const std::vector<dlframe>& dlframes,
std::vector<stacktrace_frame>& trace
) {
std::unordered_map<std::string, target_vec> entries;
for(std::size_t i = 0; i < dlframes.size(); i++) {
const auto& entry = dlframes[i];
// If libdl fails to find the shared object for a frame, the path will be empty. I've observed this
// on macos when looking up the shared object containing `start`.
if(!entry.obj_path.empty()) {
///fprintf(
/// stderr,
/// "%s %s\n",
/// to_hex(entry.raw_address).c_str(),
/// to_hex(entry.raw_address - entry.obj_base + base).c_str()
///);
try {
entries[entry.obj_path].emplace_back(
to_hex(entry.obj_address),
trace[i]
);
} catch(file_error&) {
//
} catch(...) {
throw;
}
// Set what is known for now, and resolutions from addr2line should overwrite
trace[i].filename = entry.obj_path;
trace[i].symbol = entry.symbol;
}
}
return entries;
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
void update_trace(const std::string& line, size_t entry_index, const target_vec& entries_vec) {
void update_trace(const std::string& line, size_t entry_index, const collated_vec& entries_vec) {
#if !IS_APPLE
// Result will be of the form "<symbol> at path:line"
// The path may be ?? if addr2line cannot resolve, line may be ?
@ -311,12 +274,15 @@ namespace addr2line {
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
// TODO: Refactor better
std::vector<stacktrace_frame> trace(frames.size(), stacktrace_frame { 0, 0, 0, "", "" });
for(size_t i = 0; i < frames.size(); i++) {
trace[i].address = reinterpret_cast<uintptr_t>(frames[i]);
const std::vector<dlframe> dlframes = get_frames_object_info(frames);
for(size_t i = 0; i < dlframes.size(); i++) {
trace[i].address = dlframes[i].raw_address;
// Set what is known for now, and resolutions from addr2line should overwrite
trace[i].filename = dlframes[i].obj_path;
trace[i].symbol = dlframes[i].symbol;
}
if(has_addr2line()) {
const std::vector<dlframe> dlframes = get_frames_object_info(frames);
const auto entries = get_addr2line_targets(dlframes, trace);
const auto entries = collate_frames(dlframes, trace);
for(const auto& entry : entries) {
const auto& object_name = entry.first;
const auto& entries_vec = entry.second;
@ -329,7 +295,7 @@ namespace addr2line {
}
std::string address_input;
for(const auto& pair : entries_vec) {
address_input += pair.first;
address_input += to_hex(pair.first.get().obj_address);
#if !IS_WINDOWS
address_input += '\n';
#else