Implement better logic for handling scrfile indices, related to #86
This commit is contained in:
parent
cb92c9fdfa
commit
e6627b760d
@ -75,6 +75,7 @@ namespace libdwarf {
|
|||||||
Dwarf_Unsigned version;
|
Dwarf_Unsigned version;
|
||||||
Dwarf_Line_Context line_context;
|
Dwarf_Line_Context line_context;
|
||||||
// sorted by low_addr
|
// sorted by low_addr
|
||||||
|
// TODO: Make this optional at some point, it may not be generated if cache mode switches during program exec...
|
||||||
std::vector<line_entry> line_entries;
|
std::vector<line_entry> line_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ namespace libdwarf {
|
|||||||
Dwarf_Arange* aranges = nullptr;
|
Dwarf_Arange* aranges = nullptr;
|
||||||
Dwarf_Signed arange_count = 0;
|
Dwarf_Signed arange_count = 0;
|
||||||
// Map from CU -> Line context
|
// Map from CU -> Line context
|
||||||
std::unordered_map<Dwarf_Off, line_table_info> line_contexts;
|
std::unordered_map<Dwarf_Off, line_table_info> line_tables;
|
||||||
// Map from CU -> Sorted subprograms vector
|
// Map from CU -> Sorted subprograms vector
|
||||||
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
|
||||||
@ -190,7 +191,7 @@ namespace libdwarf {
|
|||||||
~dwarf_resolver() {
|
~dwarf_resolver() {
|
||||||
// TODO: Maybe redundant since dwarf_finish(dbg); will clean up the line stuff anyway but may as well just
|
// TODO: Maybe redundant since dwarf_finish(dbg); will clean up the line stuff anyway but may as well just
|
||||||
// for thoroughness
|
// for thoroughness
|
||||||
for(auto& entry : line_contexts) {
|
for(auto& entry : line_tables) {
|
||||||
dwarf_srclines_dealloc_b(entry.second.line_context);
|
dwarf_srclines_dealloc_b(entry.second.line_context);
|
||||||
}
|
}
|
||||||
for(auto& entry : srcfiles_cache) {
|
for(auto& entry : srcfiles_cache) {
|
||||||
@ -214,7 +215,7 @@ namespace libdwarf {
|
|||||||
ok(other.ok),
|
ok(other.ok),
|
||||||
aranges(other.aranges),
|
aranges(other.aranges),
|
||||||
arange_count(other.arange_count),
|
arange_count(other.arange_count),
|
||||||
line_contexts(std::move(other.line_contexts)),
|
line_tables(std::move(other.line_tables)),
|
||||||
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),
|
generated_cu_cache(other.generated_cu_cache),
|
||||||
@ -230,7 +231,7 @@ namespace libdwarf {
|
|||||||
ok = other.ok;
|
ok = other.ok;
|
||||||
aranges = other.aranges;
|
aranges = other.aranges;
|
||||||
arange_count = other.arange_count;
|
arange_count = other.arange_count;
|
||||||
line_contexts = std::move(other.line_contexts);
|
line_tables = std::move(other.line_tables);
|
||||||
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;
|
generated_cu_cache = other.generated_cu_cache;
|
||||||
@ -335,6 +336,7 @@ namespace libdwarf {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// despite (some) dwarf using 1-indexing, file_i should be the 0-based index
|
||||||
std::string resolve_filename(const die_object& cu_die, Dwarf_Unsigned file_i) {
|
std::string resolve_filename(const die_object& cu_die, Dwarf_Unsigned file_i) {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
if(get_cache_mode() == cache_mode::prioritize_memory) {
|
if(get_cache_mode() == cache_mode::prioritize_memory) {
|
||||||
@ -343,7 +345,7 @@ namespace libdwarf {
|
|||||||
VERIFY(wrap(dwarf_srcfiles, cu_die.get(), &dw_srcfiles, &dw_filecount) == DW_DLV_OK);
|
VERIFY(wrap(dwarf_srcfiles, cu_die.get(), &dw_srcfiles, &dw_filecount) == DW_DLV_OK);
|
||||||
if(Dwarf_Signed(file_i) < dw_filecount) {
|
if(Dwarf_Signed(file_i) < dw_filecount) {
|
||||||
// dwarf is using 1-indexing
|
// dwarf is using 1-indexing
|
||||||
filename = dw_srcfiles[file_i - 1];
|
filename = dw_srcfiles[file_i];
|
||||||
}
|
}
|
||||||
dwarf_dealloc(cu_die.dbg, dw_srcfiles, DW_DLA_LIST);
|
dwarf_dealloc(cu_die.dbg, dw_srcfiles, DW_DLA_LIST);
|
||||||
} else {
|
} else {
|
||||||
@ -359,7 +361,7 @@ namespace libdwarf {
|
|||||||
Dwarf_Signed dw_filecount = it->second.second;
|
Dwarf_Signed dw_filecount = it->second.second;
|
||||||
if(Dwarf_Signed(file_i) < dw_filecount) {
|
if(Dwarf_Signed(file_i) < dw_filecount) {
|
||||||
// dwarf is using 1-indexing
|
// dwarf is using 1-indexing
|
||||||
filename = dw_srcfiles[file_i - 1];
|
filename = dw_srcfiles[file_i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filename;
|
return filename;
|
||||||
@ -380,14 +382,26 @@ namespace libdwarf {
|
|||||||
[this, &cu_die, pc, dwversion, &inlines] (const die_object& die) {
|
[this, &cu_die, pc, dwversion, &inlines] (const die_object& die) {
|
||||||
if(die.get_tag() == DW_TAG_inlined_subroutine && die.pc_in_die(dwversion, pc)) {
|
if(die.get_tag() == DW_TAG_inlined_subroutine && die.pc_in_die(dwversion, pc)) {
|
||||||
const auto name = subprogram_symbol(die, dwversion);
|
const auto name = subprogram_symbol(die, dwversion);
|
||||||
const auto file_i = die.get_unsigned_attribute(DW_AT_call_file);
|
auto file_i = die.get_unsigned_attribute(DW_AT_call_file);
|
||||||
// TODO: Somehow file_i can end up being 0 here, in a way I don't understand. The string
|
if(file_i) {
|
||||||
// table is 1-indexed and the first string isn't the correct string. Somehow dwarfdump
|
// for dwarf 2, 3, 4, and experimental line table version 0xfe06 1-indexing is used
|
||||||
// resolves this correctly. And also somehow in testing a file name ends up getting used
|
// for dwarf 5 0-indexing is used
|
||||||
// here but I have no idea where it's coming from.
|
auto line_table_opt = get_line_table(cu_die);
|
||||||
std::string file = file_i && file_i.unwrap() > 0
|
if(line_table_opt) {
|
||||||
? resolve_filename(cu_die, file_i.unwrap())
|
auto& line_table = line_table_opt.unwrap().get();
|
||||||
: "";
|
if(line_table.version != 5) {
|
||||||
|
if(file_i.unwrap() == 0) {
|
||||||
|
file_i.reset(); // 0 means no name to be found
|
||||||
|
} else {
|
||||||
|
// decrement to 0-based index
|
||||||
|
file_i.unwrap()--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// silently continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string file = file_i ? resolve_filename(cu_die, file_i.unwrap()) : "";
|
||||||
const auto line = die.get_unsigned_attribute(DW_AT_call_line);
|
const auto line = die.get_unsigned_attribute(DW_AT_call_line);
|
||||||
const auto col = die.get_unsigned_attribute(DW_AT_call_column);
|
const auto col = die.get_unsigned_attribute(DW_AT_call_column);
|
||||||
inlines.push_back(stacktrace_frame{
|
inlines.push_back(stacktrace_frame{
|
||||||
@ -578,24 +592,20 @@ namespace libdwarf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns a reference to a CU's line table, may be invalidated if the line_tables map is modified
|
||||||
CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING
|
CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING
|
||||||
void retrieve_line_info(
|
optional<std::reference_wrapper<line_table_info>> get_line_table(const die_object& cu_die) {
|
||||||
const die_object& die,
|
auto off = cu_die.get_global_offset();
|
||||||
Dwarf_Addr pc,
|
auto it = line_tables.find(off);
|
||||||
stacktrace_frame& frame
|
if(it != line_tables.end()) {
|
||||||
) {
|
return it->second;
|
||||||
auto off = die.get_global_offset();
|
|
||||||
auto it = line_contexts.find(off);
|
|
||||||
if(it != line_contexts.end()) {
|
|
||||||
// auto& entry = it->second;
|
|
||||||
// line_context = entry.line_context;
|
|
||||||
} else {
|
} else {
|
||||||
Dwarf_Unsigned version;
|
Dwarf_Unsigned version;
|
||||||
Dwarf_Small table_count;
|
Dwarf_Small table_count;
|
||||||
Dwarf_Line_Context line_context;
|
Dwarf_Line_Context line_context;
|
||||||
int ret = wrap(
|
int ret = wrap(
|
||||||
dwarf_srclines_b,
|
dwarf_srclines_b,
|
||||||
die.get(),
|
cu_die.get(),
|
||||||
&version,
|
&version,
|
||||||
&table_count,
|
&table_count,
|
||||||
&line_context
|
&line_context
|
||||||
@ -604,7 +614,7 @@ namespace libdwarf {
|
|||||||
VERIFY(/*table_count >= 0 &&*/ table_count <= 2, "Unknown dwarf line table count");
|
VERIFY(/*table_count >= 0 &&*/ table_count <= 2, "Unknown dwarf line table count");
|
||||||
if(ret == DW_DLV_NO_ENTRY) {
|
if(ret == DW_DLV_NO_ENTRY) {
|
||||||
// TODO: Failing silently for now
|
// TODO: Failing silently for now
|
||||||
return;
|
return nullopt;
|
||||||
}
|
}
|
||||||
VERIFY(ret == DW_DLV_OK);
|
VERIFY(ret == DW_DLV_OK);
|
||||||
|
|
||||||
@ -672,11 +682,22 @@ namespace libdwarf {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it = line_contexts.insert({off, {version, line_context, std::move(line_entries)}}).first;
|
it = line_tables.insert({off, {version, line_context, std::move(line_entries)}}).first;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& table_info = it->second;
|
CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING
|
||||||
|
void retrieve_line_info(
|
||||||
|
const die_object& cu_die,
|
||||||
|
Dwarf_Addr pc,
|
||||||
|
stacktrace_frame& frame
|
||||||
|
) {
|
||||||
|
auto table_info_opt = get_line_table(cu_die);
|
||||||
|
if(!table_info_opt) {
|
||||||
|
return; // failing silently for now
|
||||||
|
}
|
||||||
|
auto& table_info = table_info_opt.unwrap().get();
|
||||||
if(get_cache_mode() == cache_mode::prioritize_speed) {
|
if(get_cache_mode() == cache_mode::prioritize_speed) {
|
||||||
// Lookup in the table
|
// Lookup in the table
|
||||||
auto& line_entries = table_info.line_entries;
|
auto& line_entries = table_info.line_entries;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user