|
|
@ -1,5 +1,5 @@ |
|
|
|
static u64 |
|
|
|
static struct elf_section_table_entry_x64 |
|
|
|
get_section_offset(u8 *file, char *name) |
|
|
|
get_section_entry(u8 *file, char *name) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct elf_header_x64 header = { 0 }; |
|
|
|
struct elf_header_x64 header = { 0 }; |
|
|
|
memcpy(&header, file, sizeof(header)); |
|
|
|
memcpy(&header, file, sizeof(header)); |
|
|
@ -16,7 +16,8 @@ get_section_offset(u8 *file, char *name) |
|
|
|
memcpy(&shstrtab_header, file + shstrtab_header_offset, sizeof(shstrtab_header)); |
|
|
|
memcpy(&shstrtab_header, file + shstrtab_header_offset, sizeof(shstrtab_header)); |
|
|
|
|
|
|
|
|
|
|
|
u64 shstrtab_offset = shstrtab_header.offset_in_file; |
|
|
|
u64 shstrtab_offset = shstrtab_header.offset_in_file; |
|
|
|
u64 debug_info_offset = 0; |
|
|
|
|
|
|
|
|
|
|
|
struct elf_section_table_entry_x64 result = { 0 }; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < header.section_table_entry_count; ++i) { |
|
|
|
for (int i = 0; i < header.section_table_entry_count; ++i) { |
|
|
|
struct elf_section_table_entry_x64 section_entry = { 0 }; |
|
|
|
struct elf_section_table_entry_x64 section_entry = { 0 }; |
|
|
@ -25,12 +26,21 @@ get_section_offset(u8 *file, char *name) |
|
|
|
u64 section_name_offset = shstrtab_offset + section_entry.name_offset; |
|
|
|
u64 section_name_offset = shstrtab_offset + section_entry.name_offset; |
|
|
|
|
|
|
|
|
|
|
|
if (strncmp((char *) file + section_name_offset, name, strlen(name) + 1) == 0) { |
|
|
|
if (strncmp((char *) file + section_name_offset, name, strlen(name) + 1) == 0) { |
|
|
|
debug_info_offset = section_entry.offset_in_file; |
|
|
|
result = section_entry; |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return(debug_info_offset); |
|
|
|
return(result); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static u64 |
|
|
|
|
|
|
|
get_section_offset(u8 *file, char *name) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct elf_section_table_entry_x64 entry = get_section_entry(file, name); |
|
|
|
|
|
|
|
u64 result = entry.offset_in_file; |
|
|
|
|
|
|
|
return(result); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
static int |
|
|
@ -232,18 +242,10 @@ read_actual_debug_data(u8 *file, u64 string_offset, u32 address_size, u64 base_d |
|
|
|
return(increment); |
|
|
|
return(increment); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
static u64 |
|
|
|
parse_debug_info(u8 *file, struct mi_debuginfo *dest) |
|
|
|
read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, |
|
|
|
|
|
|
|
u64 debug_info_offset, u64 debug_abbrev_offset, u64 debug_str_offset) |
|
|
|
{ |
|
|
|
{ |
|
|
|
u64 debug_info_offset = get_section_offset(file, ".debug_info"); |
|
|
|
|
|
|
|
printf("Found .debug_info at offset %#lx\n", debug_info_offset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u64 debug_abbrev_offset = get_section_offset(file, ".debug_abbrev"); |
|
|
|
|
|
|
|
printf("Found .debug_abbrev at offset %#lx\n", debug_abbrev_offset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u64 debug_str_offset = get_section_offset(file, ".debug_str"); |
|
|
|
|
|
|
|
printf("Found .debug_str at offset %#lx\n", debug_str_offset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct dwarf_debug_info_header_x32 di_header = { 0 }; |
|
|
|
struct dwarf_debug_info_header_x32 di_header = { 0 }; |
|
|
|
u32 header_size = sizeof(di_header); |
|
|
|
u32 header_size = sizeof(di_header); |
|
|
|
memcpy(&di_header, file + debug_info_offset, header_size); |
|
|
|
memcpy(&di_header, file + debug_info_offset, header_size); |
|
|
@ -258,7 +260,8 @@ parse_debug_info(u8 *file, struct mi_debuginfo *dest) |
|
|
|
|
|
|
|
|
|
|
|
int found_sr = 0; |
|
|
|
int found_sr = 0; |
|
|
|
|
|
|
|
|
|
|
|
struct mi_function *func = dest->functions; |
|
|
|
struct mi_function *func = dest->functions + dest->func_count; |
|
|
|
|
|
|
|
struct mi_compunit *comp_unit = dest->compilation_units + dest->cu_count; |
|
|
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
for (;;) { |
|
|
|
data_offset += decode_leb128(file + data_offset, &code); |
|
|
|
data_offset += decode_leb128(file + data_offset, &code); |
|
|
@ -294,31 +297,77 @@ parse_debug_info(u8 *file, struct mi_debuginfo *dest) |
|
|
|
data_offset += read_actual_debug_data(file, debug_str_offset, di_header.address_size, base_data_offset, form, data_offset, &value); |
|
|
|
data_offset += read_actual_debug_data(file, debug_str_offset, di_header.address_size, base_data_offset, form, data_offset, &value); |
|
|
|
|
|
|
|
|
|
|
|
if (tag == DW_TAG_compile_unit) { |
|
|
|
if (tag == DW_TAG_compile_unit) { |
|
|
|
if (attribute == DW_AT_comp_dir) { |
|
|
|
if (attribute == DW_AT_low_pc) { |
|
|
|
dest->comp_dir = (char *) value; |
|
|
|
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->comp_dir = (char *) value; |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (tag == DW_TAG_subprogram) { |
|
|
|
} else if (tag == DW_TAG_subprogram) { |
|
|
|
if (attribute == DW_AT_name) { |
|
|
|
if (attribute == DW_AT_name) { |
|
|
|
func->name = (char *) value; |
|
|
|
func->name = (char *) value; |
|
|
|
} else if (attribute == DW_AT_low_pc) { |
|
|
|
} else if (attribute == DW_AT_low_pc) { |
|
|
|
func->offset = value; |
|
|
|
func->low_pc = value; |
|
|
|
|
|
|
|
} else if (attribute == DW_AT_high_pc) { |
|
|
|
|
|
|
|
func->high_pc = value; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} while (attribute != 0 || form != 0); |
|
|
|
} while (attribute != 0 || form != 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (tag == DW_TAG_compile_unit) { |
|
|
|
|
|
|
|
comp_unit->high_pc = comp_unit->low_pc + comp_unit->high_pc; |
|
|
|
|
|
|
|
++comp_unit; |
|
|
|
|
|
|
|
++dest->cu_count; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (tag == DW_TAG_subprogram) { |
|
|
|
if (tag == DW_TAG_subprogram) { |
|
|
|
|
|
|
|
func->high_pc = func->low_pc + func->high_pc; |
|
|
|
|
|
|
|
func->comp_unit = dest->cu_count; |
|
|
|
++func; |
|
|
|
++func; |
|
|
|
++dest->func_count; |
|
|
|
++dest->func_count; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return(di_header.length + 4); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
static void |
|
|
|
parse_debug_line(u8 *file, |
|
|
|
parse_debug_info(u8 *file, struct mi_debuginfo *dest) |
|
|
|
struct mi_sourcepoint *dest, struct mi_sourcefile *dest_files, char **dest_directories, |
|
|
|
{ |
|
|
|
int *dest_size, int *dest_files_size, int *dest_directories_size) |
|
|
|
struct elf_section_table_entry_x64 debug_info = get_section_entry(file, ".debug_info"); |
|
|
|
|
|
|
|
printf("Found .debug_info at offset %#lx\n", debug_info.offset_in_file); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u64 debug_abbrev_offset = get_section_offset(file, ".debug_abbrev"); |
|
|
|
|
|
|
|
printf("Found .debug_abbrev at offset %#lx\n", debug_abbrev_offset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u64 debug_str_offset = get_section_offset(file, ".debug_str"); |
|
|
|
|
|
|
|
printf("Found .debug_str at offset %#lx\n", debug_str_offset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u64 at = debug_info.offset_in_file; |
|
|
|
|
|
|
|
u64 read = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
|
|
|
u64 size = read_debug_info_for_compilation_unit(file, dest, at, debug_abbrev_offset, debug_str_offset); |
|
|
|
|
|
|
|
read += size; |
|
|
|
|
|
|
|
at += size; |
|
|
|
|
|
|
|
if (read >= debug_info.size) { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static u64 |
|
|
|
|
|
|
|
read_debug_line_for_compilation_unit(u8 *file, u64 dl_offset, struct mi_compunit *unit) |
|
|
|
{ |
|
|
|
{ |
|
|
|
u64 dl_offset = get_section_offset(file, ".debug_line"); |
|
|
|
struct mi_sourcepoint *dest = unit->sp_table; |
|
|
|
|
|
|
|
int *dest_size = &unit->sp_count; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct mi_sourcefile *dest_files = unit->source_files; |
|
|
|
|
|
|
|
int *dest_files_size = &unit->source_file_count; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char **dest_directories = unit->source_directories; |
|
|
|
|
|
|
|
int *dest_directories_size = &unit->source_dirs_count; |
|
|
|
|
|
|
|
|
|
|
|
struct dwarf_debug_line_header_v3_x32 header = { 0 }; |
|
|
|
struct dwarf_debug_line_header_v3_x32 header = { 0 }; |
|
|
|
memcpy(&header, file + dl_offset, 15); /* all fixed-size info */ |
|
|
|
memcpy(&header, file + dl_offset, 15); /* all fixed-size info */ |
|
|
@ -640,6 +689,48 @@ is followed by a single null byte." */ |
|
|
|
if (dest_directories_size) { |
|
|
|
if (dest_directories_size) { |
|
|
|
*dest_directories_size = ndirs; |
|
|
|
*dest_directories_size = ndirs; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return(header.length + 4); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
|
|
|
parse_debug_line(u8 *file, struct mi_debuginfo *debug) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct elf_section_table_entry_x64 debug_line = get_section_entry(file, ".debug_line"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u64 at = debug_line.offset_in_file; |
|
|
|
|
|
|
|
u64 read = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct mi_compunit *unit = debug->compilation_units; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// count
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
|
|
|
u64 size = read_debug_line_for_compilation_unit(file, at, unit); |
|
|
|
|
|
|
|
unit->sp_table = calloc(1, unit->sp_count * sizeof(struct mi_sourcepoint)); |
|
|
|
|
|
|
|
unit->source_directories = calloc(1, unit->source_dirs_count * sizeof(char *)); |
|
|
|
|
|
|
|
unit->source_files = calloc(1, unit->source_file_count * sizeof(struct mi_sourcefile)); |
|
|
|
|
|
|
|
read += size; |
|
|
|
|
|
|
|
at += size; |
|
|
|
|
|
|
|
++unit; |
|
|
|
|
|
|
|
if (read >= debug_line.size) { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unit = debug->compilation_units; |
|
|
|
|
|
|
|
at = debug_line.offset_in_file; |
|
|
|
|
|
|
|
read = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fill
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
|
|
|
u64 size = read_debug_line_for_compilation_unit(file, at, unit); |
|
|
|
|
|
|
|
read += size; |
|
|
|
|
|
|
|
at += size; |
|
|
|
|
|
|
|
++unit; |
|
|
|
|
|
|
|
if (read >= debug_line.size) { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static u64 |
|
|
|
static u64 |
|
|
|