Setup a lookup table for line info
This commit is contained in:
parent
f4a71c2d23
commit
fef039ba26
@ -51,11 +51,6 @@ namespace libdwarf {
|
|||||||
constexpr bool dump_dwarf = false;
|
constexpr bool dump_dwarf = false;
|
||||||
constexpr bool trace_dwarf = false;
|
constexpr bool trace_dwarf = false;
|
||||||
|
|
||||||
struct line_context {
|
|
||||||
Dwarf_Unsigned version;
|
|
||||||
Dwarf_Line_Context line_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct subprogram_entry {
|
struct subprogram_entry {
|
||||||
die_object die;
|
die_object die;
|
||||||
Dwarf_Addr low;
|
Dwarf_Addr low;
|
||||||
@ -69,6 +64,22 @@ namespace libdwarf {
|
|||||||
Dwarf_Addr high;
|
Dwarf_Addr high;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct line_entry {
|
||||||
|
Dwarf_Addr low;
|
||||||
|
// Dwarf_Addr high;
|
||||||
|
// int i;
|
||||||
|
Dwarf_Line line;
|
||||||
|
optional<std::string> path;
|
||||||
|
optional<unsigned> line_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct line_table_info {
|
||||||
|
Dwarf_Unsigned version;
|
||||||
|
Dwarf_Line_Context line_context;
|
||||||
|
// sorted by low_addr
|
||||||
|
std::vector<line_entry> line_entries;
|
||||||
|
};
|
||||||
|
|
||||||
struct dwarf_resolver {
|
struct dwarf_resolver {
|
||||||
std::string obj_path;
|
std::string obj_path;
|
||||||
Dwarf_Debug dbg = nullptr;
|
Dwarf_Debug dbg = nullptr;
|
||||||
@ -77,7 +88,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_context> line_contexts;
|
std::unordered_map<Dwarf_Off, line_table_info> line_contexts;
|
||||||
// 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
|
||||||
@ -449,13 +460,13 @@ namespace libdwarf {
|
|||||||
) {
|
) {
|
||||||
auto off = die.get_global_offset();
|
auto off = die.get_global_offset();
|
||||||
auto it = line_contexts.find(off);
|
auto it = line_contexts.find(off);
|
||||||
Dwarf_Line_Context line_context;
|
|
||||||
if(it != line_contexts.end()) {
|
if(it != line_contexts.end()) {
|
||||||
auto& entry = it->second;
|
// auto& entry = it->second;
|
||||||
line_context = entry.line_context;
|
// 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;
|
||||||
int ret = wrap(
|
int ret = wrap(
|
||||||
dwarf_srclines_b,
|
dwarf_srclines_b,
|
||||||
die.get(),
|
die.get(),
|
||||||
@ -470,66 +481,102 @@ namespace libdwarf {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VERIFY(ret == DW_DLV_OK);
|
VERIFY(ret == DW_DLV_OK);
|
||||||
line_contexts.insert({off, {version, line_context}});
|
|
||||||
}
|
// build lookup table
|
||||||
Dwarf_Line* line_buffer = nullptr;
|
Dwarf_Line* line_buffer = nullptr;
|
||||||
Dwarf_Signed line_count = 0;
|
Dwarf_Signed line_count = 0;
|
||||||
Dwarf_Line* linebuf_actuals = nullptr;
|
Dwarf_Line* linebuf_actuals = nullptr;
|
||||||
Dwarf_Signed linecount_actuals = 0;
|
Dwarf_Signed linecount_actuals = 0;
|
||||||
VERIFY(
|
VERIFY(
|
||||||
wrap(
|
wrap(
|
||||||
dwarf_srclines_two_level_from_linecontext,
|
dwarf_srclines_two_level_from_linecontext,
|
||||||
line_context,
|
line_context,
|
||||||
&line_buffer,
|
&line_buffer,
|
||||||
&line_count,
|
&line_count,
|
||||||
&linebuf_actuals,
|
&linebuf_actuals,
|
||||||
&linecount_actuals
|
&linecount_actuals
|
||||||
) == DW_DLV_OK
|
) == DW_DLV_OK
|
||||||
);
|
);
|
||||||
Dwarf_Addr last_lineaddr = 0;
|
|
||||||
Dwarf_Line last_line = nullptr;
|
std::vector<line_entry> line_entries;
|
||||||
for(int i = 0; i < line_count; i++) {
|
Dwarf_Addr last_pc = 0;
|
||||||
Dwarf_Line line = line_buffer[i];
|
// TODO: Make any attempt to note PC ranges? Handle line end sequence?
|
||||||
Dwarf_Addr lineaddr = 0;
|
for(int i = 0; i < line_count; i++) {
|
||||||
VERIFY(wrap(dwarf_lineaddr, line, &lineaddr) == DW_DLV_OK);
|
Dwarf_Line line = line_buffer[i];
|
||||||
Dwarf_Line found_line = nullptr;
|
Dwarf_Addr low_addr = 0;
|
||||||
if(pc == lineaddr) {
|
VERIFY(wrap(dwarf_lineaddr, line, &low_addr) == DW_DLV_OK);
|
||||||
// Multiple PCs may correspond to a line, find the last one
|
// scan ahead for the last line entry matching this pc
|
||||||
found_line = line;
|
int j;
|
||||||
for(int j = i + 1; j < line_count; j++) {
|
for(j = i + 1; j < line_count; j++) {
|
||||||
Dwarf_Line line = line_buffer[j];
|
Dwarf_Addr addr = 0;
|
||||||
Dwarf_Addr lineaddr = 0;
|
VERIFY(wrap(dwarf_lineaddr, line_buffer[j], &addr) == DW_DLV_OK);
|
||||||
VERIFY(wrap(dwarf_lineaddr, line, &lineaddr) == DW_DLV_OK);
|
if(addr != low_addr) {
|
||||||
if(pc == lineaddr) {
|
break;
|
||||||
found_line = line;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(last_line && pc > last_lineaddr && pc < lineaddr) {
|
line = line_buffer[j - 1];
|
||||||
// Guess that the last line had it
|
// {
|
||||||
found_line = last_line;
|
// Dwarf_Unsigned line_number = 0;
|
||||||
|
// VERIFY(wrap(dwarf_lineno, line, &line_number) == DW_DLV_OK);
|
||||||
|
// frame.line = static_cast<std::uint_least32_t>(line_number);
|
||||||
|
// char* filename = nullptr;
|
||||||
|
// VERIFY(wrap(dwarf_linesrc, line, &filename) == DW_DLV_OK);
|
||||||
|
// auto wrapper = raii_wrap(
|
||||||
|
// filename,
|
||||||
|
// [this] (char* str) { if(str) dwarf_dealloc(dbg, str, DW_DLA_STRING); }
|
||||||
|
// );
|
||||||
|
// frame.filename = filename;
|
||||||
|
// printf("%s : %d\n", filename, line_number);
|
||||||
|
// Dwarf_Bool is_line_end;
|
||||||
|
// VERIFY(wrap(dwarf_lineendsequence, line, &is_line_end) == DW_DLV_OK);
|
||||||
|
// if(is_line_end) {
|
||||||
|
// puts("Line end");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
line_entries.push_back({
|
||||||
|
low_addr,
|
||||||
|
line // j - 1
|
||||||
|
});
|
||||||
|
i = j - 1;
|
||||||
}
|
}
|
||||||
if(found_line) {
|
// sort lines
|
||||||
Dwarf_Unsigned line_number = 0;
|
std::sort(line_entries.begin(), line_entries.end(), [] (const line_entry& a, const line_entry& b) {
|
||||||
VERIFY(wrap(dwarf_lineno, found_line, &line_number) == DW_DLV_OK);
|
return a.low < b.low;
|
||||||
frame.line = static_cast<std::uint_least32_t>(line_number);
|
});
|
||||||
char* filename = nullptr;
|
|
||||||
VERIFY(wrap(dwarf_linesrc, found_line, &filename) == DW_DLV_OK);
|
it = line_contexts.insert({off, {version, line_context, std::move(line_entries)}}).first;
|
||||||
auto wrapper = raii_wrap(
|
}
|
||||||
filename,
|
|
||||||
[this] (char* str) { if(str) dwarf_dealloc(dbg, str, DW_DLA_STRING); }
|
auto& table_info = it->second;
|
||||||
);
|
auto& line_entries = table_info.line_entries;
|
||||||
frame.filename = filename;
|
Dwarf_Line_Context line_context = table_info.line_context;
|
||||||
} else {
|
|
||||||
Dwarf_Bool is_line_end;
|
auto table_it = std::lower_bound(
|
||||||
VERIFY(wrap(dwarf_lineendsequence, line, &is_line_end) == DW_DLV_OK);
|
line_entries.begin(),
|
||||||
if(is_line_end) {
|
line_entries.end(),
|
||||||
last_lineaddr = 0;
|
pc,
|
||||||
last_line = nullptr;
|
[] (const line_entry& entry, Dwarf_Addr pc) {
|
||||||
} else {
|
return entry.low < pc;
|
||||||
last_lineaddr = lineaddr;
|
|
||||||
last_line = line;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
// vec_it is first >= pc
|
||||||
|
// we want first <= pc
|
||||||
|
if(table_it != line_entries.begin()) {
|
||||||
|
table_it--;
|
||||||
|
}
|
||||||
|
// If the vector has been empty this can happen
|
||||||
|
if(table_it != line_entries.end()) {
|
||||||
|
Dwarf_Line line = table_it->line;
|
||||||
|
Dwarf_Unsigned line_number = 0;
|
||||||
|
VERIFY(wrap(dwarf_lineno, line, &line_number) == DW_DLV_OK);
|
||||||
|
frame.line = static_cast<std::uint_least32_t>(line_number);
|
||||||
|
char* filename = nullptr;
|
||||||
|
VERIFY(wrap(dwarf_linesrc, line, &filename) == DW_DLV_OK);
|
||||||
|
auto wrapper = raii_wrap(
|
||||||
|
filename,
|
||||||
|
[this] (char* str) { if(str) dwarf_dealloc(dbg, str, DW_DLA_STRING); }
|
||||||
|
);
|
||||||
|
frame.filename = filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,12 +643,12 @@ namespace libdwarf {
|
|||||||
} else {
|
} else {
|
||||||
// look up the cu
|
// look up the cu
|
||||||
auto vec_it = std::lower_bound(
|
auto vec_it = std::lower_bound(
|
||||||
cu_cache.begin(),
|
cu_cache.begin(),
|
||||||
cu_cache.end(),
|
cu_cache.end(),
|
||||||
pc,
|
pc,
|
||||||
[] (const cu_entry& entry, Dwarf_Addr pc) {
|
[] (const cu_entry& entry, Dwarf_Addr pc) {
|
||||||
return entry.low < pc;
|
return entry.low < pc;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// vec_it is first >= pc
|
// vec_it is first >= pc
|
||||||
// we want first <= pc
|
// we want first <= pc
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user