|
|
|
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)
|
|
|
|
{
|
|
|
|
ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0);
|
|
|
|
waitpid(proc.pid, 0, 0);
|
|
|
|
|
|
|
|
#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
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
command_next(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);
|
|
|
|
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);
|
|
|
|
if (is_call_instruction(instruction)) {
|
|
|
|
u64 call_at = regs.rip;
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
long saved_instruction = place_breakpoint_at(proc, return_address);
|
|
|
|
run_until_breakpoint_and_restore(proc, return_address, saved_instruction);
|
|
|
|
// TODO: disambiguate recursive calls
|
|
|
|
|
|
|
|
regs = get_process_registers(proc);
|
|
|
|
}
|
|
|
|
// TODO: skip call, repXXX
|
|
|
|
|
|
|
|
//printf("%#lx\n", regs.rip - proc.base_address);
|
|
|
|
next_sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address);
|
|
|
|
|
|
|
|
if (!next_sp) break;
|
|
|
|
} while (next_sp->line == sp->line);
|
|
|
|
|
|
|
|
print_sourcepoint(proc, next_sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
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_sourcepoint(proc, sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
command_cont(struct mi_process proc)
|
|
|
|
{
|
|
|
|
ptrace(PTRACE_CONT, proc.pid, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
command_stop(struct mi_process proc)
|
|
|
|
{
|
|
|
|
kill(proc.pid, SIGINT);
|
|
|
|
// TODO
|
|
|
|
}
|