Skip to content

Commit

Permalink
added support for extracting member names with RECOVER_VAR_NAMES=1
Browse files Browse the repository at this point in the history
  • Loading branch information
AjayBrahmakshatriya committed Mar 18, 2024
1 parent 73cea03 commit 2f0182a
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/util/var_finder.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace util {
std::string find_variable_name(void *);
std::string find_variable_name_cached(void *, std::string tag_string);
extern std::string member_separator;
} // namespace util

#endif
9 changes: 9 additions & 0 deletions samples/outputs.var_names/sample55
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
void bar (void) {
int x_0;
char x_mem2_1;
int y_mem1_2;
char y_mem2_3;
x_0 = x_mem2_1;
y_mem2_3 = y_mem1_2;
}

9 changes: 9 additions & 0 deletions samples/outputs/sample55
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
void bar (void) {
int var0;
char var1;
int var2;
char var3;
var0 = var1;
var3 = var2;
}

38 changes: 38 additions & 0 deletions samples/sample55.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Include the headers
#include "blocks/c_code_generator.h"
#include "builder/dyn_var.h"
#include "builder/static_var.h"
#include <iostream>

// Include the BuildIt types
using builder::dyn_var;
using builder::static_var;


// Members of this struct will have names except for the first one
// since we currently don't match sizes
struct wrapper1 {
dyn_var<int> mem1;
dyn_var<char> mem2;
};

// Members of this struct will have names since the first member is a non dynamic one
struct wrapper2 {
int spacer;
dyn_var<int> mem1;
dyn_var<char> mem2;
};


static void bar(void) {
struct wrapper1 x;
struct wrapper2 y;
x.mem1 = x.mem2;
y.mem2 = y.mem1;
}

int main(int argc, char *argv[]) {
block::c_code_generator::generate_code(
builder::builder_context().extract_function_ast(bar, "bar"), std::cout, 0);
return 0;
}
97 changes: 97 additions & 0 deletions src/util/var_finder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

namespace util {

// Default member separator is "_"
// this can be set by callers if they want
// the separator to be .
std::string member_separator = "_";

static int backtrace_find_cursor(void *addr, unw_cursor_t *ret, unw_cursor_t *ret_prev) {
unw_cursor_t cursor, cursor_next, cursor_prev;
unw_context_t context;
Expand Down Expand Up @@ -251,6 +256,85 @@ static void *decode_address_from_die(Dwarf_Debug dbg, Dwarf_Die die, uint64_t fr
return NULL;
}


static int find_var_size(Dwarf_Debug dbg, Dwarf_Die var_die) {
Dwarf_Attribute attr;
Dwarf_Error de;
Dwarf_Off off;
Dwarf_Die type_die;
Dwarf_Unsigned size;

if (dwarf_attr(var_die, DW_AT_type, &attr, &de) != DW_DLV_OK)
return -1;

if (dwarf_global_formref(attr, &off, &de) != DW_DLV_OK)
return -1;

if (dwarf_offdie(dbg, off, &type_die, &de) != DW_DLV_OK)
return -1;

if (dwarf_attr(type_die, DW_AT_byte_size, &attr, &de) != DW_DLV_OK)
return -1;

if (dwarf_formudata(attr, &size, &de) != DW_DLV_OK)
return -1;

return (int) size;

}


static std::string find_member_at_offset(Dwarf_Debug dbg, Dwarf_Die var_die, int offset) {
Dwarf_Attribute attr;
Dwarf_Error de;
Dwarf_Off off;
Dwarf_Die type_die;
Dwarf_Half tag;

if (dwarf_attr(var_die, DW_AT_type, &attr, &de) != DW_DLV_OK)
return "";

if (dwarf_global_formref(attr, &off, &de) != DW_DLV_OK)
return "";

if (dwarf_offdie(dbg, off, &type_die, &de) != DW_DLV_OK)
return "";

// Now we iterate over the members and check their offsets;
Dwarf_Die child, next_child;

if (dwarf_child(type_die, &next_child, &de) != DW_DLV_OK)
return "";
child = NULL;

do {
if (child != NULL)
dwarf_dealloc(dbg, child, DW_DLA_DIE);
child = next_child;
if (dwarf_tag(child, &tag, &de) != DW_DLV_OK)
continue;
if (tag == DW_TAG_member) {
if (dwarf_attr(child, DW_AT_data_member_location, &attr, &de) != DW_DLV_OK)
continue;
Dwarf_Unsigned mem_offset;
if (dwarf_formudata(attr, &mem_offset, &de) != DW_DLV_OK)
continue;
if (offset == (int) mem_offset) {
char* name = NULL;
if (dwarf_diename(child, &name, &de) != DW_DLV_OK) {
dwarf_dealloc(dbg, child, DW_DLA_DIE);
return "";
}
dwarf_dealloc(dbg, child, DW_DLA_DIE);
return name;
}
}
} while (dwarf_siblingof(dbg, child, &next_child, &de) == DW_DLV_OK);

return "";
}


static std::string find_var_in_f_tree(Dwarf_Debug dbg, Dwarf_Die in_die, uint64_t addr, uint64_t var_offset,
char *base_ptr) {
Dwarf_Error de;
Expand All @@ -277,6 +361,19 @@ static std::string find_var_in_f_tree(Dwarf_Debug dbg, Dwarf_Die in_die, uint64_
dwarf_dealloc(dbg, die, DW_DLA_DIE);
return vname;
}
// We couldn't find an exact match, now let's look for members
int var_size = find_var_size(dbg, die);
if (var_size != -1) {
if (var_offset >= var_addr && var_offset < var_addr + var_size) {
int offset = var_offset - var_addr;
// Add the member name only if we find it
std::string mem_name = find_member_at_offset(dbg, die, offset);
if (mem_name != "")
vname = vname + member_separator + mem_name;
dwarf_dealloc(dbg, die, DW_DLA_DIE);
return vname;
}
}
}
} while (dwarf_siblingof(dbg, die, &curr_die, &de) == DW_DLV_OK);
// Now check all the lexical scopes
Expand Down

0 comments on commit 2f0182a

Please sign in to comment.