Optimize dwarf handling by caching line contexts so the line info table only has to be computed once per TU per object per trace
This commit is contained in:
parent
e47cb7147d
commit
e4eab1d426
@ -558,288 +558,334 @@ namespace libdwarf {
|
|||||||
frame.symbol = name + "(" + join(params, ", ") + ")";*/
|
frame.symbol = name + "(" + join(params, ", ") + ")";*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if this call found the symbol
|
struct line_context {
|
||||||
bool retrieve_symbol(
|
|
||||||
Dwarf_Debug dbg,
|
|
||||||
const die_object& die,
|
|
||||||
Dwarf_Addr pc,
|
|
||||||
Dwarf_Half dwversion,
|
|
||||||
stacktrace_frame& frame
|
|
||||||
) {
|
|
||||||
bool found = false;
|
|
||||||
walk_die_list(
|
|
||||||
dbg,
|
|
||||||
die,
|
|
||||||
[pc, dwversion, &frame, &found] (Dwarf_Debug dbg, const die_object& die) {
|
|
||||||
if(dump_dwarf) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"-------------> %08llx %s %s\n",
|
|
||||||
(unsigned long long) die.get_global_offset(),
|
|
||||||
die.get_tag_name(),
|
|
||||||
die.get_name().c_str()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(die.get_tag() == DW_TAG_namespace || pc_in_die(dbg, die.get(), dwversion, pc))) {
|
|
||||||
if(dump_dwarf) {
|
|
||||||
fprintf(stderr, "pc not in die\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(trace_dwarf) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"%s %08llx %s\n",
|
|
||||||
die.get_tag() == DW_TAG_namespace ? "pc maybe in die (namespace)" : "pc in die",
|
|
||||||
(unsigned long long) die.get_global_offset(),
|
|
||||||
die.get_tag_name()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if(die.get_tag() == DW_TAG_subprogram) {
|
|
||||||
retrieve_symbol_for_subprogram(dbg, die, pc, dwversion, frame);
|
|
||||||
found = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto child = die.get_child();
|
|
||||||
if(child) {
|
|
||||||
if(retrieve_symbol(dbg, child, pc, dwversion, frame)) {
|
|
||||||
found = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(dump_dwarf) {
|
|
||||||
fprintf(stderr, "(no child)\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
void retrieve_line_info(
|
|
||||||
Dwarf_Debug dbg,
|
|
||||||
const die_object& die,
|
|
||||||
Dwarf_Addr pc,
|
|
||||||
Dwarf_Half dwversion,
|
|
||||||
stacktrace_frame& frame
|
|
||||||
) {
|
|
||||||
Dwarf_Unsigned version;
|
Dwarf_Unsigned version;
|
||||||
Dwarf_Small table_count;
|
Dwarf_Small table_count;
|
||||||
Dwarf_Line_Context ctxt;
|
Dwarf_Line_Context ctx;
|
||||||
Dwarf_Bool is_found = false;
|
};
|
||||||
(void)dwversion;
|
|
||||||
int ret = dwarf_srclines_b(
|
|
||||||
die.get(),
|
|
||||||
&version,
|
|
||||||
&table_count,
|
|
||||||
&ctxt,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
if(ret == DW_DLV_NO_ENTRY) {
|
|
||||||
fprintf(stderr, "dwarf_srclines_b error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(table_count == 1) {
|
|
||||||
Dwarf_Line *linebuf = 0;
|
|
||||||
Dwarf_Signed linecount = 0;
|
|
||||||
Dwarf_Addr prev_lineaddr = 0;
|
|
||||||
|
|
||||||
dwarf_srclines_from_linecontext(ctxt, &linebuf,
|
struct dwarf_resolver {
|
||||||
&linecount, nullptr);
|
std::string obj_path;
|
||||||
Dwarf_Line prev_line = 0;
|
Dwarf_Debug dbg;
|
||||||
for(int i = 0; i < linecount; i++) {
|
std::unordered_map<Dwarf_Off, line_context> line_contexts;
|
||||||
Dwarf_Line line = linebuf[i];
|
|
||||||
Dwarf_Addr lineaddr = 0;
|
|
||||||
|
|
||||||
dwarf_lineaddr(line, &lineaddr, nullptr);
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
if(pc == lineaddr) {
|
dwarf_resolver(const std::string& object_path) {
|
||||||
/* Print the last line entry containing current pc. */
|
obj_path = object_path;
|
||||||
Dwarf_Line last_pc_line = line;
|
#if IS_APPLE
|
||||||
|
if(directory_exists(obj_path + ".dSYM")) {
|
||||||
for(int j = i + 1; j < linecount; j++) {
|
obj_path += ".dSYM/Contents/Resources/DWARF/" + basename(object_path);
|
||||||
Dwarf_Line j_line = linebuf[j];
|
|
||||||
dwarf_lineaddr(j_line, &lineaddr, nullptr);
|
|
||||||
|
|
||||||
if(pc == lineaddr) {
|
|
||||||
last_pc_line = j_line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is_found = true;
|
|
||||||
print_line(dbg, last_pc_line, pc, frame);
|
|
||||||
break;
|
|
||||||
} else if(prev_line && pc > prev_lineaddr &&
|
|
||||||
pc < lineaddr) {
|
|
||||||
is_found = true;
|
|
||||||
print_line(dbg, prev_line, pc, frame);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Dwarf_Bool is_lne;
|
|
||||||
dwarf_lineendsequence(line, &is_lne, nullptr);
|
|
||||||
if(is_lne) {
|
|
||||||
prev_line = 0;
|
|
||||||
} else {
|
|
||||||
prev_lineaddr = lineaddr;
|
|
||||||
prev_line = line;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
dwarf_srclines_dealloc_b(ctxt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void walk_compilation_units(Dwarf_Debug dbg, Dwarf_Addr pc, stacktrace_frame& frame) {
|
Dwarf_Ptr errarg = 0;
|
||||||
// 0 passed as the die to the first call of dwarf_siblingof_b immediately after dwarf_next_cu_header_d
|
auto ret = dwarf_init_path(
|
||||||
// to fetch the cu die
|
obj_path.c_str(),
|
||||||
die_object cu_die(dbg, nullptr);
|
|
||||||
cu_die = cu_die.get_sibling();
|
|
||||||
if(!cu_die) {
|
|
||||||
if(dump_dwarf) {
|
|
||||||
fprintf(stderr, "End walk_compilation_units\n");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
walk_die_list(
|
|
||||||
dbg,
|
|
||||||
cu_die,
|
|
||||||
[&frame, pc] (Dwarf_Debug dbg, 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);
|
|
||||||
if(trace_dwarf) {
|
|
||||||
fprintf(stderr, "CU: %d %s\n", dwversion, cu_die.get_name().c_str());
|
|
||||||
}
|
|
||||||
Dwarf_Unsigned offset = 0;
|
|
||||||
// TODO: I'm unsure if I'm supposed to take DW_AT_rnglists_base into account here
|
|
||||||
// However it looks like it is correct when not taking an offset into account and incorrect
|
|
||||||
// otherwise
|
|
||||||
//if(dwversion >= 5) {
|
|
||||||
// Dwarf_Attribute attr;
|
|
||||||
// int ret = dwarf_attr(cu_die.get(), DW_AT_rnglists_base, &attr, nullptr);
|
|
||||||
// CPPTRACE_VERIFY(ret == DW_DLV_OK);
|
|
||||||
// Dwarf_Unsigned uval = 0;
|
|
||||||
// ret = dwarf_global_formref(attr, &uval, nullptr);
|
|
||||||
// offset = uval;
|
|
||||||
// dwarf_dealloc_attribute(attr);
|
|
||||||
//}
|
|
||||||
//fprintf(stderr, "------------> pc: %llx offset: %llx final: %llx\n", pc, offset, pc - offset);
|
|
||||||
if(pc_in_die(dbg, cu_die.get(), dwversion, pc - offset)) {
|
|
||||||
if(trace_dwarf) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"pc in die %08llx %s (now searching for %08llx)\n",
|
|
||||||
(unsigned long long) cu_die.get_global_offset(),
|
|
||||||
cu_die.get_tag_name(),
|
|
||||||
pc - offset
|
|
||||||
);
|
|
||||||
}
|
|
||||||
retrieve_line_info(dbg, cu_die, pc, dwversion, frame); // no offset for line info
|
|
||||||
retrieve_symbol(dbg, cu_die, pc - offset, dwversion, frame);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void walk_dbg(Dwarf_Debug dbg, Dwarf_Addr pc, stacktrace_frame& frame) {
|
|
||||||
// libdwarf keeps track of where it is in the file, dwarf_next_cu_header_d is statefull
|
|
||||||
Dwarf_Unsigned next_cu_header;
|
|
||||||
Dwarf_Half header_cu_type;
|
|
||||||
while(true) {
|
|
||||||
int ret = dwarf_next_cu_header_d(
|
|
||||||
dbg,
|
|
||||||
true,
|
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
0,
|
||||||
nullptr,
|
DW_GROUPNUMBER_ANY,
|
||||||
nullptr,
|
err_handler,
|
||||||
nullptr,
|
errarg,
|
||||||
nullptr,
|
&dbg,
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
&next_cu_header,
|
|
||||||
&header_cu_type,
|
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
if(ret == DW_DLV_NO_ENTRY) {
|
if(ret == DW_DLV_NO_ENTRY) {
|
||||||
|
// fail, no debug info
|
||||||
|
} else if(ret != DW_DLV_OK) {
|
||||||
|
fprintf(stderr, "Error\n");
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
~dwarf_resolver() {
|
||||||
|
dwarf_finish(dbg);
|
||||||
|
for(auto& entry : line_contexts) {
|
||||||
|
dwarf_srclines_dealloc_b(entry.second.ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if this call found the symbol
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
bool retrieve_symbol(
|
||||||
|
Dwarf_Debug dbg,
|
||||||
|
const die_object& die,
|
||||||
|
Dwarf_Addr pc,
|
||||||
|
Dwarf_Half dwversion,
|
||||||
|
stacktrace_frame& frame
|
||||||
|
) {
|
||||||
|
bool found = false;
|
||||||
|
walk_die_list(
|
||||||
|
dbg,
|
||||||
|
die,
|
||||||
|
[this, pc, dwversion, &frame, &found] (Dwarf_Debug dbg, const die_object& die) {
|
||||||
|
if(dump_dwarf) {
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
"-------------> %08llx %s %s\n",
|
||||||
|
(unsigned long long) die.get_global_offset(),
|
||||||
|
die.get_tag_name(),
|
||||||
|
die.get_name().c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(die.get_tag() == DW_TAG_namespace || pc_in_die(dbg, die.get(), dwversion, pc))) {
|
||||||
|
if(dump_dwarf) {
|
||||||
|
fprintf(stderr, "pc not in die\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(trace_dwarf) {
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
"%s %08llx %s\n",
|
||||||
|
die.get_tag() == DW_TAG_namespace ? "pc maybe in die (namespace)" : "pc in die",
|
||||||
|
(unsigned long long) die.get_global_offset(),
|
||||||
|
die.get_tag_name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if(die.get_tag() == DW_TAG_subprogram) {
|
||||||
|
retrieve_symbol_for_subprogram(dbg, die, pc, dwversion, frame);
|
||||||
|
found = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto child = die.get_child();
|
||||||
|
if(child) {
|
||||||
|
if(retrieve_symbol(dbg, child, pc, dwversion, frame)) {
|
||||||
|
found = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(dump_dwarf) {
|
||||||
|
fprintf(stderr, "(no child)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
void retrieve_line_info(
|
||||||
|
Dwarf_Debug dbg,
|
||||||
|
const die_object& die,
|
||||||
|
Dwarf_Addr pc,
|
||||||
|
Dwarf_Half dwversion,
|
||||||
|
stacktrace_frame& frame
|
||||||
|
) {
|
||||||
|
Dwarf_Unsigned version;
|
||||||
|
Dwarf_Small table_count;
|
||||||
|
Dwarf_Line_Context ctxt;
|
||||||
|
Dwarf_Bool is_found = false;
|
||||||
|
(void)dwversion;
|
||||||
|
auto off = die.get_global_offset();
|
||||||
|
auto it = line_contexts.find(off);
|
||||||
|
if(it != line_contexts.end()) {
|
||||||
|
auto& entry = it->second;
|
||||||
|
version = entry.version;
|
||||||
|
table_count = entry.table_count;
|
||||||
|
ctxt = entry.ctx;
|
||||||
|
} else {
|
||||||
|
int ret = dwarf_srclines_b(
|
||||||
|
die.get(),
|
||||||
|
&version,
|
||||||
|
&table_count,
|
||||||
|
&ctxt,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
line_contexts.insert({off, {version, table_count, ctxt}});
|
||||||
|
if(ret == DW_DLV_NO_ENTRY) {
|
||||||
|
fprintf(stderr, "dwarf_srclines_b error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(table_count == 1) {
|
||||||
|
Dwarf_Line *linebuf = 0;
|
||||||
|
Dwarf_Signed linecount = 0;
|
||||||
|
Dwarf_Addr prev_lineaddr = 0;
|
||||||
|
|
||||||
|
dwarf_srclines_from_linecontext(ctxt, &linebuf,
|
||||||
|
&linecount, nullptr);
|
||||||
|
Dwarf_Line prev_line = 0;
|
||||||
|
for(int i = 0; i < linecount; i++) {
|
||||||
|
Dwarf_Line line = linebuf[i];
|
||||||
|
Dwarf_Addr lineaddr = 0;
|
||||||
|
|
||||||
|
dwarf_lineaddr(line, &lineaddr, nullptr);
|
||||||
|
if(pc == lineaddr) {
|
||||||
|
/* Print the last line entry containing current pc. */
|
||||||
|
Dwarf_Line last_pc_line = line;
|
||||||
|
|
||||||
|
for(int j = i + 1; j < linecount; j++) {
|
||||||
|
Dwarf_Line j_line = linebuf[j];
|
||||||
|
dwarf_lineaddr(j_line, &lineaddr, nullptr);
|
||||||
|
|
||||||
|
if(pc == lineaddr) {
|
||||||
|
last_pc_line = j_line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_found = true;
|
||||||
|
print_line(dbg, last_pc_line, pc, frame);
|
||||||
|
break;
|
||||||
|
} else if(prev_line && pc > prev_lineaddr &&
|
||||||
|
pc < lineaddr) {
|
||||||
|
is_found = true;
|
||||||
|
print_line(dbg, prev_line, pc, frame);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Dwarf_Bool is_lne;
|
||||||
|
dwarf_lineendsequence(line, &is_lne, nullptr);
|
||||||
|
if(is_lne) {
|
||||||
|
prev_line = 0;
|
||||||
|
} else {
|
||||||
|
prev_lineaddr = lineaddr;
|
||||||
|
prev_line = line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
void walk_compilation_units(Dwarf_Debug dbg, Dwarf_Addr pc, stacktrace_frame& frame) {
|
||||||
|
// 0 passed as the die to the first call of dwarf_siblingof_b immediately after dwarf_next_cu_header_d
|
||||||
|
// to fetch the cu die
|
||||||
|
die_object cu_die(dbg, nullptr);
|
||||||
|
cu_die = cu_die.get_sibling();
|
||||||
|
if(!cu_die) {
|
||||||
if(dump_dwarf) {
|
if(dump_dwarf) {
|
||||||
fprintf(stderr, "End walk_dbg\n");
|
fprintf(stderr, "End walk_compilation_units\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(ret != DW_DLV_OK) {
|
walk_die_list(
|
||||||
fprintf(stderr, "Error\n");
|
dbg,
|
||||||
return;
|
cu_die,
|
||||||
}
|
[this, &frame, pc] (Dwarf_Debug dbg, const die_object& cu_die) {
|
||||||
walk_compilation_units(dbg, pc, frame);
|
Dwarf_Half offset_size = 0;
|
||||||
}
|
Dwarf_Half dwversion = 0;
|
||||||
}
|
dwarf_get_version_of_die(cu_die.get(), &dwversion, &offset_size);
|
||||||
|
if(trace_dwarf) {
|
||||||
void lookup_pc(
|
fprintf(stderr, "CU: %d %s\n", dwversion, cu_die.get_name().c_str());
|
||||||
const char* object,
|
}
|
||||||
Dwarf_Addr pc,
|
Dwarf_Unsigned offset = 0;
|
||||||
stacktrace_frame& frame
|
// TODO: I'm unsure if I'm supposed to take DW_AT_rnglists_base into account here
|
||||||
) {
|
// However it looks like it is correct when not taking an offset into account and incorrect
|
||||||
if(dump_dwarf) {
|
// otherwise
|
||||||
fprintf(stderr, "%s\n", object);
|
//if(dwversion >= 5) {
|
||||||
fprintf(stderr, "%llx\n", pc);
|
// Dwarf_Attribute attr;
|
||||||
}
|
// int ret = dwarf_attr(cu_die.get(), DW_AT_rnglists_base, &attr, nullptr);
|
||||||
Dwarf_Debug dbg;
|
// CPPTRACE_VERIFY(ret == DW_DLV_OK);
|
||||||
Dwarf_Ptr errarg = 0;
|
// Dwarf_Unsigned uval = 0;
|
||||||
auto ret = dwarf_init_path(
|
// ret = dwarf_global_formref(attr, &uval, nullptr);
|
||||||
object,
|
// offset = uval;
|
||||||
nullptr,
|
// dwarf_dealloc_attribute(attr);
|
||||||
0,
|
//}
|
||||||
DW_GROUPNUMBER_ANY,
|
//fprintf(stderr, "------------> pc: %llx offset: %llx final: %llx\n", pc, offset, pc - offset);
|
||||||
err_handler,
|
if(pc_in_die(dbg, cu_die.get(), dwversion, pc - offset)) {
|
||||||
errarg,
|
if(trace_dwarf) {
|
||||||
&dbg,
|
fprintf(
|
||||||
nullptr
|
stderr,
|
||||||
);
|
"pc in die %08llx %s (now searching for %08llx)\n",
|
||||||
if(ret == DW_DLV_NO_ENTRY) {
|
(unsigned long long) cu_die.get_global_offset(),
|
||||||
// fail, no debug info
|
cu_die.get_tag_name(),
|
||||||
} else if(ret != DW_DLV_OK) {
|
pc - offset
|
||||||
fprintf(stderr, "Error\n");
|
);
|
||||||
} else {
|
}
|
||||||
walk_dbg(dbg, pc, frame);
|
retrieve_line_info(dbg, cu_die, pc, dwversion, frame); // no offset for line info
|
||||||
}
|
retrieve_symbol(dbg, cu_die, pc - offset, dwversion, frame);
|
||||||
dwarf_finish(dbg);
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
stacktrace_frame resolve_frame(const dlframe& frame_info) {
|
}
|
||||||
stacktrace_frame frame{};
|
|
||||||
frame.filename = frame_info.obj_path;
|
|
||||||
frame.symbol = frame_info.symbol;
|
|
||||||
frame.address = frame_info.raw_address;
|
|
||||||
std::string obj_path = frame_info.obj_path;
|
|
||||||
#if IS_APPLE
|
|
||||||
if(directory_exists(obj_path + ".dSYM")) {
|
|
||||||
obj_path += ".dSYM/Contents/Resources/DWARF/" + basename(frame_info.obj_path);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(trace_dwarf) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"Starting resolution for %s %08llx %s\n",
|
|
||||||
obj_path.c_str(),
|
|
||||||
(unsigned long long)frame_info.obj_address,
|
|
||||||
frame_info.symbol.c_str()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
lookup_pc(
|
|
||||||
obj_path.c_str(),
|
|
||||||
frame_info.obj_address,
|
|
||||||
frame
|
|
||||||
);
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
void walk_dbg(Dwarf_Debug dbg, Dwarf_Addr pc, stacktrace_frame& frame) {
|
||||||
|
// libdwarf keeps track of where it is in the file, dwarf_next_cu_header_d is statefull
|
||||||
|
Dwarf_Unsigned next_cu_header;
|
||||||
|
Dwarf_Half header_cu_type;
|
||||||
|
while(true) {
|
||||||
|
int ret = dwarf_next_cu_header_d(
|
||||||
|
dbg,
|
||||||
|
true,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&next_cu_header,
|
||||||
|
&header_cu_type,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
if(ret == DW_DLV_NO_ENTRY) {
|
||||||
|
if(dump_dwarf) {
|
||||||
|
fprintf(stderr, "End walk_dbg\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ret != DW_DLV_OK) {
|
||||||
|
fprintf(stderr, "Error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
walk_compilation_units(dbg, pc, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
void lookup_pc(
|
||||||
|
const char* object,
|
||||||
|
Dwarf_Addr pc,
|
||||||
|
stacktrace_frame& frame
|
||||||
|
) {
|
||||||
|
if(dump_dwarf) {
|
||||||
|
fprintf(stderr, "%s\n", object);
|
||||||
|
fprintf(stderr, "%llx\n", pc);
|
||||||
|
}
|
||||||
|
walk_dbg(dbg, pc, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
stacktrace_frame resolve_frame(const dlframe& frame_info) {
|
||||||
|
stacktrace_frame frame{};
|
||||||
|
frame.filename = frame_info.obj_path;
|
||||||
|
frame.symbol = frame_info.symbol;
|
||||||
|
frame.address = frame_info.raw_address;
|
||||||
|
if(trace_dwarf) {
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
"Starting resolution for %s %08llx %s\n",
|
||||||
|
obj_path.c_str(),
|
||||||
|
(unsigned long long)frame_info.obj_address,
|
||||||
|
frame_info.symbol.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
lookup_pc(
|
||||||
|
obj_path.c_str(),
|
||||||
|
frame_info.obj_address,
|
||||||
|
frame
|
||||||
|
);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
|
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
|
||||||
std::vector<stacktrace_frame> trace;
|
std::vector<stacktrace_frame> trace(frames.size(), stacktrace_frame { 0, 0, 0, "", "" });
|
||||||
trace.reserve(frames.size());
|
const auto dlframes = get_frames_object_info(frames);
|
||||||
for(const auto& frame : get_frames_object_info(frames)) {
|
for(const auto& obj_entry : collate_frames(dlframes, trace)) {
|
||||||
trace.push_back(resolve_frame(frame));
|
const auto& obj_name = obj_entry.first;
|
||||||
|
dwarf_resolver resolver(obj_name);
|
||||||
|
for(const auto& entry : obj_entry.second) {
|
||||||
|
const auto& dlframe = entry.first.get();
|
||||||
|
auto& frame = entry.second.get();
|
||||||
|
frame = resolver.resolve_frame(dlframe);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user