mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 21:24:32 +02:00
Merge branch 'esp32c3/coredump_bt_summary' into 'master'
coredump: Parse backtrace info for RISCV See merge request espressif/esp-idf!13455
This commit is contained in:
@@ -90,6 +90,15 @@ menu "Core dump"
|
||||
To ensure that core dump itself will not overflow task/ISR stack set this to the value above 800.
|
||||
NOTE: It eats DRAM.
|
||||
|
||||
config ESP_COREDUMP_SUMMARY_STACKDUMP_SIZE
|
||||
int "Size of the stack dump buffer"
|
||||
depends on ESP_COREDUMP_DATA_FORMAT_ELF && ESP_COREDUMP_ENABLE_TO_FLASH && IDF_TARGET_ARCH_RISCV
|
||||
range 512 4096
|
||||
default 1024
|
||||
help
|
||||
Size of the buffer that would be reserved for extracting backtrace info summary.
|
||||
This buffer will contain the stack dump of the crashed task. This dump is useful in generating backtrace
|
||||
|
||||
choice ESP_COREDUMP_DECODE
|
||||
prompt "Handling of UART core dumps in IDF Monitor"
|
||||
depends on ESP_COREDUMP_ENABLE_TO_UART
|
||||
|
@@ -14,10 +14,11 @@
|
||||
#ifndef ESP_CORE_DUMP_H_
|
||||
#define ESP_CORE_DUMP_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "esp_core_dump_summary_extra_info.h"
|
||||
#include "esp_core_dump_summary_port.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -25,14 +26,7 @@ extern "C" {
|
||||
|
||||
#define APP_ELF_SHA256_SZ (CONFIG_APP_RETRIEVE_LEN_ELF_SHA + 1)
|
||||
|
||||
/**
|
||||
* @brief Backtrace information
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t bt[16]; /*!< Backtrace (array of PC) */
|
||||
uint32_t depth; /*!< Number of backtrace entries */
|
||||
bool corrupted; /*!< Status flag for backtrace is corrupt or not */
|
||||
} esp_core_dump_bt_info_t;
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
/**
|
||||
* @brief Core dump summary, Most meaningful contents of the core dump
|
||||
@@ -48,6 +42,8 @@ typedef struct {
|
||||
esp_core_dump_summary_extra_info_t ex_info; /*!< Architecture specific extra data */
|
||||
} esp_core_dump_summary_t;
|
||||
|
||||
#endif /* CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF */
|
||||
|
||||
/**************************************************************************************/
|
||||
/******************************** EXCEPTION MODE API **********************************/
|
||||
/**************************************************************************************/
|
||||
@@ -137,15 +133,32 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size);
|
||||
*/
|
||||
esp_err_t esp_core_dump_image_erase(void);
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
/**
|
||||
* @brief Get the summary of a core dump. This function works only with ELF format core dumps.
|
||||
* @brief Get the summary of a core dump.
|
||||
*
|
||||
* @param summary Summary of the core dump
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t
|
||||
*
|
||||
* @note This function works only if coredump is stored in flash and in ELF format
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* esp_core_dump_summary_t *summary = malloc(sizeof(esp_core_dump_summary_t));
|
||||
* if (summary) {
|
||||
* if (esp_core_dump_get_summary(summary) == ESP_OK) {
|
||||
* // Do stuff
|
||||
* }
|
||||
* }
|
||||
* free(summary);
|
||||
* @endcode
|
||||
*/
|
||||
esp_err_t esp_core_dump_get_summary(esp_core_dump_summary_t *summary);
|
||||
|
||||
#endif /* CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -19,6 +20,21 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
/**
|
||||
* @brief Backtrace information
|
||||
*
|
||||
* For RISCV, backtrace cannot be generated on device without including and parsing
|
||||
* DWARF sections. Including these sections would increase the binary size so provide
|
||||
* the stackdump that can be later used to generate backtrace with the help of GDB or by parsing the ELF file
|
||||
* on the host machine
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t stackdump[CONFIG_ESP_COREDUMP_SUMMARY_STACKDUMP_SIZE]; /*!< Stack dump of the crashing task. */
|
||||
uint32_t dump_size; /*!< Size (in bytes) of the stack dump */
|
||||
} esp_core_dump_bt_info_t;
|
||||
|
||||
/**
|
||||
* @brief RISC-V architecture specific extra information
|
||||
*/
|
||||
@@ -27,9 +43,13 @@ typedef struct {
|
||||
uint32_t mtvec; /* Machine Trap-Vector Base Address */
|
||||
uint32_t mcause; /* Machine Trap Cause */
|
||||
uint32_t mtval; /* Machine Trap Value */
|
||||
uint32_t exc_a[8]; /*!< a register set when the exception caused */
|
||||
uint32_t ra; /* Return Address */
|
||||
uint32_t sp; /* Stack pointer */
|
||||
uint32_t exc_a[8]; /* A0-A7 registers when the exception caused */
|
||||
} esp_core_dump_summary_extra_info_t;
|
||||
|
||||
#endif /* CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
#include <stdint.h>
|
||||
#include <xtensa/config/core-isa.h>
|
||||
|
||||
@@ -20,8 +21,21 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
#define EPCx_REGISTER_COUNT XCHAL_NUM_INTLEVELS
|
||||
|
||||
/**
|
||||
* @brief Backtrace information.
|
||||
*
|
||||
* For Xtensa, backtrace can be generated on device due to windowed register ABI.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t bt[16]; /*!< Backtrace (array of PC) */
|
||||
uint32_t depth; /*!< Number of backtrace entries */
|
||||
bool corrupted; /*!< Status flag for backtrace is corrupt or not */
|
||||
} esp_core_dump_bt_info_t;
|
||||
|
||||
/**
|
||||
* @brief Xtensa architecture specific extra information
|
||||
*/
|
||||
@@ -33,6 +47,8 @@ typedef struct {
|
||||
uint8_t epcx_reg_bits; /*!< Bit mask of available EPCx registers */
|
||||
} esp_core_dump_summary_extra_info_t;
|
||||
|
||||
#endif /* CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -24,6 +24,7 @@
|
||||
* both Xtensa and RISC-V architecture.
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
@@ -165,6 +166,8 @@ void esp_core_dump_port_set_crashed_tcb(uint32_t handle);
|
||||
*/
|
||||
uint32_t esp_core_dump_get_extra_info(void **info);
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
/**
|
||||
* @brief Parse extra information into summary
|
||||
*
|
||||
@@ -191,6 +194,7 @@ void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void
|
||||
*/
|
||||
void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info, const void *vaddr,
|
||||
const void *paddr, uint32_t stack_size);
|
||||
#endif /* CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -646,6 +646,8 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
|
||||
/* Below are the helper function to parse the core dump ELF stored in flash */
|
||||
|
||||
static esp_err_t elf_core_dump_image_mmap(spi_flash_mmap_handle_t* core_data_handle, const void **map_addr)
|
||||
@@ -773,4 +775,6 @@ esp_err_t esp_core_dump_get_summary(esp_core_dump_summary_t *summary)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif // CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
|
||||
#endif //CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
@@ -381,6 +381,8 @@ uint32_t esp_core_dump_get_extra_info(void **info)
|
||||
return size;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
void esp_core_dump_summary_parse_extra_info(esp_core_dump_summary_t *summary, void *ei_data)
|
||||
{
|
||||
riscv_extra_info_t *ei = (riscv_extra_info_t *)ei_data;
|
||||
@@ -400,8 +402,10 @@ void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void
|
||||
summary->ex_info.mtvec = stack->mtvec;
|
||||
summary->ex_info.mcause = stack->mcause;
|
||||
summary->ex_info.mtval = stack->mtval;
|
||||
ESP_COREDUMP_LOGD("mstatus:0x%x mtvec:0x%x mcause:0x%x mval:0x%x",
|
||||
stack->mstatus, stack->mtvec, stack->mcause, stack->mtval);
|
||||
summary->ex_info.ra = stack->ra;
|
||||
summary->ex_info.sp = stack->sp;
|
||||
ESP_COREDUMP_LOGD("mstatus:0x%x mtvec:0x%x mcause:0x%x mval:0x%x RA: 0x%x SP: 0x%x",
|
||||
stack->mstatus, stack->mtvec, stack->mcause, stack->mtval, stack->ra, stack->sp);
|
||||
a_reg = &stack->a0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
summary->ex_info.exc_a[i] = a_reg[i];
|
||||
@@ -412,7 +416,39 @@ void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void
|
||||
void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info, const void *vaddr,
|
||||
const void *paddr, uint32_t stack_size)
|
||||
{
|
||||
if (!vaddr || !paddr || !bt_info) {
|
||||
bt_info->dump_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether the stack is a fake stack created during coredump generation
|
||||
* If its a fake stack, we don't have any actual stack dump
|
||||
*/
|
||||
if (vaddr >= COREDUMP_FAKE_STACK_START && vaddr < COREDUMP_FAKE_STACK_LIMIT) {
|
||||
bt_info->dump_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Top of the stack consists of the context registers saved after crash,
|
||||
* extract the value of stack pointer (SP) at the time of crash
|
||||
*/
|
||||
RvExcFrame *stack = (RvExcFrame *) paddr;
|
||||
uint32_t *sp = (uint32_t *)stack->sp;
|
||||
|
||||
/* vaddr is actual stack address when crash occurred. However that stack is now saved
|
||||
* in the flash at a different location. Hence, we need to adjust the offset
|
||||
* to point to correct data in the flash */
|
||||
int offset = (uint32_t)stack - (uint32_t)vaddr;
|
||||
|
||||
// Skip the context saved register frame
|
||||
uint32_t regframe_size = (uint32_t)sp - (uint32_t)vaddr;
|
||||
|
||||
uint32_t dump_size = MIN(stack_size - regframe_size, CONFIG_ESP_COREDUMP_SUMMARY_STACKDUMP_SIZE);
|
||||
|
||||
memcpy(&bt_info->stackdump[0], (uint8_t *)sp + offset, dump_size);
|
||||
bt_info->dump_size = dump_size;
|
||||
}
|
||||
|
||||
#endif /* #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF */
|
||||
|
||||
#endif
|
||||
|
@@ -473,6 +473,8 @@ uint32_t esp_core_dump_get_extra_info(void **info)
|
||||
return sizeof(s_extra_info);
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
void esp_core_dump_summary_parse_extra_info(esp_core_dump_summary_t *summary, void *ei_data)
|
||||
{
|
||||
int i;
|
||||
@@ -513,6 +515,10 @@ void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void
|
||||
void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info, const void *vaddr,
|
||||
const void *paddr, uint32_t stack_size)
|
||||
{
|
||||
if (!vaddr || !paddr || !bt_info) {
|
||||
return;
|
||||
}
|
||||
|
||||
int offset;
|
||||
bool corrupted;
|
||||
esp_backtrace_frame_t frame;
|
||||
@@ -559,4 +565,6 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info
|
||||
bt_info->corrupted = corrupted;
|
||||
}
|
||||
|
||||
#endif /* #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF */
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user