target/espressif: read entry addresses of pre-defined stub functions
Debug stubs functionality provided by ESP IDF allows executing target function in any address. e.g; esp32_cmd_gcov() Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com> Change-Id: I56d844e5a862c9bf33fdb991b01abb7a76047ca7 Reviewed-on: https://review.openocd.org/c/openocd/+/7758 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
committed by
Antonio Borneo
parent
29b02402ff
commit
9fd754ca4d
@@ -17,9 +17,46 @@
|
||||
#include "esp_xtensa.h"
|
||||
#include "esp_semihosting.h"
|
||||
|
||||
#define ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(_e_) \
|
||||
do { \
|
||||
uint32_t __internal_val = (_e_); \
|
||||
if (!xtensa_data_addr_valid(target, __internal_val)) { \
|
||||
LOG_ERROR("No valid stub data entry found (0x%" PRIx32 ")!", __internal_val); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(_e_) \
|
||||
do { \
|
||||
uint32_t __internal_val = (_e_); \
|
||||
if (__internal_val == 0) { \
|
||||
LOG_ERROR("No valid stub code entry found (0x%" PRIx32 ")!", __internal_val); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void esp_xtensa_dbgstubs_info_update(struct target *target);
|
||||
static void esp_xtensa_dbgstubs_addr_check(struct target *target);
|
||||
|
||||
static int esp_xtensa_dbgstubs_restore(struct target *target)
|
||||
{
|
||||
struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
|
||||
|
||||
if (esp_xtensa->esp.dbg_stubs.base == 0)
|
||||
return ERROR_OK;
|
||||
|
||||
LOG_TARGET_INFO(target, "Restore debug stubs address %" PRIx32, esp_xtensa->esp.dbg_stubs.base);
|
||||
int res = esp_xtensa_apptrace_status_reg_write(target, esp_xtensa->esp.dbg_stubs.base);
|
||||
if (res != ERROR_OK) {
|
||||
LOG_ERROR("Failed to write trace status (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
int esp_xtensa_on_halt(struct target *target)
|
||||
{
|
||||
/* will be used in the next patches */
|
||||
/* debug stubs can be used in HALTED state only, so it is OK to get info about them here */
|
||||
esp_xtensa_dbgstubs_info_update(target);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -45,6 +82,11 @@ void esp_xtensa_target_deinit(struct target *target)
|
||||
{
|
||||
LOG_DEBUG("start");
|
||||
|
||||
if (target_was_examined(target)) {
|
||||
int ret = esp_xtensa_dbgstubs_restore(target);
|
||||
if (ret != ERROR_OK)
|
||||
return;
|
||||
}
|
||||
xtensa_target_deinit(target);
|
||||
free(target_to_esp_xtensa(target)); /* same as free(xtensa) */
|
||||
}
|
||||
@@ -56,7 +98,68 @@ int esp_xtensa_arch_state(struct target *target)
|
||||
|
||||
int esp_xtensa_poll(struct target *target)
|
||||
{
|
||||
return xtensa_poll(target);
|
||||
struct xtensa *xtensa = target_to_xtensa(target);
|
||||
struct esp_xtensa_common *esp_xtensa_common = target_to_esp_xtensa(target);
|
||||
|
||||
int ret = xtensa_poll(target);
|
||||
|
||||
if (xtensa_dm_power_status_get(&xtensa->dbg_mod) & PWRSTAT_COREWASRESET(xtensa)) {
|
||||
LOG_TARGET_DEBUG(target, "Clear debug stubs info");
|
||||
memset(&esp_xtensa_common->esp.dbg_stubs, 0, sizeof(esp_xtensa_common->esp.dbg_stubs));
|
||||
}
|
||||
if (target->state != TARGET_DEBUG_RUNNING)
|
||||
esp_xtensa_dbgstubs_addr_check(target);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void esp_xtensa_dbgstubs_addr_check(struct target *target)
|
||||
{
|
||||
struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
|
||||
uint32_t vec_addr = 0;
|
||||
|
||||
if (esp_xtensa->esp.dbg_stubs.base != 0)
|
||||
return;
|
||||
|
||||
int res = esp_xtensa_apptrace_status_reg_read(target, &vec_addr);
|
||||
if (res != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read debug stubs address location (%d)!", res);
|
||||
return;
|
||||
}
|
||||
if (xtensa_data_addr_valid(target, vec_addr)) {
|
||||
LOG_TARGET_INFO(target, "Detected debug stubs @ %" PRIx32, vec_addr);
|
||||
res = esp_xtensa_apptrace_status_reg_write(target, 0);
|
||||
if (res != ERROR_OK)
|
||||
LOG_ERROR("Failed to clear debug stubs address location (%d)!", res);
|
||||
esp_xtensa->esp.dbg_stubs.base = vec_addr;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_xtensa_dbgstubs_info_update(struct target *target)
|
||||
{
|
||||
struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
|
||||
|
||||
if (esp_xtensa->esp.dbg_stubs.base == 0 || esp_xtensa->esp.dbg_stubs.entries_count != 0)
|
||||
return;
|
||||
|
||||
int res = esp_dbgstubs_table_read(target, &esp_xtensa->esp.dbg_stubs);
|
||||
if (res != ERROR_OK)
|
||||
return;
|
||||
if (esp_xtensa->esp.dbg_stubs.entries_count == 0)
|
||||
return;
|
||||
|
||||
/* read debug stubs descriptor */
|
||||
ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(esp_xtensa->esp.dbg_stubs.entries[ESP_DBG_STUB_DESC]);
|
||||
res = target_read_buffer(target, esp_xtensa->esp.dbg_stubs.entries[ESP_DBG_STUB_DESC],
|
||||
sizeof(struct esp_dbg_stubs_desc),
|
||||
(uint8_t *)&esp_xtensa->esp.dbg_stubs.desc);
|
||||
if (res != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read debug stubs descriptor (%d)!", res);
|
||||
return;
|
||||
}
|
||||
ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.tramp_addr);
|
||||
ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(esp_xtensa->esp.dbg_stubs.desc.min_stack_addr);
|
||||
ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.data_alloc);
|
||||
ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.data_free);
|
||||
}
|
||||
|
||||
int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint)
|
||||
|
||||
Reference in New Issue
Block a user