Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions doc/openocd.texi
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
8 changes: 8 additions & 0 deletions src/target/riscv/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,

Expand Down
45 changes: 40 additions & 5 deletions src/target/target.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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:
Expand All @@ -3990,29 +4017,37 @@ 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 */
case 4:
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:
Expand Down Expand Up @@ -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 = "[<address> [<asid>] <length> ['hw'|'hw_ctx']]",
.usage = "[<address> [<asid>] (<length>|'default') ['hw'|'hw_ctx']]",
},
{
.name = "rbp",
Expand Down
3 changes: 3 additions & 0 deletions src/target/target_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,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);
};

extern struct target_type aarch64_target;
Expand Down