From 589a3d933688011f7a958ee7dfa3ec32b883134a Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Thu, 9 Jul 2020 23:50:38 +0300 Subject: [PATCH] coredump: Switches to RTOS snapshots walking API --- .../include_core_dump/core_dump_elf.h | 2 +- .../include_core_dump/esp_core_dump_port.h | 34 ++- .../include_core_dump/esp_core_dump_priv.h | 2 - components/espcoredump/src/core_dump_common.c | 186 ++++++------- components/espcoredump/src/core_dump_elf.c | 258 +++++++----------- components/espcoredump/src/core_dump_port.c | 220 +++++++-------- 6 files changed, 318 insertions(+), 384 deletions(-) diff --git a/components/espcoredump/include_core_dump/core_dump_elf.h b/components/espcoredump/include_core_dump/core_dump_elf.h index 1b858d5ac7..bb9f0194cd 100644 --- a/components/espcoredump/include_core_dump/core_dump_elf.h +++ b/components/espcoredump/include_core_dump/core_dump_elf.h @@ -16,6 +16,6 @@ #include "esp_core_dump_priv.h" -esp_err_t esp_core_dump_write_elf(panic_info_t *info, core_dump_write_config_t *write_cfg); +esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg); #endif diff --git a/components/espcoredump/include_core_dump/esp_core_dump_port.h b/components/espcoredump/include_core_dump/esp_core_dump_port.h index 46df6f7edd..afa6de69cd 100644 --- a/components/espcoredump/include_core_dump/esp_core_dump_port.h +++ b/components/espcoredump/include_core_dump/esp_core_dump_port.h @@ -35,8 +35,6 @@ extern "C" { #define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32S2 #endif -#define COREDUMP_TCB_SIZE sizeof(StaticTask_t) - typedef enum { COREDUMP_MEMORY_DRAM, COREDUMP_MEMORY_IRAM, @@ -46,20 +44,31 @@ typedef enum { COREDUMP_MEMORY_START = COREDUMP_MEMORY_DRAM } coredump_region_t; -// Gets RTOS tasks snapshot -uint32_t esp_core_dump_get_tasks_snapshot(core_dump_task_header_t** const tasks, - const uint32_t snapshot_size); +// RTOS tasks snapshots walk API +void esp_core_dump_reset_tasks_snapshots_iter(void); +void *esp_core_dump_get_next_task(void *handle); +bool esp_core_dump_get_task_snapshot(void *handle, core_dump_task_header_t *task, + core_dump_mem_seg_header_t *interrupted_stack); -// Checks TCB consistency -bool esp_core_dump_tcb_addr_is_sane(uint32_t addr); -// Checks stack address -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); void *esp_core_dump_get_current_task_handle(void); -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); uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot, uint32_t* stk_base, uint32_t* stk_len); +static inline uint32_t esp_core_dump_get_tcb_len(void) +{ + if (sizeof(StaticTask_t) % sizeof(uint32_t)) { + return ((sizeof(StaticTask_t) / sizeof(uint32_t) + 1) * sizeof(uint32_t)); + } + return sizeof(StaticTask_t); +} + +static inline uint32_t esp_core_dump_get_memory_len(uint32_t start, uint32_t end) +{ + uint32_t len = end - start; + // Take stack padding into account + return (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); +} + uint16_t esp_core_dump_get_arch_id(void); uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task, void **reg_dump); void esp_core_dump_init_extra_info(void); @@ -82,8 +91,7 @@ int esp_core_dump_sha(mbedtls_sha256_context *ctx, #endif void esp_core_dump_print_checksum(const char* msg, const void* checksum); -#define esp_core_dump_in_isr_context() xPortInterruptedFromISRContext() -uint32_t esp_core_dump_get_isr_stack_end(void); +void esp_core_dump_port_init(panic_info_t *info); #if CONFIG_ESP_COREDUMP_STACK_SIZE > 0 #if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG diff --git a/components/espcoredump/include_core_dump/esp_core_dump_priv.h b/components/espcoredump/include_core_dump/esp_core_dump_priv.h index 14149daaa2..d29d0c0416 100644 --- a/components/espcoredump/include_core_dump/esp_core_dump_priv.h +++ b/components/espcoredump/include_core_dump/esp_core_dump_priv.h @@ -113,8 +113,6 @@ typedef struct _core_dump_write_config_t esp_core_dump_write_end_t end; // this function is called to write data chunk esp_core_dump_flash_write_data_t write; - // number of tasks with corrupted TCBs - uint32_t bad_tasks_num; // pointer to data which are specific for particular core dump emitter void * priv; } core_dump_write_config_t; diff --git a/components/espcoredump/src/core_dump_common.c b/components/espcoredump/src/core_dump_common.c index 8ee07d7a4a..2d3e16a7c3 100644 --- a/components/espcoredump/src/core_dump_common.c +++ b/components/espcoredump/src/core_dump_common.c @@ -20,21 +20,6 @@ const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_commo #if CONFIG_ESP_COREDUMP_DATA_FORMAT_BIN -static inline uint32_t esp_core_dump_get_tcb_len(void) -{ - if (COREDUMP_TCB_SIZE % sizeof(uint32_t)) { - return ((COREDUMP_TCB_SIZE / sizeof(uint32_t) + 1) * sizeof(uint32_t)); - } - return COREDUMP_TCB_SIZE; -} - -static inline uint32_t esp_core_dump_get_memory_len(uint32_t stack_start, uint32_t stack_end) -{ - uint32_t len = stack_end - stack_start; - // Take stack padding into account - return (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); -} - static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg, core_dump_task_header_t *task) { @@ -99,74 +84,67 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_ return ESP_OK; } -static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_config_t *write_cfg) +static esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg) { esp_err_t err; - static core_dump_task_header_t *tasks[CONFIG_ESP_COREDUMP_MAX_TASKS_NUM]; - uint32_t task_num, tcb_sz = esp_core_dump_get_tcb_len(); - uint32_t data_len = 0, task_id; - int curr_task_index = COREDUMP_CURR_TASK_NOT_FOUND; - core_dump_header_t hdr; - core_dump_mem_seg_header_t interrupted_task_stack; - - task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP_COREDUMP_MAX_TASKS_NUM); - ESP_COREDUMP_LOGI("Found tasks: %d!", task_num); + uint32_t tcb_sz = esp_core_dump_get_tcb_len(); + uint32_t data_len = 0, bad_tasks_num = 0; + core_dump_header_t hdr = {0}; + core_dump_task_header_t task_hdr; + core_dump_mem_seg_header_t mem_seg; + void *task = NULL, *cur_task = NULL; // Verifies all tasks in the snapshot - - for (task_id = 0; task_id < task_num; task_id++) { - bool is_current_task = false, stack_is_valid = false; - 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 - if (!tcb_is_valid || !stack_is_valid) { - // If tcb or stack for task is corrupted count task as broken - write_cfg->bad_tasks_num++; + esp_core_dump_reset_tasks_snapshots_iter(); + while ((task = esp_core_dump_get_next_task(task))) { + if (!esp_core_dump_get_task_snapshot(task, &task_hdr, &mem_seg)) { + bad_tasks_num++; + continue; } - if (is_current_task) { - curr_task_index = task_id; // save current crashed task index in the snapshot - ESP_COREDUMP_LOG_PROCESS("Task #%d (TCB:%x) is first crashed task.", - task_id, - tasks[task_id]->tcb_addr); + hdr.tasks_num++; + if (task == esp_core_dump_get_current_task_handle()) { + cur_task = task; + ESP_COREDUMP_LOG_PROCESS("Task %x %x is first crashed task.", cur_task, task_hdr.tcb_addr); } + ESP_COREDUMP_LOG_PROCESS("Stack len = %lu (%x %x)", task_hdr.stack_end-task_hdr.stack_start, + task_hdr.stack_start, task_hdr.stack_end); // Increase core dump size by task stack size uint32_t stk_vaddr, stk_len; - esp_core_dump_get_stack(tasks[task_id], &stk_vaddr, &stk_len); + esp_core_dump_get_stack(&task_hdr, &stk_vaddr, &stk_len); data_len += esp_core_dump_get_memory_len(stk_vaddr, stk_vaddr+stk_len); // Add tcb size data_len += (tcb_sz + sizeof(core_dump_task_header_t)); + if (mem_seg.size > 0) { + ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x", + mem_seg.size, mem_seg.start); + data_len += esp_core_dump_get_memory_len(mem_seg.start, mem_seg.start+mem_seg.size); + data_len += sizeof(core_dump_mem_seg_header_t); + hdr.mem_segs_num++; + } } - - if (esp_core_dump_in_isr_context()) { - interrupted_task_stack.start = tasks[curr_task_index]->stack_start; - 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 - data_len += sizeof(core_dump_mem_seg_header_t); - tasks[curr_task_index]->stack_start = (uint32_t)info->frame; - 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); - // take into account size of the ISR stack - data_len += esp_core_dump_get_memory_len(tasks[curr_task_index]->stack_start, tasks[curr_task_index]->stack_end); - } + ESP_COREDUMP_LOGI("Found tasks: good %d, bad %d, mem segs %d", hdr.tasks_num, bad_tasks_num, hdr.mem_segs_num); // Check if current task TCB is broken - if (curr_task_index == COREDUMP_CURR_TASK_NOT_FOUND) { - ESP_COREDUMP_LOG_PROCESS("The current crashed task is broken."); - curr_task_index = 0; + if (cur_task == NULL) { + ESP_COREDUMP_LOG_PROCESS("The current crashed task is broken."); + cur_task = esp_core_dump_get_next_task(NULL); + if (cur_task == NULL) { + ESP_COREDUMP_LOGE("No valid tasks in the system!"); + return ESP_FAIL; + } } - // Add user memory region header size - data_len += esp_core_dump_get_user_ram_segments() * sizeof(core_dump_mem_seg_header_t); + // Add user memory regions data size for (coredump_region_t i = COREDUMP_MEMORY_START; i < COREDUMP_MEMORY_MAX; i++) { uint32_t start = 0; int data_sz = esp_core_dump_get_user_ram_info(i, &start); - if (data_sz < 0) { - ESP_COREDUMP_LOGE("Invalid memory segment size"); + ESP_COREDUMP_LOGE("Invalid memory segment size!"); return ESP_FAIL; } - if (data_sz > 0) { - data_len += esp_core_dump_get_memory_len(start, start + data_sz); + hdr.mem_segs_num++; + data_len += sizeof(core_dump_mem_seg_header_t) + esp_core_dump_get_memory_len(start, start + data_sz); } } @@ -174,7 +152,7 @@ static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_ data_len += sizeof(core_dump_header_t); ESP_COREDUMP_LOG_PROCESS("Core dump length=%lu, tasks processed: %d, broken tasks: %d", - data_len, task_num, write_cfg->bad_tasks_num); + data_len, hdr.tasks_num, bad_tasks_num); // Prepare write if (write_cfg->prepare) { err = write_cfg->prepare(write_cfg->priv, &data_len); @@ -196,12 +174,6 @@ static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_ // Write header hdr.data_len = data_len; hdr.version = COREDUMP_VERSION; - hdr.tasks_num = task_num; // save all the tasks in snapshot even broken - hdr.mem_segs_num = 0; - if (esp_core_dump_in_isr_context()) { - 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.tcb_sz = tcb_sz; err = write_cfg->write(write_cfg->priv, &hdr, sizeof(core_dump_header_t)); if (err != ESP_OK) { @@ -209,38 +181,56 @@ static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_ return err; } + // Save tasks + esp_core_dump_reset_tasks_snapshots_iter(); // Write first crashed task data first (not always first task in the snapshot) - err = esp_core_dump_save_task(write_cfg, tasks[curr_task_index]); - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to save first crashed task #%d (TCB:%x), error=%d!", - curr_task_index, tasks[curr_task_index]->tcb_addr, err); - return err; + ESP_COREDUMP_LOGD("Save first crashed task %x", cur_task); + if (esp_core_dump_get_task_snapshot(cur_task, &task_hdr, NULL)) { + err = esp_core_dump_save_task(write_cfg, &task_hdr); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to save first crashed task %x, error=%d!", + task_hdr.tcb_addr, err); + return err; + } } - // Write all other tasks in the snapshot - for (task_id = 0; task_id < task_num; task_id++) { + task = NULL; + while ((task = esp_core_dump_get_next_task(task))) { + if (!esp_core_dump_get_task_snapshot(task, &task_hdr, NULL)) + continue; // Skip first crashed task - if (task_id == curr_task_index) { + if (task == cur_task) { continue; } - err = esp_core_dump_save_task(write_cfg, tasks[task_id]); + ESP_COREDUMP_LOGD("Save task %x (TCB:%x, stack:%x..%x)", task, task_hdr.tcb_addr, task_hdr.stack_start, task_hdr.stack_end); + err = esp_core_dump_save_task(write_cfg, &task_hdr); if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to save core dump task #%d (TCB:%x), error=%d!", - task_id, tasks[curr_task_index]->tcb_addr, err); + ESP_COREDUMP_LOGE("Failed to save core dump task %x, error=%d!", + task_hdr.tcb_addr, err); return err; } } - if (esp_core_dump_in_isr_context()) { - err = esp_core_dump_save_mem_segment(write_cfg, &interrupted_task_stack); - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to save interrupted task stack, error=%d!", err); - return err; + + // Save interrupted stacks of the tasks + // Actually there can be tasks interrupted at the same time, one on every core including the crashed one. + task = NULL; + esp_core_dump_reset_tasks_snapshots_iter(); + while ((task = esp_core_dump_get_next_task(task))) { + if (!esp_core_dump_get_task_snapshot(task, &task_hdr, &mem_seg)) + continue; + if (mem_seg.size > 0) { + ESP_COREDUMP_LOG_PROCESS("Save interrupted task stack %lu bytes @ %x", + mem_seg.size, mem_seg.start); + err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to save interrupted task stack, error=%d!", err); + return err; + } } } // save user memory regions if (esp_core_dump_get_user_ram_segments() > 0) { - core_dump_mem_seg_header_t user_ram_stack_size; for (coredump_region_t i = COREDUMP_MEMORY_START; i < COREDUMP_MEMORY_MAX; i++) { uint32_t start = 0; int data_sz = esp_core_dump_get_user_ram_info(i, &start); @@ -251,11 +241,13 @@ static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_ } if (data_sz > 0) { - user_ram_stack_size.start = start; - user_ram_stack_size.size = esp_core_dump_get_memory_len(start, start + data_sz);; - err = esp_core_dump_save_mem_segment(write_cfg, &user_ram_stack_size); + mem_seg.start = start; + mem_seg.size = esp_core_dump_get_memory_len(start, start + data_sz);; + ESP_COREDUMP_LOG_PROCESS("Save user memory region %lu bytes @ %x", + mem_seg.size, mem_seg.start); + err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg); if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to save user memory data, error=%d!", err); + ESP_COREDUMP_LOGE("Failed to save user memory region, error=%d!", err); return err; } } @@ -270,8 +262,8 @@ static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_ return err; } } - if (write_cfg->bad_tasks_num) { - ESP_COREDUMP_LOGE("Found %d broken tasks!", write_cfg->bad_tasks_num); + if (bad_tasks_num) { + ESP_COREDUMP_LOGE("Found %d broken tasks!", bad_tasks_num); } return err; } @@ -280,21 +272,21 @@ static esp_err_t esp_core_dump_write_binary(panic_info_t *info, core_dump_write_ inline void esp_core_dump_write(panic_info_t *info, core_dump_write_config_t *write_cfg) { - esp_core_dump_setup_stack(); - -#ifndef CONFIG_ESP_COREDUMP_ENABLE_TO_NONE +#ifndef CONFIG_ESP_ENABLE_COREDUMP_TO_NONE esp_err_t err = ESP_ERR_NOT_SUPPORTED; + + esp_core_dump_setup_stack(); + esp_core_dump_port_init(info); #if CONFIG_ESP_COREDUMP_DATA_FORMAT_BIN - err = esp_core_dump_write_binary(info, write_cfg); + err = esp_core_dump_write_binary(write_cfg); #elif CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF - err = esp_core_dump_write_elf(info, write_cfg); + err = esp_core_dump_write_elf(write_cfg); #endif if (err != ESP_OK) { ESP_COREDUMP_LOGE("Core dump write binary failed with error=%d", err); } -#endif - esp_core_dump_report_stack_usage(); +#endif } void __attribute__((weak)) esp_core_dump_init(void) diff --git a/components/espcoredump/src/core_dump_elf.c b/components/espcoredump/src/core_dump_elf.c index a1c8a0e600..f5bbbcaa85 100644 --- a/components/espcoredump/src/core_dump_elf.c +++ b/components/espcoredump/src/core_dump_elf.c @@ -22,10 +22,7 @@ #include "elf.h" // for ELF file types -#define ELF_SEG_HEADERS_COUNT(_self_, _task_num_) (uint32_t)((_task_num_) * 2/*stack + tcb*/ \ - + 1/* regs notes */ + 1/* ver info + extra note */ + ((_self_)->interrupted_task.stack_start ? 1 : 0) \ - + /* user mapped variables */ esp_core_dump_get_user_ram_segments()) - +#define ELF_SEG_HEADERS_COUNT(_self_) ((_self_)->segs_count) #define ELF_HLEN 52 #define ELF_CORE_SEC_TYPE 1 @@ -80,8 +77,7 @@ typedef struct _core_dump_elf_t core_dump_elf_version_info_t elf_version_info; uint16_t elf_stage; uint32_t elf_next_data_offset; - uint32_t bad_tasks_num; - core_dump_task_header_t interrupted_task; + uint16_t segs_count; core_dump_write_config_t * write_cfg; } core_dump_elf_t; @@ -167,6 +163,7 @@ static int elf_add_segment(core_dump_elf_t *self, ALIGN(4, data_len); if (self->elf_stage == ELF_STAGE_CALC_SPACE) { + self->segs_count++; return data_len + sizeof(elf_phdr); } if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { @@ -295,61 +292,15 @@ static int elf_add_tcb(core_dump_elf_t *self, core_dump_task_header_t *task) ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid task pointer."); // add task tcb data into program segment of ELF ESP_COREDUMP_LOG_PROCESS("Add TCB for task 0x%x: addr 0x%x, sz %u", - task->tcb_addr, task->tcb_addr, COREDUMP_TCB_SIZE); + task->tcb_addr, task->tcb_addr, + esp_core_dump_get_tcb_len()); int ret = elf_add_segment(self, PT_LOAD, (uint32_t)task->tcb_addr, (void*)task->tcb_addr, - COREDUMP_TCB_SIZE); + esp_core_dump_get_tcb_len()); return ret; } -// get index of current crashed task (not always first task in the snapshot) -static int elf_get_current_task_index(core_dump_task_header_t** tasks, - uint32_t task_num) -{ - int task_id; - int curr_task_index = COREDUMP_CURR_TASK_NOT_FOUND; - void* curr_task_handle = esp_core_dump_get_current_task_handle(); - - // get index of current crashed task (not always first task in the snapshot) - for (task_id = 0; task_id < task_num; task_id++) { - bool tcb_is_valid = esp_core_dump_tcb_addr_is_sane((uint32_t)tasks[task_id]->tcb_addr); - bool stack_is_valid = esp_core_dump_check_stack(tasks[task_id]->stack_start, tasks[task_id]->stack_end); - if (stack_is_valid && tcb_is_valid && curr_task_handle == tasks[task_id]->tcb_addr) { - curr_task_index = task_id; // save current crashed task index in the snapshot - ESP_COREDUMP_LOG_PROCESS("Task #%d, (TCB:%x) is current crashed task.", - task_id, - tasks[task_id]->tcb_addr); - } - } - return curr_task_index; -} - -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_current = false; - - ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid input data."); - - if (self->elf_stage == ELF_STAGE_CALC_SPACE) { - // Check if task tcb is corrupted (do not update the header, save as is) - task_is_valid = esp_core_dump_check_task(info, task, &task_is_current, NULL); - if (!task_is_valid) { - if (task_is_current) { - ESP_COREDUMP_LOG_PROCESS("Task has incorrect (TCB:%x)!", - task->tcb_addr); - } else { - ESP_COREDUMP_LOG_PROCESS("The current crashed task has broken (TCB:%x)!", - task->tcb_addr); - } - self->bad_tasks_num++; - } - } - // extract registers from stack and apply elf data size for stack section - return elf_add_regs(self, task); -} - static int elf_process_task_tcb(core_dump_elf_t *self, core_dump_task_header_t *task) { int ret = ELF_PROC_ERR_OTHER; @@ -358,10 +309,7 @@ static int elf_process_task_tcb(core_dump_elf_t *self, core_dump_task_header_t * // save tcb of the task as is and apply segment size ret = elf_add_tcb(self, task); - if (ret > 0) { - ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) processing completed.", - task->tcb_addr); - } else { + if (ret <= 0) { ESP_COREDUMP_LOGE("Task (TCB:%x) processing failure = %d", task->tcb_addr, ret); @@ -376,11 +324,7 @@ static int elf_process_task_stack(core_dump_elf_t *self, core_dump_task_header_t ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid input data."); ret = elf_add_stack(self, task); - if (ret > 0) { - ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), (Stack:%x) stack is processed.", - task->tcb_addr, - task->stack_start); - } else { + if (ret <= 0) { ESP_COREDUMP_LOGE("Task (TCB:%x), (Stack:%x), stack processing failure = %d.", task->tcb_addr, task->stack_start, @@ -407,6 +351,7 @@ static int elf_process_note_segment(core_dump_elf_t *self, int notes_size) self->elf_next_data_offset += notes_size; return sizeof(seg_hdr); } else if (self->elf_stage == ELF_STAGE_CALC_SPACE) { + self->segs_count++; notes_size += sizeof(seg_hdr); } else { // in "Place Data" phase segment body is been already filled by other functions @@ -417,96 +362,107 @@ static int elf_process_note_segment(core_dump_elf_t *self, int notes_size) return (int)notes_size; } -static int elf_process_tasks_regs(core_dump_elf_t *self, panic_info_t *info, - core_dump_task_header_t** tasks, - uint32_t task_num) +static int elf_process_tasks_regs(core_dump_elf_t *self) { - int len = 0; + void *task; + int len = 0, ret; + core_dump_task_header_t task_hdr; - uint32_t curr_task_index = elf_get_current_task_index(tasks, task_num); - if (curr_task_index == COREDUMP_CURR_TASK_NOT_FOUND) { - ESP_COREDUMP_LOG_PROCESS("The current crashed task is broken."); - curr_task_index = 0; - } - - // place current task dump first - int ret = elf_process_task_regdump(self, info, tasks[curr_task_index]); - if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { - // 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); - } else { - ELF_CHECK_ERR((ret > 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", curr_task_index, ret); - } - len += ret; - - // processes PR_STATUS and register dump for each task - // each call to the processing function appends PR_STATUS note into note segment - // and writes data or updates the segment note header accordingly (if phdr is set) - for (int task_id = 0; task_id < task_num; task_id++) { - if (task_id == curr_task_index) { - continue; // skip current task (already processed) - } - ret = elf_process_task_regdump(self, info, tasks[task_id]); + esp_core_dump_reset_tasks_snapshots_iter(); + task = esp_core_dump_get_current_task_handle(); + if (esp_core_dump_get_task_snapshot(task, &task_hdr, NULL)) { + // place current task dump first + ret = elf_add_regs(self, &task_hdr); if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { // 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 %x, PR_STATUS write failed, return (%d).", task, ret); } else { - ELF_CHECK_ERR((ret > 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", task_id, ret); + ELF_CHECK_ERR((ret > 0), ret, "Task %x, PR_STATUS write failed, return (%d).", task, ret); } len += ret; } - ret = elf_process_note_segment(self, len); + // processes PR_STATUS and register dump for each task + // each call to the processing function appends PR_STATUS note into note segment + // and writes data or updates the segment note header accordingly (if phdr is set) + task = NULL; + while ((task = esp_core_dump_get_next_task(task))) { + if (task == esp_core_dump_get_current_task_handle()) { + continue; // skip current task (already processed) + } + if (esp_core_dump_get_task_snapshot(task, &task_hdr, NULL)) { + ret = elf_add_regs(self, &task_hdr); + if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { + // when writing segments headers this function writes nothing + ELF_CHECK_ERR((ret >= 0), ret, "Task %x, PR_STATUS write failed, return (%d).", task, ret); + } else { + ELF_CHECK_ERR((ret > 0), ret, "Task %x, PR_STATUS write failed, return (%d).", task, ret); + } + len += ret; + } + } + ret = elf_process_note_segment(self, len); // tasks regs note ELF_CHECK_ERR((ret > 0), ret, "PR_STATUS note segment processing failure, returned(%d).", ret); - - if (esp_core_dump_in_isr_context()) { - if (self->elf_stage == ELF_STAGE_CALC_SPACE) { - // in this stage we can safely replace task's stack with IRQ's one - // if task had corrupted stack it was replaced with fake one in HW dependent code called by elf_process_task_regdump() - // in the "write data" stage registers from ISR's stack will be saved in PR_STATUS - self->interrupted_task.stack_start = tasks[curr_task_index]->stack_start; - self->interrupted_task.stack_end = tasks[curr_task_index]->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)info->frame, (uint32_t)info->frame, isr_stk_end); - tasks[curr_task_index]->stack_start = (uint32_t)info->frame; - tasks[curr_task_index]->stack_end = isr_stk_end; - } - - // actually we write current task's stack here which was replaced by ISR's - len = elf_add_stack(self, &self->interrupted_task); - ELF_CHECK_ERR((len > 0), len, "Interrupted task stack write failed, return (%d).", len); - ret += len; - } return ret; } -static int elf_write_tasks_data(core_dump_elf_t *self, panic_info_t *info, - core_dump_task_header_t** tasks, - uint32_t task_num) +static int elf_save_task(core_dump_elf_t *self, core_dump_task_header_t *task) { int elf_len = 0; - int task_id; + + int ret = elf_process_task_tcb(self, task); + ELF_CHECK_ERR((ret > 0), ret, + "Task %x, TCB write failed, return (%d).", task->tcb_addr, ret); + elf_len += ret; + ret = elf_process_task_stack(self, task); + ELF_CHECK_ERR((ret != ELF_PROC_ERR_WRITE_FAIL), ELF_PROC_ERR_WRITE_FAIL, + "Task %x, stack write failed, return (%d).", task->tcb_addr, ret); + elf_len += ret; + return elf_len; +} + +static int elf_write_tasks_data(core_dump_elf_t *self) +{ + int elf_len = 0; + void *task; + core_dump_task_header_t task_hdr; + core_dump_mem_seg_header_t interrupted_stack; int ret = ELF_PROC_ERR_OTHER; + uint16_t tasks_num = 0, bad_tasks_num = 0; - ELF_CHECK_ERR((info && tasks), ELF_PROC_ERR_OTHER, "Invalid input data."); - - ret = elf_process_tasks_regs(self, info, tasks, task_num); + bad_tasks_num = 0; + ESP_COREDUMP_LOG_PROCESS("================ Processing task registers ================"); + ret = elf_process_tasks_regs(self); ELF_CHECK_ERR((ret > 0), ret, "Tasks regs addition failed, return (%d).", ret); elf_len += ret; - self->bad_tasks_num = 0; // reset bad task counter + ESP_COREDUMP_LOG_PROCESS("================ Processing task data ================"); // processes all task's stack data and writes segment data into partition // if flash configuration is set - for (task_id = 0; task_id < task_num; task_id++) { - ret = elf_process_task_tcb(self, tasks[task_id]); + task = NULL; + esp_core_dump_reset_tasks_snapshots_iter(); + while ((task = esp_core_dump_get_next_task(task))) { + tasks_num++; + if (!esp_core_dump_get_task_snapshot(task, &task_hdr, &interrupted_stack)) { + bad_tasks_num++; + continue; + } + ret = elf_save_task(self, &task_hdr); ELF_CHECK_ERR((ret > 0), ret, - "Task #%d, TCB write failed, return (%d).", task_id, ret); - elf_len += ret; - ret = elf_process_task_stack(self, tasks[task_id]); - ELF_CHECK_ERR((ret != ELF_PROC_ERR_WRITE_FAIL), ELF_PROC_ERR_WRITE_FAIL, - "Task #%d, stack write failed, return (%d).", task_id, ret); + "Task %x, TCB write failed, return (%d).", task, ret); elf_len += ret; + if (interrupted_stack.size > 0) { + ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x", + interrupted_stack.size, interrupted_stack.start); + ret = elf_add_segment(self, PT_LOAD, + (uint32_t)interrupted_stack.start, + (void*)interrupted_stack.start, + (uint32_t)interrupted_stack.size); + ELF_CHECK_ERR((ret > 0), ret, "Interrupted task stack write failed, return (%d).", ret); + elf_len += ret; + } } + ESP_COREDUMP_LOG_PROCESS("Found %d bad task out of %d", bad_tasks_num, tasks_num); return elf_len; } @@ -539,6 +495,7 @@ static int elf_write_core_dump_info(core_dump_elf_t *self) { void *extra_info; + ESP_COREDUMP_LOG_PROCESS("================ Processing coredump info ================"); int data_len = (int)sizeof(self->elf_version_info.app_elf_sha256); data_len = esp_ota_get_app_elf_sha256((char*)self->elf_version_info.app_elf_sha256, (size_t)data_len); ESP_COREDUMP_LOG_PROCESS("Application SHA256='%s', length=%d.", @@ -572,13 +529,11 @@ static int elf_write_core_dump_info(core_dump_elf_t *self) return ret; } -static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, panic_info_t *info, - core_dump_task_header_t** tasks, - uint32_t task_num) +static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self) { int tot_len = 0; - int data_sz = elf_write_file_header(self, ELF_SEG_HEADERS_COUNT(self, task_num)); + int data_sz = elf_write_file_header(self, ELF_SEG_HEADERS_COUNT(self)); if (self->elf_stage == ELF_STAGE_PLACE_DATA) { ELF_CHECK_ERR((data_sz >= 0), data_sz, "ELF header writing error, returned (%d).", data_sz); } else { @@ -586,7 +541,7 @@ static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, panic_info_t * } tot_len += data_sz; // Calculate whole size include headers for all tasks and main elf header - data_sz = elf_write_tasks_data(self, info, tasks, task_num); + data_sz = elf_write_tasks_data(self); ELF_CHECK_ERR((data_sz > 0), data_sz, "ELF Size writing error, returned (%d).", data_sz); tot_len += data_sz; @@ -604,32 +559,25 @@ static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, panic_info_t * return tot_len; } -esp_err_t esp_core_dump_write_elf(panic_info_t *info, core_dump_write_config_t *write_cfg) +esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg) { esp_err_t err = ESP_OK; - static core_dump_task_header_t *tasks[CONFIG_ESP_COREDUMP_MAX_TASKS_NUM]; static core_dump_elf_t self; - core_dump_header_t dump_hdr; - uint32_t tcb_sz = COREDUMP_TCB_SIZE, task_num; + static core_dump_header_t dump_hdr; int tot_len = sizeof(dump_hdr); int write_len = sizeof(dump_hdr); - ELF_CHECK_ERR((info && write_cfg), ESP_ERR_INVALID_ARG, "Invalid input data."); - - task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP_COREDUMP_MAX_TASKS_NUM); - ESP_COREDUMP_LOGI("Found tasks: %d", task_num); + ELF_CHECK_ERR((write_cfg), ESP_ERR_INVALID_ARG, "Invalid input data."); self.write_cfg = write_cfg; - esp_core_dump_init_extra_info(); // On first pass (do not write actual data), but calculate data length needed to allocate memory self.elf_stage = ELF_STAGE_CALC_SPACE; ESP_COREDUMP_LOG_PROCESS("================= Calc data size ==============="); - int ret = esp_core_dump_do_write_elf_pass(&self, info, tasks, task_num); + int ret = esp_core_dump_do_write_elf_pass(&self); if (ret < 0) return ret; tot_len += ret; - ESP_COREDUMP_LOG_PROCESS("Core dump tot_len=%lu, tasks processed: %d, broken tasks: %d", - tot_len, task_num, self.bad_tasks_num); + ESP_COREDUMP_LOG_PROCESS("Core dump tot_len=%lu", tot_len); ESP_COREDUMP_LOG_PROCESS("============== Data size = %d bytes ============", tot_len); // Prepare write elf @@ -650,16 +598,12 @@ esp_err_t esp_core_dump_write_elf(panic_info_t *info, core_dump_write_config_t * } } - write_cfg->bad_tasks_num = self.bad_tasks_num; - // Write core dump header - ALIGN(4, tot_len); - ALIGN(4, tcb_sz); dump_hdr.data_len = tot_len; dump_hdr.version = COREDUMP_VERSION; - dump_hdr.tasks_num = task_num; // broken tasks are repaired - dump_hdr.tcb_sz = tcb_sz; - dump_hdr.mem_segs_num = 0; + dump_hdr.tasks_num = 0; // unused in ELF format + dump_hdr.tcb_sz = 0; // unused in ELF format + dump_hdr.mem_segs_num = 0; // unused in ELF format err = write_cfg->write(write_cfg->priv, (void*)&dump_hdr, sizeof(core_dump_header_t)); @@ -670,16 +614,16 @@ esp_err_t esp_core_dump_write_elf(panic_info_t *info, core_dump_write_config_t * self.elf_stage = ELF_STAGE_PLACE_HEADERS; // 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); - ret = esp_core_dump_do_write_elf_pass(&self, info, tasks, task_num); + self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self) * sizeof(elf_phdr); + ret = esp_core_dump_do_write_elf_pass(&self); if (ret < 0) return ret; write_len += ret; ESP_COREDUMP_LOG_PROCESS("============== Headers size = %d bytes ============", write_len); 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 - 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, info, tasks, task_num); + self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self) * sizeof(elf_phdr); + ret = esp_core_dump_do_write_elf_pass(&self); if (ret < 0) return ret; write_len += ret; ESP_COREDUMP_LOG_PROCESS("=========== Data written size = %d bytes ==========", write_len); diff --git a/components/espcoredump/src/core_dump_port.c b/components/espcoredump/src/core_dump_port.c index ff316c29a8..515eec20ab 100644 --- a/components/espcoredump/src/core_dump_port.c +++ b/components/espcoredump/src/core_dump_port.c @@ -148,6 +148,14 @@ static uint32_t s_fake_stacks_num; static xtensa_extra_info_t s_extra_info; +static XtExcFrame *s_exc_frame; + +static bool esp_core_dump_check_task(core_dump_task_header_t *task); +static bool esp_core_dump_check_stack(core_dump_task_header_t *task); +static void esp_core_dump_switch_task_stack_to_isr(core_dump_task_header_t *task, + core_dump_mem_seg_header_t *stack); + + #if ESP_COREDUMP_STACK_SIZE > 0 uint8_t s_coredump_stack[ESP_COREDUMP_STACK_SIZE]; uint8_t *s_core_dump_sp; @@ -290,6 +298,20 @@ uint32_t esp_core_dump_checksum_finish(core_dump_write_data_t* wr_data, void** c return chs_len; } +inline void esp_core_dump_port_init(panic_info_t *info) +{ + s_extra_info.crashed_task_tcb = COREDUMP_CURR_TASK_MARKER; + // Initialize exccause register to default value (required if current task corrupted) + s_extra_info.exccause.reg_val = COREDUMP_INVALID_CAUSE_VALUE; + s_extra_info.exccause.reg_index = EXCCAUSE; + + s_exc_frame = (void *)info->frame; + s_exc_frame->exit = COREDUMP_CURR_TASK_MARKER; + if (info->pseudo_excause) { + s_exc_frame->exccause += XCHAL_EXCCAUSE_NUM; + } +} + inline uint16_t esp_core_dump_get_arch_id() { return COREDUMP_EM_XTENSA; @@ -307,50 +329,65 @@ inline bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz) ; } -inline bool esp_core_dump_task_stack_end_is_sane(uint32_t sp) +static inline bool esp_core_dump_task_stack_end_is_sane(uint32_t sp) { //TODO: currently core dump supports stacks in DRAM only, external SRAM not supported yet return esp_ptr_in_dram((void *)sp); } -inline bool esp_core_dump_tcb_addr_is_sane(uint32_t addr) +static inline bool esp_core_dump_tcb_addr_is_sane(uint32_t addr) { - return esp_core_dump_mem_seg_is_sane(addr, COREDUMP_TCB_SIZE); + return esp_core_dump_mem_seg_is_sane(addr, esp_core_dump_get_tcb_len()); } -uint32_t esp_core_dump_get_tasks_snapshot(core_dump_task_header_t** const tasks, - const uint32_t snapshot_size) +inline void esp_core_dump_reset_tasks_snapshots_iter(void) { - static TaskSnapshot_t s_tasks_snapshots[CONFIG_ESP_COREDUMP_MAX_TASKS_NUM]; - uint32_t tcb_sz; // unused + s_fake_stacks_num = 0; +} - /* implying that TaskSnapshot_t extends core_dump_task_header_t by adding extra fields */ - _Static_assert(sizeof(TaskSnapshot_t) >= sizeof(core_dump_task_header_t), "FreeRTOS task snapshot binary compatibility issue!"); +inline void *esp_core_dump_get_next_task(void *handle) +{ + return pxTaskGetNext(handle); +} - uint32_t task_num = (uint32_t)uxTaskGetSnapshotAll(s_tasks_snapshots, - (UBaseType_t)snapshot_size, - (UBaseType_t*)&tcb_sz); - for (uint32_t i = 0; i < task_num; i++) { - tasks[i] = (core_dump_task_header_t *)&s_tasks_snapshots[i]; +bool esp_core_dump_get_task_snapshot(void *handle, core_dump_task_header_t *task, + core_dump_mem_seg_header_t *interrupted_stack) +{ + TaskSnapshot_t rtos_snapshot; + + if (interrupted_stack != NULL) { + interrupted_stack->size = 0; } - return task_num; + + vTaskGetSnapshot(handle, &rtos_snapshot); + task->tcb_addr = handle; + task->stack_start = (uint32_t)rtos_snapshot.pxTopOfStack; + task->stack_end = (uint32_t)rtos_snapshot.pxEndOfStack; + + if (!xPortInterruptedFromISRContext() && handle == esp_core_dump_get_current_task_handle()) { + // Set correct stack top for current task; only modify if we came from the task, + // and not an ISR that crashed. + task->stack_start = (uint32_t)s_exc_frame; + } + if (!esp_core_dump_check_task(task)) { + ESP_COREDUMP_LOG_PROCESS("Task %x is broken!", handle); + return false; + } + if (handle == esp_core_dump_get_current_task_handle()) { + ESP_COREDUMP_LOG_PROCESS("Crashed task %x", handle); + s_extra_info.crashed_task_tcb = (uint32_t)handle; + if (xPortInterruptedFromISRContext()) { + esp_core_dump_switch_task_stack_to_isr(task, interrupted_stack); + } + } + return true; } -inline uint32_t esp_core_dump_get_isr_stack_end(void) -{ - return (uint32_t)((uint8_t *)&port_IntStack + (xPortGetCoreID()+1)*configISR_STACK_SIZE); -} - -uint32_t esp_core_dump_get_stack(core_dump_task_header_t *task_snapshot, +inline uint32_t esp_core_dump_get_stack(core_dump_task_header_t *task, uint32_t *stk_vaddr, uint32_t *stk_len) { - if (task_snapshot->stack_end > task_snapshot->stack_start) { - *stk_len = task_snapshot->stack_end - task_snapshot->stack_start; - *stk_vaddr = task_snapshot->stack_start; - } else { - *stk_len = task_snapshot->stack_start - task_snapshot->stack_end; - *stk_vaddr = task_snapshot->stack_end; - } + *stk_len = task->stack_end - task->stack_start; + *stk_vaddr = task->stack_start; if (*stk_vaddr >= COREDUMP_FAKE_STACK_START && *stk_vaddr < COREDUMP_FAKE_STACK_LIMIT) { return (uint32_t)&s_fake_stack_frame; } @@ -366,6 +403,18 @@ static void *esp_core_dump_get_fake_stack(uint32_t *stk_len) return (uint8_t*)COREDUMP_FAKE_STACK_START + sizeof(s_fake_stack_frame)*s_fake_stacks_num++; } +static void esp_core_dump_switch_task_stack_to_isr(core_dump_task_header_t *task, core_dump_mem_seg_header_t *stack) +{ + if (stack != NULL) { + stack->start = task->stack_start; + stack->size = esp_core_dump_get_memory_len(task->stack_start, task->stack_end); + } + uint32_t isr_stk_end = (uint32_t)((uint8_t *)&port_IntStack + (xPortGetCoreID()+1)*configISR_STACK_SIZE); + task->stack_start = (uint32_t)s_exc_frame; + task->stack_end = isr_stk_end; + ESP_COREDUMP_LOG_PROCESS("Switched task %x to ISR stack [%x...%x]", task->tcb_addr, task->stack_start, task->stack_end); +} + static core_dump_reg_pair_t *esp_core_dump_get_epc_regs(core_dump_reg_pair_t* src) { uint32_t* reg_ptr = (uint32_t*)src; @@ -489,37 +538,18 @@ inline void* esp_core_dump_get_current_task_handle() return (void*)xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID()); } -bool esp_core_dump_check_task(panic_info_t *info, - core_dump_task_header_t *task, - bool* is_current, - bool* stack_is_valid) +static bool esp_core_dump_check_task(core_dump_task_header_t *task) { - XtExcFrame *exc_frame = (XtExcFrame *)info->frame; - bool is_curr_task = false; - bool stack_is_sane = false; uint32_t stk_size = 0; + bool stack_is_valid = false; if (!esp_core_dump_tcb_addr_is_sane((uint32_t)task->tcb_addr)) { ESP_COREDUMP_LOG_PROCESS("Bad TCB addr=%x!", task->tcb_addr); return false; } - is_curr_task = task->tcb_addr == esp_core_dump_get_current_task_handle(); - if (is_curr_task) { - // Set correct stack top for current task; only modify if we came from the task, - // and not an ISR that crashed. - if (!xPortInterruptedFromISRContext()) { - task->stack_start = (uint32_t)exc_frame; - } - 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; - } - - stack_is_sane = esp_core_dump_check_stack(task->stack_start, task->stack_end); - if (!stack_is_sane) { + stack_is_valid = esp_core_dump_check_stack(task); + if (!stack_is_valid) { // Skip saving of invalid task if stack corrupted ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), stack is corrupted (%x, %x)", task->tcb_addr, @@ -532,80 +562,42 @@ bool esp_core_dump_check_task(panic_info_t *info, task->stack_start, task->stack_end); } - - if (is_curr_task) { - if (!stack_is_sane) - ESP_COREDUMP_LOG_PROCESS("Current task 0x%x is broken!", task->tcb_addr); - ESP_COREDUMP_LOG_PROCESS("Current task (TCB:%x), EXIT/PC/PS/A0/SP %x %x %x %x %x", - task->tcb_addr, - exc_frame->exit, - exc_frame->pc, - exc_frame->ps, - exc_frame->a0, - exc_frame->a1); + XtSolFrame *sol_frame = (XtSolFrame *)task->stack_start; + if (sol_frame->exit == 0) { + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), EXIT/PC/PS/A0/SP %x %x %x %x %x", + task->tcb_addr, + sol_frame->exit, + sol_frame->pc, + sol_frame->ps, + sol_frame->a0, + sol_frame->a1); } else { - XtSolFrame *task_frame = (XtSolFrame *)task->stack_start; - if (stack_is_sane) { - if (task_frame->exit == 0) { - ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), EXIT/PC/PS/A0/SP %x %x %x %x %x", - task->tcb_addr, - task_frame->exit, - task_frame->pc, - task_frame->ps, - task_frame->a0, - task_frame->a1); - } else { +// to avoid warning that 'exc_frame' is unused when ESP_COREDUMP_LOG_PROCESS does nothing #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH - XtExcFrame *task_frame2 = (XtExcFrame *)task->stack_start; - task_frame2->exccause = COREDUMP_INVALID_CAUSE_VALUE; - ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) EXIT/PC/PS/A0/SP %x %x %x %x %x", - task->tcb_addr, - task_frame2->exit, - task_frame2->pc, - task_frame2->ps, - task_frame2->a0, - task_frame2->a1); + XtExcFrame *exc_frame = (XtExcFrame *)task->stack_start; + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) EXIT/PC/PS/A0/SP %x %x %x %x %x", + task->tcb_addr, + exc_frame->exit, + exc_frame->pc, + exc_frame->ps, + exc_frame->a0, + exc_frame->a1); #endif - } - } else { - ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), stack_start=%x is incorrect, skip registers printing.", - task->tcb_addr, task->stack_start); - - } } - - if (is_current) { - *is_current = is_curr_task; - } - if (stack_is_valid) { - *stack_is_valid = stack_is_sane; - } - return true; } -bool esp_core_dump_check_stack(uint32_t stack_start, uint32_t stack_end) +static bool esp_core_dump_check_stack(core_dump_task_header_t *task) { - uint32_t len = stack_end - stack_start; - bool task_is_valid = false; // Check task's stack - if (!esp_stack_ptr_is_sane(stack_start) || !esp_core_dump_task_stack_end_is_sane(stack_end) || - (len > COREDUMP_MAX_TASK_STACK_SIZE)) { + if (!esp_stack_ptr_is_sane(task->stack_start) || !esp_core_dump_task_stack_end_is_sane(task->stack_end) || + (task->stack_start >= task->stack_end) || + ((task->stack_end-task->stack_start) > COREDUMP_MAX_TASK_STACK_SIZE)) { // Check if current task stack is corrupted - task_is_valid = false; - } else { - ESP_COREDUMP_LOG_PROCESS("Stack len = %lu (%x %x)", len, stack_start, stack_end); - task_is_valid = true; + ESP_COREDUMP_LOG_PROCESS("Invalid stack (%x...%x)!", task->stack_start, task->stack_end); + return false; } - return task_is_valid; -} - -void esp_core_dump_init_extra_info() -{ - s_extra_info.crashed_task_tcb = COREDUMP_CURR_TASK_MARKER; - // Initialize exccause register to default value (required if current task corrupted) - s_extra_info.exccause.reg_val = COREDUMP_INVALID_CAUSE_VALUE; - s_extra_info.exccause.reg_index = EXCCAUSE; + return true; } uint32_t esp_core_dump_get_extra_info(void **info)