Fallback to the cu cache or walking cu's if aranges lookup fails
This commit is contained in:
parent
aa5315769e
commit
e8fd01bbe1
@ -95,6 +95,7 @@ namespace libdwarf {
|
|||||||
std::unordered_map<Dwarf_Off, std::vector<subprogram_entry>> subprograms_cache;
|
std::unordered_map<Dwarf_Off, std::vector<subprogram_entry>> subprograms_cache;
|
||||||
// Vector of ranges and their corresponding CU offsets
|
// Vector of ranges and their corresponding CU offsets
|
||||||
std::vector<cu_entry> cu_cache;
|
std::vector<cu_entry> cu_cache;
|
||||||
|
bool generated_cu_cache = false;
|
||||||
// Map from CU -> {srcfiles, count}
|
// Map from CU -> {srcfiles, count}
|
||||||
std::unordered_map<Dwarf_Off, std::pair<char**, Dwarf_Signed>> srcfiles_cache;
|
std::unordered_map<Dwarf_Off, std::pair<char**, Dwarf_Signed>> srcfiles_cache;
|
||||||
|
|
||||||
@ -165,21 +166,6 @@ namespace libdwarf {
|
|||||||
// Check for .debug_aranges for fast lookup
|
// Check for .debug_aranges for fast lookup
|
||||||
wrap(dwarf_get_aranges, dbg, &aranges, &arange_count);
|
wrap(dwarf_get_aranges, dbg, &aranges, &arange_count);
|
||||||
}
|
}
|
||||||
if(ok && !aranges && get_cache_mode() != cache_mode::prioritize_memory) {
|
|
||||||
walk_compilation_units([this] (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);
|
|
||||||
auto ranges_vec = cu_die.get_rangelist_entries(dwversion);
|
|
||||||
for(auto range : ranges_vec) {
|
|
||||||
cu_cache.push_back({ cu_die.clone(), dwversion, range.first, range.second });
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
std::sort(cu_cache.begin(), cu_cache.end(), [] (const cu_entry& a, const cu_entry& b) {
|
|
||||||
return a.low < b.low;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING
|
CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING
|
||||||
@ -213,6 +199,7 @@ namespace libdwarf {
|
|||||||
line_contexts(std::move(other.line_contexts)),
|
line_contexts(std::move(other.line_contexts)),
|
||||||
subprograms_cache(std::move(other.subprograms_cache)),
|
subprograms_cache(std::move(other.subprograms_cache)),
|
||||||
cu_cache(std::move(other.cu_cache)),
|
cu_cache(std::move(other.cu_cache)),
|
||||||
|
generated_cu_cache(other.generated_cu_cache),
|
||||||
srcfiles_cache(std::move(other.srcfiles_cache))
|
srcfiles_cache(std::move(other.srcfiles_cache))
|
||||||
{
|
{
|
||||||
other.dbg = nullptr;
|
other.dbg = nullptr;
|
||||||
@ -228,6 +215,7 @@ namespace libdwarf {
|
|||||||
line_contexts = std::move(other.line_contexts);
|
line_contexts = std::move(other.line_contexts);
|
||||||
subprograms_cache = std::move(other.subprograms_cache);
|
subprograms_cache = std::move(other.subprograms_cache);
|
||||||
cu_cache = std::move(other.cu_cache);
|
cu_cache = std::move(other.cu_cache);
|
||||||
|
generated_cu_cache = other.generated_cu_cache;
|
||||||
srcfiles_cache = std::move(other.srcfiles_cache);
|
srcfiles_cache = std::move(other.srcfiles_cache);
|
||||||
other.dbg = nullptr;
|
other.dbg = nullptr;
|
||||||
other.aranges = nullptr;
|
other.aranges = nullptr;
|
||||||
@ -282,6 +270,25 @@ namespace libdwarf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lazy_generate_cu_cache() {
|
||||||
|
if(!generated_cu_cache) {
|
||||||
|
walk_compilation_units([this] (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);
|
||||||
|
auto ranges_vec = cu_die.get_rangelist_entries(dwversion);
|
||||||
|
for(auto range : ranges_vec) {
|
||||||
|
cu_cache.push_back({ cu_die.clone(), dwversion, range.first, range.second });
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
std::sort(cu_cache.begin(), cu_cache.end(), [] (const cu_entry& a, const cu_entry& b) {
|
||||||
|
return a.low < b.low;
|
||||||
|
});
|
||||||
|
generated_cu_cache = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string subprogram_symbol(
|
std::string subprogram_symbol(
|
||||||
const die_object& die,
|
const die_object& die,
|
||||||
Dwarf_Half dwversion
|
Dwarf_Half dwversion
|
||||||
@ -787,61 +794,66 @@ namespace libdwarf {
|
|||||||
}
|
}
|
||||||
retrieve_line_info(cu_die, pc, frame); // no offset for line info
|
retrieve_line_info(cu_die, pc, frame); // no offset for line info
|
||||||
retrieve_symbol(cu_die, pc, dwversion, frame, inlines);
|
retrieve_symbol(cu_die, pc, dwversion, frame, inlines);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if(get_cache_mode() == cache_mode::prioritize_memory) {
|
// otherwise, or if not in aranges
|
||||||
// walk for the cu and go from there
|
// one reason to fallback here is if the compilation has dwarf generated from different compilers and only
|
||||||
walk_compilation_units([this, pc, &frame, &inlines] (const die_object& cu_die) {
|
// some of them generate aranges (e.g. static linking with cpptrace after specifying clang++ as the c++
|
||||||
Dwarf_Half offset_size = 0;
|
// compiler while the C compiler defaults to an older gcc)
|
||||||
Dwarf_Half dwversion = 0;
|
if(get_cache_mode() == cache_mode::prioritize_memory) {
|
||||||
dwarf_get_version_of_die(cu_die.get(), &dwversion, &offset_size);
|
// walk for the cu and go from there
|
||||||
//auto p = cu_die.get_pc_range(dwversion);
|
walk_compilation_units([this, pc, &frame, &inlines] (const die_object& cu_die) {
|
||||||
//cu_die.print();
|
Dwarf_Half offset_size = 0;
|
||||||
//fprintf(stderr, " %llx, %llx\n", p.first, p.second);
|
Dwarf_Half dwversion = 0;
|
||||||
|
dwarf_get_version_of_die(cu_die.get(), &dwversion, &offset_size);
|
||||||
|
//auto p = cu_die.get_pc_range(dwversion);
|
||||||
|
//cu_die.print();
|
||||||
|
//fprintf(stderr, " %llx, %llx\n", p.first, p.second);
|
||||||
|
if(trace_dwarf) {
|
||||||
|
std::fprintf(stderr, "CU: %d %s\n", dwversion, cu_die.get_name().c_str());
|
||||||
|
}
|
||||||
|
if(cu_die.pc_in_die(dwversion, pc)) {
|
||||||
if(trace_dwarf) {
|
if(trace_dwarf) {
|
||||||
std::fprintf(stderr, "CU: %d %s\n", dwversion, cu_die.get_name().c_str());
|
std::fprintf(
|
||||||
|
stderr,
|
||||||
|
"pc in die %08llx %s (now searching for %08llx)\n",
|
||||||
|
to_ull(cu_die.get_global_offset()),
|
||||||
|
cu_die.get_tag_name(),
|
||||||
|
to_ull(pc)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(cu_die.pc_in_die(dwversion, pc)) {
|
retrieve_line_info(cu_die, pc, frame); // no offset for line info
|
||||||
if(trace_dwarf) {
|
retrieve_symbol(cu_die, pc, dwversion, frame, inlines);
|
||||||
std::fprintf(
|
return false;
|
||||||
stderr,
|
}
|
||||||
"pc in die %08llx %s (now searching for %08llx)\n",
|
return true;
|
||||||
to_ull(cu_die.get_global_offset()),
|
});
|
||||||
cu_die.get_tag_name(),
|
} else {
|
||||||
to_ull(pc)
|
lazy_generate_cu_cache();
|
||||||
);
|
// look up the cu
|
||||||
}
|
auto vec_it = std::lower_bound(
|
||||||
retrieve_line_info(cu_die, pc, frame); // no offset for line info
|
cu_cache.begin(),
|
||||||
retrieve_symbol(cu_die, pc, dwversion, frame, inlines);
|
cu_cache.end(),
|
||||||
return false;
|
pc,
|
||||||
}
|
[] (const cu_entry& entry, Dwarf_Addr pc) {
|
||||||
return true;
|
return entry.low < pc;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
// vec_it is first >= pc
|
||||||
|
// we want first <= pc
|
||||||
|
if(vec_it != cu_cache.begin()) {
|
||||||
|
vec_it--;
|
||||||
|
}
|
||||||
|
// If the vector has been empty this can happen
|
||||||
|
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);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// look up the cu
|
ASSERT(cu_cache.size() == 0, "Vec should be empty?");
|
||||||
auto vec_it = std::lower_bound(
|
|
||||||
cu_cache.begin(),
|
|
||||||
cu_cache.end(),
|
|
||||||
pc,
|
|
||||||
[] (const cu_entry& entry, Dwarf_Addr pc) {
|
|
||||||
return entry.low < pc;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// vec_it is first >= pc
|
|
||||||
// we want first <= pc
|
|
||||||
if(vec_it != cu_cache.begin()) {
|
|
||||||
vec_it--;
|
|
||||||
}
|
|
||||||
// If the vector has been empty this can happen
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ASSERT(cu_cache.size() == 0, "Vec should be empty?");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user