* that are to be ignored.
*/
if (gdb_connection->frontend_state == TARGET_RUNNING) {
- char sig_reply[4];
+ char sig_reply[20];
+ char stop_reason[20];
+ int sig_reply_len;
int signal_var;
/* stop forwarding log packets! */
} else
signal_var = gdb_last_signal(target);
- snprintf(sig_reply, 4, "T%2.2x", signal_var);
- gdb_put_packet(connection, sig_reply, 3);
+ stop_reason[0] = '\0';
+ if (target->debug_reason == DBG_REASON_WATCHPOINT) {
+ enum watchpoint_rw hit_wp_type;
+ uint32_t hit_wp_address;
+
+ if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) {
+
+ switch (hit_wp_type) {
+ case WPT_WRITE:
+ snprintf(stop_reason, sizeof(stop_reason),
+ "watch:%08x;", hit_wp_address);
+ break;
+ case WPT_READ:
+ snprintf(stop_reason, sizeof(stop_reason),
+ "rwatch:%08x;", hit_wp_address);
+ break;
+ case WPT_ACCESS:
+ snprintf(stop_reason, sizeof(stop_reason),
+ "awatch:%08x;", hit_wp_address);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s",
+ signal_var, stop_reason);
+
+ gdb_put_packet(connection, sig_reply, sig_reply_len);
gdb_connection->frontend_state = TARGET_HALTED;
rtos_update_threads(target);
}
while (target->watchpoints != NULL)
watchpoint_free(target, target->watchpoints);
}
+
+int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address)
+{
+ int retval;
+ struct watchpoint *hit_watchpoint;
+
+ retval = target_hit_watchpoint(target, &hit_watchpoint);
+ if (retval != ERROR_OK)
+ return ERROR_FAIL;
+
+ *rw = hit_watchpoint->rw;
+ *address = hit_watchpoint->address;
+
+ LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32 " (WPID: %d)",
+ hit_watchpoint->address,
+ hit_watchpoint->unique_id);
+
+ return ERROR_OK;
+}
enum watchpoint_rw rw, uint32_t value, uint32_t mask);
void watchpoint_remove(struct target *target, uint32_t address);
+/* report type and address of just hit watchpoint */
+int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address);
+
#endif /* BREAKPOINTS_H */
return ERROR_OK;
}
+/**
+ * find out which watchpoint hits
+ * get exception address and compare the address to watchpoints
+ */
+static int nds32_v2_hit_watchpoint(struct target *target,
+ struct watchpoint **hit_watchpoint)
+{
+ uint32_t exception_address;
+ struct watchpoint *wp;
+ static struct watchpoint scan_all_watchpoint;
+ struct nds32 *nds32 = target_to_nds32(target);
+
+ scan_all_watchpoint.address = 0;
+ scan_all_watchpoint.rw = WPT_WRITE;
+ scan_all_watchpoint.next = 0;
+ scan_all_watchpoint.unique_id = 0x5CA8;
+
+ exception_address = nds32->watched_address;
+
+ if (exception_address == 0) {
+ /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
+ *hit_watchpoint = &scan_all_watchpoint;
+ return ERROR_OK;
+ }
+
+ for (wp = target->watchpoints; wp; wp = wp->next) {
+ if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
+ /* TODO: dispel false match */
+ *hit_watchpoint = wp;
+ return ERROR_OK;
+ }
+ }
+
+ return ERROR_FAIL;
+}
+
static int nds32_v2_run_algorithm(struct target *target,
int num_mem_params,
struct mem_param *mem_params,
.remove_breakpoint = nds32_v2_remove_breakpoint,
.add_watchpoint = nds32_v2_add_watchpoint,
.remove_watchpoint = nds32_v2_remove_watchpoint,
+ .hit_watchpoint = nds32_v2_hit_watchpoint,
/* MMU */
.mmu = nds32_mmu,
.remove_breakpoint = nds32_v3_remove_breakpoint,
.add_watchpoint = nds32_v3_add_watchpoint,
.remove_watchpoint = nds32_v3_remove_watchpoint,
+ .hit_watchpoint = nds32_v3_hit_watchpoint,
/* MMU */
.mmu = nds32_mmu,
return ERROR_FAIL;
}
+/**
+ * find out which watchpoint hits
+ * get exception address and compare the address to watchpoints
+ */
+int nds32_v3_hit_watchpoint(struct target *target,
+ struct watchpoint **hit_watchpoint)
+{
+ static struct watchpoint scan_all_watchpoint;
+
+ uint32_t exception_address;
+ struct watchpoint *wp;
+ struct nds32 *nds32 = target_to_nds32(target);
+
+ exception_address = nds32->watched_address;
+
+ if (exception_address == 0xFFFFFFFF)
+ return ERROR_FAIL;
+
+ if (exception_address == 0) {
+ scan_all_watchpoint.address = 0;
+ scan_all_watchpoint.rw = WPT_WRITE;
+ scan_all_watchpoint.next = 0;
+ scan_all_watchpoint.unique_id = 0x5CA8;
+
+ *hit_watchpoint = &scan_all_watchpoint;
+ return ERROR_OK;
+ }
+
+ for (wp = target->watchpoints; wp; wp = wp->next) {
+ if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
+ *hit_watchpoint = wp;
+
+ return ERROR_OK;
+ }
+ }
+
+ return ERROR_FAIL;
+}
+
int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32)
{
nds32->register_map = nds32_v3_register_mapping;
.remove_breakpoint = nds32_v3m_remove_breakpoint,
.add_watchpoint = nds32_v3m_add_watchpoint,
.remove_watchpoint = nds32_v3m_remove_watchpoint,
+ .hit_watchpoint = nds32_v3_hit_watchpoint,
/* MMU */
.mmu = nds32_mmu,
{
return target->type->remove_watchpoint(target, watchpoint);
}
+int target_hit_watchpoint(struct target *target,
+ struct watchpoint **hit_watchpoint)
+{
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("target %s is not halted", target->cmd_name);
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ if (target->type->hit_watchpoint == NULL) {
+ /* For backward compatible, if hit_watchpoint is not implemented,
+ * return ERROR_FAIL such that gdb_server will not take the nonsense
+ * information. */
+ return ERROR_FAIL;
+ }
+
+ return target->type->hit_watchpoint(target, hit_watchpoint);
+}
int target_get_gdb_reg_list(struct target *target,
struct reg **reg_list[], int *reg_list_size,
int target_remove_watchpoint(struct target *target,
struct watchpoint *watchpoint);
+/**
+ * Find out the just hit @a watchpoint for @a target.
+ *
+ * This routine is a wrapper for target->type->hit_watchpoint.
+ */
+int target_hit_watchpoint(struct target *target,
+ struct watchpoint **watchpoint);
+
/**
* Obtain the registers for GDB.
*
*/
int (*remove_watchpoint)(struct target *target, struct watchpoint *watchpoint);
+ /* Find out just hit watchpoint. After the target hits a watchpoint, the
+ * information could assist gdb to locate where the modified/accessed memory is.
+ */
+ int (*hit_watchpoint)(struct target *target, struct watchpoint **hit_watchpoint);
+
/**
* Target algorithm support. Do @b not call this method directly,
* use target_run_algorithm() instead.