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.
160 lines
5.3 KiB
160 lines
5.3 KiB
static void |
|
command_regs(struct mi_process proc) |
|
{ |
|
struct mi_registers regs = get_process_registers(proc); |
|
printf("rax = %#018lx rcx = %#018lx\n" |
|
"rbp = %#018lx rbx = %#018lx\n" |
|
"rdx = %#018lx rsi = %#018lx\n" |
|
"rdi = %#018lx rip = %#018lx\n" |
|
"rsp = %#018lx\n", |
|
regs.rax, regs.rcx, regs.rbp, regs.rbx, |
|
regs.rdx, regs.rsi, regs.rdi, regs.rip, |
|
regs.rsp); |
|
} |
|
|
|
static void |
|
command_step(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, &comp_unit); |
|
struct mi_sourcepoint *next_sp; |
|
|
|
do { |
|
// TODO: step until source line changes !for active file! |
|
ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0); |
|
waitpid(proc.pid, 0, 0); |
|
regs = get_process_registers(proc); |
|
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 |
|
command_start(struct mi_process proc) |
|
{ |
|
u64 main_address = proc.base_address + proc.main_address; |
|
long saved_instruction = place_breakpoint_at(proc, main_address); |
|
run_until_breakpoint_and_restore(proc, main_address, saved_instruction); |
|
|
|
// TODO: restart if already running/paused |
|
// TODO: process state: not running / running / paused |
|
} |
|
|
|
static void |
|
command_next(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, &comp_unit); |
|
struct mi_sourcepoint *next_sp; |
|
|
|
do { |
|
// TODO: step until source line changes !for active file! |
|
|
|
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); |
|
|
|
if (is_call_instruction(instruction)) { |
|
long base_address = regs.rbp; |
|
|
|
// NOTE do single step, get return address from stack, place breakpoint there, continue |
|
ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0); |
|
waitpid(proc.pid, 0, 0); |
|
regs = get_process_registers(proc); |
|
|
|
long return_address = ptrace(PTRACE_PEEKDATA, proc.pid, regs.rsp, NULL); |
|
|
|
// NOTE: disambiguate recursive calls |
|
for (;;) { |
|
long saved_instruction = place_breakpoint_at(proc, return_address); |
|
run_until_breakpoint_and_restore(proc, return_address, saved_instruction); |
|
regs = get_process_registers(proc); |
|
long actual_base_address = regs.rbp; |
|
|
|
if (base_address == actual_base_address) { |
|
break; |
|
} else { |
|
// NOTE: step to the next instruction after the return address, so that we can add a breakpoint there |
|
ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0); |
|
waitpid(proc.pid, 0, 0); |
|
} |
|
} |
|
} |
|
// TODO: repXXX |
|
|
|
//printf("%#lx\n", 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, 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, &comp_unit); |
|
print_sourcepoint(proc, comp_unit, sp); |
|
} |
|
|
|
static void |
|
command_cont(struct mi_process proc) |
|
{ |
|
ptrace(PTRACE_CONT, proc.pid, 0, 0); |
|
} |
|
|
|
static void |
|
command_kill(struct mi_process proc) |
|
{ |
|
kill(proc.pid, SIGKILL); |
|
} |
|
|
|
static void |
|
command_backtrace(struct mi_process proc) |
|
{ |
|
struct mi_registers regs = get_process_registers(proc); |
|
struct mi_function *func = get_function_around_pc(proc, regs.rip - proc.base_address); |
|
|
|
u64 fb = regs.rbp; |
|
u64 return_address = ptrace(PTRACE_PEEKDATA, proc.pid, fb + 8, NULL); |
|
|
|
printf("%s: %#lx\n", func->name, regs.rip); |
|
|
|
for (int i = 0; i < 3; ++i) { |
|
func = get_function_around_pc(proc, return_address - proc.base_address); |
|
if (func) { |
|
printf("%s: %#lx\n", func->name, regs.rip); |
|
} |
|
fb = ptrace(PTRACE_PEEKDATA, proc.pid, fb, NULL); |
|
return_address = ptrace(PTRACE_PEEKDATA, proc.pid, fb + 8, NULL); |
|
} |
|
} |
|
|
|
static void |
|
command_print(struct mi_process proc, char *name, int name_length) |
|
{ |
|
struct mi_registers regs = get_process_registers(proc); |
|
u64 pc = regs.rip - proc.base_address; |
|
u64 cfa = get_cfa_at_pc(proc, pc); |
|
struct mi_variable *variable = get_variable(proc, name, name_length, pc); |
|
|
|
if (cfa && variable) { |
|
u64 address = cfa + variable->location; |
|
long value = ptrace(PTRACE_PEEKDATA, proc.pid, address, NULL); |
|
int val4 = value & 0x00000000FFFFFFFF; |
|
printf("%.*s = %d\n", name_length, name, val4); |
|
} else { |
|
printf("Variable %.*s not found\n", name_length, name); |
|
} |
|
} |