mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
espcoredump: On device core dump parsing to generate summary
This commit is contained in:
parent
ab8b292407
commit
9928f44894
@ -5,20 +5,23 @@
|
||||
"src/core_dump_elf.c"
|
||||
"src/core_dump_binary.c")
|
||||
|
||||
set(includes "include")
|
||||
set(priv_includes "include_core_dump")
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||
set(srcs ${srcs} "src/port/xtensa/core_dump_port.c")
|
||||
set(priv_includes ${priv_includes} "include_core_dump/port/xtensa")
|
||||
list(APPEND srcs "src/port/xtensa/core_dump_port.c")
|
||||
list(APPEND includes "include/port/xtensa")
|
||||
list(APPEND priv_includes "include_core_dump/port/xtensa")
|
||||
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
|
||||
set(srcs ${srcs} "src/port/riscv/core_dump_port.c")
|
||||
set(priv_includes ${priv_includes} "include_core_dump/port/riscv")
|
||||
list(APPEND srcs "src/port/riscv/core_dump_port.c")
|
||||
list(APPEND includes "include/port/riscv")
|
||||
list(APPEND priv_includes "include_core_dump/port/riscv")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS "include"
|
||||
INCLUDE_DIRS ${includes}
|
||||
PRIV_INCLUDE_DIRS ${priv_includes}
|
||||
LDFRAGMENTS linker.lf
|
||||
PRIV_REQUIRES spi_flash app_update mbedtls esp_rom soc)
|
||||
|
@ -5,10 +5,12 @@ COMPONENT_ADD_LDFRAGMENTS += linker.lf
|
||||
|
||||
ifdef CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
COMPONENT_SRCDIRS += src/port/xtensa
|
||||
COMPONENT_ADD_INCLUDEDIRS += include/port/xtensa
|
||||
COMPONENT_PRIV_INCLUDEDIRS += include_core_dump/port/xtensa
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
COMPONENT_SRCDIRS += src/port/riscv
|
||||
COMPONENT_ADD_INCLUDEDIRS += include/port/riscv
|
||||
COMPONENT_PRIV_INCLUDEDIRS += include_core_dump/port/riscv
|
||||
endif
|
||||
|
@ -17,11 +17,37 @@
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "esp_core_dump_summary_extra_info.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#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;
|
||||
|
||||
/**
|
||||
* @brief Core dump summary, Most meaningful contents of the core dump
|
||||
* are accommodated in this structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t exc_tcb; /*!< TCB pointer to the task causing exception */
|
||||
char exc_task[16]; /*!< Name of the task that caused exception */
|
||||
uint32_t exc_pc; /*!< Program counter for exception */
|
||||
esp_core_dump_bt_info_t exc_bt_info; /*!< Backtrace information for task causing exception */
|
||||
uint32_t core_dump_version; /*!< Core dump version */
|
||||
uint8_t app_elf_sha256[APP_ELF_SHA256_SZ]; /*!< Crashing application's SHA256 sum as a string */
|
||||
esp_core_dump_summary_extra_info_t ex_info; /*!< Architecture specific extra data */
|
||||
} esp_core_dump_summary_t;
|
||||
|
||||
/**************************************************************************************/
|
||||
/******************************** EXCEPTION MODE API **********************************/
|
||||
/**************************************************************************************/
|
||||
@ -111,6 +137,15 @@ 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);
|
||||
|
||||
/**
|
||||
* @brief Get the summary of a core dump. This function works only with ELF format core dumps.
|
||||
*
|
||||
* @param summary Summary of the core dump
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_core_dump_get_summary(esp_core_dump_summary_t *summary);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -0,0 +1,35 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief RISC-V architecture specific extra information
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t mstatus; /* Machine Status */
|
||||
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 */
|
||||
} esp_core_dump_summary_extra_info_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,38 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <xtensa/config/core-isa.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define EPCx_REGISTER_COUNT XCHAL_NUM_INTLEVELS
|
||||
|
||||
/**
|
||||
* @brief Xtensa architecture specific extra information
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t exc_cause; /*!< Cause of exception */
|
||||
uint32_t exc_vaddr; /*!< Virtual address of exception */
|
||||
uint32_t exc_a[16]; /*!< a register set when the exception caused */
|
||||
uint32_t epcx[EPCx_REGISTER_COUNT]; /*!< PC register address at exception level(1 to 7) */
|
||||
uint8_t epcx_reg_bits; /*!< Bit mask of available EPCx registers */
|
||||
} esp_core_dump_summary_extra_info_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -30,6 +30,7 @@
|
||||
#include "esp_app_format.h"
|
||||
#include "esp_core_dump_types.h"
|
||||
#include "esp_core_dump_port_impl.h"
|
||||
#include "esp_core_dump.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -164,6 +165,33 @@ void esp_core_dump_port_set_crashed_tcb(uint32_t handle);
|
||||
*/
|
||||
uint32_t esp_core_dump_get_extra_info(void **info);
|
||||
|
||||
/**
|
||||
* @brief Parse extra information into summary
|
||||
*
|
||||
* @param summary Pointer to core dump summary structure
|
||||
* @param ei_data Pointer to data of EXTRA_INFO note read from flash
|
||||
*/
|
||||
void esp_core_dump_summary_parse_extra_info(esp_core_dump_summary_t *summary, void *ei_data);
|
||||
|
||||
/**
|
||||
* @brief Parse exception registers into summary
|
||||
*
|
||||
* @param summary Pointer to core dump summary structure
|
||||
* @param stack_data Pointer to data of crashed task's stack read from flash
|
||||
*/
|
||||
void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void *stack_data);
|
||||
|
||||
/**
|
||||
* @brief Parse backtrace into bt_info
|
||||
*
|
||||
* @param bt_info Pointer to store backtrace info
|
||||
* @param vaddr Pointer to crashed task's stack vaddr
|
||||
* @param paddr Pointe to crashed task's stack paddr
|
||||
* @param stack_size Stack size
|
||||
*/
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "core_dump_checksum.h"
|
||||
#include "core_dump_elf.h"
|
||||
@ -644,4 +646,131 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
size_t out_size;
|
||||
assert (core_data_handle);
|
||||
assert(map_addr);
|
||||
|
||||
/* Find the partition that could potentially contain a (previous) core dump. */
|
||||
const esp_partition_t *core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
||||
ESP_PARTITION_SUBTYPE_DATA_COREDUMP,
|
||||
NULL);
|
||||
if (!core_part) {
|
||||
ESP_COREDUMP_LOGE("Core dump partition not found!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
if (core_part->size < sizeof(uint32_t)) {
|
||||
ESP_COREDUMP_LOGE("Core dump partition too small!");
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
/* Data read from the mmapped core dump partition will be garbage if flash
|
||||
* encryption is enabled in hardware and core dump partition is not encrypted
|
||||
*/
|
||||
if (esp_flash_encryption_enabled() && !core_part->encrypted) {
|
||||
ESP_COREDUMP_LOGE("Flash encryption enabled in hardware and core dump partition is not encrypted!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
/* Read the size of the core dump file from the partition */
|
||||
esp_err_t ret = esp_partition_read(core_part, 0, &out_size, sizeof(uint32_t));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to read core dump data size");
|
||||
return ret;
|
||||
}
|
||||
/* map the full core dump parition, including the checksum. */
|
||||
return esp_partition_mmap(core_part, 0, out_size, SPI_FLASH_MMAP_DATA,
|
||||
map_addr, core_data_handle);
|
||||
}
|
||||
|
||||
static void elf_parse_version_info(esp_core_dump_summary_t *summary, void *data)
|
||||
{
|
||||
core_dump_elf_version_info_t *version = (core_dump_elf_version_info_t *)data;
|
||||
summary->core_dump_version = version->version;
|
||||
memcpy(summary->app_elf_sha256, version->app_elf_sha256, ELF_APP_SHA256_SIZE);
|
||||
ESP_COREDUMP_LOGD("Core dump version 0x%x", summary->core_dump_version);
|
||||
ESP_COREDUMP_LOGD("App ELF SHA2 %s", (char *)summary->app_elf_sha256);
|
||||
}
|
||||
|
||||
static void elf_parse_exc_task_name(esp_core_dump_summary_t *summary, void *tcb_data)
|
||||
{
|
||||
StaticTask_t *tcb = (StaticTask_t *) tcb_data;
|
||||
/* An ugly way to get the task name. We could possibly use pcTaskGetTaskName here.
|
||||
* But that has assumption that TCB pointer can be used as TaskHandle. So let's
|
||||
* keep it this way. */
|
||||
memset(summary->exc_task, 0, sizeof(summary->exc_task));
|
||||
strncpy(summary->exc_task, (char *)tcb->ucDummy7, sizeof(summary->exc_task) - 1);
|
||||
ESP_COREDUMP_LOGD("Crashing task %s", summary->exc_task);
|
||||
}
|
||||
|
||||
esp_err_t esp_core_dump_get_summary(esp_core_dump_summary_t *summary)
|
||||
{
|
||||
int i;
|
||||
elf_phdr *ph;
|
||||
elf_note *note;
|
||||
const void *map_addr;
|
||||
size_t consumed_note_sz;
|
||||
spi_flash_mmap_handle_t core_data_handle;
|
||||
|
||||
if (!summary) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t err = elf_core_dump_image_mmap(&core_data_handle, &map_addr);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
uint8_t *ptr = (uint8_t *) map_addr + sizeof(core_dump_header_t);
|
||||
elfhdr *eh = (elfhdr *)ptr;
|
||||
|
||||
ESP_COREDUMP_LOGD("ELF ident %02x %c %c %c", eh->e_ident[0], eh->e_ident[1], eh->e_ident[2], eh->e_ident[3]);
|
||||
ESP_COREDUMP_LOGD("Ph_num %d offset %x", eh->e_phnum, eh->e_phoff);
|
||||
|
||||
for (i = 0; i < eh->e_phnum; i++) {
|
||||
ph = (elf_phdr *)((ptr + i * sizeof(*ph)) + eh->e_phoff);
|
||||
ESP_COREDUMP_LOGD("PHDR type %d off %x vaddr %x paddr %x filesz %x memsz %x flags %x align %x",
|
||||
ph->p_type, ph->p_offset, ph->p_vaddr, ph->p_paddr, ph->p_filesz, ph->p_memsz,
|
||||
ph->p_flags, ph->p_align);
|
||||
if (ph->p_type == PT_NOTE) {
|
||||
consumed_note_sz = 0;
|
||||
while(consumed_note_sz < ph->p_memsz) {
|
||||
note = (elf_note *)(ptr + ph->p_offset + consumed_note_sz);
|
||||
char *nm = (char *)(ptr + ph->p_offset + consumed_note_sz + sizeof(elf_note));
|
||||
ESP_COREDUMP_LOGD("Note NameSZ %x DescSZ %x Type %x name %s", note->n_namesz,
|
||||
note->n_descsz, note->n_type, nm);
|
||||
if (strncmp(nm, "EXTRA_INFO", note->n_namesz) == 0 ) {
|
||||
esp_core_dump_summary_parse_extra_info(summary, (void *)(nm + note->n_namesz));
|
||||
}
|
||||
if (strncmp(nm, "ESP_CORE_DUMP_INFO", note->n_namesz) == 0 ) {
|
||||
elf_parse_version_info(summary, (void *)(nm + note->n_namesz));
|
||||
}
|
||||
consumed_note_sz += note->n_namesz + note->n_descsz + sizeof(elf_note);
|
||||
ALIGN(4, consumed_note_sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Following code assumes that task stack segment follows the TCB segment for the respective task.
|
||||
* In general ELF does not impose any restrictions on segments' order so this can be changed without impacting core dump version.
|
||||
* More universal and flexible way would be to retrieve stack start address from crashed task TCB segment and then look for the stack segment with that address.
|
||||
*/
|
||||
int flag = 0;
|
||||
for (i = 0; i < eh->e_phnum; i++) {
|
||||
ph = (elf_phdr *)((ptr + i * sizeof(*ph)) + eh->e_phoff);
|
||||
if (ph->p_type == PT_LOAD) {
|
||||
if (flag) {
|
||||
esp_core_dump_summary_parse_exc_regs(summary, (void *)(ptr + ph->p_offset));
|
||||
esp_core_dump_summary_parse_backtrace_info(&summary->exc_bt_info, (void *) ph->p_vaddr,
|
||||
(void *)(ptr + ph->p_offset), ph->p_memsz);
|
||||
break;
|
||||
}
|
||||
if (ph->p_vaddr == summary->exc_tcb) {
|
||||
elf_parse_exc_task_name(summary, (void *)(ptr + ph->p_offset));
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
spi_flash_munmap(core_data_handle);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif //CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
@ -381,4 +381,38 @@ uint32_t esp_core_dump_get_extra_info(void **info)
|
||||
return size;
|
||||
}
|
||||
|
||||
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;
|
||||
summary->exc_tcb = ei->crashed_task_tcb;
|
||||
ESP_COREDUMP_LOGD("Crash TCB 0x%x", summary->exc_tcb);
|
||||
}
|
||||
|
||||
void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void *stack_data)
|
||||
{
|
||||
int i;
|
||||
long *a_reg;
|
||||
RvExcFrame *stack = (RvExcFrame *)stack_data;
|
||||
summary->exc_pc = stack->mepc;
|
||||
ESP_COREDUMP_LOGD("Crashing PC 0x%x", summary->exc_pc);
|
||||
|
||||
summary->ex_info.mstatus = stack->mstatus;
|
||||
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);
|
||||
a_reg = &stack->a0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
summary->ex_info.exc_a[i] = a_reg[i];
|
||||
ESP_COREDUMP_LOGD("A[%d] 0x%x", i, summary->ex_info.exc_a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_core_dump_common.h"
|
||||
#include "esp_core_dump_port.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
|
||||
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port";
|
||||
|
||||
@ -472,4 +473,90 @@ uint32_t esp_core_dump_get_extra_info(void **info)
|
||||
return sizeof(s_extra_info);
|
||||
}
|
||||
|
||||
void esp_core_dump_summary_parse_extra_info(esp_core_dump_summary_t *summary, void *ei_data)
|
||||
{
|
||||
int i;
|
||||
xtensa_extra_info_t *ei = (xtensa_extra_info_t *) ei_data;
|
||||
summary->exc_tcb = ei->crashed_task_tcb;
|
||||
summary->ex_info.exc_vaddr = ei->excvaddr.reg_val;
|
||||
summary->ex_info.exc_cause = ei->exccause.reg_val;
|
||||
ESP_COREDUMP_LOGD("Crash TCB 0x%x", summary->exc_tcb);
|
||||
ESP_COREDUMP_LOGD("excvaddr 0x%x", summary->ex_info.exc_vaddr);
|
||||
ESP_COREDUMP_LOGD("exccause 0x%x", summary->ex_info.exc_cause);
|
||||
|
||||
memset(summary->ex_info.epcx, 0, sizeof(summary->ex_info.epcx));
|
||||
summary->ex_info.epcx_reg_bits = 0;
|
||||
for (i = 0; i < COREDUMP_EXTRA_REG_NUM; i++ ) {
|
||||
if (ei->extra_regs[i].reg_index >= EPC_1
|
||||
&& ei->extra_regs[i].reg_index < (EPC_1 + XCHAL_NUM_INTLEVELS)) {
|
||||
summary->ex_info.epcx[ei->extra_regs[i].reg_index - EPC_1] = ei->extra_regs[i].reg_val;
|
||||
summary->ex_info.epcx_reg_bits |= (1 << (ei->extra_regs[i].reg_index - EPC_1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void *stack_data)
|
||||
{
|
||||
int i;
|
||||
long *a_reg;
|
||||
XtExcFrame *stack = (XtExcFrame *) stack_data;
|
||||
summary->exc_pc = esp_cpu_process_stack_pc(stack->pc);
|
||||
ESP_COREDUMP_LOGD("Crashing PC 0x%x", summary->exc_pc);
|
||||
|
||||
a_reg = &stack->a0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
summary->ex_info.exc_a[i] = a_reg[i];
|
||||
ESP_COREDUMP_LOGD("A[%d] 0x%x", i, summary->ex_info.exc_a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int offset;
|
||||
bool corrupted;
|
||||
esp_backtrace_frame_t frame;
|
||||
XtExcFrame *stack = (XtExcFrame *) paddr;
|
||||
int max_depth = (int) (sizeof(bt_info->bt) / sizeof(bt_info->bt[0]));
|
||||
int index = 0;
|
||||
|
||||
frame.pc = stack->pc;
|
||||
frame.sp = stack->a1;
|
||||
frame.next_pc = stack->a0;
|
||||
|
||||
corrupted = !(esp_stack_ptr_is_sane(frame.sp) &&
|
||||
esp_ptr_executable((void *)esp_cpu_process_stack_pc(frame.pc)));
|
||||
|
||||
/* vaddr is actual stack address when crash occurred. However that stack is now saved
|
||||
* in the flash at a different location. Hence for each SP, we need to adjust the offset
|
||||
* to point to next frame in the flash */
|
||||
offset = (uint32_t) stack - (uint32_t) vaddr;
|
||||
|
||||
ESP_COREDUMP_LOGD("Crash Backtrace");
|
||||
bt_info->bt[index] = esp_cpu_process_stack_pc(frame.pc);
|
||||
ESP_COREDUMP_LOGD(" 0x%x", bt_info->bt[index]);
|
||||
index++;
|
||||
|
||||
while (max_depth-- > 0 && frame.next_pc && !corrupted) {
|
||||
/* Check if the Stack Pointer is in valid address range */
|
||||
if (!((uint32_t)frame.sp >= (uint32_t)vaddr &&
|
||||
((uint32_t)frame.sp <= (uint32_t)vaddr + stack_size))) {
|
||||
corrupted = true;
|
||||
break;
|
||||
}
|
||||
/* Adjusting the SP to address in flash than in actual RAM */
|
||||
frame.sp += offset;
|
||||
if (!esp_backtrace_get_next_frame(&frame)) {
|
||||
corrupted = true;
|
||||
}
|
||||
if (corrupted == false) {
|
||||
bt_info->bt[index] = esp_cpu_process_stack_pc(frame.pc);
|
||||
ESP_COREDUMP_LOGD(" 0x%x", bt_info->bt[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
bt_info->depth = index;
|
||||
bt_info->corrupted = corrupted;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user