Refactor of some dwarf handling and debug improvements

This commit is contained in:
Jeremy 2023-09-11 23:58:00 -04:00
parent 851199d46d
commit 4b0af6b6d0
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4

View File

@ -185,6 +185,7 @@ namespace cpptrace {
namespace libdwarf { namespace libdwarf {
// printbugging as we go // printbugging as we go
constexpr bool dump_dwarf = false; constexpr bool dump_dwarf = false;
constexpr bool trace_dwarf = false;
static void err_handler(Dwarf_Error err, Dwarf_Ptr errarg) { static void err_handler(Dwarf_Error err, Dwarf_Ptr errarg) {
printf("libdwarf error reading %s: %lu %s\n", "xx", (unsigned long)dwarf_errno(err), dwarf_errmsg(err)); printf("libdwarf error reading %s: %lu %s\n", "xx", (unsigned long)dwarf_errno(err), dwarf_errmsg(err));
@ -262,23 +263,30 @@ namespace cpptrace {
struct die_object { struct die_object {
Dwarf_Debug dbg = nullptr; Dwarf_Debug dbg = nullptr;
Dwarf_Die die = nullptr; Dwarf_Die die = nullptr;
die_object(Dwarf_Debug dbg, Dwarf_Die die) : dbg(dbg), die(die) {} die_object(Dwarf_Debug dbg, Dwarf_Die die) : dbg(dbg), die(die) {}
~die_object() { ~die_object() {
if(die) { if(die) {
dwarf_dealloc(dbg, die, DW_DLA_DIE); dwarf_dealloc(dbg, die, DW_DLA_DIE);
} }
} }
die_object(const die_object&) = delete; die_object(const die_object&) = delete;
die_object& operator=(const die_object&) = delete; die_object& operator=(const die_object&) = delete;
die_object(die_object&& other) : dbg(other.dbg), die(other.die) { die_object(die_object&& other) : dbg(other.dbg), die(other.die) {
other.die = nullptr; other.die = nullptr;
} }
die_object& operator=(die_object&& other) { die_object& operator=(die_object&& other) {
dbg = other.dbg; dbg = other.dbg;
die = other.die; die = other.die;
other.die = nullptr; other.die = nullptr;
return *this; return *this;
} }
die_object get_child() const { die_object get_child() const {
Dwarf_Die child = nullptr; Dwarf_Die child = nullptr;
int ret = dwarf_child( int ret = dwarf_child(
@ -295,6 +303,7 @@ namespace cpptrace {
exit(1); exit(1);
} }
} }
die_object get_sibling() const { die_object get_sibling() const {
Dwarf_Die sibling = 0; Dwarf_Die sibling = 0;
int ret = dwarf_siblingof_b(dbg, die, true, &sibling, nullptr); int ret = dwarf_siblingof_b(dbg, die, true, &sibling, nullptr);
@ -307,12 +316,15 @@ namespace cpptrace {
exit(1); exit(1);
} }
} }
operator bool() const { operator bool() const {
return die != nullptr; return die != nullptr;
} }
Dwarf_Die get() const { Dwarf_Die get() const {
return die; return die;
} }
std::string get_name() const { std::string get_name() const {
char* name; char* name;
int ret = dwarf_diename(die, &name, nullptr); int ret = dwarf_diename(die, &name, nullptr);
@ -323,11 +335,25 @@ namespace cpptrace {
} }
return name; return name;
} }
Dwarf_Half get_tag() const { Dwarf_Half get_tag() const {
Dwarf_Half tag = 0; Dwarf_Half tag = 0;
dwarf_tag(die, &tag, nullptr); dwarf_tag(die, &tag, nullptr);
return tag; return tag;
} }
const char* get_tag_name() const {
const char* tag_name;
dwarf_get_TAG_name(get_tag(), &tag_name);
return tag_name;
}
Dwarf_Off get_global_offset() const {
Dwarf_Off off;
int ret = dwarf_dieoffset(die, &off, nullptr);
assert(ret == DW_DLV_OK);
return off;
}
}; };
void walk_die_list( void walk_die_list(
@ -486,9 +512,7 @@ namespace cpptrace {
extents += "[" + std::to_string(val + 1) + "]"; extents += "[" + std::to_string(val + 1) + "]";
dwarf_dealloc_attribute(attr); dwarf_dealloc_attribute(attr);
} else { } else {
const char* tag_name = nullptr; fprintf(stderr, "unknown tag %s\n", subrange.get_tag_name());
dwarf_get_TAG_name(subrange.get_tag(), &tag_name);
fprintf(stderr, "unknown tag %s\n", tag_name);
} }
}); });
return extents; return extents;
@ -602,9 +626,7 @@ namespace cpptrace {
} }
default: default:
{ {
const char* tag_name = nullptr; fprintf(stderr, "unknown tag %s\n", die.get_tag_name());
dwarf_get_TAG_name(die.get_tag(), &tag_name);
fprintf(stderr, "unknown tag %s\n", tag_name);
exit(1); exit(1);
} }
} }
@ -696,13 +718,11 @@ namespace cpptrace {
[pc, dwversion, &frame] (Dwarf_Debug dbg, const die_object& die) { [pc, dwversion, &frame] (Dwarf_Debug dbg, const die_object& die) {
int ret; int ret;
if(dump_dwarf) { if(dump_dwarf) {
const char* tag_name;
dwarf_get_TAG_name(die.get_tag(), &tag_name);
fprintf( fprintf(
stderr, stderr,
"-------------> %d %s %s\n", "-------------> %d %s %s\n",
dwversion, dwversion,
tag_name, die.get_tag_name(),
die.get_name().c_str() die.get_name().c_str()
); );
} }
@ -712,6 +732,9 @@ namespace cpptrace {
fprintf(stderr, "pc not in die\n"); fprintf(stderr, "pc not in die\n");
} }
} else { } else {
if(trace_dwarf) {
fprintf(stderr, "pc in die %08llx %s\n", die.get_global_offset(), die.get_tag_name());
}
if(dump_dwarf) { if(dump_dwarf) {
fprintf(stderr, "pc in die <-----------------------------------\n"); fprintf(stderr, "pc in die <-----------------------------------\n");
} }
@ -819,6 +842,9 @@ namespace cpptrace {
Dwarf_Half offset_size = 0; Dwarf_Half offset_size = 0;
Dwarf_Half dwversion = 0; Dwarf_Half dwversion = 0;
dwarf_get_version_of_die(cu_die.get(), &dwversion, &offset_size); 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());
}
/*auto child = cu_die.get_child(); /*auto child = cu_die.get_child();
if(child) { if(child) {
walk_die_list_recursive( walk_die_list_recursive(
@ -872,7 +898,7 @@ namespace cpptrace {
} }
} }
void lookup_pc2( void lookup_pc(
const char* object, const char* object,
Dwarf_Addr pc, Dwarf_Addr pc,
stacktrace_frame& frame stacktrace_frame& frame
@ -883,8 +909,16 @@ namespace cpptrace {
} }
Dwarf_Debug dbg; Dwarf_Debug dbg;
Dwarf_Ptr errarg = 0; Dwarf_Ptr errarg = 0;
auto ret = dwarf_init_path(object, nullptr, 0, auto ret = dwarf_init_path(
DW_GROUPNUMBER_ANY, err_handler, errarg, &dbg, nullptr); object,
nullptr,
0,
DW_GROUPNUMBER_ANY,
err_handler,
errarg,
&dbg,
nullptr
);
if(ret == DW_DLV_NO_ENTRY) { if(ret == DW_DLV_NO_ENTRY) {
// fail, no debug info // fail, no debug info
} else if(ret != DW_DLV_OK) { } else if(ret != DW_DLV_OK) {
@ -900,7 +934,16 @@ namespace cpptrace {
frame.filename = frame_info.obj_path; frame.filename = frame_info.obj_path;
frame.symbol = frame_info.symbol; frame.symbol = frame_info.symbol;
frame.address = frame_info.raw_address; frame.address = frame_info.raw_address;
lookup_pc2( if(trace_dwarf) {
fprintf(
stderr,
"%s %08lx %s\n",
frame_info.obj_path.c_str(),
frame_info.obj_address,
frame_info.symbol.c_str()
);
}
lookup_pc(
frame_info.obj_path.c_str(), frame_info.obj_path.c_str(),
frame_info.obj_address, frame_info.obj_address,
frame frame