The do_trigger_action() receives index of fired trigger as second
parameter. However, in current implementation, the argument is hardcoded
as DBG_ACTION_BP which is 0. This is a bug because we may match/fire any
breakpoints or watchpoints at other index than 0.

Fix this bug by iterating cpu_breakpoint[] and cpu_watchpoint[] to
compare and match necessary checkpoints. The index of the fired
cpu_breakpoint or the cpu_watchpoint is the index of the trigger we want
to provide to do_trigger_action().

Signed-off-by: Alvin Chang <[email protected]>
Reviewed-by: Yu-Ming Chang <[email protected]>
---
 target/riscv/debug.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 5664466..f3bca8e 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -929,11 +929,24 @@ void riscv_cpu_debug_excp_handler(CPUState *cs)
 
     if (cs->watchpoint_hit) {
         if (cs->watchpoint_hit->flags & BP_CPU) {
-            do_trigger_action(env, DBG_ACTION_BP);
+            /* Search fired trigger and do its action */
+            for (int i = 0; i < ARRAY_SIZE(env->cpu_watchpoint); i++) {
+                if (cs->watchpoint_hit == env->cpu_watchpoint[i]) {
+                    do_trigger_action(env, i);
+                    break;
+                }
+            }
         }
     } else {
         if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) {
-            do_trigger_action(env, DBG_ACTION_BP);
+            /* Search fired trigger and do its action */
+            for (int i = 0; i < ARRAY_SIZE(env->cpu_breakpoint); i++) {
+                CPUBreakpoint *bp = env->cpu_breakpoint[i];
+                if (bp && bp->pc == env->pc && (bp->flags & BP_CPU)) {
+                    do_trigger_action(env, i);
+                    break;
+                }
+            }
         }
     }
 }
-- 
2.43.0


Reply via email to