From 6f28ac8fdef91b665b3edf5132c03f73fd4e1d1d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 13 Aug 2021 18:52:20 +0200 Subject: [PATCH] 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 Reviewed-on: https://review.openocd.org/c/openocd/+/6434 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/cortex_m.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 9f035a093..f3c8527cf 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
*/ - 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);