Setup global dwarf_resolver cache for dwarf resolving

This commit is contained in:
Jeremy 2023-09-30 03:37:16 -04:00
parent e82f6e360f
commit d4bc913607
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4

View File

@ -17,6 +17,7 @@
#include <mutex>
#include <stdexcept>
#include <type_traits>
#include <unordered_map>
#include <vector>
#include <libdwarf.h>
@ -199,6 +200,39 @@ namespace libdwarf {
}
}
dwarf_resolver(const dwarf_resolver&) = delete;
dwarf_resolver& operator=(const dwarf_resolver&) = delete;
dwarf_resolver(dwarf_resolver&& other) :
obj_path(std::move(other.obj_path)),
dbg(other.dbg),
ok(other.ok),
aranges(other.aranges),
arange_count(other.arange_count),
line_contexts(std::move(other.line_contexts)),
subprograms_cache(std::move(other.subprograms_cache)),
cu_cache(std::move(other.cu_cache)),
tmp_object_path(std::move(other.tmp_object_path))
{
other.dbg = nullptr;
other.aranges = nullptr;
}
dwarf_resolver& operator=(dwarf_resolver&& other) {
obj_path = std::move(other.obj_path);
dbg = other.dbg;
ok = other.ok;
aranges = other.aranges;
arange_count = other.arange_count;
line_contexts = std::move(other.line_contexts);
subprograms_cache = std::move(other.subprograms_cache);
cu_cache = std::move(other.cu_cache);
tmp_object_path = std::move(other.tmp_object_path);
other.dbg = nullptr;
other.aranges = nullptr;
return *this;
}
// walk all CU's in a dbg, callback is called on each die and should return true to
// continue traversal
void walk_compilation_units(std::function<bool(const die_object&)> fn) {
@ -633,19 +667,29 @@ namespace libdwarf {
std::vector<stacktrace_frame> resolve_frames(const std::vector<object_frame>& frames) {
std::vector<stacktrace_frame> trace(frames.size(), null_frame);
static std::mutex mutex;
// cache resolvers since objects are likely to be traced more than once
static std::unordered_map<std::string, dwarf_resolver> resolver_map;
// Locking around all libdwarf interaction per https://github.com/davea42/libdwarf-code/discussions/184
const std::lock_guard<std::mutex> lock(mutex);
for(const auto& obj_entry : collate_frames(frames, trace)) {
try {
const auto& obj_name = obj_entry.first;
dwarf_resolver resolver(obj_name);
optional<dwarf_resolver> resolver_object;// = nullopt;
dwarf_resolver* resolver = nullptr;
auto it = resolver_map.find(obj_name);
if(it != resolver_map.end()) {
resolver = &it->second;
} else {
resolver_object = dwarf_resolver(obj_name);
resolver = &resolver_object.unwrap();
}
// If there's no debug information it'll mark itself as not ok
if(resolver.ok) {
if(resolver->ok) {
for(const auto& entry : obj_entry.second) {
try {
const auto& dlframe = entry.first.get();
auto& frame = entry.second.get();
frame = resolver.resolve_frame(dlframe);
frame = resolver->resolve_frame(dlframe);
} catch(...) {
if(!should_absorb_trace_exceptions()) {
throw;
@ -653,6 +697,9 @@ namespace libdwarf {
}
}
}
if(resolver_object.has_value() && get_cache_mode() == cache_mode::prioritize_speed) {
resolver_map.insert({obj_name, std::move(resolver_object).unwrap()});
}
} catch(...) {
if(!should_absorb_trace_exceptions()) {
throw;