mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
coredump: Fixes ESP-specific panic reasons handling
This commit is contained in:
parent
2f74b4e023
commit
21091c6b0e
@ -1,6 +1,5 @@
|
|||||||
idf_component_register(SRCS "panic.c" "system_api.c" "startup.c"
|
idf_component_register(SRCS "panic.c" "system_api.c" "startup.c"
|
||||||
INCLUDE_DIRS include
|
INCLUDE_DIRS include
|
||||||
PRIV_INCLUDE_DIRS private_include
|
|
||||||
PRIV_REQUIRES spi_flash app_update
|
PRIV_REQUIRES spi_flash app_update
|
||||||
# requirements due to startup code
|
# requirements due to startup code
|
||||||
nvs_flash pthread app_trace
|
nvs_flash pthread app_trace
|
||||||
|
@ -15,11 +15,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "port/panic_funcs.h"
|
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
extern bool g_panic_abort;
|
extern bool g_panic_abort;
|
||||||
|
|
||||||
// Function to print longer amounts of information such as the details
|
// Function to print longer amounts of information such as the details
|
||||||
@ -49,6 +51,7 @@ typedef struct {
|
|||||||
panic_info_dump_fn_t state; // processor state, usually the contents of the registers
|
panic_info_dump_fn_t state; // processor state, usually the contents of the registers
|
||||||
const void* addr; // instruction address that triggered the exception
|
const void* addr; // instruction address that triggered the exception
|
||||||
const void* frame; // reference to the frame
|
const void* frame; // reference to the frame
|
||||||
|
bool pseudo_excause; // flag indicating that exception cause has special meaning
|
||||||
} panic_info_t;
|
} panic_info_t;
|
||||||
|
|
||||||
#define PANIC_INFO_DUMP(info, dump_fn) {if ((info)->dump_fn) (*(info)->dump_fn)((info->frame));}
|
#define PANIC_INFO_DUMP(info, dump_fn) {if ((info)->dump_fn) (*(info)->dump_fn)((info->frame));}
|
||||||
@ -67,4 +70,8 @@ void panic_print_hex(int h);
|
|||||||
#define panic_print_hex(h)
|
#define panic_print_hex(h)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __attribute__((noreturn)) panic_abort(const char *details);
|
void __attribute__((noreturn)) panic_abort(const char *details);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -43,7 +43,7 @@
|
|||||||
#include "hal/uart_hal.h"
|
#include "hal/uart_hal.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "panic_internal.h"
|
#include "esp_private/panic_internal.h"
|
||||||
#include "port/panic_funcs.h"
|
#include "port/panic_funcs.h"
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
@ -204,7 +204,7 @@ void esp_panic_handler(panic_info_t *info)
|
|||||||
* description - a short description regarding the exception that occured
|
* description - a short description regarding the exception that occured
|
||||||
* details - more details about the exception
|
* details - more details about the exception
|
||||||
* state - processor state like register contents, and backtrace
|
* state - processor state like register contents, and backtrace
|
||||||
* elf_info - details about the image currently running
|
* elf_info - details about the image currently running
|
||||||
*
|
*
|
||||||
* NULL fields in panic_info_t are not printed.
|
* NULL fields in panic_info_t are not printed.
|
||||||
*
|
*
|
||||||
@ -302,10 +302,10 @@ void esp_panic_handler(panic_info_t *info)
|
|||||||
disable_all_wdts();
|
disable_all_wdts();
|
||||||
s_dumping_core = true;
|
s_dumping_core = true;
|
||||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||||
esp_core_dump_to_flash((XtExcFrame*) info->frame);
|
esp_core_dump_to_flash(info);
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
||||||
esp_core_dump_to_uart((XtExcFrame*) info->frame);
|
esp_core_dump_to_uart(info);
|
||||||
#endif
|
#endif
|
||||||
s_dumping_core = false;
|
s_dumping_core = false;
|
||||||
reconfigure_all_wdts();
|
reconfigure_all_wdts();
|
||||||
@ -332,7 +332,7 @@ void esp_panic_handler(panic_info_t *info)
|
|||||||
break; // do not touch the previously set reset reason hint
|
break; // do not touch the previously set reset reason hint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic_print_str("Rebooting...\r\n");
|
panic_print_str("Rebooting...\r\n");
|
||||||
panic_restart();
|
panic_restart();
|
||||||
#else
|
#else
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "panic_internal.h"
|
#include "esp_private/panic_internal.h"
|
||||||
|
|
||||||
extern int _invalid_pc_placeholder;
|
extern int _invalid_pc_placeholder;
|
||||||
|
|
||||||
@ -383,6 +383,7 @@ static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseu
|
|||||||
info->exception = PANIC_EXCEPTION_FAULT;
|
info->exception = PANIC_EXCEPTION_FAULT;
|
||||||
info->details = NULL;
|
info->details = NULL;
|
||||||
|
|
||||||
|
info->pseudo_excause = pseudo_excause;
|
||||||
if (pseudo_excause) {
|
if (pseudo_excause) {
|
||||||
if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
|
if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
|
||||||
info->core = 0;
|
info->core = 0;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "soc/cpu.h"
|
#include "soc/cpu.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "panic_internal.h"
|
#include "esp_private/panic_internal.h"
|
||||||
#include "esp_rom_uart.h"
|
#include "esp_rom_uart.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/memprot.h"
|
#include "esp32s2/memprot.h"
|
||||||
|
@ -53,6 +53,7 @@ else:
|
|||||||
CLOSE_FDS = True
|
CLOSE_FDS = True
|
||||||
|
|
||||||
INVALID_CAUSE_VALUE = 0xFFFF
|
INVALID_CAUSE_VALUE = 0xFFFF
|
||||||
|
XCHAL_EXCCAUSE_NUM = 64
|
||||||
|
|
||||||
# Exception cause dictionary to get translation of exccause register
|
# Exception cause dictionary to get translation of exccause register
|
||||||
# From 4.4.1.5 table 4-64 Exception Causes of Xtensa
|
# From 4.4.1.5 table 4-64 Exception Causes of Xtensa
|
||||||
@ -88,7 +89,17 @@ xtensa_exception_cause_dict = {
|
|||||||
37: ("Coprocessor5Disabled", "Coprocessor 5 instruction when cp5 disabled"),
|
37: ("Coprocessor5Disabled", "Coprocessor 5 instruction when cp5 disabled"),
|
||||||
38: ("Coprocessor6Disabled", "Coprocessor 6 instruction when cp6 disabled"),
|
38: ("Coprocessor6Disabled", "Coprocessor 6 instruction when cp6 disabled"),
|
||||||
39: ("Coprocessor7Disabled", "Coprocessor 7 instruction when cp7 disabled"),
|
39: ("Coprocessor7Disabled", "Coprocessor 7 instruction when cp7 disabled"),
|
||||||
INVALID_CAUSE_VALUE: ("InvalidCauseRegister", "Invalid EXCCAUSE register value or current task is broken and was skipped")}
|
INVALID_CAUSE_VALUE: ("InvalidCauseRegister", "Invalid EXCCAUSE register value or current task is broken and was skipped"),
|
||||||
|
# ESP panic pseudo reasons
|
||||||
|
XCHAL_EXCCAUSE_NUM + 0: ("UnknownException", "Unknown exception"),
|
||||||
|
XCHAL_EXCCAUSE_NUM + 1: ("DebugException", "Unhandled debug exception"),
|
||||||
|
XCHAL_EXCCAUSE_NUM + 2: ("DoubleException", "Double exception"),
|
||||||
|
XCHAL_EXCCAUSE_NUM + 3: ("KernelException", "Unhandled kernel exception"),
|
||||||
|
XCHAL_EXCCAUSE_NUM + 4: ("CoprocessorException", "Coprocessor exception"),
|
||||||
|
XCHAL_EXCCAUSE_NUM + 5: ("InterruptWDTTimoutCPU0", "Interrupt wdt timeout on CPU0"),
|
||||||
|
XCHAL_EXCCAUSE_NUM + 6: ("InterruptWDTTimoutCPU1", "Interrupt wdt timeout on CPU1"),
|
||||||
|
XCHAL_EXCCAUSE_NUM + 7: ("CacheError", "Cache disabled but cached memory region accessed"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ESPCoreDumpError(RuntimeError):
|
class ESPCoreDumpError(RuntimeError):
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "freertos/xtensa_context.h"
|
#include "freertos/xtensa_context.h"
|
||||||
|
#include "esp_private/panic_internal.h"
|
||||||
|
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
/******************************** EXCEPTION MODE API **********************************/
|
/******************************** EXCEPTION MODE API **********************************/
|
||||||
@ -46,7 +47,7 @@ void esp_core_dump_init(void);
|
|||||||
* The structure of core dump data is described below in details.
|
* The structure of core dump data is described below in details.
|
||||||
* 1) Core dump starts with header:
|
* 1) Core dump starts with header:
|
||||||
* 1.1) TOTAL_LEN is total length of core dump data in flash including CRC. Size is 4 bytes.
|
* 1.1) TOTAL_LEN is total length of core dump data in flash including CRC. Size is 4 bytes.
|
||||||
* 1.2) VERSION field keeps 4 byte version of core dump.
|
* 1.2) VERSION field keeps 4 byte version of core dump.
|
||||||
* 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes.
|
* 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes.
|
||||||
* 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes.
|
* 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes.
|
||||||
* 2) Core dump header is followed by the data for every task in the system.
|
* 2) Core dump header is followed by the data for every task in the system.
|
||||||
@ -58,7 +59,7 @@ void esp_core_dump_init(void);
|
|||||||
* 4) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes.
|
* 4) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes.
|
||||||
* 5) CRC is placed at the end of the data.
|
* 5) CRC is placed at the end of the data.
|
||||||
*/
|
*/
|
||||||
void esp_core_dump_to_flash(XtExcFrame *frame);
|
void esp_core_dump_to_flash(panic_info_t *info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Print base64-encoded core dump to UART.
|
* @brief Print base64-encoded core dump to UART.
|
||||||
@ -68,7 +69,7 @@ void esp_core_dump_to_flash(XtExcFrame *frame);
|
|||||||
* 2) Since CRC is omitted TOTAL_LEN does not include its size.
|
* 2) Since CRC is omitted TOTAL_LEN does not include its size.
|
||||||
* 3) Printed base64 data are surrounded with special messages to help user recognize the start and end of actual data.
|
* 3) Printed base64 data are surrounded with special messages to help user recognize the start and end of actual data.
|
||||||
*/
|
*/
|
||||||
void esp_core_dump_to_uart(XtExcFrame *frame);
|
void esp_core_dump_to_uart(panic_info_t *info);
|
||||||
|
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
/*********************************** USER MODE API ************************************/
|
/*********************************** USER MODE API ************************************/
|
||||||
|
@ -16,6 +16,6 @@
|
|||||||
|
|
||||||
#include "esp_core_dump_priv.h"
|
#include "esp_core_dump_priv.h"
|
||||||
|
|
||||||
esp_err_t esp_core_dump_write_elf(void *frame, core_dump_write_config_t *write_cfg);
|
esp_err_t esp_core_dump_write_elf(panic_info_t *info, core_dump_write_config_t *write_cfg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,7 +56,7 @@ bool esp_core_dump_tcb_addr_is_sane(uint32_t addr);
|
|||||||
bool esp_core_dump_task_stack_end_is_sane(uint32_t sp);
|
bool esp_core_dump_task_stack_end_is_sane(uint32_t sp);
|
||||||
bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz);
|
bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz);
|
||||||
void *esp_core_dump_get_current_task_handle(void);
|
void *esp_core_dump_get_current_task_handle(void);
|
||||||
bool esp_core_dump_check_task(void *frame, core_dump_task_header_t *task_snaphort, bool* is_current, bool* stack_is_valid);
|
bool esp_core_dump_check_task(panic_info_t *info, core_dump_task_header_t *task_snaphort, bool* is_current, bool* stack_is_valid);
|
||||||
bool esp_core_dump_check_stack(uint32_t stack_start, uint32_t stack_end);
|
bool esp_core_dump_check_stack(uint32_t stack_start, uint32_t stack_end);
|
||||||
uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot, uint32_t* stk_base, uint32_t* stk_len);
|
uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot, uint32_t* stk_base, uint32_t* stk_len);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ extern "C" {
|
|||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_private/panic_internal.h"
|
||||||
#if CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256
|
#if CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256
|
||||||
// TODO: move this to portable part of the code
|
// TODO: move this to portable part of the code
|
||||||
#include "mbedtls/sha256.h"
|
#include "mbedtls/sha256.h"
|
||||||
@ -137,7 +138,7 @@ typedef struct _core_dump_mem_seg_header_t
|
|||||||
void esp_core_dump_flash_init(void);
|
void esp_core_dump_flash_init(void);
|
||||||
|
|
||||||
// Common core dump write function
|
// Common core dump write function
|
||||||
void esp_core_dump_write(void *frame, core_dump_write_config_t *write_cfg);
|
void esp_core_dump_write(panic_info_t *info, core_dump_write_config_t *write_cfg);
|
||||||
|
|
||||||
#include "esp_core_dump_port.h"
|
#include "esp_core_dump_port.h"
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_core_dump_priv.h"
|
|
||||||
#include "core_dump_elf.h"
|
#include "core_dump_elf.h"
|
||||||
|
|
||||||
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_common";
|
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_common";
|
||||||
@ -100,7 +99,7 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_t *write_cfg)
|
static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_config_t *write_cfg)
|
||||||
{
|
{
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
static core_dump_task_header_t *tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM];
|
static core_dump_task_header_t *tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM];
|
||||||
@ -117,7 +116,7 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_
|
|||||||
|
|
||||||
for (task_id = 0; task_id < task_num; task_id++) {
|
for (task_id = 0; task_id < task_num; task_id++) {
|
||||||
bool is_current_task = false, stack_is_valid = false;
|
bool is_current_task = false, stack_is_valid = false;
|
||||||
bool tcb_is_valid = esp_core_dump_check_task(frame, tasks[task_id], &is_current_task, &stack_is_valid);
|
bool tcb_is_valid = esp_core_dump_check_task(info, tasks[task_id], &is_current_task, &stack_is_valid);
|
||||||
// Check if task tcb or stack is corrupted
|
// Check if task tcb or stack is corrupted
|
||||||
if (!tcb_is_valid || !stack_is_valid) {
|
if (!tcb_is_valid || !stack_is_valid) {
|
||||||
// If tcb or stack for task is corrupted count task as broken
|
// If tcb or stack for task is corrupted count task as broken
|
||||||
@ -142,7 +141,7 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_
|
|||||||
interrupted_task_stack.size = esp_core_dump_get_memory_len(tasks[curr_task_index]->stack_start, tasks[curr_task_index]->stack_end);
|
interrupted_task_stack.size = esp_core_dump_get_memory_len(tasks[curr_task_index]->stack_start, tasks[curr_task_index]->stack_end);
|
||||||
// size of the task's stack has been already taken into account, also addresses have also been checked
|
// size of the task's stack has been already taken into account, also addresses have also been checked
|
||||||
data_len += sizeof(core_dump_mem_seg_header_t);
|
data_len += sizeof(core_dump_mem_seg_header_t);
|
||||||
tasks[curr_task_index]->stack_start = (uint32_t)frame;
|
tasks[curr_task_index]->stack_start = (uint32_t)info->frame;
|
||||||
tasks[curr_task_index]->stack_end = esp_core_dump_get_isr_stack_end();
|
tasks[curr_task_index]->stack_end = esp_core_dump_get_isr_stack_end();
|
||||||
ESP_COREDUMP_LOG_PROCESS("Add ISR stack %lu to %lu", tasks[curr_task_index]->stack_end - tasks[curr_task_index]->stack_start, data_len);
|
ESP_COREDUMP_LOG_PROCESS("Add ISR stack %lu to %lu", tasks[curr_task_index]->stack_end - tasks[curr_task_index]->stack_start, data_len);
|
||||||
// take into account size of the ISR stack
|
// take into account size of the ISR stack
|
||||||
@ -199,7 +198,7 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_
|
|||||||
hdr.version = COREDUMP_VERSION;
|
hdr.version = COREDUMP_VERSION;
|
||||||
hdr.tasks_num = task_num; // save all the tasks in snapshot even broken
|
hdr.tasks_num = task_num; // save all the tasks in snapshot even broken
|
||||||
hdr.mem_segs_num = 0;
|
hdr.mem_segs_num = 0;
|
||||||
if (xPortInterruptedFromISRContext()) {
|
if (esp_core_dump_in_isr_context()) {
|
||||||
hdr.mem_segs_num++; // stack of interrupted task
|
hdr.mem_segs_num++; // stack of interrupted task
|
||||||
}
|
}
|
||||||
hdr.mem_segs_num += esp_core_dump_get_user_ram_segments(); // stack of user mapped memory
|
hdr.mem_segs_num += esp_core_dump_get_user_ram_segments(); // stack of user mapped memory
|
||||||
@ -231,7 +230,7 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xPortInterruptedFromISRContext()) {
|
if (esp_core_dump_in_isr_context()) {
|
||||||
err = esp_core_dump_save_mem_segment(write_cfg, &interrupted_task_stack);
|
err = esp_core_dump_save_mem_segment(write_cfg, &interrupted_task_stack);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_COREDUMP_LOGE("Failed to save interrupted task stack, error=%d!", err);
|
ESP_COREDUMP_LOGE("Failed to save interrupted task stack, error=%d!", err);
|
||||||
@ -279,16 +278,16 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void esp_core_dump_write(void *frame, core_dump_write_config_t *write_cfg)
|
inline void esp_core_dump_write(panic_info_t *info, core_dump_write_config_t *write_cfg)
|
||||||
{
|
{
|
||||||
esp_core_dump_setup_stack();
|
esp_core_dump_setup_stack();
|
||||||
|
|
||||||
#ifndef CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE
|
#ifndef CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE
|
||||||
esp_err_t err = ESP_ERR_NOT_SUPPORTED;
|
esp_err_t err = ESP_ERR_NOT_SUPPORTED;
|
||||||
#if CONFIG_ESP32_COREDUMP_DATA_FORMAT_BIN
|
#if CONFIG_ESP32_COREDUMP_DATA_FORMAT_BIN
|
||||||
err = esp_core_dump_write_binary(frame, write_cfg);
|
err = esp_core_dump_write_binary(info, write_cfg);
|
||||||
#elif CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF
|
#elif CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF
|
||||||
err = esp_core_dump_write_elf(frame, write_cfg);
|
err = esp_core_dump_write_elf(info, write_cfg);
|
||||||
#endif
|
#endif
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_COREDUMP_LOGE("Core dump write binary failed with error=%d", err);
|
ESP_COREDUMP_LOGE("Core dump write binary failed with error=%d", err);
|
||||||
|
@ -325,7 +325,7 @@ static int elf_get_current_task_index(core_dump_task_header_t** tasks,
|
|||||||
return curr_task_index;
|
return curr_task_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elf_process_task_regdump(core_dump_elf_t *self, void *frame, core_dump_task_header_t *task)
|
static int elf_process_task_regdump(core_dump_elf_t *self, panic_info_t *info, core_dump_task_header_t *task)
|
||||||
{
|
{
|
||||||
bool task_is_valid = false;
|
bool task_is_valid = false;
|
||||||
bool task_is_current = false;
|
bool task_is_current = false;
|
||||||
@ -334,7 +334,7 @@ static int elf_process_task_regdump(core_dump_elf_t *self, void *frame, core_dum
|
|||||||
|
|
||||||
if (self->elf_stage == ELF_STAGE_CALC_SPACE) {
|
if (self->elf_stage == ELF_STAGE_CALC_SPACE) {
|
||||||
// Check if task tcb is corrupted (do not update the header, save as is)
|
// Check if task tcb is corrupted (do not update the header, save as is)
|
||||||
task_is_valid = esp_core_dump_check_task(frame, task, &task_is_current, NULL);
|
task_is_valid = esp_core_dump_check_task(info, task, &task_is_current, NULL);
|
||||||
if (!task_is_valid) {
|
if (!task_is_valid) {
|
||||||
if (task_is_current) {
|
if (task_is_current) {
|
||||||
ESP_COREDUMP_LOG_PROCESS("Task has incorrect (TCB:%x)!",
|
ESP_COREDUMP_LOG_PROCESS("Task has incorrect (TCB:%x)!",
|
||||||
@ -417,7 +417,7 @@ static int elf_process_note_segment(core_dump_elf_t *self, int notes_size)
|
|||||||
return (int)notes_size;
|
return (int)notes_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elf_process_tasks_regs(core_dump_elf_t *self, void* frame,
|
static int elf_process_tasks_regs(core_dump_elf_t *self, panic_info_t *info,
|
||||||
core_dump_task_header_t** tasks,
|
core_dump_task_header_t** tasks,
|
||||||
uint32_t task_num)
|
uint32_t task_num)
|
||||||
{
|
{
|
||||||
@ -430,7 +430,7 @@ static int elf_process_tasks_regs(core_dump_elf_t *self, void* frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// place current task dump first
|
// place current task dump first
|
||||||
int ret = elf_process_task_regdump(self, frame, tasks[curr_task_index]);
|
int ret = elf_process_task_regdump(self, info, tasks[curr_task_index]);
|
||||||
if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) {
|
if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) {
|
||||||
// when writing segments headers this function writes nothing
|
// when writing segments headers this function writes nothing
|
||||||
ELF_CHECK_ERR((ret >= 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", curr_task_index, ret);
|
ELF_CHECK_ERR((ret >= 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", curr_task_index, ret);
|
||||||
@ -446,7 +446,7 @@ static int elf_process_tasks_regs(core_dump_elf_t *self, void* frame,
|
|||||||
if (task_id == curr_task_index) {
|
if (task_id == curr_task_index) {
|
||||||
continue; // skip current task (already processed)
|
continue; // skip current task (already processed)
|
||||||
}
|
}
|
||||||
ret = elf_process_task_regdump(self, frame, tasks[task_id]);
|
ret = elf_process_task_regdump(self, info, tasks[task_id]);
|
||||||
if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) {
|
if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) {
|
||||||
// when writing segments headers this function writes nothing
|
// when writing segments headers this function writes nothing
|
||||||
ELF_CHECK_ERR((ret >= 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", task_id, ret);
|
ELF_CHECK_ERR((ret >= 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", task_id, ret);
|
||||||
@ -467,8 +467,8 @@ static int elf_process_tasks_regs(core_dump_elf_t *self, void* frame,
|
|||||||
self->interrupted_task.stack_start = tasks[curr_task_index]->stack_start;
|
self->interrupted_task.stack_start = tasks[curr_task_index]->stack_start;
|
||||||
self->interrupted_task.stack_end = tasks[curr_task_index]->stack_end;
|
self->interrupted_task.stack_end = tasks[curr_task_index]->stack_end;
|
||||||
uint32_t isr_stk_end = esp_core_dump_get_isr_stack_end();
|
uint32_t isr_stk_end = esp_core_dump_get_isr_stack_end();
|
||||||
ESP_COREDUMP_LOG_PROCESS("Add ISR stack %lu (%x - %x)", isr_stk_end - (uint32_t)frame, (uint32_t)frame, isr_stk_end);
|
ESP_COREDUMP_LOG_PROCESS("Add ISR stack %lu (%x - %x)", isr_stk_end - (uint32_t)info->frame, (uint32_t)info->frame, isr_stk_end);
|
||||||
tasks[curr_task_index]->stack_start = (uint32_t)frame;
|
tasks[curr_task_index]->stack_start = (uint32_t)info->frame;
|
||||||
tasks[curr_task_index]->stack_end = isr_stk_end;
|
tasks[curr_task_index]->stack_end = isr_stk_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +480,7 @@ static int elf_process_tasks_regs(core_dump_elf_t *self, void* frame,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elf_write_tasks_data(core_dump_elf_t *self, void* frame,
|
static int elf_write_tasks_data(core_dump_elf_t *self, panic_info_t *info,
|
||||||
core_dump_task_header_t** tasks,
|
core_dump_task_header_t** tasks,
|
||||||
uint32_t task_num)
|
uint32_t task_num)
|
||||||
{
|
{
|
||||||
@ -488,9 +488,9 @@ static int elf_write_tasks_data(core_dump_elf_t *self, void* frame,
|
|||||||
int task_id;
|
int task_id;
|
||||||
int ret = ELF_PROC_ERR_OTHER;
|
int ret = ELF_PROC_ERR_OTHER;
|
||||||
|
|
||||||
ELF_CHECK_ERR((frame && tasks), ELF_PROC_ERR_OTHER, "Invalid input data.");
|
ELF_CHECK_ERR((info && tasks), ELF_PROC_ERR_OTHER, "Invalid input data.");
|
||||||
|
|
||||||
ret = elf_process_tasks_regs(self, frame, tasks, task_num);
|
ret = elf_process_tasks_regs(self, info, tasks, task_num);
|
||||||
ELF_CHECK_ERR((ret > 0), ret, "Tasks regs addition failed, return (%d).", ret);
|
ELF_CHECK_ERR((ret > 0), ret, "Tasks regs addition failed, return (%d).", ret);
|
||||||
elf_len += ret;
|
elf_len += ret;
|
||||||
self->bad_tasks_num = 0; // reset bad task counter
|
self->bad_tasks_num = 0; // reset bad task counter
|
||||||
@ -572,7 +572,7 @@ static int elf_write_core_dump_info(core_dump_elf_t *self)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, void* frame,
|
static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, panic_info_t *info,
|
||||||
core_dump_task_header_t** tasks,
|
core_dump_task_header_t** tasks,
|
||||||
uint32_t task_num)
|
uint32_t task_num)
|
||||||
{
|
{
|
||||||
@ -586,7 +586,7 @@ static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, void* frame,
|
|||||||
}
|
}
|
||||||
tot_len += data_sz;
|
tot_len += data_sz;
|
||||||
// Calculate whole size include headers for all tasks and main elf header
|
// Calculate whole size include headers for all tasks and main elf header
|
||||||
data_sz = elf_write_tasks_data(self, frame, tasks, task_num);
|
data_sz = elf_write_tasks_data(self, info, tasks, task_num);
|
||||||
ELF_CHECK_ERR((data_sz > 0), data_sz, "ELF Size writing error, returned (%d).", data_sz);
|
ELF_CHECK_ERR((data_sz > 0), data_sz, "ELF Size writing error, returned (%d).", data_sz);
|
||||||
tot_len += data_sz;
|
tot_len += data_sz;
|
||||||
|
|
||||||
@ -604,7 +604,7 @@ static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, void* frame,
|
|||||||
return tot_len;
|
return tot_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_core_dump_write_elf(void *frame, core_dump_write_config_t *write_cfg)
|
esp_err_t esp_core_dump_write_elf(panic_info_t *info, core_dump_write_config_t *write_cfg)
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
static core_dump_task_header_t *tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM];
|
static core_dump_task_header_t *tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM];
|
||||||
@ -614,7 +614,7 @@ esp_err_t esp_core_dump_write_elf(void *frame, core_dump_write_config_t *write_c
|
|||||||
int tot_len = sizeof(dump_hdr);
|
int tot_len = sizeof(dump_hdr);
|
||||||
int write_len = sizeof(dump_hdr);
|
int write_len = sizeof(dump_hdr);
|
||||||
|
|
||||||
ELF_CHECK_ERR((frame && write_cfg), ESP_ERR_INVALID_ARG, "Invalid input data.");
|
ELF_CHECK_ERR((info && write_cfg), ESP_ERR_INVALID_ARG, "Invalid input data.");
|
||||||
|
|
||||||
task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM);
|
task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM);
|
||||||
ESP_COREDUMP_LOGI("Found tasks: %d", task_num);
|
ESP_COREDUMP_LOGI("Found tasks: %d", task_num);
|
||||||
@ -625,7 +625,7 @@ esp_err_t esp_core_dump_write_elf(void *frame, core_dump_write_config_t *write_c
|
|||||||
// On first pass (do not write actual data), but calculate data length needed to allocate memory
|
// On first pass (do not write actual data), but calculate data length needed to allocate memory
|
||||||
self.elf_stage = ELF_STAGE_CALC_SPACE;
|
self.elf_stage = ELF_STAGE_CALC_SPACE;
|
||||||
ESP_COREDUMP_LOG_PROCESS("================= Calc data size ===============");
|
ESP_COREDUMP_LOG_PROCESS("================= Calc data size ===============");
|
||||||
int ret = esp_core_dump_do_write_elf_pass(&self, frame, tasks, task_num);
|
int ret = esp_core_dump_do_write_elf_pass(&self, info, tasks, task_num);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) return ret;
|
||||||
tot_len += ret;
|
tot_len += ret;
|
||||||
ESP_COREDUMP_LOG_PROCESS("Core dump tot_len=%lu, tasks processed: %d, broken tasks: %d",
|
ESP_COREDUMP_LOG_PROCESS("Core dump tot_len=%lu, tasks processed: %d, broken tasks: %d",
|
||||||
@ -671,7 +671,7 @@ esp_err_t esp_core_dump_write_elf(void *frame, core_dump_write_config_t *write_c
|
|||||||
self.elf_stage = ELF_STAGE_PLACE_HEADERS;
|
self.elf_stage = ELF_STAGE_PLACE_HEADERS;
|
||||||
// set initial offset to elf segments data area
|
// set initial offset to elf segments data area
|
||||||
self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self, task_num) * sizeof(elf_phdr);
|
self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self, task_num) * sizeof(elf_phdr);
|
||||||
ret = esp_core_dump_do_write_elf_pass(&self, frame, tasks, task_num);
|
ret = esp_core_dump_do_write_elf_pass(&self, info, tasks, task_num);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) return ret;
|
||||||
write_len += ret;
|
write_len += ret;
|
||||||
ESP_COREDUMP_LOG_PROCESS("============== Headers size = %d bytes ============", write_len);
|
ESP_COREDUMP_LOG_PROCESS("============== Headers size = %d bytes ============", write_len);
|
||||||
@ -679,7 +679,7 @@ esp_err_t esp_core_dump_write_elf(void *frame, core_dump_write_config_t *write_c
|
|||||||
self.elf_stage = ELF_STAGE_PLACE_DATA;
|
self.elf_stage = ELF_STAGE_PLACE_DATA;
|
||||||
// set initial offset to elf segments data area, this is not necessary in this stage, just for pretty debug output
|
// set initial offset to elf segments data area, this is not necessary in this stage, just for pretty debug output
|
||||||
self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self, task_num) * sizeof(elf_phdr);
|
self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self, task_num) * sizeof(elf_phdr);
|
||||||
ret = esp_core_dump_do_write_elf_pass(&self, frame, tasks, task_num);
|
ret = esp_core_dump_do_write_elf_pass(&self, info, tasks, task_num);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) return ret;
|
||||||
write_len += ret;
|
write_len += ret;
|
||||||
ESP_COREDUMP_LOG_PROCESS("=========== Data written size = %d bytes ==========", write_len);
|
ESP_COREDUMP_LOG_PROCESS("=========== Data written size = %d bytes ==========", write_len);
|
||||||
|
@ -222,7 +222,7 @@ static esp_err_t esp_core_dump_flash_write_end(void *priv)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void esp_core_dump_to_flash(void *frame)
|
void esp_core_dump_to_flash(panic_info_t *info)
|
||||||
{
|
{
|
||||||
static core_dump_write_config_t wr_cfg;
|
static core_dump_write_config_t wr_cfg;
|
||||||
static core_dump_write_data_t wr_data;
|
static core_dump_write_data_t wr_data;
|
||||||
@ -250,7 +250,7 @@ void esp_core_dump_to_flash(void *frame)
|
|||||||
wr_cfg.priv = &wr_data;
|
wr_cfg.priv = &wr_data;
|
||||||
|
|
||||||
ESP_COREDUMP_LOGI("Save core dump to flash...");
|
ESP_COREDUMP_LOGI("Save core dump to flash...");
|
||||||
esp_core_dump_write(frame, &wr_cfg);
|
esp_core_dump_write(info, &wr_cfg);
|
||||||
ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
|
ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,12 +454,12 @@ inline void* esp_core_dump_get_current_task_handle()
|
|||||||
return (void*)xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID());
|
return (void*)xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool esp_core_dump_check_task(void *frame,
|
bool esp_core_dump_check_task(panic_info_t *info,
|
||||||
core_dump_task_header_t *task,
|
core_dump_task_header_t *task,
|
||||||
bool* is_current,
|
bool* is_current,
|
||||||
bool* stack_is_valid)
|
bool* stack_is_valid)
|
||||||
{
|
{
|
||||||
XtExcFrame *exc_frame = frame;
|
XtExcFrame *exc_frame = (XtExcFrame *)info->frame;
|
||||||
bool is_curr_task = false;
|
bool is_curr_task = false;
|
||||||
bool stack_is_sane = false;
|
bool stack_is_sane = false;
|
||||||
uint32_t stk_size = 0;
|
uint32_t stk_size = 0;
|
||||||
@ -477,6 +477,9 @@ bool esp_core_dump_check_task(void *frame,
|
|||||||
task->stack_start = (uint32_t)exc_frame;
|
task->stack_start = (uint32_t)exc_frame;
|
||||||
}
|
}
|
||||||
exc_frame->exit = COREDUMP_CURR_TASK_MARKER;
|
exc_frame->exit = COREDUMP_CURR_TASK_MARKER;
|
||||||
|
if (info->pseudo_excause) {
|
||||||
|
exc_frame->exccause += XCHAL_EXCCAUSE_NUM;
|
||||||
|
}
|
||||||
s_extra_info.crashed_task_tcb = (uint32_t)task->tcb_addr;
|
s_extra_info.crashed_task_tcb = (uint32_t)task->tcb_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ static int esp_core_dump_uart_get_char(void) {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void esp_core_dump_to_uart(XtExcFrame *frame)
|
void esp_core_dump_to_uart(panic_info_t *info)
|
||||||
{
|
{
|
||||||
core_dump_write_config_t wr_cfg;
|
core_dump_write_config_t wr_cfg;
|
||||||
core_dump_write_data_t wr_data;
|
core_dump_write_data_t wr_data;
|
||||||
@ -161,7 +161,7 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
|
|||||||
ch = esp_core_dump_uart_get_char();
|
ch = esp_core_dump_uart_get_char();
|
||||||
}
|
}
|
||||||
ESP_COREDUMP_LOGI("Print core dump to uart...");
|
ESP_COREDUMP_LOGI("Print core dump to uart...");
|
||||||
esp_core_dump_write((void*)frame, &wr_cfg);
|
esp_core_dump_write(info, &wr_cfg);
|
||||||
ESP_COREDUMP_LOGI("Core dump has been written to uart.");
|
ESP_COREDUMP_LOGI("Core dump has been written to uart.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user