Merge commit 'eba5d211937d1ebcb3669810ff63ad1083600b67' into from_upstream
Conflicts: src/target/breakpoints.c Change-Id: I62b67651956ba3e1dba791ad129e0853517cd7ba
This commit is contained in:
commit
64f5ec0408
|
@ -9387,8 +9387,8 @@ for similar mechanisms that do not consume hardware breakpoints.)
|
||||||
Remove the breakpoint at @var{address} or all breakpoints.
|
Remove the breakpoint at @var{address} or all breakpoints.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {rwp} address
|
@deffn {Command} {rwp} @option{all} | address
|
||||||
Remove data watchpoint on @var{address}
|
Remove data watchpoint on @var{address} or all watchpoints.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]]
|
@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]]
|
||||||
|
@ -12709,7 +12709,7 @@ Return information about the flash banks
|
||||||
@item @b{capture} <@var{command}>
|
@item @b{capture} <@var{command}>
|
||||||
|
|
||||||
Run <@var{command}> and return full log output that was produced during
|
Run <@var{command}> and return full log output that was produced during
|
||||||
its execution. Example:
|
its execution together with the command output. Example:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
> capture "reset init"
|
> capture "reset init"
|
||||||
|
|
|
@ -99,8 +99,7 @@ static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
|
||||||
* The tcl return value is empty for openocd commands that provide
|
* The tcl return value is empty for openocd commands that provide
|
||||||
* progress output.
|
* progress output.
|
||||||
*
|
*
|
||||||
* Therefore we set the tcl return value only if we actually
|
* For other commands, we prepend the logs to the tcl return value.
|
||||||
* captured output.
|
|
||||||
*/
|
*/
|
||||||
static void command_log_capture_finish(struct log_capture_state *state)
|
static void command_log_capture_finish(struct log_capture_state *state)
|
||||||
{
|
{
|
||||||
|
@ -109,15 +108,18 @@ static void command_log_capture_finish(struct log_capture_state *state)
|
||||||
|
|
||||||
log_remove_callback(tcl_output, state);
|
log_remove_callback(tcl_output, state);
|
||||||
|
|
||||||
int length;
|
int loglen;
|
||||||
Jim_GetString(state->output, &length);
|
const char *log_result = Jim_GetString(state->output, &loglen);
|
||||||
|
int reslen;
|
||||||
|
const char *cmd_result = Jim_GetString(Jim_GetResult(state->interp), &reslen);
|
||||||
|
|
||||||
if (length > 0)
|
// Just in case the log doesn't end with a newline, we add it
|
||||||
Jim_SetResult(state->interp, state->output);
|
if (loglen != 0 && reslen != 0 && log_result[loglen - 1] != '\n')
|
||||||
else {
|
Jim_AppendString(state->interp, state->output, "\n", 1);
|
||||||
/* No output captured, use tcl return value (which could
|
|
||||||
* be empty too). */
|
Jim_AppendString(state->interp, state->output, cmd_result, reslen);
|
||||||
}
|
|
||||||
|
Jim_SetResult(state->interp, state->output);
|
||||||
Jim_DecrRefCount(state->interp, state->output);
|
Jim_DecrRefCount(state->interp, state->output);
|
||||||
|
|
||||||
free(state);
|
free(state);
|
||||||
|
@ -691,8 +693,8 @@ COMMAND_HANDLER(handle_echo)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Capture progress output and return as tcl return value. If the
|
/* Return both the progress output (LOG_INFO and higher)
|
||||||
* progress output was empty, return tcl return value.
|
* and the tcl return value of a command.
|
||||||
*/
|
*/
|
||||||
static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
#include "rtos/rtos.h"
|
#include "rtos/rtos.h"
|
||||||
#include "smp.h"
|
#include "smp.h"
|
||||||
|
|
||||||
|
enum breakpoint_watchpoint {
|
||||||
|
BREAKPOINT,
|
||||||
|
WATCHPOINT,
|
||||||
|
};
|
||||||
|
|
||||||
static const char * const breakpoint_type_strings[] = {
|
static const char * const breakpoint_type_strings[] = {
|
||||||
"hardware",
|
"hardware",
|
||||||
"software"
|
"software"
|
||||||
|
@ -418,26 +423,90 @@ int breakpoint_remove(struct target *target, target_addr_t address)
|
||||||
return retval;
|
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_WATCHPOINT_NOT_FOUND;
|
||||||
|
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;
|
int retval = ERROR_OK;
|
||||||
if (target->smp) {
|
if (target->smp) {
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
|
|
||||||
foreach_smp_target(head, target->smp_targets) {
|
foreach_smp_target(head, target->smp_targets) {
|
||||||
struct target *curr = head->target;
|
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)
|
if (status != ERROR_OK)
|
||||||
retval = status;
|
retval = status;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
int breakpoint_clear_target(struct target *target)
|
int breakpoint_clear_target(struct target *target)
|
||||||
{
|
{
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
@ -562,35 +631,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_WATCHPOINT_NOT_FOUND;
|
|
||||||
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)
|
static int watchpoint_remove_internal(struct target *target, target_addr_t address)
|
||||||
{
|
{
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
|
|
@ -73,6 +73,7 @@ int watchpoint_add(struct target *target,
|
||||||
target_addr_t address, uint32_t length,
|
target_addr_t address, uint32_t length,
|
||||||
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
|
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
|
||||||
int watchpoint_remove(struct target *target, target_addr_t address);
|
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 */
|
/* report type and address of just hit watchpoint */
|
||||||
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
||||||
|
|
|
@ -4138,17 +4138,28 @@ COMMAND_HANDLER(handle_wp_command)
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_rwp_command)
|
COMMAND_HANDLER(handle_rwp_command)
|
||||||
{
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
target_addr_t addr;
|
|
||||||
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
|
|
||||||
|
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
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)
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
|
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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -7067,7 +7078,7 @@ static const struct command_registration target_exec_command_handlers[] = {
|
||||||
.handler = handle_rwp_command,
|
.handler = handle_rwp_command,
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.help = "remove watchpoint",
|
.help = "remove watchpoint",
|
||||||
.usage = "address",
|
.usage = "'all' | address",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "load_image",
|
.name = "load_image",
|
||||||
|
|
Loading…
Reference in New Issue