From 5556aedddb8cc5f40bb5858efa5114b279c8fda8 Mon Sep 17 00:00:00 2001 From: Jeremy <51220084+jeremy-rifkin@users.noreply.github.com> Date: Sat, 25 May 2024 16:18:57 -0500 Subject: [PATCH] Refactor cu lookup out of pc resolution --- src/symbols/dwarf/dwarf_resolver.cpp | 57 +++++++++++++++++++--------- src/utils/dwarf.hpp | 23 +++++++++++ 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/symbols/dwarf/dwarf_resolver.cpp b/src/symbols/dwarf/dwarf_resolver.cpp index c99fefc..fa4da59 100644 --- a/src/symbols/dwarf/dwarf_resolver.cpp +++ b/src/symbols/dwarf/dwarf_resolver.cpp @@ -809,16 +809,17 @@ namespace libdwarf { } } + struct cu_info { + maybe_owned_die_object cu_die; + Dwarf_Half dwversion; + }; + + // CU resolution has three paths: + // - If aranges are present, the pc is looked up in aranges (falls through to next cases if not in aranges) + // - If cache mode is prioritize memory, the CUs are walked for a match + // - Otherwise a CU cache is built up and CUs are looked up in the map CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING - void lookup_pc( - Dwarf_Addr pc, - stacktrace_frame& frame, - std::vector& inlines - ) { - if(dump_dwarf) { - std::fprintf(stderr, "%s\n", object_path.c_str()); - std::fprintf(stderr, "%llx\n", to_ull(pc)); - } + optional lookup_cu(Dwarf_Addr pc) { // Check for .debug_aranges for fast lookup if(aranges) { // Try to find pc in aranges @@ -838,9 +839,8 @@ namespace libdwarf { std::fprintf(stderr, "Found CU in aranges\n"); cu_die.print(); } - retrieve_line_info(cu_die, pc, frame); // no offset for line info - retrieve_symbol(cu_die, pc, dwversion, frame, inlines); - return; + // resolve_pc(cu_die, dwversion, pc, frame, inlines); + return cu_info{maybe_owned_die_object::owned(std::move(cu_die)), dwversion}; } } // otherwise, or if not in aranges @@ -849,7 +849,8 @@ namespace libdwarf { // compiler while the C compiler defaults to an older gcc) if(get_cache_mode() == cache_mode::prioritize_memory) { // walk for the cu and go from there - walk_compilation_units([this, pc, &frame, &inlines] (const die_object& cu_die) { + optional info; + walk_compilation_units([pc, &info] (const die_object& cu_die) { Dwarf_Half offset_size = 0; Dwarf_Half dwversion = 0; dwarf_get_version_of_die(cu_die.get(), &dwversion, &offset_size); @@ -869,12 +870,13 @@ namespace libdwarf { to_ull(pc) ); } - retrieve_line_info(cu_die, pc, frame); // no offset for line info - retrieve_symbol(cu_die, pc, dwversion, frame, inlines); + // resolve_pc(cu_die, dwversion, pc, frame, inlines); + info = cu_info{maybe_owned_die_object::owned(cu_die.clone()), dwversion}; return false; } return true; }); + return info; } else { lazy_generate_cu_cache(); // look up the cu @@ -890,14 +892,33 @@ namespace libdwarf { if(vec_it != cu_cache.end()) { //vec_it->die.print(); if(vec_it->die.pc_in_die(vec_it->dwversion, pc)) { - retrieve_line_info(vec_it->die, pc, frame); // no offset for line info - retrieve_symbol(vec_it->die, pc, vec_it->dwversion, frame, inlines); + // resolve_pc(vec_it->die, vec_it->dwversion, pc, frame, inlines); + return cu_info{maybe_owned_die_object::ref(vec_it->die), vec_it->dwversion}; } } else { // I've had this happen for _start, where there is a cached CU for the object but _start is outside // of the CU's PC range // ASSERT(cu_cache.size() == 0, "Vec should be empty?"); } + return nullopt; + } + } + + CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING + void resolve_pc( + Dwarf_Addr pc, + stacktrace_frame& frame, + std::vector& inlines + ) { + if(dump_dwarf) { + std::fprintf(stderr, "%s\n", object_path.c_str()); + std::fprintf(stderr, "%llx\n", to_ull(pc)); + } + optional cu = lookup_cu(pc); + if(cu) { + const auto& cu_die = cu.unwrap().cu_die.get(); + retrieve_line_info(cu_die, pc, frame); + retrieve_symbol(cu_die, pc, cu.unwrap().dwversion, frame, inlines); } } @@ -931,7 +952,7 @@ namespace libdwarf { ); } std::vector inlines; - lookup_pc( + resolve_pc( frame_info.object_address, frame, inlines diff --git a/src/utils/dwarf.hpp b/src/utils/dwarf.hpp index 80aa839..3cbef03 100644 --- a/src/utils/dwarf.hpp +++ b/src/utils/dwarf.hpp @@ -491,6 +491,29 @@ namespace libdwarf { } ); } + + class maybe_owned_die_object { + // Hacky... I wish std::variant existed. + optional owned_die; + optional ref_die; + maybe_owned_die_object(die_object&& die) : owned_die(std::move(die)) {} + maybe_owned_die_object(const die_object& die) : ref_die(&die) {} + public: + static maybe_owned_die_object owned(die_object&& die) { + return maybe_owned_die_object{std::move(die)}; + } + static maybe_owned_die_object ref(const die_object& die) { + return maybe_owned_die_object{die}; + } + const die_object& get() { + ASSERT(owned_die || ref_die, "Mal-formed maybe_owned_die_object"); + if(owned_die) { + return owned_die.unwrap(); + } else { + return *ref_die.unwrap(); + } + } + }; } } }