Reviewed-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
On 26.07.2023 21:35, Nicholas Piggin wrote:
> The reverse-debugging test creates a trace, then replays it and:
>
> 1. Steps the first 10 instructions and records their addresses.
> 2. Steps backward and verifies their addresses match.
> 3. Runs to (near) the end of the trace.
> 4. Sets breakpoints on the first 10 instructions.
> 5. Continues backward and verifies execution stops at the last
> breakpoint.
>
> Step 5 breaks if any of the other 9 breakpoints are re-executed in the
> trace after the 10th instruction is run, because those will be
> unexpectedly hit when reverse continuing. This situation does arise
> with the ppc pseries machine, the SLOF bios branches to its own entry
> point.
>
> Permit this breakpoint re-execution by switching steps 4 and 5, so that
> the trace will be run to the end *or* the next breakpoint hit.
> Reversing from there to the 10th intsruction will not hit another
> breakpoint, by definition.
>
> Another step is added between steps 2 and 3, which steps forward over
> the first 10 instructions and verifies their addresses, to support this.
>
> Cc: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> tests/avocado/reverse_debugging.py | 25 +++++++++++++++++++++----
> 1 file changed, 21 insertions(+), 4 deletions(-)
>
> diff --git a/tests/avocado/reverse_debugging.py b/tests/avocado/reverse_debugging.py
> index 680c314cfc..7d1a478df1 100644
> --- a/tests/avocado/reverse_debugging.py
> +++ b/tests/avocado/reverse_debugging.py
> @@ -150,16 +150,33 @@ def reverse_debugging(self, shift=7, args=None):
> self.check_pc(g, addr)
> logger.info('found position %x' % addr)
>
> - logger.info('seeking to the end (icount %s)' % (last_icount - 1))
> - vm.qmp('replay-break', icount=last_icount - 1)
> - # continue - will return after pausing
> - g.cmd(b'c', b'T02thread:01;')
> + # visit the recorded instruction in forward order
> + logger.info('stepping forward')
> + for addr in steps:
> + self.check_pc(g, addr)
> + self.gdb_step(g)
> + logger.info('found position %x' % addr)
>
> + # set breakpoints for the instructions just stepped over
> logger.info('setting breakpoints')
> for addr in steps:
> # hardware breakpoint at addr with len=1
> g.cmd(b'Z1,%x,1' % addr, b'OK')
>
> + # this may hit a breakpoint if first instructions are executed
> + # again
> + logger.info('continuing execution')
> + vm.qmp('replay-break', icount=last_icount - 1)
> + # continue - will return after pausing
> + # This could stop at the end and get a T02 return, or by
> + # re-executing one of the breakpoints and get a T05 return.
> + g.cmd(b'c')
> + if self.vm_get_icount(vm) == last_icount - 1:
> + logger.info('reached the end (icount %s)' % (last_icount - 1))
> + else:
> + logger.info('hit a breakpoint again at %x (icount %s)' %
> + (self.get_pc(g), self.vm_get_icount(vm)))
> +
> logger.info('running reverse continue to reach %x' % steps[-1])
> # reverse continue - will return after stopping at the breakpoint
> g.cmd(b'bc', b'T05thread:01;')