diff options
author | Antonio Borneo <borneo.antonio@gmail.com> | 2021-08-13 18:52:20 +0200 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2021-08-22 20:23:09 +0000 |
commit | 6f28ac8fdef91b665b3edf5132c03f73fd4e1d1d (patch) | |
tree | da983abbef0d1cd3761995f5ea014ef2e56fc890 /src/target | |
parent | 044e0f8c9aec9fe94d77199e64c813fb4336984b (diff) | |
download | riscv-openocd-6f28ac8fdef91b665b3edf5132c03f73fd4e1d1d.zip riscv-openocd-6f28ac8fdef91b665b3edf5132c03f73fd4e1d1d.tar.gz riscv-openocd-6f28ac8fdef91b665b3edf5132c03f73fd4e1d1d.tar.bz2 |
cortex_m: fix command 'step address'
The command 'step' accepts an optional parameter 'address' to run
the step-by-step execution from an address different from current
program counter.
When OpenOCD sets the new program counter value in the register
cache, it doesn't flag it as dirty. The following call to function
armv7m_restore_context() does not propagate the new value of the
program counter to the target. This cause the target to continue
from the old program counter value, ignoring the user's request.
It is hard to notice the issue if the target is halted in an idle
loop! In fact the default mode to operate step-by-step is to set a
breakpoint to the following instruction and resume execution. In
the idle loop the CPU will pass through the breakpoint whatever
the resume address is. User will find the target halting at the
instruction following 'address' which is consistent with the
expected behaviour of command 'step address'.
To verify the issue on an STM32F4, use a dummy code in SRAM:
halt
mww 0x20000000 0xbf00bf00
mww 0x20000004 0xbf00bf00
mww 0x20000008 0xe7fcbf00
arm disassemble 0x20000000 6
0x20000000 bf00 nop
0x20000002 bf00 nop
0x20000004 bf00 nop
+--> 0x20000006 bf00 nop
| 0x20000008 bf00 nop
+-<- 0x2000000a e7fc b #0x20000006
resume 0x20000006
halt
step 0x20000000
the target doesn't halt because it is in the loop from 0x20000006
to 0x2000000a. The 'step 0x20000000' did not changed the program
counter so the temporary breakpoint at 0x20000002 is never hit.
Then:
halt
step 0x20000008
target halted ...
... pc: 0x2000000a
gives the feeling that only the instruction at 0x20000008 has been
executed, but actually the whole loop has been executed from the
place 'halt' stopped the execution till the breakpoint at the
instruction following 0x20000008.
Flag the program counter cached value as 'valid' and 'dirty' to
force armv7m_restore_context() to update the target's register.
Change-Id: I49bd8bb95b2f5429ec38ed016f2ad706618ae68a
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6434
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Diffstat (limited to 'src/target')
-rw-r--r-- | src/target/cortex_m.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 9f035a0..f3c8527 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -975,8 +975,11 @@ static int cortex_m_step(struct target *target, int current, } /* current = 1: continue on current pc, otherwise continue at <address> */ - if (!current) + if (!current) { buf_set_u32(pc->value, 0, 32, address); + pc->dirty = true; + pc->valid = true; + } uint32_t pc_value = buf_get_u32(pc->value, 0, 32); |