Page 1 of 1

"Step out" in a debugger

Posted: Sat Sep 29, 2018 7:49 pm
by dfzx
The Fuse debugger has a "finish" feature which is sort of like the "step out" feature of other debuggers. The idea is that it runs to the end of the current subroutine. Only in Fuse it's implemented by placing a temporary breakpoint at the address at SP, which really isn't ideal. If the subroutine has done anything with the stack the feature is going to fail.

I was thinking about reimplementing this a different way. One way would be to collect a stack of return addresses by hooking into the emulator's CALL, CALL cc and RST instructions. "Step out" can then just put a temporary breakpoint at the address at the head of this "internal" stack.

It then occurred to me that maybe it's possible to implement it simply by hooking into the emulator's RET and RET cc instructions. Set an internal flag when the user does a "step out" and check for that flag at return instructions. If found, execute the return then stop at the next instruction.

I prefer the first option because it allows a stack trace to be generated and presented. But the second way appears temptingly simple. Is there a reason the second way wouldn't work?

Re: "Step out" in a debugger

Posted: Sat Sep 29, 2018 10:41 pm
by AndyC
Either way can be defeated by weird enough code, but if I were implementing it I'd go for "step out" being equivalent to "run until a RET occurs" - it's probably what most developers would expect to happen and I suspect will give the right behaviour 99% of the time.

Re: "Step out" in a debugger

Posted: Sun Sep 30, 2018 12:04 am
by Einar Saukas
Agreed. However I suggest "run until the number of RETs exceeds the number of CALLs". For instance:

Code: Select all

subroutine:
    ...
    RET
main:
    LD B,8    <--- current position
loop:
    CALL subroutine
    DJNZ loop
    RET
In this example, stepping out should happen upon reaching the second RET, not the first.