Re: [discuss] Support for reverse-execution

Johan Rydberg
2005-05-20T12:22:36Z

Eli Zaretskii wrote:

>>What I have done is add a new variable, step_direction, that can either
>>be STEP_DIR_FORWARD or STEP_DIR_REVERSE.
>
> I'd prefer STEP_FORWARD and STEP_BACKWARD.

Ok.

>>To implement "rnext" I had to add a new target-specific function that
>>tries to figure out the address of the call instruction based on the
>>last executed instruction and the instruction to be executed, IF the
>>current instruction can be identified as a return insn.
>
> Sorry, I'm confused. Isn't it right that if I'm stepping backwards
> through code such as this:
>
> i += 1;
> foo (i);
> =>i = 0;
>
> where "=>" shows the current source line, then typing `rnext' once
> will get me to this:
>
> i += 1;
> =>foo (i);
> i = 0;
>
> which means I'm now before the CALL insn that calls `foo'? If so,
> what ``return insn'' were you talking about? If it's the return
> instruction that returns from `foo', then that insn is inside the code
> generatedfor `foo', which GDB won't see. What am I missing?

When you're single stepping backwards you can end up almost anywhere
in the code. Take this scenario (in pseudo-PPC-assembler):

(1) foo (i);
0: 80 7f 00 08 lwz r3,8(r31)
4: 48 00 00 01 bl X <foo>
8: nop
(2) i = 0;
c: 38 00 00 00 li r0,0
10: 90 1f 00 08 stw r0,8(r31)

<foo>:
....
4c: 4e 80 00 20 blr

You start with PC = c, and single steps backwards. You end up on
the nop-insn. This is inside the single step range of line 1. So
you single step another instruction backwards, and suddenly you
stop at PC = 4c, which is far outside the stepping range. To detect
if this was due to a "return from subroutine" you inspect the current
instruction, blr, and if it happens to be return insn you can deduct
the address of the call insn that called "foo". Since PowerPC does
not have any delay slots, it's "safe" to assume that the insn _before_
the LAST stop_pc (== prev_pc) is the call insn.

So to skip the subroutine call, you set a breakpoint on 0x4
(prev_pc - 4 = 8 - 4 = 4) and do a reverse-continue. When the
breakpoint hits, you continue stepping until you reach the start
of the stepping range.

>>+ add_com ("rnext", class_run, rnext_command,
>>+ "Step program until it reaches the previous source line.\n\
>
> "Go backwards until the program reaches the source line before the
> current one."

Ok.

>
>>+ add_com_alias ("rn", "rnext", class_run, 1);
>
> Do we want another alias called "previous"?

I think so, and maybe also "prev" and/or "pre".

>>+extern enum step_direction_kind step_direction;
>
> Yuk! a global variable!

I though it was OK since other variables in this context
are global, such as step_range_start and step_frame_id.

>>+ if (step_direction == STEP_DIR_FORWARD)
>>+ target_resume (resume_ptid, step, sig);
>>+ else
>>+ {
>>+ target_reverse (resume_ptid, step);
>>+ }
>
> I'd prefer that target_resume accepted the direction argument. Is
> there something that I'm missing that makes this hard or impossible?

I don't think so. You just need to update more targets, though.

~j