You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.3 KiB
207 lines
5.3 KiB
static u64 |
|
get_address_of_subroutine(struct mi_process proc, char *sr) |
|
{ |
|
for (int i = 0; i < proc.debug.func_count; ++i) { |
|
struct mi_function *func = proc.debug.functions + i; |
|
if (0 == strcmp(func->name, sr)) { |
|
return(func->offset); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
static struct mi_sourcepoint * |
|
pc_to_sourcepoint(struct mi_process proc, u64 pc) |
|
{ |
|
// 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); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
static void |
|
print_word_at_address(int child, u64 address) |
|
{ |
|
long word = ptrace(PTRACE_PEEKDATA, child, address, NULL); |
|
u8 nb[4]; |
|
memcpy(nb, &word, 4); |
|
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_sourcepoint(struct mi_process proc, struct mi_sourcepoint *sp) |
|
{ |
|
if (!sp) { |
|
printf("Unknown location\n"); |
|
return; |
|
} |
|
|
|
// 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; |
|
|
|
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; |
|
} |
|
|
|
struct mi_buffer file = proc.source_files[sp->file - 1].file; |
|
|
|
char *source = (char *) file.data; |
|
u64 size = file.size; |
|
int current_line = 1; |
|
|
|
for (u32 i = 0; i < size; ++i) { |
|
if (current_line == sp->line) { |
|
int len = 0; |
|
int start = 0; |
|
int leading = 1; |
|
|
|
for (u32 j = i; j < size; ++j) { |
|
if (leading && (source[j] == '\t' || source[j] == ' ')) { |
|
++start; |
|
} else { |
|
leading = 0; |
|
} |
|
|
|
if (source[j] == '\n') { |
|
break; |
|
} |
|
|
|
++len; |
|
} |
|
|
|
|
|
printf("%.*s\n", len - start, source + i + start); |
|
return; |
|
} |
|
|
|
if (source[i] == '\n') { |
|
current_line++; |
|
} |
|
} |
|
} |
|
|
|
static struct mi_process |
|
process_create(char *path) |
|
{ |
|
struct mi_process result = { 0 }; |
|
|
|
/* disable ASLR */ |
|
syscall(SYS_personality, ADDR_NO_RANDOMIZE); |
|
|
|
pid_t pid = fork(); |
|
|
|
if (pid == -1) { |
|
DIE("fork error\n"); |
|
} |
|
|
|
if (pid == 0) { |
|
int rt = ptrace(PTRACE_TRACEME, 0, 0, 0); |
|
assert(rt == 0); |
|
char *args[] = { path, NULL }; |
|
rt = execvp(path, args); |
|
if (rt == -1) { |
|
DIE("exevp error\n"); |
|
} |
|
} |
|
|
|
struct mi_buffer file = read_file_mmap(path); |
|
|
|
result.elf = file.data; |
|
result.elf_size = file.size; |
|
result.pid = pid; |
|
|
|
return(result); |
|
} |
|
|
|
static struct mi_registers |
|
get_process_registers(struct mi_process proc) |
|
{ |
|
struct user_regs_struct regs = { 0 }; |
|
struct iovec iov = { ®s, sizeof(regs) }; |
|
struct mi_registers result = { 0 }; |
|
|
|
ptrace(PTRACE_GETREGSET, proc.pid, NT_PRSTATUS, &iov); |
|
|
|
result.rax = regs.rax; |
|
result.rip = regs.rip; |
|
result.rbp = regs.rbp; |
|
result.rbx = regs.rbx; |
|
result.rcx = regs.rcx; |
|
result.rdx = regs.rdx; |
|
result.rsi = regs.rsi; |
|
result.rdi = regs.rdi; |
|
result.rsp = regs.rsp; |
|
|
|
result._sys = regs; |
|
|
|
return(result); |
|
} |
|
|
|
static void |
|
set_process_registers(struct mi_process proc, struct mi_registers regs) |
|
{ |
|
regs._sys.rax = regs.rax; |
|
regs._sys.rip = regs.rip; |
|
regs._sys.rbp = regs.rbp; |
|
regs._sys.rbx = regs.rbx; |
|
regs._sys.rcx = regs.rcx; |
|
regs._sys.rdx = regs.rdx; |
|
regs._sys.rsi = regs.rsi; |
|
regs._sys.rdi = regs.rdi; |
|
regs._sys.rsp = regs.rsp; |
|
|
|
struct iovec iov = { ®s._sys, sizeof(regs._sys) }; |
|
ptrace(PTRACE_SETREGSET, proc.pid, NT_PRSTATUS, &iov); |
|
} |
|
|
|
static void |
|
print_current_instruction(struct mi_process proc) |
|
{ |
|
struct mi_registers regs = get_process_registers(proc); |
|
|
|
long wordb = ptrace(PTRACE_PEEKDATA, proc.pid, regs.rip - 4, NULL); |
|
long word = ptrace(PTRACE_PEEKDATA, proc.pid, regs.rip, NULL); |
|
long worda = ptrace(PTRACE_PEEKDATA, proc.pid, regs.rip + 4, NULL); |
|
|
|
u8 nb[12]; |
|
memcpy(nb, &wordb, 4); |
|
memcpy(nb + 4, &word, 4); |
|
memcpy(nb + 8, &worda, 4); |
|
|
|
printf("PC = %#018lx: %x %x %x %x [%x] %x %x %x %x %x %x %x\n", regs.rip, |
|
nb[0], nb[1], nb[2], nb[3], nb[4], nb[5], nb[6], nb[7], |
|
nb[8], nb[9], nb[10], nb[11]); |
|
} |