From bb6a5ef557688eaf77f86295b8f7c94be62b50e9 Mon Sep 17 00:00:00 2001 From: "A.Olokhtonov" Date: Sun, 1 Aug 2021 22:41:19 +0300 Subject: [PATCH] Get actual DIE _tree_. No useful info extracted from the tree for now. Nodes malloc()-ed all over the place --- src/dwarf.c | 188 +++++++++++++++++++++++++++++++++--------------- src/elf_dwarf.h | 8 ++- 2 files changed, 137 insertions(+), 59 deletions(-) diff --git a/src/dwarf.c b/src/dwarf.c index 685134b..3eeb717 100644 --- a/src/dwarf.c +++ b/src/dwarf.c @@ -967,8 +967,8 @@ read_die_structure_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 } static void -read_die_member(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset, - u8 address_size, struct dwarf_die_type *dest) +read_die_structure_member(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset, + u8 address_size, struct dwarf_die_type *dest) { u64 data = *data_offset; u64 schema = *schema_offset; @@ -979,6 +979,18 @@ read_die_member(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_of schema += decode_leb128(file + schema, &attribute); schema += decode_leb128(file + schema, &form); data += read_actual_debug_data(file, debug_str_offset, address_size, form, data, &value); + + switch (attribute) { + case DW_AT_name: { + dest->name = (char *) value; + break; + } + + case DW_AT_type: { + dest->pointer = value; + break; + } + } } while (attribute != 0 || form != 0); *data_offset = data; @@ -986,53 +998,155 @@ read_die_member(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_of } static void -read_one_die(u8 *file, u64 debug_info_offset, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset, - enum dwarf_die_tag tag, u8 address_size, struct dwarf_die *dest) +read_die_pointer_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset, + u8 address_size, struct dwarf_die_type *dest) { + u64 data = *data_offset; u64 schema = *schema_offset; + + u32 attribute, form; + do { + u64 value; + schema += decode_leb128(file + schema, &attribute); + schema += decode_leb128(file + schema, &form); + data += read_actual_debug_data(file, debug_str_offset, address_size, form, data, &value); + + switch (attribute) { + case DW_AT_byte_size: { + dest->size = value; + break; + } + + case DW_AT_type: { + dest->pointer = value; + break; + } + } + } while (attribute != 0 || form != 0); + + *data_offset = data; + *schema_offset = schema; +} + +static void +read_die_const_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset, + u8 address_size, struct dwarf_die_type *dest) +{ u64 data = *data_offset; + u64 schema = *schema_offset; - dest->offset = data - debug_info_offset; - dest->tag = tag; + u32 attribute, form; + do { + u64 value; + schema += decode_leb128(file + schema, &attribute); + schema += decode_leb128(file + schema, &form); + data += read_actual_debug_data(file, debug_str_offset, address_size, form, data, &value); + + switch (attribute) { + case DW_AT_type: { + dest->pointer = value; + break; + } + } + } while (attribute != 0 || form != 0); + *data_offset = data; + *schema_offset = schema; +} + +// NOTE(aolo2): parse one DIE and all of its children +static struct dwarf_die * +read_one_die(u8 *file, u64 string_offset, u64 info_offset, u64 abbrev_offset, u8 address_size, u64 *data_offset, u32 depth) +{ + u64 data = *data_offset; + u64 record_offset = data - info_offset; + + u32 code; + u32 tag; + + data += decode_leb128(file + data, &code); + + if (code == 0) { + *data_offset = data; + return(0); + } + + // TODO: use a custom allocator / preallocated memory for this + struct dwarf_die *die = calloc(1, sizeof(struct dwarf_die)); + + u64 schema_offset = abbrev_entry_offset(file, abbrev_offset, code); + schema_offset += decode_leb128(file + schema_offset, NULL); + schema_offset += decode_leb128(file + schema_offset, &tag); + + u8 has_children = file[schema_offset++]; + + die->tag = tag; + die->offset = record_offset; + + // TODO: remove code duplication for prologue/epilogue of all these functions switch (tag) { case DW_TAG_compile_unit: { - read_die_compilation_unit(file, debug_str_offset, &schema, &data, address_size, &dest->compilation_unit); + read_die_compilation_unit(file, string_offset, &schema_offset, &data, address_size, &die->compilation_unit); break; } case DW_TAG_subprogram: { - read_die_subprogram(file, debug_str_offset, &schema, &data, address_size, &dest->subprogram); + read_die_subprogram(file, string_offset, &schema_offset, &data, address_size, &die->subprogram); break; } case DW_TAG_variable: { - read_die_variable(file, debug_str_offset, &schema, &data, address_size, &dest->variable); + read_die_variable(file, string_offset, &schema_offset, &data, address_size, &die->variable); break; } case DW_TAG_base_type: { - read_die_base_type(file, debug_str_offset, &schema, &data, address_size, &dest->type); + read_die_base_type(file, string_offset, &schema_offset, &data, address_size, &die->type); break; } case DW_TAG_structure_type: { - read_die_structure_type(file, debug_str_offset, &schema, &data, address_size, &dest->type); + read_die_structure_type(file, string_offset, &schema_offset, &data, address_size, &die->type); break; } case DW_TAG_member: { - read_die_member(file, debug_str_offset, &schema, &data, address_size, &dest->type); + read_die_structure_member(file, string_offset, &schema_offset, &data, address_size, &die->type); + break; + } + + case DW_TAG_pointer_type: { + read_die_pointer_type(file, string_offset, &schema_offset, &data, address_size, &die->type); + break; + } + + case DW_TAG_const_type: { + read_die_const_type(file, string_offset, &schema_offset, &data, address_size, &die->type); break; } default: { - read_die_nop(file, debug_str_offset, &schema, &data, address_size); + read_die_nop(file, string_offset, &schema_offset, &data, address_size); } - } + } + + if (has_children) { + die->first_child = read_one_die(file, string_offset, info_offset, abbrev_offset, address_size, &data, depth + 1); + } + + if (depth > 0) { + die->next = read_one_die(file, string_offset, info_offset, abbrev_offset, address_size, &data, depth); + } - *schema_offset = schema; *data_offset = data; + + return(die); +} + +static void +decrap_die_tree(struct mi_debuginfo *dest, struct dwarf_die *die_root) +{ + } static u64 @@ -1045,49 +1159,11 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, u64 abbrev_offset = debug_abbrev_offset + di_header.debug_abbrev_offset; u64 data_offset = debug_info_offset + header_size; - u8 address_size = di_header.address_size; - - u32 code, tag; - u64 schema_offset; - u32 depth = 0; - //u64 base_data_offset = data_offset - header_size; - - int vars_from = dest->var_count; - int types_from = dest->type_count; - - struct mi_compunit *comp_unit = dest->compilation_units + dest->cu_count; - struct mi_function *func = dest->functions + dest->func_count; - struct mi_variable *variable = dest->variables + dest->var_count; - struct mi_type *type = dest->types + dest->type_count; - - struct dwarf_die d_die = { 0 }; - struct dwarf_die *die = &d_die; + u8 address_size = di_header.address_size; - comp_unit->functions_from = dest->func_count; + struct dwarf_die *root_die = read_one_die(file, debug_str_offset, debug_info_offset, abbrev_offset, address_size, &data_offset, 0); - for (;;) { - data_offset += decode_leb128(file + data_offset, &code); - - if (code == 0) { - if (depth > 1) { - --depth; - continue; - } else { - break; - } - } - - schema_offset = abbrev_entry_offset(file, abbrev_offset, code); - schema_offset += decode_leb128(file + schema_offset, NULL); - schema_offset += decode_leb128(file + schema_offset, &tag); - - u32 has_children = file[schema_offset++]; - if (has_children) { - ++depth; - } - - read_one_die(file, debug_info_offset, debug_str_offset, &schema_offset, &data_offset, tag, address_size, die); - } + decrap_die_tree(dest, root_die); return(di_header.length + 4); } diff --git a/src/elf_dwarf.h b/src/elf_dwarf.h index a700651..1043d7a 100644 --- a/src/elf_dwarf.h +++ b/src/elf_dwarf.h @@ -753,13 +753,15 @@ struct dwarf_die_type { int is_pointer; int is_restrict; - struct dwarf_die_type *next; - struct dwarf_die_type *first_child; + u64 pointer; }; struct dwarf_die { u64 offset; - struct dwarf_die *parent; + + struct dwarf_die *first_child; + struct dwarf_die *next; + enum dwarf_die_tag tag; union { struct dwarf_die_compilation_unit compilation_unit;