diff --git a/include/sys/arch_interface.h b/include/sys/arch_interface.h index ccaedaff701..e3d61ba020e 100644 --- a/include/sys/arch_interface.h +++ b/include/sys/arch_interface.h @@ -907,6 +907,36 @@ size_t arch_gdb_reg_readone(struct gdb_ctx *ctx, uint8_t *buf, size_t buflen, size_t arch_gdb_reg_writeone(struct gdb_ctx *ctx, uint8_t *hex, size_t hexlen, uint32_t regno); +/** + * @brief Add breakpoint or watchpoint. + * + * @param ctx GDB context + * @param type Breakpoint or watchpoint type + * @param addr Address of breakpoint or watchpoint + * @param kind Size of breakpoint/watchpoint in bytes + * + * @retval 0 Operation successful + * @retval -1 Error encountered + * @retval -2 Not supported + */ +int arch_gdb_add_breakpoint(struct gdb_ctx *ctx, uint8_t type, + uintptr_t addr, uint32_t kind); + +/** + * @brief Remove breakpoint or watchpoint. + * + * @param ctx GDB context + * @param type Breakpoint or watchpoint type + * @param addr Address of breakpoint or watchpoint + * @param kind Size of breakpoint/watchpoint in bytes + * + * @retval 0 Operation successful + * @retval -1 Error encountered + * @retval -2 Not supported + */ +int arch_gdb_remove_breakpoint(struct gdb_ctx *ctx, uint8_t type, + uintptr_t addr, uint32_t kind); + #endif /** @} */ diff --git a/subsys/debug/gdbstub.c b/subsys/debug/gdbstub.c index ed46c1e08ec..04f3caf8145 100644 --- a/subsys/debug/gdbstub.c +++ b/subsys/debug/gdbstub.c @@ -157,6 +157,21 @@ size_t gdb_bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) return 2 * buflen; } +__weak +int arch_gdb_add_breakpoint(struct gdb_ctx *ctx, uint8_t type, + uintptr_t addr, uint32_t kind) +{ + return -2; +} + +__weak +int arch_gdb_remove_breakpoint(struct gdb_ctx *ctx, uint8_t type, + uintptr_t addr, uint32_t kind) +{ + return -2; +} + + /** * Add preamble and termination to the given data. * @@ -608,6 +623,7 @@ int z_gdb_main_loop(struct gdb_ctx *ctx) uint8_t *ptr; size_t data_len, pkt_len; uintptr_t addr; + uint32_t type; int ret; ret = gdb_get_packet(buf, sizeof(buf), &pkt_len); @@ -742,6 +758,37 @@ int z_gdb_main_loop(struct gdb_ctx *ctx) gdb_send_packet("OK", 2); break; + /* + * Breakpoints and Watchpoints + */ + case 'z': + __fallthrough; + case 'Z': + CHECK_INT(type); + CHECK_SYMBOL(','); + CHECK_INT(addr); + CHECK_SYMBOL(','); + CHECK_INT(data_len); + + if (buf[0] == 'Z') { + ret = arch_gdb_add_breakpoint(ctx, type, + addr, data_len); + } else if (buf[0] == 'z') { + ret = arch_gdb_remove_breakpoint(ctx, type, + addr, data_len); + } + + if (ret == -2) { + /* breakpoint/watchpoint not supported */ + gdb_send_packet(NULL, 0); + } else if (ret == -1) { + state = ERROR; + } else { + gdb_send_packet("OK", 2); + } + + break; + /* What cause the pause */ case '?':