Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for extracting member names with RECOVER_VAR_NAMES=1 #70

Merged
merged 1 commit into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading