|  |  |  | @ -753,214 +753,341 @@ read_actual_debug_data(u8 *file, u64 string_offset, u32 address_size, u32 form,@@ -753,214 +753,341 @@ read_actual_debug_data(u8 *file, u64 string_offset, u32 address_size, u32 form, | 
			
		
	
		
			
				
					|  |  |  |  |     return(increment); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static u64 | 
			
		
	
		
			
				
					|  |  |  |  | read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, | 
			
		
	
		
			
				
					|  |  |  |  |                                      u64 debug_info_offset, u64 debug_abbrev_offset, u64 debug_str_offset) | 
			
		
	
		
			
				
					|  |  |  |  | static void | 
			
		
	
		
			
				
					|  |  |  |  | read_die_compilation_unit(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset,  | 
			
		
	
		
			
				
					|  |  |  |  |                           u8 address_size, struct dwarf_die_compilation_unit *dest) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     struct dwarf_debug_info_header_x32 di_header = { 0 }; | 
			
		
	
		
			
				
					|  |  |  |  |     u32 header_size = sizeof(di_header); | 
			
		
	
		
			
				
					|  |  |  |  |     memcpy(&di_header, file + debug_info_offset, header_size); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     u64 abbrev_offset = debug_abbrev_offset + di_header.debug_abbrev_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 data_offset = debug_info_offset + header_size; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     u32 code, tag; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 schema_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u32 depth = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     //u64 base_data_offset = data_offset - header_size;
 | 
			
		
	
		
			
				
					|  |  |  |  |     u64 schema = *schema_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 data   = *data_offset; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     int vars_from = dest->var_count; | 
			
		
	
		
			
				
					|  |  |  |  |     int types_from = dest->type_count; | 
			
		
	
		
			
				
					|  |  |  |  |     u32 attribute, form; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     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; | 
			
		
	
		
			
				
					|  |  |  |  |     do { | 
			
		
	
		
			
				
					|  |  |  |  |         u64 value; | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |     struct mi_type *parent_type = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         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); | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |     comp_unit->functions_from = dest->func_count; | 
			
		
	
		
			
				
					|  |  |  |  |         switch (attribute) { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_name: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |     for (;;) { | 
			
		
	
		
			
				
					|  |  |  |  |         s64 record_offset = data_offset - debug_info_offset; | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_comp_dir: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->comp_dir = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |         data_offset += decode_leb128(file + data_offset, &code); | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_low_pc: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->low_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |         if (code == 0) { | 
			
		
	
		
			
				
					|  |  |  |  |             if (depth > 1) { | 
			
		
	
		
			
				
					|  |  |  |  |                 --depth; | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } else { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_high_pc: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->high_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |         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); | 
			
		
	
		
			
				
					|  |  |  |  |     dest->high_pc = dest->low_pc + dest->high_pc; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |         //printf("%d %s\n", code, tag_to_str(tag));
 | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset   = data; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         u32 has_children = file[schema_offset++]; | 
			
		
	
		
			
				
					|  |  |  |  |         if (has_children) { | 
			
		
	
		
			
				
					|  |  |  |  |             ++depth; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         switch (tag) { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_TAG_compile_unit: { | 
			
		
	
		
			
				
					|  |  |  |  | static void | 
			
		
	
		
			
				
					|  |  |  |  | read_die_subprogram(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset,  | 
			
		
	
		
			
				
					|  |  |  |  |                     u8 address_size, struct dwarf_die_subprogram *dest) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     u64 schema = *schema_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 data   = *data_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_name: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_TAG_subprogram: { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_low_pc: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->low_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_TAG_variable: { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_high_pc: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->high_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_TAG_structure_type: { | 
			
		
	
		
			
				
					|  |  |  |  |     dest->high_pc = dest->low_pc + dest->high_pc; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset   = data; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void | 
			
		
	
		
			
				
					|  |  |  |  | read_die_variable(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset,  | 
			
		
	
		
			
				
					|  |  |  |  |                   u8 address_size, struct dwarf_die_variable *dest) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     u64 schema = *schema_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 data   = *data_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_name: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_TAG_member: { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_location: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->location = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_TAG_base_type: { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_type: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->type = (void * ) value; // TODO TODO TODO
 | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | #if 0 | 
			
		
	
		
			
				
					|  |  |  |  |     } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset   = data; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void | 
			
		
	
		
			
				
					|  |  |  |  | read_die_base_type(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset,  | 
			
		
	
		
			
				
					|  |  |  |  |                    u8 address_size, struct dwarf_die_type *dest) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     u64 schema = *schema_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 data   = *data_offset; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     u32 attribute, form; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     do { | 
			
		
	
		
			
				
					|  |  |  |  |             schema_offset += decode_leb128(file + schema_offset, &attribute); | 
			
		
	
		
			
				
					|  |  |  |  |             schema_offset += decode_leb128(file + schema_offset, &form); | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |         u64 value; | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |             data_offset += read_actual_debug_data(file, debug_str_offset, di_header.address_size, form, data_offset, &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); | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |             if (tag == DW_TAG_compile_unit) { | 
			
		
	
		
			
				
					|  |  |  |  |                 if (attribute == DW_AT_low_pc) { | 
			
		
	
		
			
				
					|  |  |  |  |                     comp_unit->low_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_high_pc) { | 
			
		
	
		
			
				
					|  |  |  |  |                     comp_unit->high_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_comp_dir) { | 
			
		
	
		
			
				
					|  |  |  |  |                     comp_unit->source.comp_dir = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |         switch (attribute) { | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_name: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             } else if (tag == DW_TAG_subprogram) { | 
			
		
	
		
			
				
					|  |  |  |  |                 if (attribute == DW_AT_name) { | 
			
		
	
		
			
				
					|  |  |  |  |                     func->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_low_pc) { | 
			
		
	
		
			
				
					|  |  |  |  |                     func->low_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_high_pc) { | 
			
		
	
		
			
				
					|  |  |  |  |                     func->high_pc = value; | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_byte_size: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->size = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             } else if (tag == DW_TAG_variable) { | 
			
		
	
		
			
				
					|  |  |  |  |                 if (attribute == DW_AT_name) { | 
			
		
	
		
			
				
					|  |  |  |  |                     variable->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_location) { | 
			
		
	
		
			
				
					|  |  |  |  |                     variable->location = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_type) { | 
			
		
	
		
			
				
					|  |  |  |  |                     variable->type = value; | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_encoding: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->encoding = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             } else if (tag == DW_TAG_structure_type) { | 
			
		
	
		
			
				
					|  |  |  |  |                 type->_offset = record_offset; | 
			
		
	
		
			
				
					|  |  |  |  |                 if (attribute == DW_AT_name) { | 
			
		
	
		
			
				
					|  |  |  |  |                     type->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_byte_size) { | 
			
		
	
		
			
				
					|  |  |  |  |                     type->size = value; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |             } else if (tag == DW_TAG_member) { | 
			
		
	
		
			
				
					|  |  |  |  |     } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |             } else if (tag == DW_TAG_base_type) { | 
			
		
	
		
			
				
					|  |  |  |  |                 type->_offset = record_offset; | 
			
		
	
		
			
				
					|  |  |  |  |                 if (attribute == DW_AT_name) { | 
			
		
	
		
			
				
					|  |  |  |  |                     type->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_byte_size) { | 
			
		
	
		
			
				
					|  |  |  |  |                     type->size = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (attribute == DW_AT_encoding) { | 
			
		
	
		
			
				
					|  |  |  |  |                     enum dwarf_type_encoding encoding = value; | 
			
		
	
		
			
				
					|  |  |  |  |                     switch (encoding) { | 
			
		
	
		
			
				
					|  |  |  |  |                         case DW_ATE_address: { | 
			
		
	
		
			
				
					|  |  |  |  |                             type->encoding = MI_ADDRESS; | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset   = data; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void | 
			
		
	
		
			
				
					|  |  |  |  | read_die_nop(u8 *file, u64 debug_str_offset, u64 *schema_offset, u64 *data_offset,  | 
			
		
	
		
			
				
					|  |  |  |  |              u8 address_size) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     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); | 
			
		
	
		
			
				
					|  |  |  |  |     } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset = data; | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void | 
			
		
	
		
			
				
					|  |  |  |  | read_die_structure_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_name: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->name = (char *) value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |                         case DW_ATE_boolean: { | 
			
		
	
		
			
				
					|  |  |  |  |                             type->encoding = MI_BOOLEAN; | 
			
		
	
		
			
				
					|  |  |  |  |             case DW_AT_byte_size: { | 
			
		
	
		
			
				
					|  |  |  |  |                 dest->size = value; | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |                         case DW_ATE_float: { | 
			
		
	
		
			
				
					|  |  |  |  |                             type->encoding = MI_FLOAT; | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset = data; | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 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) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     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); | 
			
		
	
		
			
				
					|  |  |  |  |     } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset = data; | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 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) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     u64 schema = *schema_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 data = *data_offset; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     dest->offset = data - debug_info_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     dest->tag = tag; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     switch (tag) { | 
			
		
	
		
			
				
					|  |  |  |  |         case DW_TAG_compile_unit: { | 
			
		
	
		
			
				
					|  |  |  |  |             read_die_compilation_unit(file, debug_str_offset, &schema, &data, address_size, &dest->compilation_unit); | 
			
		
	
		
			
				
					|  |  |  |  |             break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |                         case DW_ATE_signed_char: | 
			
		
	
		
			
				
					|  |  |  |  |                         case DW_ATE_signed: { | 
			
		
	
		
			
				
					|  |  |  |  |                             type->encoding = MI_SIGNED; | 
			
		
	
		
			
				
					|  |  |  |  |         case DW_TAG_subprogram: { | 
			
		
	
		
			
				
					|  |  |  |  |             read_die_subprogram(file, debug_str_offset, &schema, &data, address_size, &dest->subprogram); | 
			
		
	
		
			
				
					|  |  |  |  |             break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |                         case DW_ATE_unsigned_char: | 
			
		
	
		
			
				
					|  |  |  |  |                         case DW_ATE_unsigned: { | 
			
		
	
		
			
				
					|  |  |  |  |                             type->encoding = MI_UNSIGNED; | 
			
		
	
		
			
				
					|  |  |  |  |         case DW_TAG_variable: { | 
			
		
	
		
			
				
					|  |  |  |  |             read_die_variable(file, debug_str_offset, &schema, &data, address_size, &dest->variable); | 
			
		
	
		
			
				
					|  |  |  |  |             break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |                         default: { | 
			
		
	
		
			
				
					|  |  |  |  |                             DIE("unexpected type encoding!\n"); | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |         case DW_TAG_base_type: { | 
			
		
	
		
			
				
					|  |  |  |  |             read_die_base_type(file, debug_str_offset, &schema, &data, address_size, &dest->type); | 
			
		
	
		
			
				
					|  |  |  |  |             break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |         case DW_TAG_structure_type: { | 
			
		
	
		
			
				
					|  |  |  |  |             read_die_structure_type(file, debug_str_offset, &schema, &data, address_size, &dest->type); | 
			
		
	
		
			
				
					|  |  |  |  |             break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |         case DW_TAG_member: { | 
			
		
	
		
			
				
					|  |  |  |  |             read_die_member(file, debug_str_offset, &schema, &data, address_size, &dest->type); | 
			
		
	
		
			
				
					|  |  |  |  |             break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         } while (attribute != 0 || form != 0); | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |         // NOTE(aolo2): DIE completely processed, finish it ??uploads??
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (tag == DW_TAG_subprogram) { | 
			
		
	
		
			
				
					|  |  |  |  |             func->high_pc = func->low_pc + func->high_pc; | 
			
		
	
		
			
				
					|  |  |  |  |             func->variables_from = dest->var_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++comp_unit->functions_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++dest->func_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++func; | 
			
		
	
		
			
				
					|  |  |  |  |         } else if (tag == DW_TAG_variable) { | 
			
		
	
		
			
				
					|  |  |  |  |             struct mi_function *parent = func - 1;  | 
			
		
	
		
			
				
					|  |  |  |  |             ++parent->variables_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++dest->var_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++variable; | 
			
		
	
		
			
				
					|  |  |  |  |         } else if (tag == DW_TAG_base_type) { | 
			
		
	
		
			
				
					|  |  |  |  |             ++parent_type->children_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++dest->type_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++type; | 
			
		
	
		
			
				
					|  |  |  |  |         } else if (tag == DW_TAG_structure_type) { | 
			
		
	
		
			
				
					|  |  |  |  |             parent_type = type; | 
			
		
	
		
			
				
					|  |  |  |  |             parent_type->children_from = dest->type_count; | 
			
		
	
		
			
				
					|  |  |  |  |             ++type; | 
			
		
	
		
			
				
					|  |  |  |  |         default: { | 
			
		
	
		
			
				
					|  |  |  |  |             read_die_nop(file, debug_str_offset, &schema, &data, address_size); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     }  | 
			
		
	
		
			
				
					|  |  |  |  | #endif | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     *schema_offset = schema; | 
			
		
	
		
			
				
					|  |  |  |  |     *data_offset = data; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | static u64 | 
			
		
	
		
			
				
					|  |  |  |  | read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, | 
			
		
	
		
			
				
					|  |  |  |  |                                      u64 debug_info_offset, u64 debug_abbrev_offset, u64 debug_str_offset) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     struct dwarf_debug_info_header_x32 di_header = { 0 }; | 
			
		
	
		
			
				
					|  |  |  |  |     u32 header_size = sizeof(di_header); | 
			
		
	
		
			
				
					|  |  |  |  |     memcpy(&di_header, file + debug_info_offset, header_size); | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     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; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     // Resolve types
 | 
			
		
	
		
			
				
					|  |  |  |  |     for (int v = vars_from; v < dest->var_count; ++v) { | 
			
		
	
		
			
				
					|  |  |  |  |         struct mi_variable *variable = dest->variables + v; | 
			
		
	
		
			
				
					|  |  |  |  |     u32 code, tag; | 
			
		
	
		
			
				
					|  |  |  |  |     u64 schema_offset; | 
			
		
	
		
			
				
					|  |  |  |  |     u32 depth = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     //u64 base_data_offset = data_offset - header_size;
 | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |         for (int t = types_from; t < dest->type_count; ++t) { | 
			
		
	
		
			
				
					|  |  |  |  |             struct mi_type *type = dest->types + t; | 
			
		
	
		
			
				
					|  |  |  |  |     int vars_from = dest->var_count; | 
			
		
	
		
			
				
					|  |  |  |  |     int types_from = dest->type_count; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |             if (type->_offset == variable->type) { | 
			
		
	
		
			
				
					|  |  |  |  |                 variable->type = t; | 
			
		
	
		
			
				
					|  |  |  |  |     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; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     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; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |     comp_unit->high_pc = comp_unit->low_pc + comp_unit->high_pc; | 
			
		
	
		
			
				
					|  |  |  |  |     ++dest->cu_count; | 
			
		
	
		
			
				
					|  |  |  |  |         read_one_die(file, debug_info_offset, debug_str_offset, &schema_offset, &data_offset, tag, address_size, die); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     return(di_header.length + 4); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |