This is an automated email from Gerrit. "Alexandra Kulyatskaya <a.kulyatsk...@syntacore.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9116
-- gerrit commit 337ee3f5a6c3449851d23ab7f35b9cfaa32c0e56 Author: Kulyatskaya Alexandra <a.kulyatsk...@syntacore.com> Date: Fri Jul 11 18:08:08 2025 +0300 target: support auto-selection of software breakpoint size Add default breakpoint length specifier. When passed, derivation of breakpoint length is delegated to target-type-specific method. Change-Id: Ie3473514beace15b76714aa6d5441122cd3262aa Signed-off-by: Kulyatskaya Alexandra <a.kulyatsk...@syntacore.com> diff --git a/doc/openocd.texi b/doc/openocd.texi index 7f7c8892fe..0ccd12051e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9898,10 +9898,11 @@ hardware support for a handful of code breakpoints and data watchpoints. In addition, CPUs almost always support software breakpoints. -@deffn {Command} {bp} [address [asid] len [@option{hw} | @option{hw_ctx}]] +@deffn {Command} {bp} [address [asid] (len|@option{default}) [@option{hw} | @option{hw_ctx}]] With no parameters, lists all active breakpoints. Else sets a breakpoint on code execution starting -at @var{address} for @var{length} bytes. +at @var{address} for @var{length} bytes. When @option{default} is passed +the length is derived automatically. This is a software breakpoint, unless @option{hw} or @option{hw_ctx} is specified in which case it will be a hardware, context or hybrid breakpoint. The context and hybrid breakpoints require an additional parameter @var{asid}: diff --git a/src/target/target.c b/src/target/target.c index 1bdbee19a7..a911da2a16 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1310,6 +1310,14 @@ int target_add_breakpoint(struct target *target, return target->type->add_breakpoint(target, breakpoint); } +static int target_get_default_breakpoint_size(struct target *target, target_addr_t addr, + uint32_t asid, int hw, unsigned int *length) +{ + if (!target->type->get_default_breakpoint_length) + return ERROR_NOT_IMPLEMENTED; + return target->type->get_default_breakpoint_length(target, addr, asid, hw, length); +} + int target_add_context_breakpoint(struct target *target, struct breakpoint *breakpoint) { @@ -3988,6 +3996,24 @@ static int handle_bp_command_set(struct command_invocation *cmd, return retval; } +static COMMAND_HELPER(parse_bp_length, uint32_t asid, target_addr_t addr, + int hw, unsigned int *length) +{ + if (strcmp(CMD_ARGV[1], "default") == 0) { + struct target *target = get_current_target(CMD_CTX); + int ret_errno = target_get_default_breakpoint_size(target, addr, asid, hw, length); + if (ret_errno == ERROR_NOT_IMPLEMENTED) { + command_print(CMD, "Default breakpoint size derivation is " + "not implemented on target %s", target_name(target)); + } else if (ret_errno != ERROR_OK) { + command_print(CMD, "Unknown error when deriving default breakpoint size"); + } + return ret_errno; + } + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], *length); + return ERROR_OK; +} + COMMAND_HANDLER(handle_bp_command) { target_addr_t addr; @@ -4002,21 +4028,21 @@ COMMAND_HANDLER(handle_bp_command) case 2: asid = 0; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); return handle_bp_command_set(CMD, addr, asid, length, hw); case 3: if (strcmp(CMD_ARGV[2], "hw") == 0) { hw = BKPT_HARD; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); asid = 0; + CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); return handle_bp_command_set(CMD, addr, asid, length, hw); } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) { hw = BKPT_HARD; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); addr = 0; + CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); return handle_bp_command_set(CMD, addr, asid, length, hw); } /* fallthrough */ @@ -4024,7 +4050,7 @@ COMMAND_HANDLER(handle_bp_command) hw = BKPT_HARD; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); + CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); return handle_bp_command_set(CMD, addr, asid, length, hw); default: @@ -6653,7 +6679,7 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_bp_command, .mode = COMMAND_EXEC, .help = "list or set hardware or software breakpoint", - .usage = "[<address> [<asid>] <length> ['hw'|'hw_ctx']]", + .usage = "[<address> [<asid>] (<length>|'default') ['hw'|'hw_ctx']]", }, { .name = "rbp", diff --git a/src/target/target_type.h b/src/target/target_type.h index ccbe03a476..f7b0538e54 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -305,6 +305,9 @@ struct target_type { * will typically be 32 for 32-bit targets, and 64 for 64-bit targets. If * not implemented, it's assumed to be 32. */ unsigned int (*data_bits)(struct target *target); + + int (*get_default_breakpoint_length)(struct target *target, target_addr_t addr, + uint32_t asid, int hw, unsigned int *length); }; // Keep in alphabetic order this list of targets --