diff --git a/command.c b/command.c index a971536..094db31 100644 --- a/command.c +++ b/command.c @@ -22,7 +22,7 @@ command_step(struct mi_process proc) 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_current_line(proc, sp->line); + print_sourcepoint(proc, sp); #endif } @@ -68,7 +68,7 @@ command_next(struct mi_process proc) // TODO: skip call, repXXX, etc } while (next_sp->line == sp->line); - print_current_line(proc, next_sp->line); + print_sourcepoint(proc, next_sp); } static void @@ -76,7 +76,7 @@ command_list(struct mi_process proc) { struct mi_registers regs = get_process_registers(proc); struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address); - print_current_line(proc, sp->line); + print_sourcepoint(proc, sp); } static void diff --git a/common.h b/common.h index b06251d..93206ff 100644 --- a/common.h +++ b/common.h @@ -31,6 +31,11 @@ typedef int64_t s64; #include "elf_dwarf.h" +struct mi_buffer { + u8 *data; + u64 size; +}; + struct mi_sourcepoint { u64 pc; int line; @@ -41,9 +46,6 @@ struct mi_sourcepoint { struct mi_process { pid_t pid; - char *source; - u64 source_size; - u8 *elf; u64 elf_size; @@ -52,6 +54,10 @@ struct mi_process { struct mi_sourcepoint *sp_table; int sp_count; + + char **source_file_names; + struct mi_buffer *source_files; + int source_file_count; }; struct mi_registers { diff --git a/dwarf.c b/dwarf.c index 422d3a5..ba2a671 100644 --- a/dwarf.c +++ b/dwarf.c @@ -295,7 +295,7 @@ find_subroutine_offset(u8 *file, u64 header_size, u8 address_size, } static void -construct_line_number_table(u8 *file, struct mi_sourcepoint *dest, int *dest_size) +construct_line_number_table(u8 *file, struct mi_sourcepoint *dest, char **dest_files, int *dest_size, int *dest_files_size) { u64 dl_offset = get_section_offset(file, ".debug_line"); @@ -331,9 +331,13 @@ is followed by a single null byte." */ p = file + dl_offset; while (*p != 0) { + /* null-terminated string */ + if (dest_files) { + dest_files[nfiles] = (char *) p; + } + ++nfiles; - /* null-terminated string */ while (*p != 0) { ++p; } @@ -350,33 +354,8 @@ is followed by a single null byte." */ p += offset; } - header.files = malloc(nfiles * sizeof(struct dwarf_debug_line_file_info)); - header.nfiles = nfiles; - - struct dwarf_debug_line_file_info *f = header.files; - - p = file + dl_offset; - while (*p != 0) { - - /* null-terminated string */ - f->name = (char *) p; - - while (*p != 0) { - ++p; - } - - ++p; - - u64 offset = 0; - u32 dummy = 0; - - offset += decode_leb128(p, &f->directory_index); - offset += decode_leb128(p, &f->time_modified); - offset += decode_leb128(p, &f->file_size); - - p += offset; - - ++f; + if (dest_files_size) { + *dest_files_size = nfiles; } dl_offset = p - file + 1; @@ -618,7 +597,7 @@ is followed by a single null byte." */ } while (opcode_extended != DW_LNE_end_sequence); - if (!dest) { + if (dest_size) { *dest_size = pc_count; } } diff --git a/main.c b/main.c index 20a1663..580f19a 100644 --- a/main.c +++ b/main.c @@ -28,9 +28,11 @@ main(int argc, char *argv[]) printf("> "); fflush(stdout); - construct_line_number_table(process.elf, 0, &process.sp_count); + construct_line_number_table(process.elf, 0, 0, &process.sp_count, &process.source_file_count); process.sp_table = malloc(process.sp_count * sizeof(struct mi_sourcepoint)); - construct_line_number_table(process.elf, process.sp_table, 0); + process.source_file_names = malloc(process.source_file_count * sizeof(char *)); + process.source_files = malloc(process.source_file_count * sizeof(char *)); + construct_line_number_table(process.elf, process.sp_table, process.source_file_names, 0, 0); while ((command_length = getline(&command, &max_command_length, stdin))) { if (0 == strncmp(command, "exit\n", command_length) || 0 == strncmp(command, "q\n", command_length)) { diff --git a/util.c b/util.c index e61584b..762ec65 100644 --- a/util.c +++ b/util.c @@ -22,15 +22,44 @@ print_word_at_address(int child, u64 address) printf("word at %#018lx: {%x %x %x %x}\n", address, nb[0], nb[1], nb[2], nb[3]); } +static struct mi_buffer +read_file_mmap(char *path) +{ + struct mi_buffer result = { 0 }; + + struct stat s; + int fd = open(path, O_RDONLY); + assert(fd != -1); + fstat(fd, &s); + + result.data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + result.size = s.st_size; + + printf("mmap()-ed %ld bytes (%s)\n", result.size, path); + + close(fd); + + return(result); +} + static void -print_current_line(struct mi_process proc, u64 line) +print_sourcepoint(struct mi_process proc, struct mi_sourcepoint *sp) { - char *source = proc.source; - u64 size = proc.source_size; - u64 current_line = 1; + // NOTE: sourcepoint file indices are 1-based + if (proc.source_files[sp->file - 1].data == 0) { + char *path = proc.source_file_names[sp->file - 1]; + struct mi_buffer file = read_file_mmap(path); + proc.source_files[sp->file - 1] = file; + } + + struct mi_buffer file = proc.source_files[sp->file - 1]; + + char *source = (char *) file.data; + u64 size = file.size; + int current_line = 1; for (u32 i = 0; i < size; ++i) { - if (current_line == line) { + if (current_line == sp->line) { int len = 0; int start = 0; int leading = 1; @@ -84,35 +113,10 @@ process_create(char *path) } } - u64 source_size; - u64 elf_size; - u8 *elf; - char *source; - struct stat s; - int fd; - - { - fd = open(path, O_RDONLY); - assert(fd != -1); - fstat(fd, &s); - elf_size = s.st_size; - elf = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - } - - { - fd = open("/code/trace-test/traceme.c", O_RDONLY); // TODO - assert(fd != -1); - fstat(fd, &s); - source_size = s.st_size; - source = mmap(0, source_size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - } + struct mi_buffer file = read_file_mmap(path); - result.elf = elf; - result.elf_size = elf_size; - result.source = source; - result.source_size = source_size; + result.elf = file.data; + result.elf_size = file.size; result.pid = pid; return(result);