From 7c1fa37da2634550e2618d4504d8ca5c7675a08a Mon Sep 17 00:00:00 2001 From: aolo2 Date: Tue, 20 Jul 2021 17:01:35 +0300 Subject: [PATCH] Multiple compilation units --- .gitignore | 4 + command.c | 37 ++++--- common.h | 37 ++++--- dwarf.c | 139 ++++++++++++++++++++---- main.c | 6 +- trace_include.c => res/001-simple-inc.c | 0 traceme.c => res/001-simple.c | 2 +- res/002-compilation-units-impl.c | 8 ++ res/002-compilation-units.c | 9 ++ res/002-compilation-units.h | 1 + res/Makefile | 3 + res/traceme | Bin 0 -> 19416 bytes util.c | 35 +++--- 13 files changed, 211 insertions(+), 70 deletions(-) create mode 100644 .gitignore rename trace_include.c => res/001-simple-inc.c (100%) rename traceme.c => res/001-simple.c (92%) create mode 100644 res/002-compilation-units-impl.c create mode 100644 res/002-compilation-units.c create mode 100644 res/002-compilation-units.h create mode 100644 res/Makefile create mode 100755 res/traceme diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..733fb82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.gdb_history +build/ +res/001-simple +res/002-compilation-units diff --git a/command.c b/command.c index e2dc883..56d01be 100644 --- a/command.c +++ b/command.c @@ -15,15 +15,22 @@ command_regs(struct mi_process proc) static void command_step(struct mi_process proc) { - ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0); - waitpid(proc.pid, 0, 0); + int comp_unit; -#if 1 - print_current_instruction(proc); struct mi_registers regs = get_process_registers(proc); - struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address); - print_sourcepoint(proc, sp); -#endif + struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address, &comp_unit); + struct mi_sourcepoint *next_sp; + + do { + ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0); + waitpid(proc.pid, 0, 0); + regs = get_process_registers(proc); + long instruction = ptrace(PTRACE_PEEKDATA, proc.pid, regs.rip, NULL); + next_sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address, &comp_unit); + if (!next_sp) break; + } while (next_sp->line == sp->line); + + print_sourcepoint(proc, comp_unit, next_sp); } static void @@ -37,9 +44,10 @@ command_start(struct mi_process proc) static void command_next(struct mi_process proc) { - struct mi_registers regs = get_process_registers(proc); + int comp_unit; - struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address); + struct mi_registers regs = get_process_registers(proc); + struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address, &comp_unit); struct mi_sourcepoint *next_sp; do { @@ -63,23 +71,24 @@ command_next(struct mi_process proc) regs = get_process_registers(proc); } - // TODO: skip call, repXXX + // TODO: repXXX //printf("%#lx\n", regs.rip - proc.base_address); - next_sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address); + next_sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address, &comp_unit); if (!next_sp) break; } while (next_sp->line == sp->line); - print_sourcepoint(proc, next_sp); + print_sourcepoint(proc, comp_unit, next_sp); } static void command_list(struct mi_process proc) { + int comp_unit; struct mi_registers regs = get_process_registers(proc); - struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address); - print_sourcepoint(proc, sp); + struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address, &comp_unit); + print_sourcepoint(proc, comp_unit, sp); } static void diff --git a/common.h b/common.h index 7f78f4a..e34dcf1 100644 --- a/common.h +++ b/common.h @@ -45,23 +45,39 @@ struct mi_sourcepoint { struct mi_function { char *name; - u64 offset; + int comp_unit; + u64 low_pc; + u64 high_pc; }; -struct mi_debuginfo { +struct mi_sourcefile { + char *filename; + char *dir; + struct mi_buffer file; +}; + +struct mi_compunit { + u64 low_pc; + u64 high_pc; + struct mi_sourcepoint *sp_table; int sp_count; - struct mi_function functions[64]; // TODO - int func_count; + int source_file_count; + struct mi_sourcefile *source_files; + + char **source_directories; + int source_dirs_count; char *comp_dir; }; -struct mi_sourcefile { - char *filename; - char *dir; - struct mi_buffer file; +struct mi_debuginfo { + struct mi_compunit compilation_units[16]; // TODO + int cu_count; + + struct mi_function functions[64]; // TODO + int func_count; }; struct mi_process { @@ -74,11 +90,6 @@ struct mi_process { u64 main_address; struct mi_debuginfo debug; - - int source_file_count; - int source_dirs_count; - struct mi_sourcefile *source_files; - char **source_directories; }; struct mi_registers { diff --git a/dwarf.c b/dwarf.c index 10aa800..ed708da 100644 --- a/dwarf.c +++ b/dwarf.c @@ -1,5 +1,5 @@ -static u64 -get_section_offset(u8 *file, char *name) +static struct elf_section_table_entry_x64 +get_section_entry(u8 *file, char *name) { struct elf_header_x64 header = { 0 }; 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)); 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) { 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; 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 @@ -232,18 +242,10 @@ read_actual_debug_data(u8 *file, u64 string_offset, u32 address_size, u64 base_d return(increment); } -static void -parse_debug_info(u8 *file, struct mi_debuginfo *dest) +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) { - 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 }; u32 header_size = sizeof(di_header); 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; - 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 (;;) { 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); if (tag == DW_TAG_compile_unit) { - if (attribute == DW_AT_comp_dir) { - dest->comp_dir = (char *) value; + 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->comp_dir = (char *) value; } } else if (tag == DW_TAG_subprogram) { if (attribute == DW_AT_name) { func->name = (char *) value; } 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); + 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) { + func->high_pc = func->low_pc + func->high_pc; + func->comp_unit = dest->cu_count; ++func; ++dest->func_count; } } + + return(di_header.length + 4); } static void -parse_debug_line(u8 *file, - struct mi_sourcepoint *dest, struct mi_sourcefile *dest_files, char **dest_directories, - int *dest_size, int *dest_files_size, int *dest_directories_size) +parse_debug_info(u8 *file, struct mi_debuginfo *dest) { - u64 dl_offset = get_section_offset(file, ".debug_line"); + 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) +{ + 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 }; 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) { *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 diff --git a/main.c b/main.c index 3ab2a48..f5cbeb5 100644 --- a/main.c +++ b/main.c @@ -31,11 +31,7 @@ main(int argc, char *argv[]) printf("> "); fflush(stdout); - parse_debug_line(process.elf, 0, 0, 0, &process.debug.sp_count, &process.source_file_count, &process.source_dirs_count); - process.debug.sp_table = calloc(1, process.debug.sp_count * sizeof(struct mi_sourcepoint)); - process.source_directories = calloc(1, process.source_dirs_count * sizeof(char *)); - process.source_files = calloc(1, process.source_file_count * sizeof(struct mi_sourcefile)); - parse_debug_line(process.elf, process.debug.sp_table, process.source_files, process.source_directories, 0, 0, 0); + parse_debug_line(process.elf, &process.debug); while ((command_length = getline(&command, &max_command_length, stdin))) { if (command_length == 1) { diff --git a/trace_include.c b/res/001-simple-inc.c similarity index 100% rename from trace_include.c rename to res/001-simple-inc.c diff --git a/traceme.c b/res/001-simple.c similarity index 92% rename from traceme.c rename to res/001-simple.c index 503f53d..9a0210d 100644 --- a/traceme.c +++ b/res/001-simple.c @@ -1,7 +1,7 @@ #include #include -#include "trace_include.c" +#include "001-simple-inc.c" int main() { diff --git a/res/002-compilation-units-impl.c b/res/002-compilation-units-impl.c new file mode 100644 index 0000000..6ea94bb --- /dev/null +++ b/res/002-compilation-units-impl.c @@ -0,0 +1,8 @@ +#include "002-compilation-units.h" + +int foo(int arg) +{ + int sq = arg * arg; + int sq2 = sq * 2; + return(sq2); +} diff --git a/res/002-compilation-units.c b/res/002-compilation-units.c new file mode 100644 index 0000000..09b0031 --- /dev/null +++ b/res/002-compilation-units.c @@ -0,0 +1,9 @@ +#include "002-compilation-units.h" + +int +main(void) +{ + int a = 3; + int b = foo(a); + return(b); +} diff --git a/res/002-compilation-units.h b/res/002-compilation-units.h new file mode 100644 index 0000000..f243ad9 --- /dev/null +++ b/res/002-compilation-units.h @@ -0,0 +1 @@ +int foo(int arg); diff --git a/res/Makefile b/res/Makefile new file mode 100644 index 0000000..159ef78 --- /dev/null +++ b/res/Makefile @@ -0,0 +1,3 @@ +all: + gcc -g -o 001-simple 001-simple.c + gcc -g -o 002-compilation-units 002-compilation-units.c 002-compilation-units-impl.c diff --git a/res/traceme b/res/traceme new file mode 100755 index 0000000000000000000000000000000000000000..fdc818f46611f7a4f06d3804a4b46c436801dcd3 GIT binary patch literal 19416 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, sr)) { - return(func->offset); + return(func->low_pc); } } @@ -106,14 +106,21 @@ get_address_of_subroutine(struct mi_process proc, char *sr) } static struct mi_sourcepoint * -pc_to_sourcepoint(struct mi_process proc, u64 pc) +pc_to_sourcepoint(struct mi_process proc, u64 pc, int *comp_unit) { // NOTE: find first point BIGGER that pc, return the sourcepoint just before that // TODO: binary search - for (int i = 0; i < proc.debug.sp_count; ++i) { - struct mi_sourcepoint *point = proc.debug.sp_table + i; - if (point->pc > pc) { - return(proc.debug.sp_table + i - 1); + + for (int c = 0; c < proc.debug.cu_count; ++c) { + struct mi_compunit unit = proc.debug.compilation_units[c]; + if (unit.low_pc <= pc && pc < unit.high_pc) { + for (int i = 0; i < unit.sp_count; ++i) { + struct mi_sourcepoint *point = unit.sp_table + i; + if (point->pc > pc) { + *comp_unit = c; + return(unit.sp_table + i - 1); + } + } } } @@ -155,27 +162,29 @@ read_file_mmap(char *path) } static void -print_sourcepoint(struct mi_process proc, struct mi_sourcepoint *sp) +print_sourcepoint(struct mi_process proc, int comp_unit, struct mi_sourcepoint *sp) { if (!sp) { printf("Unknown location\n"); return; } + struct mi_compunit unit = proc.debug.compilation_units[comp_unit]; + // NOTE: sourcepoint file indices are 1-based - if (proc.source_files[sp->file - 1].file.data == 0) { - char *file_filename = proc.source_files[sp->file - 1].filename; - char *file_dirname = proc.source_files[sp->file - 1].dir; - char *comp_dir = proc.debug.comp_dir; + if (unit.source_files[sp->file - 1].file.data == 0) { + char *file_filename = unit.source_files[sp->file - 1].filename; + char *file_dirname = unit.source_files[sp->file - 1].dir; + char *comp_dir = unit.comp_dir; char full_path[512] = { 0 }; snprintf(full_path, 511, "%s/%s/%s", comp_dir, file_dirname, file_filename); struct mi_buffer file = read_file_mmap(full_path); - proc.source_files[sp->file - 1].file = file; + unit.source_files[sp->file - 1].file = file; } - struct mi_buffer file = proc.source_files[sp->file - 1].file; + struct mi_buffer file = unit.source_files[sp->file - 1].file; char *source = (char *) file.data; u64 size = file.size;