From 2f0182a2022b3430afd041f054deebe155ec7841 Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Sun, 17 Mar 2024 21:16:26 -0400 Subject: [PATCH] added support for extracting member names with RECOVER_VAR_NAMES=1 --- include/util/var_finder.h | 1 + samples/outputs.var_names/sample55 | 9 +++ samples/outputs/sample55 | 9 +++ samples/sample55.cpp | 38 ++++++++++++ src/util/var_finder.cpp | 97 ++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 samples/outputs.var_names/sample55 create mode 100644 samples/outputs/sample55 create mode 100644 samples/sample55.cpp diff --git a/include/util/var_finder.h b/include/util/var_finder.h index 0b5d7f3..8373f8d 100644 --- a/include/util/var_finder.h +++ b/include/util/var_finder.h @@ -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 diff --git a/samples/outputs.var_names/sample55 b/samples/outputs.var_names/sample55 new file mode 100644 index 0000000..2a9664d --- /dev/null +++ b/samples/outputs.var_names/sample55 @@ -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; +} + diff --git a/samples/outputs/sample55 b/samples/outputs/sample55 new file mode 100644 index 0000000..43bf0b2 --- /dev/null +++ b/samples/outputs/sample55 @@ -0,0 +1,9 @@ +void bar (void) { + int var0; + char var1; + int var2; + char var3; + var0 = var1; + var3 = var2; +} + diff --git a/samples/sample55.cpp b/samples/sample55.cpp new file mode 100644 index 0000000..4421152 --- /dev/null +++ b/samples/sample55.cpp @@ -0,0 +1,38 @@ +// Include the headers +#include "blocks/c_code_generator.h" +#include "builder/dyn_var.h" +#include "builder/static_var.h" +#include + +// 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 mem1; + dyn_var mem2; +}; + +// Members of this struct will have names since the first member is a non dynamic one +struct wrapper2 { + int spacer; + dyn_var mem1; + dyn_var 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; +} diff --git a/src/util/var_finder.cpp b/src/util/var_finder.cpp index b0a44ac..5b9569e 100644 --- a/src/util/var_finder.cpp +++ b/src/util/var_finder.cpp @@ -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; @@ -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; @@ -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