From 28c205c5ec498bd8d0e4a79ddabbb87e01df0ba1 Mon Sep 17 00:00:00 2001 From: "A.Olokhtonov" Date: Tue, 20 Jul 2021 23:57:47 +0300 Subject: [PATCH] Disambiguate recursive calls in step over --- .gitignore | 1 + command.c | 27 +++++++++++++++++++++------ res/003-recursion.c | 15 +++++++++++++++ res/Makefile | 1 + 4 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 res/003-recursion.c diff --git a/.gitignore b/.gitignore index 733fb82..a92e670 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build/ res/001-simple res/002-compilation-units +res/003-recursion diff --git a/command.c b/command.c index 56d01be..e142c9a 100644 --- a/command.c +++ b/command.c @@ -22,6 +22,7 @@ command_step(struct mi_process proc) 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); @@ -51,25 +52,39 @@ command_next(struct mi_process proc) 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)) { - u64 call_at = regs.rip; + long base_address = regs.rbp; - // Do single step, get return address from stack, place breakpoint there, continue + // 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); - 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); + // 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 diff --git a/res/003-recursion.c b/res/003-recursion.c new file mode 100644 index 0000000..903d181 --- /dev/null +++ b/res/003-recursion.c @@ -0,0 +1,15 @@ +static int +fact(int n) +{ + if (n == 0 || n == 1) { + return(1); + } + return(n * fact(n - 1)); +} + +int +main(void) +{ + int result = fact(5); + return(0); +} diff --git a/res/Makefile b/res/Makefile index 159ef78..fe1d447 100644 --- a/res/Makefile +++ b/res/Makefile @@ -1,3 +1,4 @@ all: gcc -g -o 001-simple 001-simple.c gcc -g -o 002-compilation-units 002-compilation-units.c 002-compilation-units-impl.c + gcc -g -o 003-recursion 003-recursion.c