breakpoints: add rwp all command

This patch adds the "all" option to the rwp command.
It removes all watchpoints, much like rbp all removes
all breakpoints.

Change-Id: Id58dd103085e558f17afa4a287888cf085566ca9
Signed-off-by: Marek Vrbka <marek.vrbka@codasip.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/7907
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Marek Vrbka 2023-09-22 13:57:04 +02:00 committed by Antonio Borneo
parent 2c8c2cb6b1
commit eba5d21193
4 changed files with 93 additions and 41 deletions

View File

@ -9358,8 +9358,8 @@ for similar mechanisms that do not consume hardware breakpoints.)
Remove the breakpoint at @var{address} or all breakpoints.
@end deffn
@deffn {Command} {rwp} address
Remove data watchpoint on @var{address}
@deffn {Command} {rwp} @option{all} | address
Remove data watchpoint on @var{address} or all watchpoints.
@end deffn
@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]]

View File

@ -17,6 +17,11 @@
#include "breakpoints.h"
#include "smp.h"
enum breakpoint_watchpoint {
BREAKPOINT,
WATCHPOINT,
};
static const char * const breakpoint_type_strings[] = {
"hardware",
"software"
@ -375,26 +380,90 @@ int breakpoint_remove(struct target *target, target_addr_t address)
return retval;
}
int breakpoint_remove_all(struct target *target)
static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
{
struct watchpoint *watchpoint = target->watchpoints;
struct watchpoint **watchpoint_p = &target->watchpoints;
int retval;
while (watchpoint) {
if (watchpoint == watchpoint_to_remove)
break;
watchpoint_p = &watchpoint->next;
watchpoint = watchpoint->next;
}
if (!watchpoint)
return ERROR_OK;
retval = target_remove_watchpoint(target, watchpoint);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target",
watchpoint->number);
return retval;
}
LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
(*watchpoint_p) = watchpoint->next;
free(watchpoint);
return ERROR_OK;
}
static int watchpoint_remove_all_internal(struct target *target)
{
struct watchpoint *watchpoint = target->watchpoints;
int retval = ERROR_OK;
while (watchpoint) {
struct watchpoint *tmp = watchpoint;
watchpoint = watchpoint->next;
int status = watchpoint_free(target, tmp);
if (status != ERROR_OK)
retval = status;
}
return retval;
}
int breakpoint_watchpoint_remove_all(struct target *target, enum breakpoint_watchpoint bp_wp)
{
assert(bp_wp == BREAKPOINT || bp_wp == WATCHPOINT);
int retval = ERROR_OK;
if (target->smp) {
struct target_list *head;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
int status = breakpoint_remove_all_internal(curr);
int status = ERROR_OK;
if (bp_wp == BREAKPOINT)
status = breakpoint_remove_all_internal(curr);
else
status = watchpoint_remove_all_internal(curr);
if (status != ERROR_OK)
retval = status;
}
} else {
retval = breakpoint_remove_all_internal(target);
if (bp_wp == BREAKPOINT)
retval = breakpoint_remove_all_internal(target);
else
retval = watchpoint_remove_all_internal(target);
}
return retval;
}
int breakpoint_remove_all(struct target *target)
{
return breakpoint_watchpoint_remove_all(target, BREAKPOINT);
}
int watchpoint_remove_all(struct target *target)
{
return breakpoint_watchpoint_remove_all(target, WATCHPOINT);
}
static int breakpoint_clear_target_internal(struct target *target)
{
LOG_DEBUG("Delete all breakpoints for target: %s",
@ -532,35 +601,6 @@ int watchpoint_add(struct target *target, target_addr_t address,
}
}
static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
{
struct watchpoint *watchpoint = target->watchpoints;
struct watchpoint **watchpoint_p = &target->watchpoints;
int retval;
while (watchpoint) {
if (watchpoint == watchpoint_to_remove)
break;
watchpoint_p = &watchpoint->next;
watchpoint = watchpoint->next;
}
if (!watchpoint)
return ERROR_OK;
retval = target_remove_watchpoint(target, watchpoint);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target",
watchpoint->number);
return retval;
}
LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
(*watchpoint_p) = watchpoint->next;
free(watchpoint);
return ERROR_OK;
}
static int watchpoint_remove_internal(struct target *target, target_addr_t address)
{
struct watchpoint *watchpoint = target->watchpoints;

View File

@ -73,6 +73,7 @@ int watchpoint_add(struct target *target,
target_addr_t address, uint32_t length,
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
int watchpoint_remove(struct target *target, target_addr_t address);
int watchpoint_remove_all(struct target *target);
/* report type and address of just hit watchpoint */
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,

View File

@ -4136,17 +4136,28 @@ COMMAND_HANDLER(handle_wp_command)
COMMAND_HANDLER(handle_rwp_command)
{
int retval;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
target_addr_t addr;
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
struct target *target = get_current_target(CMD_CTX);
int retval = watchpoint_remove(target, addr);
if (!strcmp(CMD_ARGV[0], "all")) {
retval = watchpoint_remove_all(target);
if (retval != ERROR_OK)
command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
if (retval != ERROR_OK) {
command_print(CMD, "Error encountered during removal of all watchpoints.");
command_print(CMD, "Some watchpoints may have remained set.");
}
} else {
target_addr_t addr;
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
retval = watchpoint_remove(target, addr);
if (retval != ERROR_OK)
command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
}
return retval;
}
@ -7065,7 +7076,7 @@ static const struct command_registration target_exec_command_handlers[] = {
.handler = handle_rwp_command,
.mode = COMMAND_EXEC,
.help = "remove watchpoint",
.usage = "address",
.usage = "'all' | address",
},
{
.name = "load_image",