diff --git a/doc/openocd.texi b/doc/openocd.texi index 1dcb7f3f5a..1d90af19ba 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9696,10 +9696,11 @@ hardware support for a handful of code breakpoints and data watchpoints. In addition, CPUs almost always support software breakpoints. -@deffn {Command} {bp} [address len [@option{hw}]] +@deffn {Command} {bp} [address (len|@option{default}) [@option{hw}]] 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} is specified in which case it will be a hardware breakpoint. diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 2e475a5d4f..985b06d49b 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1604,6 +1604,13 @@ int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_ return ERROR_FAIL; } +static int riscv_get_default_breakpoint_length(struct target *target, target_addr_t addr, + uint32_t asid, int hw, unsigned int *length) +{ + *length = riscv_supports_extension(target, 'c') ? 2 : 4; + return ERROR_OK; +} + static int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { LOG_TARGET_DEBUG(target, "@0x%" TARGET_PRIxADDR, breakpoint->address); @@ -5919,6 +5926,7 @@ struct target_type riscv_target = { .get_gdb_reg_list = riscv_get_gdb_reg_list, .get_gdb_reg_list_noread = riscv_get_gdb_reg_list_noread, + .get_default_breakpoint_length = riscv_get_default_breakpoint_length, .add_breakpoint = riscv_add_breakpoint, .remove_breakpoint = riscv_remove_breakpoint, diff --git a/src/target/target.c b/src/target/target.c index 442e8beba3..fb549a122d 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1315,6 +1315,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) { @@ -3976,12 +3984,31 @@ 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) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], *length); + return ERROR_OK; + } + 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_HANDLER(handle_bp_command) { target_addr_t addr; uint32_t asid; uint32_t length; int hw = BKPT_SOFT; + int ret_errno; switch (CMD_ARGC) { case 0: @@ -3990,21 +4017,27 @@ COMMAND_HANDLER(handle_bp_command) case 2: asid = 0; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + ret_errno = CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); + if (ret_errno != ERROR_OK) + return ret_errno; 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; + ret_errno = CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); + if (ret_errno != ERROR_OK) + return ret_errno; 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; + ret_errno = CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); + if (ret_errno != ERROR_OK) + return ret_errno; return handle_bp_command_set(CMD, addr, asid, length, hw); } /* fallthrough */ @@ -4012,7 +4045,9 @@ 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); + ret_errno = CALL_COMMAND_HANDLER(parse_bp_length, asid, addr, hw, &length); + if (ret_errno != ERROR_OK) + return ret_errno; return handle_bp_command_set(CMD, addr, asid, length, hw); default: @@ -6630,7 +6665,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 = "[
[