diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index d4fc880f6..d422fac53 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -29,6 +29,8 @@ static int hwthread_read_buffer(struct rtos *rtos, target_addr_t address, static int hwthread_write_buffer(struct rtos *rtos, target_addr_t address, uint32_t size, const uint8_t *buffer); static bool hwthread_needs_fake_step(struct target *target, int64_t thread_id); +struct target *hwthread_swbp_target(struct rtos *rtos, target_addr_t address, + uint32_t length, enum breakpoint_type type); #define HW_THREAD_NAME_STR_SIZE (32) @@ -60,7 +62,8 @@ const struct rtos_type hwthread_rtos = { .set_reg = hwthread_set_reg, .read_buffer = hwthread_read_buffer, .write_buffer = hwthread_write_buffer, - .needs_fake_step = hwthread_needs_fake_step + .needs_fake_step = hwthread_needs_fake_step, + .swbp_target = hwthread_swbp_target, }; struct hwthread_params { @@ -456,3 +459,9 @@ bool hwthread_needs_fake_step(struct target *target, int64_t thread_id) { return false; } + +struct target *hwthread_swbp_target(struct rtos *rtos, target_addr_t address, + uint32_t length, enum breakpoint_type type) +{ + return hwthread_find_thread(rtos->target, rtos->current_thread); +} diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 7957a5b6b..547314c0a 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -762,3 +762,11 @@ bool rtos_needs_fake_step(struct target *target, int64_t thread_id) return target->rtos->type->needs_fake_step(target, thread_id); return target->rtos->current_thread != thread_id; } + +struct target *rtos_swbp_target(struct target *target, target_addr_t address, + uint32_t length, enum breakpoint_type type) +{ + if (target->rtos->type->swbp_target) + return target->rtos->type->swbp_target(target->rtos, address, length, type); + return target; +} diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index bbd1d1a1d..2084739cf 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -9,6 +9,7 @@ #define OPENOCD_RTOS_RTOS_H #include "server/server.h" +#include "target/breakpoints.h" #include "target/target.h" typedef int64_t threadid_t; @@ -86,6 +87,12 @@ struct rtos_type { * target running a multi-threading OS. If an RTOS can do this, override * needs_fake_step(). */ bool (*needs_fake_step)(struct target *target, int64_t thread_id); + /* When a software breakpoint is set, it is set on only one target, + * because we assume memory is shared across them. By default this is the + * first target in the SMP group. Override this function to have + * breakpoint_add() use a different target. */ + struct target * (*swbp_target)(struct rtos *rtos, target_addr_t address, + uint32_t length, enum breakpoint_type type); }; struct stack_register_offset { @@ -145,6 +152,8 @@ int rtos_read_buffer(struct target *target, target_addr_t address, int rtos_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer); bool rtos_needs_fake_step(struct target *target, int64_t thread_id); +struct target *rtos_swbp_target(struct target *target, target_addr_t address, + uint32_t length, enum breakpoint_type type); // Keep in alphabetic order this list of rtos extern const struct rtos_type chibios_rtos; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 486080bbd..f09e4807e 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1814,7 +1814,15 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, case 0: case 1: if (packet[0] == 'Z') { - retval = breakpoint_add(target, address, size, bp_type); + struct target *bp_target = target; + if (target->rtos && bp_type == BKPT_SOFT) { + bp_target = rtos_swbp_target(target, address, size, bp_type); + if (!bp_target) { + retval = ERROR_FAIL; + break; + } + } + retval = breakpoint_add(bp_target, address, size, bp_type); } else { assert(packet[0] == 'z'); retval = breakpoint_remove(target, address); diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index fa6b635f0..753c343c5 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -210,16 +210,10 @@ int breakpoint_add(struct target *target, unsigned int length, enum breakpoint_type type) { - if (target->smp) { - struct target_list *head; - - if (type == BKPT_SOFT) { - head = list_first_entry(target->smp_targets, struct target_list, lh); - return breakpoint_add_internal(head->target, address, length, type); - } - - foreach_smp_target(head, target->smp_targets) { - struct target *curr = head->target; + if (target->smp && type == BKPT_HARD) { + struct target_list *list_node; + foreach_smp_target(list_node, target->smp_targets) { + struct target *curr = list_node->target; int retval = breakpoint_add_internal(curr, address, length, type); if (retval != ERROR_OK) return retval;