Browse Source

Get actual DIE _tree_. No useful info extracted from the tree for now. Nodes malloc()-ed all over the place

master
A.Olokhtonov 3 years ago
parent
commit
bb6a5ef557
  1. 188
      src/dwarf.c
  2. 8
      src/elf_dwarf.h

188
src/dwarf.c

@ -967,8 +967,8 @@ read_die_structure_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64
} }
static void static void
read_die_member(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset, read_die_structure_member(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset,
u8 address_size, struct dwarf_die_type *dest) u8 address_size, struct dwarf_die_type *dest)
{ {
u64 data = *data_offset; u64 data = *data_offset;
u64 schema = *schema_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, &attribute);
schema += decode_leb128(file + schema, &form); schema += decode_leb128(file + schema, &form);
data += read_actual_debug_data(file, debug_str_offset, address_size, form, data, &value); 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); } while (attribute != 0 || form != 0);
*data_offset = data; *data_offset = data;
@ -986,53 +998,155 @@ read_die_member(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_of
} }
static void static void
read_one_die(u8 *file, u64 debug_info_offset, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset, read_die_pointer_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset,
enum dwarf_die_tag tag, u8 address_size, struct dwarf_die *dest) u8 address_size, struct dwarf_die_type *dest)
{ {
u64 data = *data_offset;
u64 schema = *schema_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 data = *data_offset;
u64 schema = *schema_offset;
dest->offset = data - debug_info_offset; u32 attribute, form;
dest->tag = tag; 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) { switch (tag) {
case DW_TAG_compile_unit: { 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; break;
} }
case DW_TAG_subprogram: { 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; break;
} }
case DW_TAG_variable: { 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; break;
} }
case DW_TAG_base_type: { 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; break;
} }
case DW_TAG_structure_type: { 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; break;
} }
case DW_TAG_member: { 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; break;
} }
default: { 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; *data_offset = data;
return(die);
}
static void
decrap_die_tree(struct mi_debuginfo *dest, struct dwarf_die *die_root)
{
} }
static u64 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 abbrev_offset = debug_abbrev_offset + di_header.debug_abbrev_offset;
u64 data_offset = debug_info_offset + header_size; u64 data_offset = debug_info_offset + header_size;
u8 address_size = di_header.address_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;
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 (;;) { decrap_die_tree(dest, root_die);
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);
}
return(di_header.length + 4); return(di_header.length + 4);
} }

8
src/elf_dwarf.h

@ -753,13 +753,15 @@ struct dwarf_die_type {
int is_pointer; int is_pointer;
int is_restrict; int is_restrict;
struct dwarf_die_type *next; u64 pointer;
struct dwarf_die_type *first_child;
}; };
struct dwarf_die { struct dwarf_die {
u64 offset; u64 offset;
struct dwarf_die *parent;
struct dwarf_die *first_child;
struct dwarf_die *next;
enum dwarf_die_tag tag; enum dwarf_die_tag tag;
union { union {
struct dwarf_die_compilation_unit compilation_unit; struct dwarf_die_compilation_unit compilation_unit;

Loading…
Cancel
Save