mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 11:03:11 +00:00
feat(esp_gdbstub): support watchpoint trigger reason
This commit is contained in:
@@ -169,6 +169,15 @@ void esp_gdbstub_clear_step(void);
|
||||
void esp_gdbstub_do_step(esp_gdbstub_frame_t *regs_frame);
|
||||
void esp_gdbstub_trigger_cpu(void);
|
||||
|
||||
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
/**
|
||||
* Check if a watchpoint triggered the current debug exception.
|
||||
* @param[out] addr Address of the triggered watchpoint (only valid if return is true)
|
||||
* @return true if a watchpoint triggered, false otherwise (breakpoint/step/other)
|
||||
*/
|
||||
bool esp_gdbstub_get_watchpoint_trigger_addr(uint32_t *addr);
|
||||
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
|
||||
/**
|
||||
* Write a value to register in frame
|
||||
* @param frame gdbstub frame
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#define GDBSTUB_QXFER_SUPPORTED_STR ""
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
static void send_watchpoint_reason(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||
static inline int gdb_tid_to_task_index(int tid);
|
||||
static inline int task_index_to_gdb_tid(int tid);
|
||||
@@ -107,6 +111,9 @@ static void send_reason(void)
|
||||
esp_gdbstub_send_start();
|
||||
esp_gdbstub_send_char('T');
|
||||
esp_gdbstub_send_hex(s_scratch.signal, 8);
|
||||
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
send_watchpoint_reason();
|
||||
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
esp_gdbstub_send_end();
|
||||
}
|
||||
|
||||
@@ -212,6 +219,35 @@ static bool not_send_reason = false;
|
||||
static bool process_gdb_kill = false;
|
||||
static bool gdb_debug_int = false;
|
||||
|
||||
/**
|
||||
* Detect if a watchpoint triggered and append the corresponding
|
||||
* GDB RSP stop-reply field (watch/rwatch/awatch) to the current packet.
|
||||
*/
|
||||
static void send_watchpoint_reason(void)
|
||||
{
|
||||
uint32_t wp_addr = 0;
|
||||
if (!esp_gdbstub_get_watchpoint_trigger_addr(&wp_addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *type_str = "watch";
|
||||
for (size_t i = 0; i < SOC_CPU_WATCHPOINTS_NUM; i++) {
|
||||
if (wp_list[i] == wp_addr) {
|
||||
if (wp_access[i] == ESP_CPU_WATCHPOINT_LOAD) {
|
||||
type_str = "rwatch";
|
||||
} else if (wp_access[i] == ESP_CPU_WATCHPOINT_ACCESS) {
|
||||
type_str = "awatch";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
esp_gdbstub_send_str(type_str);
|
||||
esp_gdbstub_send_char(':');
|
||||
esp_gdbstub_send_hex(wp_addr, 32);
|
||||
esp_gdbstub_send_char(';');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle UART interrupt
|
||||
*
|
||||
|
||||
@@ -250,6 +250,22 @@ void esp_gdbstub_init_dports(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool esp_gdbstub_get_watchpoint_trigger_addr(uint32_t *addr)
|
||||
{
|
||||
for (int i = 0; i < SOC_CPU_BREAKPOINTS_NUM; i++) {
|
||||
RV_WRITE_CSR(tselect, i);
|
||||
uint32_t tdata1 = RV_READ_CSR(tdata1);
|
||||
bool is_load = tdata1 & TDATA1_LOAD;
|
||||
bool is_store = tdata1 & TDATA1_STORE;
|
||||
bool is_exec = tdata1 & TDATA1_EXECUTE;
|
||||
if (!is_exec && (is_load || is_store)) {
|
||||
*addr = RV_READ_CSR(tdata2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
|
||||
#if (!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE) && CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
|
||||
@@ -307,6 +307,23 @@ void esp_gdbstub_init_dports(void)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
bool esp_gdbstub_get_watchpoint_trigger_addr(uint32_t *addr)
|
||||
{
|
||||
uint32_t debugcause;
|
||||
RSR(XT_REG_DEBUGCAUSE, debugcause);
|
||||
if (debugcause & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
|
||||
if (debugcause & (1 << 8)) {
|
||||
RSR(XT_REG_DBREAKA_1, *addr);
|
||||
} else {
|
||||
RSR(XT_REG_DBREAKA_0, *addr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA && (!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE) && CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||
static bool stall_started = false;
|
||||
#endif
|
||||
|
||||
@@ -368,14 +368,11 @@ def test_gdbstub_runtime(dut: PanicTestDut) -> None:
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
cmd = '-exec-continue'
|
||||
payload = run_and_break(dut, cmd)
|
||||
assert payload['reason'] == 'signal-received'
|
||||
assert payload['reason'] == 'watchpoint-trigger'
|
||||
assert int(payload['value']['new']) == int(payload['value']['old']) + 2
|
||||
assert payload['frame']['func'] == 'foo'
|
||||
assert payload['frame']['line'] == str(get_line_number('var_2--;'))
|
||||
assert payload['stopped-threads'] == 'all'
|
||||
# Uncomment this when implement send reason to gdb: GCC-313
|
||||
#
|
||||
# assert payload['reason'] == 'watchpoint-trigger'
|
||||
# assert int(payload['value']['new']) == int(payload['value']['old']) + 1
|
||||
# assert payload['frame']['line'] == '14'
|
||||
|
||||
cmd = '-break-delete 2'
|
||||
responses = dut.gdb_write(cmd)
|
||||
|
||||
Reference in New Issue
Block a user