@ -868,7 +868,7 @@ read_die_variable(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_
@@ -868,7 +868,7 @@ read_die_variable(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_
}
case DW_AT_type : {
dest - > type = ( void * ) value ; // TODO TODO TODO
dest - > type = value ;
break ;
}
}
@ -1056,7 +1056,7 @@ read_die_const_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *dat
@@ -1056,7 +1056,7 @@ read_die_const_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *dat
// 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 )
read_one_die ( u8 * file , u64 string_offset , u64 info_offset , u64 abbrev_offset , u8 address_size , u64 * data_offset , struct dwarf_die * parent , u32 depth )
{
u64 data = * data_offset ;
u64 record_offset = data - info_offset ;
@ -1074,6 +1074,8 @@ read_one_die(u8 *file, u64 string_offset, u64 info_offset, u64 abbrev_offset, u8
@@ -1074,6 +1074,8 @@ read_one_die(u8 *file, u64 string_offset, u64 info_offset, u64 abbrev_offset, u8
// TODO: use a custom allocator / preallocated memory for this
struct dwarf_die * die = calloc ( 1 , sizeof ( struct dwarf_die ) ) ;
die - > parent = parent ;
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 ) ;
@ -1131,11 +1133,11 @@ read_one_die(u8 *file, u64 string_offset, u64 info_offset, u64 abbrev_offset, u8
@@ -1131,11 +1133,11 @@ read_one_die(u8 *file, u64 string_offset, u64 info_offset, u64 abbrev_offset, u8
}
if ( has_children ) {
die - > first_child = read_one_die ( file , string_offset , info_offset , abbrev_offset , address_size , & data , depth + 1 ) ;
die - > first_child = read_one_die ( file , string_offset , info_offset , abbrev_offset , address_size , & data , die , d epth + 1 ) ;
}
if ( depth > 0 ) {
die - > next = read_one_die ( file , string_offset , info_offset , abbrev_offset , address_size , & data , depth ) ;
die - > next = read_one_die ( file , string_offset , info_offset , abbrev_offset , address_size , & data , parent , depth ) ;
}
* data_offset = data ;
@ -1143,10 +1145,94 @@ read_one_die(u8 *file, u64 string_offset, u64 info_offset, u64 abbrev_offset, u8
@@ -1143,10 +1145,94 @@ read_one_die(u8 *file, u64 string_offset, u64 info_offset, u64 abbrev_offset, u8
return ( die ) ;
}
static void
traverse_die_tree_rec ( struct mi_debuginfo * dest , struct dwarf_die * die )
{
switch ( die - > tag ) {
case DW_TAG_compile_unit : {
struct mi_compunit * comp_unit = dest - > compilation_units + dest - > cu_count ;
comp_unit - > low_pc = die - > compilation_unit . low_pc ;
comp_unit - > high_pc = die - > compilation_unit . high_pc ;
comp_unit - > source . comp_dir = die - > compilation_unit . comp_dir ;
comp_unit - > functions_from = dest - > func_count ;
+ + dest - > cu_count ;
break ;
}
case DW_TAG_subprogram : {
struct mi_compunit * comp_unit = dest - > compilation_units + dest - > cu_count - 1 ;
struct mi_function * func = dest - > functions + dest - > func_count ;
func - > name = die - > subprogram . name ;
func - > low_pc = die - > subprogram . low_pc ;
func - > high_pc = die - > subprogram . high_pc ;
func - > variables_from = dest - > var_count ;
+ + comp_unit - > functions_count ;
+ + dest - > func_count ;
break ;
}
case DW_TAG_variable : {
struct mi_function * func = dest - > functions + dest - > func_count - 1 ;
struct mi_variable * var = dest - > variables + dest - > var_count ;
var - > name = die - > variable . name ;
var - > location = die - > variable . location ;
var - > type = die - > variable . type ;
+ + func - > variables_count ;
+ + dest - > var_count ;
break ;
}
case DW_TAG_base_type : {
struct mi_type * type = dest - > types + dest - > type_count ;
type - > encoding = die - > type . encoding ;
type - > name = die - > type . name ;
type - > size = die - > type . size ;
type - > _offset = die - > offset ;
+ + dest - > type_count ;
break ;
}
}
if ( die - > first_child ) {
traverse_die_tree_rec ( dest , die - > first_child ) ;
}
if ( die - > next ) {
traverse_die_tree_rec ( dest , die - > next ) ;
}
}
// NOTE(aolo2): turn the DIE tree into something usable
static void
decrap_die_tree ( struct mi_debuginfo * dest , struct dwarf_die * die_root )
{
traverse_die_tree_rec ( dest , die_root ) ;
// Resolve types
for ( int v = 0 ; v < dest - > var_count ; + + v ) {
struct mi_variable * var = dest - > variables + v ;
for ( int t = 0 ; t < dest - > type_count ; + + t ) {
struct mi_type * type = dest - > types + t ;
if ( type - > _offset = = var - > type ) {
var - > type = t ;
break ;
}
}
}
}
static u64
@ -1161,7 +1247,7 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
@@ -1161,7 +1247,7 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
u64 data_offset = debug_info_offset + header_size ;
u8 address_size = di_header . address_size ;
struct dwarf_die * root_die = read_one_die ( file , debug_str_offset , debug_info_offset , abbrev_offset , address_size , & data_offset , 0 ) ;
struct dwarf_die * root_die = read_one_die ( file , debug_str_offset , debug_info_offset , abbrev_offset , address_size , & data_offset , 0 , 0 ) ;
decrap_die_tree ( dest , root_die ) ;