Merge branch 'astyle_format_coredump' into 'master'

refactor(espcoredump): format coredump component with astyle

See merge request espressif/esp-idf!29114
This commit is contained in:
Erhan Kurubas
2024-02-20 17:59:23 +08:00
18 changed files with 379 additions and 405 deletions

View File

@@ -78,7 +78,7 @@ enum class CreateAnd {
}; };
struct MockQueue : public CMockFix { struct MockQueue : public CMockFix {
MockQueue (CreateAnd flags) : queue(reinterpret_cast<QueueHandle_t>(0xdeadbeef)) MockQueue(CreateAnd flags) : queue(reinterpret_cast<QueueHandle_t>(0xdeadbeef))
{ {
if (flags == CreateAnd::FAIL) { if (flags == CreateAnd::FAIL) {
xQueueGenericCreate_ExpectAnyArgsAndReturn(nullptr); xQueueGenericCreate_ExpectAnyArgsAndReturn(nullptr);
@@ -101,7 +101,7 @@ struct MockQueue : public CMockFix {
}; };
struct MockMutex : public CMockFix { struct MockMutex : public CMockFix {
MockMutex (CreateAnd flags) : sem(reinterpret_cast<QueueHandle_t>(0xdeadbeef)) MockMutex(CreateAnd flags) : sem(reinterpret_cast<QueueHandle_t>(0xdeadbeef))
{ {
if (flags == CreateAnd::FAIL) { if (flags == CreateAnd::FAIL) {
xQueueCreateMutex_ExpectAnyArgsAndReturn(nullptr); xQueueCreateMutex_ExpectAnyArgsAndReturn(nullptr);
@@ -124,7 +124,7 @@ struct MockMutex : public CMockFix {
}; };
struct MockTask : public CMockFix { struct MockTask : public CMockFix {
MockTask (CreateAnd flags) : task((TaskHandle_t) 1) MockTask(CreateAnd flags) : task((TaskHandle_t) 1)
{ {
if (flags == CreateAnd::FAIL) { if (flags == CreateAnd::FAIL) {
xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdFALSE); xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdFALSE);

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -142,11 +142,11 @@ esp_err_t esp_core_dump_image_erase(void);
* *
* Example usage: * Example usage:
* @code{c} * @code{c}
char panic_reason[200]; char panic_reason[200];
esp_err_t err = esp_core_dump_get_panic_reason(panic_reason, sizeof(panic_reason)); esp_err_t err = esp_core_dump_get_panic_reason(panic_reason, sizeof(panic_reason));
if (err == ESP_OK) { if (err == ESP_OK) {
ESP_LOGW(TAG, "%s", panic_reason); ESP_LOGW(TAG, "%s", panic_reason);
} }
* @endcode * @endcode
*/ */
esp_err_t esp_core_dump_get_panic_reason(char *reason_buffer, size_t buffer_size); esp_err_t esp_core_dump_get_panic_reason(char *reason_buffer, size_t buffer_size);

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -50,7 +50,6 @@ bool esp_core_dump_get_task_snapshot(core_dump_task_handle_t handle,
*/ */
void esp_core_dump_reset_tasks_snapshots_iter(void); void esp_core_dump_reset_tasks_snapshots_iter(void);
/** /**
* @brief Check if the TCB passed as a parameter is sane. * @brief Check if the TCB passed as a parameter is sane.
* *
@@ -67,7 +66,6 @@ bool esp_core_dump_tcb_addr_is_sane(uint32_t addr);
*/ */
uint32_t esp_core_dump_get_user_ram_segments(void); uint32_t esp_core_dump_get_user_ram_segments(void);
/** /**
* @brief Get start address and size of a memory region. * @brief Get start address and size of a memory region.
* *
@@ -79,7 +77,6 @@ uint32_t esp_core_dump_get_user_ram_segments(void);
*/ */
int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start); int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start);
/** /**
* @brief Check if the current task is in an ISR. * @brief Check if the current task is in an ISR.
* *
@@ -87,7 +84,6 @@ int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start);
*/ */
bool esp_core_dump_in_isr_context(void); bool esp_core_dump_in_isr_context(void);
/** /**
* @brief Get the size all the memory regions (DRAM, RTC, RTC_FAST, IRAM) * @brief Get the size all the memory regions (DRAM, RTC, RTC_FAST, IRAM)
* *
@@ -95,7 +91,6 @@ bool esp_core_dump_in_isr_context(void);
*/ */
uint32_t esp_core_dump_get_user_ram_size(void); uint32_t esp_core_dump_get_user_ram_size(void);
/** /**
* @brief Get TCB length, in bytes. * @brief Get TCB length, in bytes.
* *

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -60,7 +60,6 @@ void esp_core_dump_reset_fake_stacks(void);
*/ */
uint32_t esp_core_dump_get_isr_stack_end(void); uint32_t esp_core_dump_get_isr_stack_end(void);
/** /**
* @brief Get the top of the ISR stack. * @brief Get the top of the ISR stack.
* *
@@ -68,7 +67,6 @@ uint32_t esp_core_dump_get_isr_stack_end(void);
*/ */
uint8_t* esp_core_dump_get_isr_stack_top(void); uint8_t* esp_core_dump_get_isr_stack_top(void);
/** /**
* @brief Check the stack defined by address given. * @brief Check the stack defined by address given.
* *
@@ -78,7 +76,6 @@ uint8_t* esp_core_dump_get_isr_stack_top(void);
*/ */
bool esp_core_dump_check_stack(core_dump_task_header_t *task); bool esp_core_dump_check_stack(core_dump_task_header_t *task);
/** /**
* @brief Check if the memory segment is sane. * @brief Check if the memory segment is sane.
* *
@@ -89,7 +86,6 @@ bool esp_core_dump_check_stack(core_dump_task_header_t *task);
*/ */
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);
/** /**
* @brief Get the stack of a task. * @brief Get the stack of a task.
* *
@@ -104,7 +100,6 @@ bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz);
uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot, uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot,
uint32_t* stk_vaddr, uint32_t* stk_paddr); uint32_t* stk_vaddr, uint32_t* stk_paddr);
/** /**
* @brief Check the task passed as a parameter. * @brief Check the task passed as a parameter.
* *
@@ -120,7 +115,6 @@ uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot,
*/ */
bool esp_core_dump_check_task(core_dump_task_header_t *task); bool esp_core_dump_check_task(core_dump_task_header_t *task);
/** /**
* @brief Get a dump of the task's registers. * @brief Get a dump of the task's registers.
* *

View File

@@ -88,7 +88,7 @@ extern "C" {
* MUST be a multiple of 16. * MUST be a multiple of 16.
*/ */
#if (COREDUMP_CACHE_SIZE % 16) != 0 #if (COREDUMP_CACHE_SIZE % 16) != 0
#error "Coredump cache size must be a multiple of 16" #error "Coredump cache size must be a multiple of 16"
#endif #endif
/** /**
@@ -96,8 +96,7 @@ extern "C" {
*/ */
#define COREDUMP_VERSION_CHIP CONFIG_IDF_FIRMWARE_CHIP_ID #define COREDUMP_VERSION_CHIP CONFIG_IDF_FIRMWARE_CHIP_ID
typedef struct _core_dump_write_data_t typedef struct _core_dump_write_data_t {
{
uint32_t off; /*!< Current offset of data being written */ uint32_t off; /*!< Current offset of data being written */
uint8_t cached_data[COREDUMP_CACHE_SIZE]; /*!< Cache used to write to flash */ uint8_t cached_data[COREDUMP_CACHE_SIZE]; /*!< Cache used to write to flash */
uint8_t cached_bytes; /*!< Number of bytes filled in the cached */ uint8_t cached_bytes; /*!< Number of bytes filled in the cached */
@@ -116,7 +115,6 @@ typedef esp_err_t (*esp_core_dump_flash_write_data_t)(core_dump_write_data_t* pr
void * data, void * data,
uint32_t data_len); uint32_t data_len);
/** /**
* @brief Core dump emitter control structure. * @brief Core dump emitter control structure.
* This structure contains the functions that are called in order to write * This structure contains the functions that are called in order to write
@@ -127,8 +125,7 @@ typedef esp_err_t (*esp_core_dump_flash_write_data_t)(core_dump_write_data_t* pr
* - write called once or more * - write called once or more
* - end * - end
*/ */
typedef struct _core_dump_write_config_t typedef struct _core_dump_write_config_t {
{
esp_core_dump_write_prepare_t prepare; /*!< Function called for sanity checks */ esp_core_dump_write_prepare_t prepare; /*!< Function called for sanity checks */
esp_core_dump_write_start_t start; /*!< Function called at the beginning of data writing */ esp_core_dump_write_start_t start; /*!< Function called at the beginning of data writing */
esp_core_dump_flash_write_data_t write; /*!< Function called to write data chunk */ esp_core_dump_flash_write_data_t write; /*!< Function called to write data chunk */
@@ -139,8 +136,7 @@ typedef struct _core_dump_write_config_t
/** /**
* @brief Core dump data header * @brief Core dump data header
* This header predecesses the actual core dump data (ELF or binary). */ * This header predecesses the actual core dump data (ELF or binary). */
typedef struct _core_dump_header_t typedef struct _core_dump_header_t {
{
uint32_t data_len; /*!< Data length */ uint32_t data_len; /*!< Data length */
uint32_t version; /*!< Core dump version */ uint32_t version; /*!< Core dump version */
uint32_t tasks_num; /*!< Number of tasks */ uint32_t tasks_num; /*!< Number of tasks */
@@ -158,8 +154,7 @@ typedef void* core_dump_task_handle_t;
/** /**
* @brief Header for the tasks * @brief Header for the tasks
*/ */
typedef struct _core_dump_task_header_t typedef struct _core_dump_task_header_t {
{
core_dump_task_handle_t tcb_addr; /*!< TCB address */ core_dump_task_handle_t tcb_addr; /*!< TCB address */
uint32_t stack_start; /*!< Start of the stack address */ uint32_t stack_start; /*!< Start of the stack address */
uint32_t stack_end; /*!< End of the stack address */ uint32_t stack_end; /*!< End of the stack address */
@@ -168,8 +163,7 @@ typedef struct _core_dump_task_header_t
/** /**
* @brief Core dump memory segment header * @brief Core dump memory segment header
*/ */
typedef struct _core_dump_mem_seg_header_t typedef struct _core_dump_mem_seg_header_t {
{
uint32_t start; /*!< Memory region start address */ uint32_t start; /*!< Memory region start address */
uint32_t size; /*!< Memory region size */ uint32_t size; /*!< Memory region size */
} core_dump_mem_seg_header_t; } core_dump_mem_seg_header_t;
@@ -179,7 +173,6 @@ typedef struct _core_dump_mem_seg_header_t
*/ */
void esp_core_dump_flash_init(void); void esp_core_dump_flash_init(void);
/** /**
* @brief Common core dump write function * @brief Common core dump write function
*/ */

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,14 +35,13 @@ typedef struct {
*/ */
FORCE_INLINE_ATTR void esp_core_dump_replace_sp(void* new_sp, core_dump_stack_context_t* old_ctx) FORCE_INLINE_ATTR void esp_core_dump_replace_sp(void* new_sp, core_dump_stack_context_t* old_ctx)
{ {
asm volatile ("mv %0, sp \n\t\ asm volatile("mv %0, sp \n\t\
mv sp, %1 \n\t\ mv sp, %1 \n\t\
" "
: "=&r"(old_ctx->sp) : "=&r"(old_ctx->sp)
: "r"(new_sp)); : "r"(new_sp));
} }
/** /**
* @brief Restore the stack pointer that was returned when calling `esp_core_dump_replace_sp()` function. * @brief Restore the stack pointer that was returned when calling `esp_core_dump_replace_sp()` function.
* *
@@ -50,7 +49,7 @@ FORCE_INLINE_ATTR void esp_core_dump_replace_sp(void* new_sp, core_dump_stack_co
*/ */
FORCE_INLINE_ATTR void esp_core_dump_restore_sp(core_dump_stack_context_t* old_ctx) FORCE_INLINE_ATTR void esp_core_dump_restore_sp(core_dump_stack_context_t* old_ctx)
{ {
asm volatile ("mv sp, %0 \n\t" :: "r"(old_ctx->sp)); asm volatile("mv sp, %0 \n\t" :: "r"(old_ctx->sp));
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -48,22 +48,21 @@ FORCE_INLINE_ATTR void esp_core_dump_replace_sp(void* new_sp, core_dump_stack_co
xthal_window_spill(); xthal_window_spill();
/* Backup the special registers PS, WindowBase and WindowStart. We will need to restore them later */ /* Backup the special registers PS, WindowBase and WindowStart. We will need to restore them later */
asm volatile ("mov %0, sp \n" \ asm volatile("mov %0, sp \n" \
"mov %1, a0 \n" \ "mov %1, a0 \n" \
"rsr.ps %2 \n"\ "rsr.ps %2 \n"\
"rsr.windowbase %3 \n"\ "rsr.windowbase %3 \n"\
"rsr.windowstart %4 \n"\ "rsr.windowstart %4 \n"\
: "=r"(old_ctx->sp), : "=r"(old_ctx->sp),
"=r"(old_ctx->a0), "=r"(old_ctx->a0),
"=r"(old_ctx->ps), "=r"(old_ctx->ps),
"=r"(old_ctx->windowbase), "=r"(old_ctx->windowbase),
"=r"(old_ctx->windowstart) :); "=r"(old_ctx->windowstart) :);
/* Set the new stack */ /* Set the new stack */
SET_STACK(new_sp); SET_STACK(new_sp);
} }
/** /**
* @brief Restore the stack pointer that was returned when calling `esp_core_dump_replace_sp()` function. * @brief Restore the stack pointer that was returned when calling `esp_core_dump_replace_sp()` function.
* *
@@ -74,23 +73,23 @@ FORCE_INLINE_ATTR void esp_core_dump_restore_sp(core_dump_stack_context_t* old_c
/* Start by disabling WindowOverflowEnable bit from PS to make sure we won't get a Window Overflow exception /* Start by disabling WindowOverflowEnable bit from PS to make sure we won't get a Window Overflow exception
* restoring WindowBase and WindowStart registers */ * restoring WindowBase and WindowStart registers */
const uint32_t ps_woe = old_ctx->ps & ~(PS_WOE_MASK); const uint32_t ps_woe = old_ctx->ps & ~(PS_WOE_MASK);
asm volatile ( \ asm volatile(\
"wsr.ps %0 \n"\ "wsr.ps %0 \n"\
"rsync \n"\ "rsync \n"\
"wsr.windowbase %1 \n"\ "wsr.windowbase %1 \n"\
"rsync \n"\ "rsync \n"\
"wsr.windowstart %2 \n"\ "wsr.windowstart %2 \n"\
"rsync \n"\ "rsync \n"\
"mov sp, %3 \n" \ "mov sp, %3 \n" \
"mov a0, %4 \n" \ "mov a0, %4 \n" \
"wsr.ps %5 \n"\ "wsr.ps %5 \n"\
"rsync \n"\ "rsync \n"\
:: "r"(ps_woe), :: "r"(ps_woe),
"r"(old_ctx->windowbase), "r"(old_ctx->windowbase),
"r"(old_ctx->windowstart), "r"(old_ctx->windowstart),
"r"(old_ctx->sp), "r"(old_ctx->sp),
"r"(old_ctx->a0), "r"(old_ctx->a0),
"r"(old_ctx->ps)); "r"(old_ctx->ps));
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -16,7 +16,6 @@
const static char TAG[] __attribute__((unused)) = "esp_core_dump_binary"; const static char TAG[] __attribute__((unused)) = "esp_core_dump_binary";
static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg, static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg,
core_dump_task_header_t *task) core_dump_task_header_t *task)
{ {
@@ -25,7 +24,7 @@ static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg,
uint32_t stk_paddr = 0; uint32_t stk_paddr = 0;
uint32_t stk_len = esp_core_dump_get_stack(task, &stk_vaddr, &stk_paddr); uint32_t stk_len = esp_core_dump_get_stack(task, &stk_vaddr, &stk_paddr);
stk_len = esp_core_dump_get_memory_len(stk_vaddr, stk_vaddr+stk_len); stk_len = esp_core_dump_get_memory_len(stk_vaddr, stk_vaddr + stk_len);
// Save memory segment header // Save memory segment header
err = write_cfg->write(write_cfg->priv, (void*)task, sizeof(core_dump_task_header_t)); err = write_cfg->write(write_cfg->priv, (void*)task, sizeof(core_dump_task_header_t));
@@ -43,14 +42,14 @@ static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg,
err = write_cfg->write(write_cfg->priv, (void*)stk_paddr, stk_len); err = write_cfg->write(write_cfg->priv, (void*)stk_paddr, stk_len);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write stack for task (TCB:%x), stack_start=%x, error=%d!", ESP_COREDUMP_LOGE("Failed to write stack for task (TCB:%x), stack_start=%x, error=%d!",
task->tcb_addr, task->tcb_addr,
stk_vaddr, stk_vaddr,
err); err);
return err; return err;
} }
ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) dump is saved.", ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) dump is saved.",
task->tcb_addr); task->tcb_addr);
return ESP_OK; return ESP_OK;
} }
@@ -61,7 +60,7 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_
if (!esp_core_dump_mem_seg_is_sane(seg->start, seg->size)) { if (!esp_core_dump_mem_seg_is_sane(seg->start, seg->size)) {
ESP_COREDUMP_LOGE("Failed to write memory segment, (%x, %lu)!", ESP_COREDUMP_LOGE("Failed to write memory segment, (%x, %lu)!",
seg->start, seg->size); seg->start, seg->size);
return ESP_FAIL; return ESP_FAIL;
} }
// Save TCB address, stack base and stack top addr // Save TCB address, stack base and stack top addr
@@ -74,11 +73,11 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_
err = write_cfg->write(write_cfg->priv, (void*)seg->start, seg->size); err = write_cfg->write(write_cfg->priv, (void*)seg->start, seg->size);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write memory segment, (%x, %lu), error=%d!", ESP_COREDUMP_LOGE("Failed to write memory segment, (%x, %lu), error=%d!",
seg->start, seg->size, err); seg->start, seg->size, err);
return err; return err;
} }
ESP_COREDUMP_LOG_PROCESS("Memory segment (%x, %lu) is saved.", ESP_COREDUMP_LOG_PROCESS("Memory segment (%x, %lu) is saved.",
seg->start, seg->size); seg->start, seg->size);
return ESP_OK; return ESP_OK;
} }
@@ -107,19 +106,19 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
cur_task = task_iter.pxTaskHandle; cur_task = task_iter.pxTaskHandle;
ESP_COREDUMP_LOG_PROCESS("Task %x %x is first crashed task.", cur_task, task_hdr.tcb_addr); 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, 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); task_hdr.stack_start, task_hdr.stack_end);
// Increase core dump size by task stack size // Increase core dump size by task stack size
uint32_t stk_vaddr = 0; uint32_t stk_vaddr = 0;
uint32_t stk_paddr = 0; uint32_t stk_paddr = 0;
uint32_t stk_len = esp_core_dump_get_stack(&task_hdr, &stk_vaddr, &stk_paddr); uint32_t stk_len = esp_core_dump_get_stack(&task_hdr, &stk_vaddr, &stk_paddr);
data_len += esp_core_dump_get_memory_len(stk_vaddr, stk_vaddr+stk_len); data_len += esp_core_dump_get_memory_len(stk_vaddr, stk_vaddr + stk_len);
// Add tcb size // Add tcb size
data_len += (tcb_sz + sizeof(core_dump_task_header_t)); data_len += (tcb_sz + sizeof(core_dump_task_header_t));
if (mem_seg.size > 0) { if (mem_seg.size > 0) {
ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x", ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x",
mem_seg.size, mem_seg.start); 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 += esp_core_dump_get_memory_len(mem_seg.start, mem_seg.start + mem_seg.size);
data_len += sizeof(core_dump_mem_seg_header_t); data_len += sizeof(core_dump_mem_seg_header_t);
hdr.mem_segs_num++; hdr.mem_segs_num++;
} }
@@ -130,16 +129,16 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
if (cur_task == NULL) { if (cur_task == NULL) {
ESP_COREDUMP_LOG_PROCESS("The current crashed task is broken."); ESP_COREDUMP_LOG_PROCESS("The current crashed task is broken.");
esp_core_dump_task_iterator_init(&task_iter); esp_core_dump_task_iterator_init(&task_iter);
while (esp_core_dump_task_iterator_next(&task_iter) != -1) { while (esp_core_dump_task_iterator_next(&task_iter) != -1) {
if (task_iter.pxTaskHandle != NULL) { if (task_iter.pxTaskHandle != NULL) {
cur_task = task_iter.pxTaskHandle; cur_task = task_iter.pxTaskHandle;
break; break;
} }
} }
if (cur_task == NULL) { if (cur_task == NULL) {
ESP_COREDUMP_LOGE("No valid tasks in the system!"); ESP_COREDUMP_LOGE("No valid tasks in the system!");
return ESP_FAIL; return ESP_FAIL;
} }
} }
// Add user memory regions data size // Add user memory regions data size
@@ -160,7 +159,7 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
data_len += sizeof(core_dump_header_t); data_len += sizeof(core_dump_header_t);
ESP_COREDUMP_LOG_PROCESS("Core dump length=%lu, tasks processed: %d, broken tasks: %d", ESP_COREDUMP_LOG_PROCESS("Core dump length=%lu, tasks processed: %d, broken tasks: %d",
data_len, hdr.tasks_num, bad_tasks_num); data_len, hdr.tasks_num, bad_tasks_num);
// Prepare write // Prepare write
if (write_cfg->prepare) { if (write_cfg->prepare) {
err = write_cfg->prepare(write_cfg->priv, &data_len); err = write_cfg->prepare(write_cfg->priv, &data_len);
@@ -198,25 +197,26 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
err = esp_core_dump_save_task(write_cfg, &task_hdr); err = esp_core_dump_save_task(write_cfg, &task_hdr);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save first crashed task %x, error=%d!", ESP_COREDUMP_LOGE("Failed to save first crashed task %x, error=%d!",
task_hdr.tcb_addr, err); task_hdr.tcb_addr, err);
return err; return err;
} }
} }
// Write all other tasks in the snapshot // Write all other tasks in the snapshot
esp_core_dump_task_iterator_init(&task_iter); esp_core_dump_task_iterator_init(&task_iter);
while (esp_core_dump_task_iterator_next(&task_iter) != -1) { while (esp_core_dump_task_iterator_next(&task_iter) != -1) {
if (!esp_core_dump_get_task_snapshot(task_iter.pxTaskHandle, &task_hdr, NULL)) if (!esp_core_dump_get_task_snapshot(task_iter.pxTaskHandle, &task_hdr, NULL)) {
continue; continue;
}
// Skip first crashed task // Skip first crashed task
if (task_iter.pxTaskHandle == cur_task) { if (task_iter.pxTaskHandle == cur_task) {
continue; continue;
} }
ESP_COREDUMP_LOGD("Save task %x (TCB:%x, stack:%x..%x)", ESP_COREDUMP_LOGD("Save task %x (TCB:%x, stack:%x..%x)",
task_iter.pxTaskHandle, task_hdr.tcb_addr, task_hdr.stack_start, task_hdr.stack_end); task_iter.pxTaskHandle, task_hdr.tcb_addr, task_hdr.stack_start, task_hdr.stack_end);
err = esp_core_dump_save_task(write_cfg, &task_hdr); err = esp_core_dump_save_task(write_cfg, &task_hdr);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save core dump task %x, error=%d!", ESP_COREDUMP_LOGE("Failed to save core dump task %x, error=%d!",
task_hdr.tcb_addr, err); task_hdr.tcb_addr, err);
return err; return err;
} }
} }
@@ -225,12 +225,13 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
// Actually there can be tasks interrupted at the same time, one on every core including the crashed one. // Actually there can be tasks interrupted at the same time, one on every core including the crashed one.
esp_core_dump_reset_tasks_snapshots_iter(); esp_core_dump_reset_tasks_snapshots_iter();
esp_core_dump_task_iterator_init(&task_iter); esp_core_dump_task_iterator_init(&task_iter);
while (esp_core_dump_task_iterator_next(&task_iter) != -1) { while (esp_core_dump_task_iterator_next(&task_iter) != -1) {
if (!esp_core_dump_get_task_snapshot(task_iter.pxTaskHandle, &task_hdr, &mem_seg)) if (!esp_core_dump_get_task_snapshot(task_iter.pxTaskHandle, &task_hdr, &mem_seg)) {
continue; continue;
}
if (mem_seg.size > 0) { if (mem_seg.size > 0) {
ESP_COREDUMP_LOG_PROCESS("Save interrupted task stack %lu bytes @ %x", ESP_COREDUMP_LOG_PROCESS("Save interrupted task stack %lu bytes @ %x",
mem_seg.size, mem_seg.start); mem_seg.size, mem_seg.start);
err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg); err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg);
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);
@@ -254,7 +255,7 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
mem_seg.start = start; mem_seg.start = start;
mem_seg.size = esp_core_dump_get_memory_len(start, start + data_sz);; mem_seg.size = esp_core_dump_get_memory_len(start, start + data_sz);;
ESP_COREDUMP_LOG_PROCESS("Save user memory region %lu bytes @ %x", ESP_COREDUMP_LOG_PROCESS("Save user memory region %lu bytes @ %x",
mem_seg.size, mem_seg.start); mem_seg.size, mem_seg.start);
err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg); err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save user memory region, error=%d!", err); ESP_COREDUMP_LOGE("Failed to save user memory region, error=%d!", err);

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -46,13 +46,12 @@ extern int _coredump_rtc_fast_end;
* a stack that will be used during the whole core dump generation. * a stack that will be used during the whole core dump generation.
*/ */
#if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG #if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG
/* Increase stack size in verbose mode */ /* Increase stack size in verbose mode */
#define ESP_COREDUMP_STACK_SIZE (CONFIG_ESP_COREDUMP_STACK_SIZE+100) #define ESP_COREDUMP_STACK_SIZE (CONFIG_ESP_COREDUMP_STACK_SIZE+100)
#else #else
#define ESP_COREDUMP_STACK_SIZE CONFIG_ESP_COREDUMP_STACK_SIZE #define ESP_COREDUMP_STACK_SIZE CONFIG_ESP_COREDUMP_STACK_SIZE
#endif #endif
#define COREDUMP_STACK_FILL_BYTE (0xa5U) #define COREDUMP_STACK_FILL_BYTE (0xa5U)
static uint8_t s_coredump_stack[ESP_COREDUMP_STACK_SIZE]; static uint8_t s_coredump_stack[ESP_COREDUMP_STACK_SIZE];
@@ -71,8 +70,8 @@ FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
memset(s_coredump_stack, COREDUMP_STACK_FILL_BYTE, ESP_COREDUMP_STACK_SIZE); memset(s_coredump_stack, COREDUMP_STACK_FILL_BYTE, ESP_COREDUMP_STACK_SIZE);
/* watchpoint 1 can be used for task stack overflow detection, re-use it, it is no more necessary */ /* watchpoint 1 can be used for task stack overflow detection, re-use it, it is no more necessary */
//esp_cpu_clear_watchpoint(1); //esp_cpu_clear_watchpoint(1);
//esp_cpu_set_watchpoint(1, s_coredump_stack, 1, ESP_WATCHPOINT_STORE); //esp_cpu_set_watchpoint(1, s_coredump_stack, 1, ESP_WATCHPOINT_STORE);
/* Replace the stack pointer depending on the architecture, but save the /* Replace the stack pointer depending on the architecture, but save the
* current stack pointer, in order to be able too restore it later. * current stack pointer, in order to be able too restore it later.
@@ -90,9 +89,8 @@ FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
FORCE_INLINE_ATTR uint32_t esp_core_dump_free_stack_space(const uint8_t *pucStackByte) FORCE_INLINE_ATTR uint32_t esp_core_dump_free_stack_space(const uint8_t *pucStackByte)
{ {
uint32_t ulCount = 0U; uint32_t ulCount = 0U;
while ( ulCount < ESP_COREDUMP_STACK_SIZE && while (ulCount < ESP_COREDUMP_STACK_SIZE &&
*pucStackByte == (uint8_t)COREDUMP_STACK_FILL_BYTE ) *pucStackByte == (uint8_t)COREDUMP_STACK_FILL_BYTE) {
{
pucStackByte -= portSTACK_GROWTH; pucStackByte -= portSTACK_GROWTH;
ulCount++; ulCount++;
} }
@@ -109,7 +107,7 @@ FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)
#if CONFIG_ESP_COREDUMP_LOGS #if CONFIG_ESP_COREDUMP_LOGS
uint32_t bytes_free = esp_core_dump_free_stack_space(s_coredump_stack); uint32_t bytes_free = esp_core_dump_free_stack_space(s_coredump_stack);
ESP_COREDUMP_LOGI("Core dump used %u bytes on stack. %u bytes left free.", ESP_COREDUMP_LOGI("Core dump used %u bytes on stack. %u bytes left free.",
s_core_dump_sp - s_coredump_stack - bytes_free, bytes_free); s_core_dump_sp - s_coredump_stack - bytes_free, bytes_free);
#endif #endif
/* Restore the stack pointer. */ /* Restore the stack pointer. */
@@ -121,7 +119,7 @@ FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)
/* Here, we are not going to use a custom stack for coredump. Make sure the current configuration doesn't require one. */ /* Here, we are not going to use a custom stack for coredump. Make sure the current configuration doesn't require one. */
#if CONFIG_ESP_COREDUMP_USE_STACK_SIZE #if CONFIG_ESP_COREDUMP_USE_STACK_SIZE
#pragma error "CONFIG_ESP_COREDUMP_STACK_SIZE must not be 0 in the current configuration" #pragma error "CONFIG_ESP_COREDUMP_STACK_SIZE must not be 0 in the current configuration"
#endif // ESP_COREDUMP_USE_STACK_SIZE #endif // ESP_COREDUMP_USE_STACK_SIZE
FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void) FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
@@ -130,14 +128,13 @@ FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
if (esp_core_dump_in_isr_context()) { if (esp_core_dump_in_isr_context()) {
uint8_t* topStack = esp_core_dump_get_isr_stack_top(); uint8_t* topStack = esp_core_dump_get_isr_stack_top();
esp_cpu_clear_watchpoint(1); esp_cpu_clear_watchpoint(1);
esp_cpu_set_watchpoint(1, topStack+xPortGetCoreID()*configISR_STACK_SIZE, 1, ESP_CPU_WATCHPOINT_STORE); esp_cpu_set_watchpoint(1, topStack + xPortGetCoreID()*configISR_STACK_SIZE, 1, ESP_CPU_WATCHPOINT_STORE);
} else { } else {
/* for tasks user should enable stack overflow detection in menuconfig /* for tasks user should enable stack overflow detection in menuconfig
TODO: if not enabled in menuconfig enable it ourselves */ TODO: if not enabled in menuconfig enable it ourselves */
} }
} }
FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void) FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)
{ {
} }
@@ -185,8 +182,8 @@ static void esp_core_dump_switch_task_stack_to_isr(core_dump_task_header_t *task
task->stack_start = (uint32_t) s_exc_frame; task->stack_start = (uint32_t) s_exc_frame;
task->stack_end = esp_core_dump_get_isr_stack_end(); task->stack_end = esp_core_dump_get_isr_stack_end();
ESP_COREDUMP_LOG_PROCESS("Switched task %x to ISR stack [%x...%x]", task->tcb_addr, ESP_COREDUMP_LOG_PROCESS("Switched task %x to ISR stack [%x...%x]", task->tcb_addr,
task->stack_start, task->stack_start,
task->stack_end); task->stack_end);
} }
inline void esp_core_dump_reset_tasks_snapshots_iter(void) inline void esp_core_dump_reset_tasks_snapshots_iter(void)
@@ -263,30 +260,30 @@ int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start)
ESP_COREDUMP_DEBUG_ASSERT(start != NULL); ESP_COREDUMP_DEBUG_ASSERT(start != NULL);
switch (region) { switch (region) {
case COREDUMP_MEMORY_DRAM: case COREDUMP_MEMORY_DRAM:
*start = (uint32_t)&_coredump_dram_start; *start = (uint32_t)&_coredump_dram_start;
total_sz = (uint8_t *)&_coredump_dram_end - (uint8_t *)&_coredump_dram_start; total_sz = (uint8_t *)&_coredump_dram_end - (uint8_t *)&_coredump_dram_start;
break; break;
case COREDUMP_MEMORY_IRAM: case COREDUMP_MEMORY_IRAM:
*start = (uint32_t)&_coredump_iram_start; *start = (uint32_t)&_coredump_iram_start;
total_sz = (uint8_t *)&_coredump_iram_end - (uint8_t *)&_coredump_iram_start; total_sz = (uint8_t *)&_coredump_iram_end - (uint8_t *)&_coredump_iram_start;
break; break;
#if SOC_RTC_MEM_SUPPORTED #if SOC_RTC_MEM_SUPPORTED
case COREDUMP_MEMORY_RTC: case COREDUMP_MEMORY_RTC:
*start = (uint32_t)&_coredump_rtc_start; *start = (uint32_t)&_coredump_rtc_start;
total_sz = (uint8_t *)&_coredump_rtc_end - (uint8_t *)&_coredump_rtc_start; total_sz = (uint8_t *)&_coredump_rtc_end - (uint8_t *)&_coredump_rtc_start;
break; break;
case COREDUMP_MEMORY_RTC_FAST: case COREDUMP_MEMORY_RTC_FAST:
*start = (uint32_t)&_coredump_rtc_fast_start; *start = (uint32_t)&_coredump_rtc_fast_start;
total_sz = (uint8_t *)&_coredump_rtc_fast_end - (uint8_t *)&_coredump_rtc_fast_start; total_sz = (uint8_t *)&_coredump_rtc_fast_end - (uint8_t *)&_coredump_rtc_fast_start;
break; break;
#endif #endif
default: default:
break; break;
} }
return total_sz; return total_sz;

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -44,23 +44,20 @@
return (ret_val); \ return (ret_val); \
} }
typedef enum typedef enum {
{
ELF_STAGE_CALC_SPACE = 0, ELF_STAGE_CALC_SPACE = 0,
ELF_STAGE_PLACE_HEADERS = 1, ELF_STAGE_PLACE_HEADERS = 1,
ELF_STAGE_PLACE_DATA = 2 ELF_STAGE_PLACE_DATA = 2
} core_dump_elf_stages_t; } core_dump_elf_stages_t;
typedef enum _elf_err_t typedef enum _elf_err_t {
{
ELF_PROC_ERR_SKIP_HEADER = 0, ELF_PROC_ERR_SKIP_HEADER = 0,
ELF_PROC_ERR_STACK_CORRUPTED = -1, ELF_PROC_ERR_STACK_CORRUPTED = -1,
ELF_PROC_ERR_WRITE_FAIL = -2, ELF_PROC_ERR_WRITE_FAIL = -2,
ELF_PROC_ERR_OTHER = -3 ELF_PROC_ERR_OTHER = -3
} core_dump_elf_proc_err_t; } core_dump_elf_proc_err_t;
typedef struct _core_dump_task_info_t typedef struct _core_dump_task_info_t {
{
elf_phdr* phdr; elf_phdr* phdr;
void* frame; void* frame;
core_dump_task_header_t* task_hdr; core_dump_task_header_t* task_hdr;
@@ -69,8 +66,7 @@ typedef struct _core_dump_task_info_t
int* size_ptr; int* size_ptr;
} core_dump_task_data_t; } core_dump_task_data_t;
typedef struct typedef struct {
{
uint32_t version; // coredump version uint32_t version; // coredump version
uint8_t app_elf_sha256[ELF_APP_SHA256_SIZE]; // sha256 of elf file uint8_t app_elf_sha256[ELF_APP_SHA256_SIZE]; // sha256 of elf file
} core_dump_elf_version_info_t; } core_dump_elf_version_info_t;
@@ -78,8 +74,7 @@ typedef struct
const static char TAG[] __attribute__((unused)) = "esp_core_dump_elf"; const static char TAG[] __attribute__((unused)) = "esp_core_dump_elf";
// Main ELF handle type // Main ELF handle type
typedef struct _core_dump_elf_t typedef struct _core_dump_elf_t {
{
core_dump_elf_version_info_t elf_version_info; core_dump_elf_version_info_t elf_version_info;
uint16_t elf_stage; uint16_t elf_stage;
uint32_t elf_next_data_offset; uint32_t elf_next_data_offset;
@@ -137,7 +132,7 @@ static int elf_write_file_header(core_dump_elf_t *self, uint32_t seg_count)
// write built elf header into elf image // write built elf header into elf image
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)&elf_hdr, sizeof(elf_hdr)); esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)&elf_hdr, sizeof(elf_hdr));
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF header failure (%d)", err); "Write ELF header failure (%d)", err);
ESP_COREDUMP_LOG_PROCESS("Add file header %u bytes", sizeof(elf_hdr)); ESP_COREDUMP_LOG_PROCESS("Add file header %u bytes", sizeof(elf_hdr));
} }
@@ -147,29 +142,29 @@ static int elf_write_file_header(core_dump_elf_t *self, uint32_t seg_count)
static int elf_write_segment_header(core_dump_elf_t *self, elf_phdr* phdr) static int elf_write_segment_header(core_dump_elf_t *self, elf_phdr* phdr)
{ {
ELF_CHECK_ERR(phdr, ELF_PROC_ERR_SKIP_HEADER, ELF_CHECK_ERR(phdr, ELF_PROC_ERR_SKIP_HEADER,
"Header is skipped, stage=(%d).", self->elf_stage); "Header is skipped, stage=(%d).", self->elf_stage);
phdr->p_offset = self->elf_next_data_offset; phdr->p_offset = self->elf_next_data_offset;
// set segment data information and write it into image // set segment data information and write it into image
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)phdr, sizeof(elf_phdr)); esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)phdr, sizeof(elf_phdr));
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF segment header failure (%d)", err); "Write ELF segment header failure (%d)", err);
ESP_COREDUMP_LOG_PROCESS("Add segment header %u bytes: type %d, sz %u, off = 0x%x", ESP_COREDUMP_LOG_PROCESS("Add segment header %u bytes: type %d, sz %u, off = 0x%x",
sizeof(elf_phdr), phdr->p_type, phdr->p_filesz, phdr->p_offset); sizeof(elf_phdr), phdr->p_type, phdr->p_filesz, phdr->p_offset);
return sizeof(elf_phdr); return sizeof(elf_phdr);
} }
static int elf_add_segment(core_dump_elf_t *self, static int elf_add_segment(core_dump_elf_t *self,
uint32_t type, uint32_t vaddr, uint32_t type, uint32_t vaddr,
void* data, uint32_t data_sz) void* data, uint32_t data_sz)
{ {
esp_err_t err = ESP_FAIL; esp_err_t err = ESP_FAIL;
elf_phdr seg_hdr = { 0 }; elf_phdr seg_hdr = { 0 };
int data_len = ALIGN_UP(data_sz, 4); int data_len = ALIGN_UP(data_sz, 4);
ELF_CHECK_ERR((data != NULL), ELF_PROC_ERR_OTHER, ELF_CHECK_ERR((data != NULL), ELF_PROC_ERR_OTHER,
"Invalid data for segment."); "Invalid data for segment.");
if (self->elf_stage == ELF_STAGE_CALC_SPACE) { if (self->elf_stage == ELF_STAGE_CALC_SPACE) {
self->segs_count++; self->segs_count++;
@@ -184,23 +179,23 @@ static int elf_add_segment(core_dump_elf_t *self,
seg_hdr.p_flags = (PF_R | PF_W); seg_hdr.p_flags = (PF_R | PF_W);
int ret = elf_write_segment_header(self, &seg_hdr); int ret = elf_write_segment_header(self, &seg_hdr);
ELF_CHECK_ERR((ret > 0), ret, ELF_CHECK_ERR((ret > 0), ret,
"Write ELF segment data failure (%d)", ret); "Write ELF segment data failure (%d)", ret);
self->elf_next_data_offset += data_len; self->elf_next_data_offset += data_len;
return ret; return ret;
} }
ESP_COREDUMP_LOG_PROCESS("Add segment size=%u, start_off=0x%x", ESP_COREDUMP_LOG_PROCESS("Add segment size=%u, start_off=0x%x",
(uint32_t)data_len, self->elf_next_data_offset); (uint32_t)data_len, self->elf_next_data_offset);
// write segment data only when write function is set and phdr = NULL // write segment data only when write function is set and phdr = NULL
// write data into segment // write data into segment
err = self->write_cfg->write(self->write_cfg->priv, data, (uint32_t)data_len); err = self->write_cfg->write(self->write_cfg->priv, data, (uint32_t)data_len);
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF segment data failure (%d)", err); "Write ELF segment data failure (%d)", err);
self->elf_next_data_offset += data_len; self->elf_next_data_offset += data_len;
return data_len; return data_len;
} }
static int elf_write_note_header(core_dump_elf_t *self, static int elf_write_note_header(core_dump_elf_t *self,
const char* name, uint32_t name_len, uint32_t data_sz, uint32_t type) const char* name, uint32_t name_len, uint32_t data_sz, uint32_t type)
{ {
// temporary aligned buffer for note name // temporary aligned buffer for note name
static char name_buffer[ELF_NOTE_NAME_MAX_SIZE] = { 0 }; static char name_buffer[ELF_NOTE_NAME_MAX_SIZE] = { 0 };
@@ -213,27 +208,27 @@ static int elf_write_note_header(core_dump_elf_t *self,
// write note header // write note header
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, &note_hdr, sizeof(note_hdr)); esp_err_t err = self->write_cfg->write(self->write_cfg->priv, &note_hdr, sizeof(note_hdr));
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF note header failure (%d)", err); "Write ELF note header failure (%d)", err);
// write note name // write note name
err = self->write_cfg->write(self->write_cfg->priv, name_buffer, name_len); err = self->write_cfg->write(self->write_cfg->priv, name_buffer, name_len);
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF note name failure (%d)", err); "Write ELF note name failure (%d)", err);
return err; return err;
} }
static int elf_write_note(core_dump_elf_t *self, static int elf_write_note(core_dump_elf_t *self,
const char* name, const char* name,
uint32_t type, uint32_t type,
void* data, void* data,
uint32_t data_sz) uint32_t data_sz)
{ {
esp_err_t err = ESP_FAIL; esp_err_t err = ESP_FAIL;
uint32_t name_len = ALIGN_UP(strlen(name) + 1, 4); // get name length including terminator uint32_t name_len = ALIGN_UP(strlen(name) + 1, 4); // get name length including terminator
uint32_t data_len = ALIGN_UP(data_sz, 4); uint32_t data_len = ALIGN_UP(data_sz, 4);
ELF_CHECK_ERR((name_len <= ELF_NOTE_NAME_MAX_SIZE), 0, ELF_CHECK_ERR((name_len <= ELF_NOTE_NAME_MAX_SIZE), 0,
"Segment note name is too long %d.", name_len); "Segment note name is too long %d.", name_len);
uint32_t note_size = ALIGN_UP(name_len + data_len + sizeof(elf_note), 4); uint32_t note_size = ALIGN_UP(name_len + data_len + sizeof(elf_note), 4);
@@ -258,9 +253,9 @@ static int elf_write_note(core_dump_elf_t *self,
} }
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF note data failure (%d)", err); "Write ELF note data failure (%d)", err);
ESP_COREDUMP_LOG_PROCESS("Add note size=%d, start_off=0x%x", ESP_COREDUMP_LOG_PROCESS("Add note size=%d, start_off=0x%x",
note_size, self->elf_next_data_offset); note_size, self->elf_next_data_offset);
} }
return note_size; // return actual note size return note_size; // return actual note size
} }
@@ -272,11 +267,11 @@ static int elf_add_note(core_dump_elf_t *self,
uint32_t data_sz) uint32_t data_sz)
{ {
ELF_CHECK_ERR((data != NULL), ELF_PROC_ERR_OTHER, ELF_CHECK_ERR((data != NULL), ELF_PROC_ERR_OTHER,
"Invalid data pointer for segment"); "Invalid data pointer for segment");
int note_size = elf_write_note(self, name, type, data, data_sz); int note_size = elf_write_note(self, name, type, data, data_sz);
ELF_CHECK_ERR((note_size > 0), note_size, ELF_CHECK_ERR((note_size > 0), note_size,
"Write ELF note data failure, returned (%d)", note_size); "Write ELF note data failure, returned (%d)", note_size);
return note_size; // return actual note segment size return note_size; // return actual note segment size
} }
@@ -307,11 +302,11 @@ static int elf_add_stack(core_dump_elf_t *self, core_dump_task_header_t *task)
stack_len = esp_core_dump_get_stack(task, &stack_vaddr, &stack_paddr); stack_len = esp_core_dump_get_stack(task, &stack_vaddr, &stack_paddr);
ESP_COREDUMP_LOG_PROCESS("Add stack for task 0x%x: addr 0x%x, sz %u", ESP_COREDUMP_LOG_PROCESS("Add stack for task 0x%x: addr 0x%x, sz %u",
task->tcb_addr, stack_vaddr, stack_len); task->tcb_addr, stack_vaddr, stack_len);
int ret = elf_add_segment(self, PT_LOAD, int ret = elf_add_segment(self, PT_LOAD,
(uint32_t)stack_vaddr, (uint32_t)stack_vaddr,
(void*)stack_paddr, (void*)stack_paddr,
(uint32_t) stack_len); (uint32_t) stack_len);
return ret; return ret;
} }
@@ -320,12 +315,12 @@ 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."); ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid task pointer.");
// add task tcb data into program segment of ELF // add task tcb data into program segment of ELF
ESP_COREDUMP_LOG_PROCESS("Add TCB for task 0x%x: addr 0x%x, sz %u", ESP_COREDUMP_LOG_PROCESS("Add TCB for task 0x%x: addr 0x%x, sz %u",
task->tcb_addr, task->tcb_addr, task->tcb_addr, task->tcb_addr,
esp_core_dump_get_tcb_len()); esp_core_dump_get_tcb_len());
int ret = elf_add_segment(self, PT_LOAD, int ret = elf_add_segment(self, PT_LOAD,
(uint32_t)task->tcb_addr, (uint32_t)task->tcb_addr,
task->tcb_addr, task->tcb_addr,
esp_core_dump_get_tcb_len()); esp_core_dump_get_tcb_len());
return ret; return ret;
} }
@@ -339,8 +334,8 @@ static int elf_process_task_tcb(core_dump_elf_t *self, core_dump_task_header_t *
ret = elf_add_tcb(self, task); ret = elf_add_tcb(self, task);
if (ret <= 0) { if (ret <= 0) {
ESP_COREDUMP_LOGE("Task (TCB:%x) processing failure = %d", ESP_COREDUMP_LOGE("Task (TCB:%x) processing failure = %d",
task->tcb_addr, task->tcb_addr,
ret); ret);
} }
return ret; return ret;
} }
@@ -354,9 +349,9 @@ static int elf_process_task_stack(core_dump_elf_t *self, core_dump_task_header_t
ret = elf_add_stack(self, task); ret = elf_add_stack(self, task);
if (ret <= 0) { if (ret <= 0) {
ESP_COREDUMP_LOGE("Task (TCB:%x), (Stack:%x), stack processing failure = %d.", ESP_COREDUMP_LOGE("Task (TCB:%x), (Stack:%x), stack processing failure = %d.",
task->tcb_addr, task->tcb_addr,
task->stack_start, task->stack_start,
ret); ret);
} }
return ret; return ret;
} }
@@ -384,7 +379,7 @@ static int elf_process_note_segment(core_dump_elf_t *self, int notes_size)
} else { } else {
// in "Place Data" phase segment body is been already filled by other functions // in "Place Data" phase segment body is been already filled by other functions
ESP_COREDUMP_LOG_PROCESS("Add NOTE segment, size=%d, start_off=0x%x", ESP_COREDUMP_LOG_PROCESS("Add NOTE segment, size=%d, start_off=0x%x",
notes_size, self->elf_next_data_offset); notes_size, self->elf_next_data_offset);
self->elf_next_data_offset += notes_size; self->elf_next_data_offset += notes_size;
} }
return (int)notes_size; return (int)notes_size;
@@ -417,8 +412,9 @@ static int elf_process_tasks_regs(core_dump_elf_t *self)
esp_core_dump_task_iterator_init(&task_iter); esp_core_dump_task_iterator_init(&task_iter);
while (esp_core_dump_task_iterator_next(&task_iter) != -1) { while (esp_core_dump_task_iterator_next(&task_iter) != -1) {
task = task_iter.pxTaskHandle; task = task_iter.pxTaskHandle;
if (!task || task == esp_core_dump_get_current_task_handle()) // skip current task (already processed) if (!task || task == esp_core_dump_get_current_task_handle()) { // skip current task (already processed)
continue; continue;
}
if (esp_core_dump_get_task_snapshot(task, &task_hdr, NULL)) { if (esp_core_dump_get_task_snapshot(task, &task_hdr, NULL)) {
ret = elf_add_regs(self, &task_hdr); ret = elf_add_regs(self, &task_hdr);
if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) {
@@ -432,7 +428,7 @@ static int elf_process_tasks_regs(core_dump_elf_t *self)
} }
ret = elf_process_note_segment(self, len); // tasks regs note ret = elf_process_note_segment(self, len); // tasks regs note
ELF_CHECK_ERR((ret > 0), ret, ELF_CHECK_ERR((ret > 0), ret,
"PR_STATUS note segment processing failure, returned(%d).", ret); "PR_STATUS note segment processing failure, returned(%d).", ret);
return ret; return ret;
} }
@@ -442,11 +438,11 @@ static int elf_save_task(core_dump_elf_t *self, core_dump_task_header_t *task)
int ret = elf_process_task_tcb(self, task); int ret = elf_process_task_tcb(self, task);
ELF_CHECK_ERR((ret > 0), ret, ELF_CHECK_ERR((ret > 0), ret,
"Task %x, TCB write failed, return (%d).", task->tcb_addr, ret); "Task %x, TCB write failed, return (%d).", task->tcb_addr, ret);
elf_len += ret; elf_len += ret;
ret = elf_process_task_stack(self, task); ret = elf_process_task_stack(self, task);
ELF_CHECK_ERR((ret != ELF_PROC_ERR_WRITE_FAIL), ELF_PROC_ERR_WRITE_FAIL, 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); "Task %x, stack write failed, return (%d).", task->tcb_addr, ret);
elf_len += ret; elf_len += ret;
return elf_len; return elf_len;
} }
@@ -479,15 +475,15 @@ static int elf_write_tasks_data(core_dump_elf_t *self)
} }
ret = elf_save_task(self, &task_hdr); ret = elf_save_task(self, &task_hdr);
ELF_CHECK_ERR((ret > 0), ret, ELF_CHECK_ERR((ret > 0), ret,
"Task %x, TCB write failed, return (%d).", task_iter.pxTaskHandle, ret); "Task %x, TCB write failed, return (%d).", task_iter.pxTaskHandle, ret);
elf_len += ret; elf_len += ret;
if (interrupted_stack.size > 0) { if (interrupted_stack.size > 0) {
ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x", ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x",
interrupted_stack.size, interrupted_stack.start); interrupted_stack.size, interrupted_stack.start);
ret = elf_add_segment(self, PT_LOAD, ret = elf_add_segment(self, PT_LOAD,
(uint32_t)interrupted_stack.start, (uint32_t)interrupted_stack.start,
(void*)interrupted_stack.start, (void*)interrupted_stack.start,
(uint32_t)interrupted_stack.size); (uint32_t)interrupted_stack.size);
ELF_CHECK_ERR((ret > 0), ret, "Interrupted task stack write failed, return (%d).", ret); ELF_CHECK_ERR((ret > 0), ret, "Interrupted task stack write failed, return (%d).", ret);
elf_len += ret; elf_len += ret;
} }
@@ -509,9 +505,9 @@ static int elf_write_core_dump_user_data(core_dump_elf_t *self)
if (data_len > 0) { if (data_len > 0) {
int ret = elf_add_segment(self, PT_LOAD, int ret = elf_add_segment(self, PT_LOAD,
(uint32_t)start, (uint32_t)start,
(void*)start, (void*)start,
(uint32_t) data_len); (uint32_t) data_len);
ELF_CHECK_ERR((ret > 0), ret, "memory region write failed. Returned (%d).", ret); ELF_CHECK_ERR((ret > 0), ret, "memory region write failed. Returned (%d).", ret);
total_sz += ret; total_sz += ret;
@@ -524,20 +520,20 @@ static int elf_write_core_dump_user_data(core_dump_elf_t *self)
#if CONFIG_ESP_TASK_WDT_EN #if CONFIG_ESP_TASK_WDT_EN
static void elf_write_core_dump_note_cb(void *opaque, const char *data) static void elf_write_core_dump_note_cb(void *opaque, const char *data)
{ {
core_dump_elf_opaque_t *param = opaque; core_dump_elf_opaque_t *param = opaque;
core_dump_elf_t *self = param->self; core_dump_elf_t *self = param->self;
const size_t data_len = strlen(data); const size_t data_len = strlen(data);
ESP_COREDUMP_LOG_PROCESS("Core dump note cb data_len:(%d)", data_len); ESP_COREDUMP_LOG_PROCESS("Core dump note cb data_len:(%d)", data_len);
param->total_size += data_len; param->total_size += data_len;
if (!param->size_only) { if (!param->size_only) {
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void *)data, data_len); esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void *)data, data_len);
if (err != ESP_OK) { if (err != ESP_OK) {
param->total_size = 0; param->total_size = 0;
} }
} }
} }
static int elf_add_wdt_panic_details(core_dump_elf_t *self) static int elf_add_wdt_panic_details(core_dump_elf_t *self)
@@ -556,10 +552,10 @@ static int elf_add_wdt_panic_details(core_dump_elf_t *self)
self->note_data_size = param.total_size; self->note_data_size = param.total_size;
} else if (self->elf_stage == ELF_STAGE_PLACE_DATA) { } else if (self->elf_stage == ELF_STAGE_PLACE_DATA) {
esp_err_t err = elf_write_note_header(self, esp_err_t err = elf_write_note_header(self,
ELF_ESP_CORE_DUMP_PANIC_DETAILS_NOTE_NAME, ELF_ESP_CORE_DUMP_PANIC_DETAILS_NOTE_NAME,
name_len, name_len,
self->note_data_size, self->note_data_size,
ELF_ESP_CORE_DUMP_PANIC_DETAILS_TYPE); ELF_ESP_CORE_DUMP_PANIC_DETAILS_TYPE);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
@@ -576,7 +572,7 @@ static int elf_add_wdt_panic_details(core_dump_elf_t *self)
} }
} }
return ALIGN_UP(name_len + ALIGN_UP(self->note_data_size, 4) + sizeof(elf_note), 4); return ALIGN_UP(name_len + ALIGN_UP(self->note_data_size, 4) + sizeof(elf_note), 4);
} }
#endif //CONFIG_ESP_TASK_WDT_EN #endif //CONFIG_ESP_TASK_WDT_EN
@@ -589,15 +585,15 @@ static int elf_write_core_dump_info(core_dump_elf_t *self)
// esp_app_get_elf_sha256() into IRAM. But we want to reduce IRAM usage, // esp_app_get_elf_sha256() into IRAM. But we want to reduce IRAM usage,
// so we use a function that returns an already formatted string. // so we use a function that returns an already formatted string.
size_t data_len = strlcpy((char*)self->elf_version_info.app_elf_sha256, esp_app_get_elf_sha256_str(), size_t data_len = strlcpy((char*)self->elf_version_info.app_elf_sha256, esp_app_get_elf_sha256_str(),
sizeof(self->elf_version_info.app_elf_sha256)); sizeof(self->elf_version_info.app_elf_sha256));
ESP_COREDUMP_LOG_PROCESS("Application SHA256='%s', length=%d.", ESP_COREDUMP_LOG_PROCESS("Application SHA256='%s', length=%d.",
self->elf_version_info.app_elf_sha256, data_len); self->elf_version_info.app_elf_sha256, data_len);
self->elf_version_info.version = esp_core_dump_elf_version(); self->elf_version_info.version = esp_core_dump_elf_version();
int ret = elf_add_note(self, int ret = elf_add_note(self,
"ESP_CORE_DUMP_INFO", "ESP_CORE_DUMP_INFO",
ELF_ESP_CORE_DUMP_INFO_TYPE, ELF_ESP_CORE_DUMP_INFO_TYPE,
&self->elf_version_info, &self->elf_version_info,
sizeof(self->elf_version_info)); sizeof(self->elf_version_info));
ELF_CHECK_ERR((ret > 0), ret, "Version info note write failed. Returned (%d).", ret); ELF_CHECK_ERR((ret > 0), ret, "Version info note write failed. Returned (%d).", ret);
data_len = ret; data_len = ret;
@@ -608,35 +604,37 @@ static int elf_write_core_dump_info(core_dump_elf_t *self)
} }
ret = elf_add_note(self, ret = elf_add_note(self,
"ESP_EXTRA_INFO", "ESP_EXTRA_INFO",
ELF_ESP_CORE_DUMP_EXTRA_INFO_TYPE, ELF_ESP_CORE_DUMP_EXTRA_INFO_TYPE,
extra_info, extra_info,
extra_info_len); extra_info_len);
ELF_CHECK_ERR((ret > 0), ret, "Extra info note write failed. Returned (%d).", ret); ELF_CHECK_ERR((ret > 0), ret, "Extra info note write failed. Returned (%d).", ret);
data_len += ret; data_len += ret;
#if CONFIG_ESP_TASK_WDT_EN #if CONFIG_ESP_TASK_WDT_EN
extern bool g_twdt_isr; extern bool g_twdt_isr;
if (g_twdt_isr) { if (g_twdt_isr) {
ret = elf_add_wdt_panic_details(self); ret = elf_add_wdt_panic_details(self);
if (ret <= 0) { return ret; } if (ret <= 0) {
data_len += ret; return ret;
}
data_len += ret;
} }
#endif #endif
if (g_panic_abort_details && strlen(g_panic_abort_details) > 0) { if (g_panic_abort_details && strlen(g_panic_abort_details) > 0) {
ret = elf_add_note(self, ret = elf_add_note(self,
ELF_ESP_CORE_DUMP_PANIC_DETAILS_NOTE_NAME, ELF_ESP_CORE_DUMP_PANIC_DETAILS_NOTE_NAME,
ELF_ESP_CORE_DUMP_PANIC_DETAILS_TYPE, ELF_ESP_CORE_DUMP_PANIC_DETAILS_TYPE,
g_panic_abort_details, g_panic_abort_details,
strlen(g_panic_abort_details)); strlen(g_panic_abort_details));
ELF_CHECK_ERR((ret > 0), ret, "Panic details note write failed. Returned (%d).", ret); ELF_CHECK_ERR((ret > 0), ret, "Panic details note write failed. Returned (%d).", ret);
data_len += ret; data_len += ret;
} }
ret = elf_process_note_segment(self, data_len); ret = elf_process_note_segment(self, data_len);
ELF_CHECK_ERR((ret > 0), ret, ELF_CHECK_ERR((ret > 0), ret,
"EXTRA_INFO note segment processing failure, returned(%d).", ret); "EXTRA_INFO note segment processing failure, returned(%d).", ret);
return ret; return ret;
} }
@@ -686,7 +684,9 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
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); int ret = esp_core_dump_do_write_elf_pass(&self);
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", tot_len); ESP_COREDUMP_LOG_PROCESS("Core dump tot_len=%lu", tot_len);
ESP_COREDUMP_LOG_PROCESS("============== Data size = %d bytes ============", tot_len); ESP_COREDUMP_LOG_PROCESS("============== Data size = %d bytes ============", tot_len);
@@ -728,7 +728,9 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
// 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) * sizeof(elf_phdr); self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self) * sizeof(elf_phdr);
ret = esp_core_dump_do_write_elf_pass(&self); ret = esp_core_dump_do_write_elf_pass(&self);
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);
@@ -736,7 +738,9 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
// 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) * sizeof(elf_phdr); self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self) * sizeof(elf_phdr);
ret = esp_core_dump_do_write_elf_pass(&self); ret = esp_core_dump_do_write_elf_pass(&self);
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);
@@ -761,14 +765,14 @@ typedef struct {
Elf64_Word n_type; Elf64_Word n_type;
Elf64_Word n_descsz; Elf64_Word n_descsz;
#endif #endif
void *n_ptr; void *n_ptr;
} elf_note_content_t; } elf_note_content_t;
/* Below are the helper function to parse the core dump ELF stored in flash */ /* Below are the helper function to parse the core dump ELF stored in flash */
static esp_err_t elf_core_dump_image_mmap(esp_partition_mmap_handle_t* core_data_handle, const void **map_addr) static esp_err_t elf_core_dump_image_mmap(esp_partition_mmap_handle_t* core_data_handle, const void **map_addr)
{ {
size_t out_size; size_t out_size;
assert (core_data_handle); assert(core_data_handle);
assert(map_addr); assert(map_addr);
/* Find the partition that could potentially contain a (previous) core dump. */ /* Find the partition that could potentially contain a (previous) core dump. */
@@ -823,46 +827,46 @@ static void elf_parse_exc_task_name(esp_core_dump_summary_t *summary, void *tcb_
static uint8_t *elf_core_dump_image_ptr(esp_partition_mmap_handle_t *core_data_handle) static uint8_t *elf_core_dump_image_ptr(esp_partition_mmap_handle_t *core_data_handle)
{ {
if (!core_data_handle) { if (!core_data_handle) {
return NULL; return NULL;
} }
const void *map_addr; const void *map_addr;
esp_err_t err = elf_core_dump_image_mmap(core_data_handle, &map_addr); esp_err_t err = elf_core_dump_image_mmap(core_data_handle, &map_addr);
if (err != ESP_OK) { if (err != ESP_OK) {
return NULL; return NULL;
} }
return (uint8_t *)map_addr + sizeof(core_dump_header_t); return (uint8_t *)map_addr + sizeof(core_dump_header_t);
} }
static void esp_core_dump_parse_note_section(uint8_t *coredump_data, elf_note_content_t *target_notes, size_t size) static void esp_core_dump_parse_note_section(uint8_t *coredump_data, elf_note_content_t *target_notes, size_t size)
{ {
elfhdr *eh = (elfhdr *)coredump_data; elfhdr *eh = (elfhdr *)coredump_data;
elf_phdr *phdr = (elf_phdr *)(coredump_data + eh->e_phoff); elf_phdr *phdr = (elf_phdr *)(coredump_data + eh->e_phoff);
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("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); ESP_COREDUMP_LOGD("Ph_num %d offset %x", eh->e_phnum, eh->e_phoff);
for (unsigned int i = 0; i < eh->e_phnum; i++) { for (unsigned int i = 0; i < eh->e_phnum; i++) {
const elf_phdr *ph = &phdr[i]; const elf_phdr *ph = &phdr[i];
ESP_COREDUMP_LOGD("PHDR type %d off %x vaddr %x paddr %x filesz %x memsz %x flags %x align %x", 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_type, ph->p_offset, ph->p_vaddr, ph->p_paddr, ph->p_filesz, ph->p_memsz,
ph->p_flags, ph->p_align); ph->p_flags, ph->p_align);
if (ph->p_type == PT_NOTE) { if (ph->p_type == PT_NOTE) {
size_t consumed_note_sz = 0; size_t consumed_note_sz = 0;
while (consumed_note_sz < ph->p_memsz) { while (consumed_note_sz < ph->p_memsz) {
const elf_note *note = (const elf_note *)(coredump_data + ph->p_offset + consumed_note_sz); const elf_note *note = (const elf_note *)(coredump_data + ph->p_offset + consumed_note_sz);
for (size_t idx = 0; idx < size; ++idx) { for (size_t idx = 0; idx < size; ++idx) {
if (target_notes[idx].n_type == note->n_type) { if (target_notes[idx].n_type == note->n_type) {
char *nm = (char *)&note[1]; char *nm = (char *)&note[1];
target_notes[idx].n_ptr = nm + note->n_namesz; target_notes[idx].n_ptr = nm + note->n_namesz;
target_notes[idx].n_descsz = note->n_descsz; target_notes[idx].n_descsz = note->n_descsz;
ESP_COREDUMP_LOGD("%d bytes target note (%X) found in the note section", ESP_COREDUMP_LOGD("%d bytes target note (%X) found in the note section",
note->n_descsz, note->n_type); note->n_descsz, note->n_type);
break; break;
} }
} }
consumed_note_sz += ALIGN_UP(note->n_namesz + note->n_descsz + sizeof(elf_note), 4); consumed_note_sz += ALIGN_UP(note->n_namesz + note->n_descsz + sizeof(elf_note), 4);
} }
} }
@@ -875,59 +879,59 @@ esp_err_t esp_core_dump_get_panic_reason(char *reason_buffer, size_t buffer_size
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
esp_partition_mmap_handle_t core_data_handle; esp_partition_mmap_handle_t core_data_handle;
uint8_t *ptr = elf_core_dump_image_ptr(&core_data_handle); uint8_t *ptr = elf_core_dump_image_ptr(&core_data_handle);
if (ptr == NULL) { if (ptr == NULL) {
return ESP_FAIL; return ESP_FAIL;
} }
elf_note_content_t target_note = { .n_type = ELF_ESP_CORE_DUMP_PANIC_DETAILS_TYPE, .n_ptr = NULL }; elf_note_content_t target_note = { .n_type = ELF_ESP_CORE_DUMP_PANIC_DETAILS_TYPE, .n_ptr = NULL };
esp_core_dump_parse_note_section(ptr, &target_note, 1); esp_core_dump_parse_note_section(ptr, &target_note, 1);
if (target_note.n_ptr) { if (target_note.n_ptr) {
size_t len = MIN(target_note.n_descsz, buffer_size - 1); size_t len = MIN(target_note.n_descsz, buffer_size - 1);
strncpy(reason_buffer, target_note.n_ptr, len); strncpy(reason_buffer, target_note.n_ptr, len);
reason_buffer[len] = '\0'; reason_buffer[len] = '\0';
} }
esp_partition_munmap(core_data_handle); esp_partition_munmap(core_data_handle);
return target_note.n_ptr ? ESP_OK : ESP_ERR_NOT_FOUND; return target_note.n_ptr ? ESP_OK : ESP_ERR_NOT_FOUND;
} }
esp_err_t esp_core_dump_get_summary(esp_core_dump_summary_t *summary) esp_err_t esp_core_dump_get_summary(esp_core_dump_summary_t *summary)
{ {
if (!summary) { if (!summary) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
esp_partition_mmap_handle_t core_data_handle; esp_partition_mmap_handle_t core_data_handle;
uint8_t *ptr = elf_core_dump_image_ptr(&core_data_handle); uint8_t *ptr = elf_core_dump_image_ptr(&core_data_handle);
if (ptr == NULL) { if (ptr == NULL) {
return ESP_FAIL; return ESP_FAIL;
} }
elf_note_content_t target_notes[2] = { elf_note_content_t target_notes[2] = {
[0] = { .n_type = ELF_ESP_CORE_DUMP_EXTRA_INFO_TYPE, .n_ptr = NULL }, [0] = { .n_type = ELF_ESP_CORE_DUMP_EXTRA_INFO_TYPE, .n_ptr = NULL },
[1] = { .n_type = ELF_ESP_CORE_DUMP_INFO_TYPE, .n_ptr = NULL } [1] = { .n_type = ELF_ESP_CORE_DUMP_INFO_TYPE, .n_ptr = NULL }
}; };
esp_core_dump_parse_note_section(ptr, target_notes, sizeof(target_notes) / sizeof(target_notes[0])); esp_core_dump_parse_note_section(ptr, target_notes, sizeof(target_notes) / sizeof(target_notes[0]));
if (target_notes[0].n_ptr) { if (target_notes[0].n_ptr) {
esp_core_dump_summary_parse_extra_info(summary, target_notes[0].n_ptr); esp_core_dump_summary_parse_extra_info(summary, target_notes[0].n_ptr);
} }
if (target_notes[1].n_ptr) { if (target_notes[1].n_ptr) {
elf_parse_version_info(summary, target_notes[1].n_ptr); elf_parse_version_info(summary, target_notes[1].n_ptr);
} }
/* Following code assumes that task stack segment follows the TCB segment for the respective task. /* 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. * 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. * 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.
*/ */
elfhdr *eh = (elfhdr *)ptr; elfhdr *eh = (elfhdr *)ptr;
elf_phdr *phdr = (elf_phdr *)(ptr + eh->e_phoff); elf_phdr *phdr = (elf_phdr *)(ptr + eh->e_phoff);
int flag = 0; int flag = 0;
for (unsigned int i = 0; i < eh->e_phnum; i++) { for (unsigned int i = 0; i < eh->e_phnum; i++) {
const elf_phdr *ph = &phdr[i]; const elf_phdr *ph = &phdr[i];
if (ph->p_type == PT_LOAD) { if (ph->p_type == PT_LOAD) {
if (flag) { if (flag) {
esp_core_dump_summary_parse_exc_regs(summary, (void *)(ptr + ph->p_offset)); esp_core_dump_summary_parse_exc_regs(summary, (void *)(ptr + ph->p_offset));

View File

@@ -19,8 +19,7 @@ const static char TAG[] __attribute__((unused)) = "esp_core_dump_flash";
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
typedef struct _core_dump_partition_t typedef struct _core_dump_partition_t {
{
/* Core dump partition start. */ /* Core dump partition start. */
uint32_t start; uint32_t start;
/* Core dump partition size. */ /* Core dump partition size. */
@@ -35,8 +34,7 @@ typedef struct _core_dump_partition_t
typedef uint32_t core_dump_crc_t; typedef uint32_t core_dump_crc_t;
typedef struct _core_dump_flash_config_t typedef struct _core_dump_flash_config_t {
{
/* Core dump partition config. */ /* Core dump partition config. */
core_dump_partition_t partition; core_dump_partition_t partition;
/* CRC of core dump partition config. */ /* CRC of core dump partition config. */
@@ -119,10 +117,11 @@ static esp_err_t esp_core_dump_flash_write_data(core_dump_write_data_t* priv, ui
/* Some bytes are in the cache, let's continue filling the cache /* Some bytes are in the cache, let's continue filling the cache
* with the data received as parameter. Let's calculate the maximum * with the data received as parameter. Let's calculate the maximum
* amount of bytes we can still fill the cache with. */ * amount of bytes we can still fill the cache with. */
if ((COREDUMP_CACHE_SIZE - wr_data->cached_bytes) > data_size) if ((COREDUMP_CACHE_SIZE - wr_data->cached_bytes) > data_size) {
wr_sz = data_size; wr_sz = data_size;
else } else {
wr_sz = COREDUMP_CACHE_SIZE - wr_data->cached_bytes; wr_sz = COREDUMP_CACHE_SIZE - wr_data->cached_bytes;
}
/* Append wr_sz bytes from data parameter to the cache. */ /* Append wr_sz bytes from data parameter to the cache. */
memcpy(&wr_data->cached_data[wr_data->cached_bytes], data, wr_sz); memcpy(&wr_data->cached_data[wr_data->cached_bytes], data, wr_sz);
@@ -366,7 +365,7 @@ void esp_core_dump_init(void)
uint32_t size = 0; uint32_t size = 0;
if (esp_core_dump_image_check() == ESP_OK if (esp_core_dump_image_check() == ESP_OK
&& esp_core_dump_partition_and_size_get(&partition, &size) == ESP_OK) { && esp_core_dump_partition_and_size_get(&partition, &size) == ESP_OK) {
ESP_COREDUMP_LOGI("Found core dump %d bytes in flash @ 0x%x", size, partition->address); ESP_COREDUMP_LOGI("Found core dump %d bytes in flash @ 0x%x", size, partition->address);
} }
#endif #endif

View File

@@ -21,7 +21,8 @@ const static char TAG[] __attribute__((unused)) = "esp_core_dump_uart";
* explicitly the header for each board. */ * explicitly the header for each board. */
int esp_clk_cpu_freq(void); int esp_clk_cpu_freq(void);
static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8_t *dst) { static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8_t *dst)
{
const static char b64[] = const static char b64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int i, j, a, b, c; int i, j, a, b, c;
@@ -97,7 +98,9 @@ static esp_err_t esp_core_dump_uart_write_data(core_dump_write_data_t *priv, voi
while (addr < end) { while (addr < end) {
size_t len = end - addr; size_t len = end - addr;
if (len > 48) len = 48; if (len > 48) {
len = 48;
}
/* Copy to stack to avoid alignment restrictions. */ /* Copy to stack to avoid alignment restrictions. */
char *tmp = buf + (sizeof(buf) - len); char *tmp = buf + (sizeof(buf) - len);
memcpy(tmp, addr, len); memcpy(tmp, addr, len);
@@ -113,7 +116,8 @@ static esp_err_t esp_core_dump_uart_write_data(core_dump_write_data_t *priv, voi
return err; return err;
} }
static int esp_core_dump_uart_get_char(void) { static int esp_core_dump_uart_get_char(void)
{
int i = -1; int i = -1;
uint32_t reg = (READ_PERI_REG(UART_STATUS_REG(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT; uint32_t reg = (READ_PERI_REG(UART_STATUS_REG(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
if (reg) { if (reg) {
@@ -130,7 +134,7 @@ void esp_core_dump_to_uart(panic_info_t *info)
.start = esp_core_dump_uart_write_start, .start = esp_core_dump_uart_write_start,
.end = esp_core_dump_uart_write_end, .end = esp_core_dump_uart_write_end,
.write = esp_core_dump_uart_write_data, .write = esp_core_dump_uart_write_data,
.priv = (void*)&wr_data .priv = (void*) &wr_data
}; };
uint32_t tm_end = 0; uint32_t tm_end = 0;
uint32_t tm_cur = 0; uint32_t tm_cur = 0;
@@ -153,7 +157,7 @@ void esp_core_dump_to_uart(panic_info_t *info)
ch = esp_core_dump_uart_get_char(); ch = esp_core_dump_uart_get_char();
while (!(ch == '\n' || ch == '\r')) { while (!(ch == '\n' || ch == '\r')) {
tm_cur = esp_cpu_get_cycle_count() / cpu_ticks_per_ms; tm_cur = esp_cpu_get_cycle_count() / cpu_ticks_per_ms;
if (tm_cur >= tm_end){ if (tm_cur >= tm_end) {
break; break;
} }
ch = esp_core_dump_uart_get_char(); ch = esp_core_dump_uart_get_char();

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -100,11 +100,11 @@ typedef union {
* Other fields are not strictly required by GDB, we can then replace them * Other fields are not strictly required by GDB, we can then replace them
* by a padding. Among these fields, we can find PPID, SID or system time. * by a padding. Among these fields, we can find PPID, SID or system time.
*/ */
#define PRSTATUS_SIZE 204 #define PRSTATUS_SIZE 204
#define PRSTATUS_OFFSET_PR_CURSIG 12 #define PRSTATUS_OFFSET_PR_CURSIG 12
#define PRSTATUS_OFFSET_PR_PID 24 #define PRSTATUS_OFFSET_PR_PID 24
#define PRSTATUS_OFFSET_PR_REG 72 #define PRSTATUS_OFFSET_PR_REG 72
#define ELF_GREGSET_T_SIZE 128 #define ELF_GREGSET_T_SIZE 128
/* We can determine the padding thanks to the previous macros */ /* We can determine the padding thanks to the previous macros */
#define PRSTATUS_SIG_PADDING (PRSTATUS_OFFSET_PR_CURSIG) #define PRSTATUS_SIG_PADDING (PRSTATUS_OFFSET_PR_CURSIG)
@@ -126,15 +126,15 @@ typedef struct {
* Assert that our structure is designed the way we are expecting it to be. * Assert that our structure is designed the way we are expecting it to be.
*/ */
_Static_assert(offsetof(riscv_prstatus, signal) == PRSTATUS_OFFSET_PR_CURSIG, _Static_assert(offsetof(riscv_prstatus, signal) == PRSTATUS_OFFSET_PR_CURSIG,
"Wrong offset for signal field in riscv_prstatus structure"); "Wrong offset for signal field in riscv_prstatus structure");
_Static_assert(offsetof(riscv_prstatus, pid) == PRSTATUS_OFFSET_PR_PID, _Static_assert(offsetof(riscv_prstatus, pid) == PRSTATUS_OFFSET_PR_PID,
"Wrong offset for pid field in riscv_prstatus structure"); "Wrong offset for pid field in riscv_prstatus structure");
_Static_assert(offsetof(riscv_prstatus, regs) == PRSTATUS_OFFSET_PR_REG, _Static_assert(offsetof(riscv_prstatus, regs) == PRSTATUS_OFFSET_PR_REG,
"Wrong offset for regs field in riscv_prstatus structure"); "Wrong offset for regs field in riscv_prstatus structure");
_Static_assert(sizeof(riscv_regs) == ELF_GREGSET_T_SIZE, _Static_assert(sizeof(riscv_regs) == ELF_GREGSET_T_SIZE,
"Wrong size for riscv_regs union"); "Wrong size for riscv_regs union");
_Static_assert(sizeof(riscv_prstatus) == PRSTATUS_SIZE, _Static_assert(sizeof(riscv_prstatus) == PRSTATUS_SIZE,
"Wrong size for riscv_prstatus structure"); "Wrong size for riscv_prstatus structure");
/** /**
* Structure used to add some extra info inside core file. * Structure used to add some extra info inside core file.
@@ -144,7 +144,6 @@ typedef struct {
uint32_t isr_context; uint32_t isr_context;
} riscv_extra_info_t; } riscv_extra_info_t;
/* Allocate the fake stack that will be used by broken tasks. */ /* Allocate the fake stack that will be used by broken tasks. */
static RvExcFrame s_fake_stack_frame = { static RvExcFrame s_fake_stack_frame = {
.mepc = COREDUMP_FAKE_STACK_START, .mepc = COREDUMP_FAKE_STACK_START,
@@ -214,7 +213,7 @@ uint8_t* esp_core_dump_get_isr_stack_top(void)
uint32_t esp_core_dump_get_isr_stack_end(void) uint32_t esp_core_dump_get_isr_stack_end(void)
{ {
uint8_t* isr_top_stack = esp_core_dump_get_isr_stack_top(); uint8_t* isr_top_stack = esp_core_dump_get_isr_stack_top();
return (uint32_t)(isr_top_stack + (xPortGetCoreID()+1)*configISR_STACK_SIZE); return (uint32_t)(isr_top_stack + (xPortGetCoreID() + 1) * configISR_STACK_SIZE);
} }
/** /**
@@ -224,21 +223,21 @@ static inline bool esp_core_dump_task_stack_end_is_sane(uint32_t sp)
{ {
return esp_ptr_in_dram((void *)sp) return esp_ptr_in_dram((void *)sp)
#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY #if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|| esp_stack_ptr_in_extram(sp) || esp_stack_ptr_in_extram(sp)
#endif #endif
#if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|| esp_ptr_in_rtc_dram_fast((void*) sp) || esp_ptr_in_rtc_dram_fast((void*) sp)
#endif #endif
; ;
} }
bool esp_core_dump_check_stack(core_dump_task_header_t *task) bool esp_core_dump_check_stack(core_dump_task_header_t *task)
{ {
// Check task's stack // Check task's stack
if (!esp_stack_ptr_is_sane(task->stack_start) || if (!esp_stack_ptr_is_sane(task->stack_start) ||
!esp_core_dump_task_stack_end_is_sane(task->stack_end) || !esp_core_dump_task_stack_end_is_sane(task->stack_end) ||
(task->stack_start >= task->stack_end) || (task->stack_start >= task->stack_end) ||
((task->stack_end-task->stack_start) > COREDUMP_MAX_TASK_STACK_SIZE)) { ((task->stack_end - task->stack_start) > COREDUMP_MAX_TASK_STACK_SIZE)) {
// Check if current task stack is corrupted // Check if current task stack is corrupted
ESP_COREDUMP_LOG_PROCESS("Invalid stack (%x...%x)!", task->stack_start, task->stack_end); ESP_COREDUMP_LOG_PROCESS("Invalid stack (%x...%x)!", task->stack_start, task->stack_end);
return false; return false;
@@ -264,7 +263,7 @@ uint32_t esp_core_dump_get_stack(core_dump_task_header_t *task,
*stk_vaddr = stack_addr; *stk_vaddr = stack_addr;
if (stack_addr >= COREDUMP_FAKE_STACK_START && if (stack_addr >= COREDUMP_FAKE_STACK_START &&
stack_addr < COREDUMP_FAKE_STACK_LIMIT) { stack_addr < COREDUMP_FAKE_STACK_LIMIT) {
/* In this case, the stack address pointed by the task is a fake stack /* In this case, the stack address pointed by the task is a fake stack
* generated previously. So it doesn't really point to actual data. * generated previously. So it doesn't really point to actual data.
* Thus, we must provide the address of the fake stack data. */ * Thus, we must provide the address of the fake stack data. */
@@ -308,11 +307,11 @@ bool esp_core_dump_check_task(core_dump_task_header_t *task)
*/ */
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)
{ {
return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr+sz-1))) return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr + sz - 1)))
|| (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr+sz-1))) || (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr + sz - 1)))
|| (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr+sz-1))) || (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr + sz - 1)))
|| (esp_ptr_external_ram((void *)addr) && esp_ptr_external_ram((void *)(addr+sz-1))) || (esp_ptr_external_ram((void *)addr) && esp_ptr_external_ram((void *)(addr + sz - 1)))
|| (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr+sz-1))); || (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr + sz - 1)));
} }
/** /**
@@ -355,7 +354,8 @@ uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task, void **
/** /**
* Save the crashed task handle in the extra info structure. * Save the crashed task handle in the extra info structure.
*/ */
void esp_core_dump_port_set_crashed_tcb(uint32_t handle) { void esp_core_dump_port_set_crashed_tcb(uint32_t handle)
{
s_extra_info.crashed_task_tcb = handle; s_extra_info.crashed_task_tcb = handle;
} }
@@ -401,7 +401,7 @@ void esp_core_dump_summary_parse_exc_regs(esp_core_dump_summary_t *summary, void
summary->ex_info.ra = stack->ra; summary->ex_info.ra = stack->ra;
summary->ex_info.sp = stack->sp; summary->ex_info.sp = stack->sp;
ESP_COREDUMP_LOGD("mstatus:0x%x mtvec:0x%x mcause:0x%x mval:0x%x RA: 0x%x SP: 0x%x", ESP_COREDUMP_LOGD("mstatus:0x%x mtvec:0x%x mcause:0x%x mval:0x%x RA: 0x%x SP: 0x%x",
stack->mstatus, stack->mtvec, stack->mcause, stack->mtval, stack->ra, stack->sp); stack->mstatus, stack->mtvec, stack->mcause, stack->mtval, stack->ra, stack->sp);
a_reg = &stack->a0; a_reg = &stack->a0;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
summary->ex_info.exc_a[i] = a_reg[i]; summary->ex_info.exc_a[i] = a_reg[i];
@@ -420,7 +420,7 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info
/* Check whether the stack is a fake stack created during coredump generation /* Check whether the stack is a fake stack created during coredump generation
* If its a fake stack, we don't have any actual stack dump * If its a fake stack, we don't have any actual stack dump
*/ */
if (vaddr >= (void*) COREDUMP_FAKE_STACK_START && vaddr < (void*) COREDUMP_FAKE_STACK_LIMIT) { if (vaddr >= (void *) COREDUMP_FAKE_STACK_START && vaddr < (void *) COREDUMP_FAKE_STACK_LIMIT) {
bt_info->dump_size = 0; bt_info->dump_size = 0;
return; return;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -44,8 +44,7 @@ const static char TAG[] __attribute__((unused)) = "esp_core_dump_port";
// Enumeration of registers of exception stack frame // Enumeration of registers of exception stack frame
// and solicited stack frame // and solicited stack frame
typedef enum typedef enum {
{
// XT_SOL_EXIT = 0, // XT_SOL_EXIT = 0,
XT_SOL_PC = 1, XT_SOL_PC = 1,
XT_SOL_PS = 2, XT_SOL_PS = 2,
@@ -69,8 +68,7 @@ typedef enum
// Xtensa ELF core file register set representation ('.reg' section). // Xtensa ELF core file register set representation ('.reg' section).
// Copied from target-side ELF header <xtensa/elf.h>. // Copied from target-side ELF header <xtensa/elf.h>.
typedef struct typedef struct {
{
uint32_t pc; uint32_t pc;
uint32_t ps; uint32_t ps;
uint32_t lbeg; uint32_t lbeg;
@@ -79,18 +77,16 @@ typedef struct
uint32_t sar; uint32_t sar;
uint32_t windowstart; uint32_t windowstart;
uint32_t windowbase; uint32_t windowbase;
uint32_t reserved[8+48]; uint32_t reserved[8 + 48];
uint32_t ar[XCHAL_NUM_AREGS]; uint32_t ar[XCHAL_NUM_AREGS];
} __attribute__((packed)) xtensa_gregset_t; } __attribute__((packed)) xtensa_gregset_t;
typedef struct typedef struct {
{
uint32_t reg_index; uint32_t reg_index;
uint32_t reg_val; uint32_t reg_val;
} __attribute__((packed)) core_dump_reg_pair_t; } __attribute__((packed)) core_dump_reg_pair_t;
typedef struct typedef struct {
{
uint32_t crashed_task_tcb; uint32_t crashed_task_tcb;
core_dump_reg_pair_t exccause; core_dump_reg_pair_t exccause;
core_dump_reg_pair_t excvaddr; core_dump_reg_pair_t excvaddr;
@@ -99,8 +95,7 @@ typedef struct
} __attribute__((packed)) xtensa_extra_info_t; } __attribute__((packed)) xtensa_extra_info_t;
// Xtensa Program Status for GDB // Xtensa Program Status for GDB
typedef struct typedef struct {
{
uint32_t si_signo; uint32_t si_signo;
uint32_t si_code; uint32_t si_code;
uint32_t si_errno; uint32_t si_errno;
@@ -118,8 +113,7 @@ typedef struct
uint64_t pr_cstime; uint64_t pr_cstime;
} __attribute__((packed)) xtensa_pr_status_t; } __attribute__((packed)) xtensa_pr_status_t;
typedef struct typedef struct {
{
xtensa_pr_status_t pr_status; xtensa_pr_status_t pr_status;
xtensa_gregset_t regs; xtensa_gregset_t regs;
// Todo: acc to xtensa_gregset_t number of regs must be 128, // Todo: acc to xtensa_gregset_t number of regs must be 128,
@@ -132,7 +126,7 @@ typedef struct
static XtExcFrame s_fake_stack_frame = { static XtExcFrame s_fake_stack_frame = {
.pc = (UBaseType_t) COREDUMP_FAKE_STACK_START, // task entrypoint fake_ptr .pc = (UBaseType_t) COREDUMP_FAKE_STACK_START, // task entrypoint fake_ptr
.a0 = (UBaseType_t) 0, // to terminate GDB backtrace .a0 = (UBaseType_t) 0, // to terminate GDB backtrace
.a1 = (UBaseType_t) (COREDUMP_FAKE_STACK_START + sizeof(XtExcFrame)), // physical top of stack frame .a1 = (UBaseType_t)(COREDUMP_FAKE_STACK_START + sizeof(XtExcFrame)), // physical top of stack frame
.exit = (UBaseType_t) 0, // user exception exit dispatcher .exit = (UBaseType_t) 0, // user exception exit dispatcher
.ps = (PS_UM | PS_EXCM), .ps = (PS_UM | PS_EXCM),
.exccause = (UBaseType_t) COREDUMP_INVALID_CAUSE_VALUE, .exccause = (UBaseType_t) COREDUMP_INVALID_CAUSE_VALUE,
@@ -152,10 +146,9 @@ static xtensa_extra_info_t s_extra_info;
static void *esp_core_dump_get_fake_stack(uint32_t *stk_len) static void *esp_core_dump_get_fake_stack(uint32_t *stk_len)
{ {
*stk_len = sizeof(s_fake_stack_frame); *stk_len = sizeof(s_fake_stack_frame);
return (uint8_t*)COREDUMP_FAKE_STACK_START + sizeof(s_fake_stack_frame)*s_fake_stacks_num++; return (uint8_t*)COREDUMP_FAKE_STACK_START + sizeof(s_fake_stack_frame) * s_fake_stacks_num++;
} }
static core_dump_reg_pair_t *esp_core_dump_get_epc_regs(core_dump_reg_pair_t* src) static core_dump_reg_pair_t *esp_core_dump_get_epc_regs(core_dump_reg_pair_t* src)
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
@@ -195,8 +188,8 @@ static core_dump_reg_pair_t *esp_core_dump_get_eps_regs(core_dump_reg_pair_t* sr
// Returns list of registers (in GDB format) from xtensa stack frame // Returns list of registers (in GDB format) from xtensa stack frame
static esp_err_t esp_core_dump_get_regs_from_stack(void* stack_addr, static esp_err_t esp_core_dump_get_regs_from_stack(void* stack_addr,
size_t size, size_t size,
xtensa_gregset_t* regs) xtensa_gregset_t* regs)
{ {
XtExcFrame* exc_frame = (XtExcFrame*)stack_addr; XtExcFrame* exc_frame = (XtExcFrame*)stack_addr;
uint32_t* stack_arr = (uint32_t*)stack_addr; uint32_t* stack_arr = (uint32_t*)stack_addr;
@@ -210,8 +203,7 @@ static esp_err_t esp_core_dump_get_regs_from_stack(void* stack_addr,
uint32_t rc = exc_frame->exit; uint32_t rc = exc_frame->exit;
// is this current crashed task? // is this current crashed task?
if (rc == COREDUMP_CURR_TASK_MARKER) if (rc == COREDUMP_CURR_TASK_MARKER) {
{
s_extra_info.exccause.reg_val = exc_frame->exccause; s_extra_info.exccause.reg_val = exc_frame->exccause;
s_extra_info.exccause.reg_index = EXCCAUSE; s_extra_info.exccause.reg_index = EXCCAUSE;
s_extra_info.excvaddr.reg_val = exc_frame->excvaddr; s_extra_info.excvaddr.reg_val = exc_frame->excvaddr;
@@ -301,30 +293,28 @@ uint8_t* esp_core_dump_get_isr_stack_top(void)
uint32_t esp_core_dump_get_isr_stack_end(void) uint32_t esp_core_dump_get_isr_stack_end(void)
{ {
uint8_t* isr_top_stack = esp_core_dump_get_isr_stack_top(); uint8_t* isr_top_stack = esp_core_dump_get_isr_stack_top();
return (uint32_t)(isr_top_stack + (xPortGetCoreID()+1)*configISR_STACK_SIZE); return (uint32_t)(isr_top_stack + (xPortGetCoreID() + 1) * configISR_STACK_SIZE);
} }
static 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)
{ {
return esp_ptr_in_dram((void *)sp) return esp_ptr_in_dram((void *)sp)
#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY #if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|| esp_stack_ptr_in_extram(sp) || esp_stack_ptr_in_extram(sp)
#endif #endif
#if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|| esp_ptr_in_rtc_dram_fast((void*) sp) || esp_ptr_in_rtc_dram_fast((void*) sp)
#endif #endif
; ;
} }
bool esp_core_dump_check_stack(core_dump_task_header_t *task) bool esp_core_dump_check_stack(core_dump_task_header_t *task)
{ {
// Check task's stack // Check task's stack
if (!esp_stack_ptr_is_sane(task->stack_start) || if (!esp_stack_ptr_is_sane(task->stack_start) ||
!esp_core_dump_task_stack_end_is_sane(task->stack_end) || !esp_core_dump_task_stack_end_is_sane(task->stack_end) ||
(task->stack_start >= task->stack_end) || (task->stack_start >= task->stack_end) ||
((task->stack_end-task->stack_start) > COREDUMP_MAX_TASK_STACK_SIZE)) { ((task->stack_end - task->stack_start) > COREDUMP_MAX_TASK_STACK_SIZE)) {
// Check if current task stack is corrupted // Check if current task stack is corrupted
ESP_COREDUMP_LOG_PROCESS("Invalid stack (%x...%x)!", task->stack_start, task->stack_end); ESP_COREDUMP_LOG_PROCESS("Invalid stack (%x...%x)!", task->stack_start, task->stack_end);
return false; return false;
@@ -339,11 +329,11 @@ bool esp_core_dump_check_stack(core_dump_task_header_t *task)
*/ */
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)
{ {
return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr+sz-1))) return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr + sz - 1)))
|| (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr+sz-1))) || (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr + sz - 1)))
|| (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr+sz-1))) || (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr + sz - 1)))
|| (esp_ptr_external_ram((void *)addr) && esp_ptr_external_ram((void *)(addr+sz-1))) || (esp_ptr_external_ram((void *)addr) && esp_ptr_external_ram((void *)(addr + sz - 1)))
|| (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr+sz-1))); || (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr + sz - 1)));
} }
/** /**
@@ -363,7 +353,7 @@ uint32_t esp_core_dump_get_stack(core_dump_task_header_t *task,
*stk_vaddr = stack_addr; *stk_vaddr = stack_addr;
if (stack_addr >= COREDUMP_FAKE_STACK_START && if (stack_addr >= COREDUMP_FAKE_STACK_START &&
stack_addr < COREDUMP_FAKE_STACK_LIMIT) { stack_addr < COREDUMP_FAKE_STACK_LIMIT) {
/* In this case, the stack address pointed by the task is a fake stack /* In this case, the stack address pointed by the task is a fake stack
* generated previously. So it doesn't really point to actual data. * generated previously. So it doesn't really point to actual data.
* Thus, we must provide the address of the fake stack data. */ * Thus, we must provide the address of the fake stack data. */
@@ -393,45 +383,44 @@ bool esp_core_dump_check_task(core_dump_task_header_t *task)
if (!stack_is_valid) { if (!stack_is_valid) {
// Skip saving of invalid task if stack corrupted // Skip saving of invalid task if stack corrupted
ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), stack is corrupted (%x, %x)", ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), stack is corrupted (%x, %x)",
task->tcb_addr, task->tcb_addr,
task->stack_start, task->stack_start,
task->stack_end); task->stack_end);
task->stack_start = (uint32_t)esp_core_dump_get_fake_stack(&stk_size); task->stack_start = (uint32_t)esp_core_dump_get_fake_stack(&stk_size);
task->stack_end = (uint32_t)(task->stack_start + stk_size); task->stack_end = (uint32_t)(task->stack_start + stk_size);
ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), use start, end (%x, %x)", ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), use start, end (%x, %x)",
task->tcb_addr, task->tcb_addr,
task->stack_start, task->stack_start,
task->stack_end); task->stack_end);
} else { } else {
/* This shall be done only if the stack was correct, else, stack_start /* This shall be done only if the stack was correct, else, stack_start
* would point to a fake address. */ * would point to a fake address. */
XtSolFrame *sol_frame = (XtSolFrame *)task->stack_start; XtSolFrame *sol_frame = (XtSolFrame *)task->stack_start;
if (sol_frame->exit == 0) { if (sol_frame->exit == 0) {
ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), EXIT/PC/PS/A0/SP %x %x %x %x %x", ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), EXIT/PC/PS/A0/SP %x %x %x %x %x",
task->tcb_addr, task->tcb_addr,
sol_frame->exit, sol_frame->exit,
sol_frame->pc, sol_frame->pc,
sol_frame->ps, sol_frame->ps,
sol_frame->a0, sol_frame->a0,
sol_frame->a1); sol_frame->a1);
} else { } else {
// to avoid warning that 'exc_frame' is unused when ESP_COREDUMP_LOG_PROCESS does nothing // to avoid warning that 'exc_frame' is unused when ESP_COREDUMP_LOG_PROCESS does nothing
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_LOGS #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_LOGS
XtExcFrame *exc_frame = (XtExcFrame *)task->stack_start; XtExcFrame *exc_frame = (XtExcFrame *)task->stack_start;
ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) EXIT/PC/PS/A0/SP %x %x %x %x %x", ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) EXIT/PC/PS/A0/SP %x %x %x %x %x",
task->tcb_addr, task->tcb_addr,
exc_frame->exit, exc_frame->exit,
exc_frame->pc, exc_frame->pc,
exc_frame->ps, exc_frame->ps,
exc_frame->a0, exc_frame->a0,
exc_frame->a1); exc_frame->a1);
#endif #endif
} }
} }
return true; return true;
} }
/** /**
* Get a dump of the task's registers. * Get a dump of the task's registers.
* Check core dump port interface for more information about this function. * Check core dump port interface for more information about this function.
@@ -455,8 +444,8 @@ uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task, void **
// fill the gdb registers structure from stack // fill the gdb registers structure from stack
esp_err_t err = esp_core_dump_get_regs_from_stack((void*)stack_paddr, esp_err_t err = esp_core_dump_get_regs_from_stack((void*)stack_paddr,
stack_len, stack_len,
&s_reg_dump.regs); &s_reg_dump.regs);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Error while registers processing."); ESP_COREDUMP_LOGE("Error while registers processing.");
} }
@@ -464,8 +453,8 @@ uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task, void **
return sizeof(s_reg_dump); return sizeof(s_reg_dump);
} }
void esp_core_dump_port_set_crashed_tcb(uint32_t handle)
void esp_core_dump_port_set_crashed_tcb(uint32_t handle) { {
s_extra_info.crashed_task_tcb = handle; s_extra_info.crashed_task_tcb = handle;
} }
@@ -496,9 +485,9 @@ void esp_core_dump_summary_parse_extra_info(esp_core_dump_summary_t *summary, vo
memset(summary->ex_info.epcx, 0, sizeof(summary->ex_info.epcx)); memset(summary->ex_info.epcx, 0, sizeof(summary->ex_info.epcx));
summary->ex_info.epcx_reg_bits = 0; summary->ex_info.epcx_reg_bits = 0;
for (i = 0; i < COREDUMP_EXTRA_REG_NUM; i++ ) { for (i = 0; i < COREDUMP_EXTRA_REG_NUM; i++) {
if (ei->extra_regs[i].reg_index >= EPC_1 if (ei->extra_regs[i].reg_index >= EPC_1
&& ei->extra_regs[i].reg_index < (EPC_1 + XCHAL_NUM_INTLEVELS)) { && 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[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)); summary->ex_info.epcx_reg_bits |= (1 << (ei->extra_regs[i].reg_index - EPC_1));
} }
@@ -531,7 +520,7 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info
bool corrupted; bool corrupted;
esp_backtrace_frame_t frame; esp_backtrace_frame_t frame;
XtExcFrame *stack = (XtExcFrame *) paddr; XtExcFrame *stack = (XtExcFrame *) paddr;
int max_depth = (int) (sizeof(bt_info->bt) / sizeof(bt_info->bt[0])); int max_depth = (int)(sizeof(bt_info->bt) / sizeof(bt_info->bt[0]));
int index = 0; int index = 0;
frame.pc = stack->pc; frame.pc = stack->pc;
@@ -539,8 +528,8 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info
frame.next_pc = stack->a0; frame.next_pc = stack->a0;
corrupted = !(esp_stack_ptr_is_sane(frame.sp) && corrupted = !(esp_stack_ptr_is_sane(frame.sp) &&
(esp_ptr_executable((void *)esp_cpu_process_stack_pc(frame.pc)) || (esp_ptr_executable((void *)esp_cpu_process_stack_pc(frame.pc)) ||
stack->exccause == EXCCAUSE_INSTR_PROHIBITED)); /* Ignore the first corrupted PC in case of InstrFetchProhibited */ stack->exccause == EXCCAUSE_INSTR_PROHIBITED)); /* Ignore the first corrupted PC in case of InstrFetchProhibited */
/* vaddr is actual stack address when crash occurred. However that stack is now saved /* 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 * in the flash at a different location. Hence for each SP, we need to adjust the offset
@@ -555,7 +544,7 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info
while (max_depth-- > 0 && frame.next_pc && !corrupted) { while (max_depth-- > 0 && frame.next_pc && !corrupted) {
/* Check if the Stack Pointer is in valid address range */ /* Check if the Stack Pointer is in valid address range */
if (!((uint32_t)frame.sp >= (uint32_t)vaddr && if (!((uint32_t)frame.sp >= (uint32_t)vaddr &&
((uint32_t)frame.sp <= (uint32_t)vaddr + stack_size))) { ((uint32_t)frame.sp <= (uint32_t)vaddr + stack_size))) {
corrupted = true; corrupted = true;
break; break;
} }

View File

@@ -30,7 +30,7 @@ extern int _coredump_rtc_fast_end;
static inline bool is_addr_in_region(void *addr, uint8_t *region, int region_size) static inline bool is_addr_in_region(void *addr, uint8_t *region, int region_size)
{ {
const void *start = (void *) region; const void *start = (void *) region;
const void *end = (void *) (region + region_size); const void *end = (void *)(region + region_size);
return addr >= start && addr < end; return addr >= start && addr < end;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -291,9 +291,9 @@ static bool enum_stage_start(enum_ctrl_t *enum_ctrl)
enum_ctrl->pipe = enum_dflt_pipe_hdl; enum_ctrl->pipe = enum_dflt_pipe_hdl;
// Flag to gracefully exit the enumeration process if requested by the user in the enumeration filter cb // Flag to gracefully exit the enumeration process if requested by the user in the enumeration filter cb
#ifdef ENABLE_ENUM_FILTER_CALLBACK #ifdef ENABLE_ENUM_FILTER_CALLBACK
enum_ctrl->graceful_exit = false; enum_ctrl->graceful_exit = false;
#endif // ENABLE_ENUM_FILTER_CALLBACK #endif // ENABLE_ENUM_FILTER_CALLBACK
return true; return true;
} }
@@ -339,7 +339,7 @@ static void get_string_desc_index_and_langid(enum_ctrl_t *enum_ctrl, uint8_t *in
static bool set_config_index(enum_ctrl_t *enum_ctrl, const usb_device_desc_t *device_desc) static bool set_config_index(enum_ctrl_t *enum_ctrl, const usb_device_desc_t *device_desc)
{ {
#ifdef ENABLE_ENUM_FILTER_CALLBACK #ifdef ENABLE_ENUM_FILTER_CALLBACK
// Callback enabled in the menuncofig, but the callback function was not defined // Callback enabled in the menuncofig, but the callback function was not defined
if (enum_ctrl->enum_filter_cb == NULL) { if (enum_ctrl->enum_filter_cb == NULL) {
enum_ctrl->enum_config_index = ENUM_CONFIG_INDEX_DEFAULT; enum_ctrl->enum_config_index = ENUM_CONFIG_INDEX_DEFAULT;
@@ -363,9 +363,9 @@ static bool set_config_index(enum_ctrl_t *enum_ctrl, const usb_device_desc_t *de
} else { } else {
enum_ctrl->enum_config_index = enum_config_index - 1; enum_ctrl->enum_config_index = enum_config_index - 1;
} }
#else // ENABLE_ENUM_FILTER_CALLBACK #else // ENABLE_ENUM_FILTER_CALLBACK
enum_ctrl->enum_config_index = ENUM_CONFIG_INDEX_DEFAULT; enum_ctrl->enum_config_index = ENUM_CONFIG_INDEX_DEFAULT;
#endif // ENABLE_ENUM_FILTER_CALLBACK #endif // ENABLE_ENUM_FILTER_CALLBACK
return true; return true;
} }
@@ -971,15 +971,15 @@ static void enum_handle_events(void)
if (stage_pass) { if (stage_pass) {
ESP_LOGD(HUB_DRIVER_TAG, "Stage done: %s", enum_stage_strings[enum_ctrl->stage]); ESP_LOGD(HUB_DRIVER_TAG, "Stage done: %s", enum_stage_strings[enum_ctrl->stage]);
} else { } else {
#ifdef ENABLE_ENUM_FILTER_CALLBACK #ifdef ENABLE_ENUM_FILTER_CALLBACK
if (!enum_ctrl->graceful_exit) { if (!enum_ctrl->graceful_exit) {
ESP_LOGE(HUB_DRIVER_TAG, "Stage failed: %s", enum_stage_strings[enum_ctrl->stage]); ESP_LOGE(HUB_DRIVER_TAG, "Stage failed: %s", enum_stage_strings[enum_ctrl->stage]);
} else { } else {
ESP_LOGD(HUB_DRIVER_TAG, "Stage done: %s", enum_stage_strings[enum_ctrl->stage]); ESP_LOGD(HUB_DRIVER_TAG, "Stage done: %s", enum_stage_strings[enum_ctrl->stage]);
} }
#else // ENABLE_ENUM_FILTER_CALLBACK #else // ENABLE_ENUM_FILTER_CALLBACK
ESP_LOGE(HUB_DRIVER_TAG, "Stage failed: %s", enum_stage_strings[enum_ctrl->stage]); ESP_LOGE(HUB_DRIVER_TAG, "Stage failed: %s", enum_stage_strings[enum_ctrl->stage]);
#endif // ENABLE_ENUM_FILTER_CALLBACK #endif // ENABLE_ENUM_FILTER_CALLBACK
} }
enum_set_next_stage(enum_ctrl, stage_pass); enum_set_next_stage(enum_ctrl, stage_pass);
} }
@@ -1014,9 +1014,9 @@ esp_err_t hub_install(hub_config_t *hub_config)
hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED; hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED;
hub_driver_obj->single_thread.enum_ctrl.stage = ENUM_STAGE_NONE; hub_driver_obj->single_thread.enum_ctrl.stage = ENUM_STAGE_NONE;
hub_driver_obj->single_thread.enum_ctrl.urb = enum_urb; hub_driver_obj->single_thread.enum_ctrl.urb = enum_urb;
#ifdef ENABLE_ENUM_FILTER_CALLBACK #ifdef ENABLE_ENUM_FILTER_CALLBACK
hub_driver_obj->single_thread.enum_ctrl.enum_filter_cb = hub_config->enum_filter_cb; hub_driver_obj->single_thread.enum_ctrl.enum_filter_cb = hub_config->enum_filter_cb;
#endif // ENABLE_ENUM_FILTER_CALLBACK #endif // ENABLE_ENUM_FILTER_CALLBACK
hub_driver_obj->constant.root_port_hdl = port_hdl; hub_driver_obj->constant.root_port_hdl = port_hdl;
hub_driver_obj->constant.proc_req_cb = hub_config->proc_req_cb; hub_driver_obj->constant.proc_req_cb = hub_config->proc_req_cb;
hub_driver_obj->constant.proc_req_cb_arg = hub_config->proc_req_cb_arg; hub_driver_obj->constant.proc_req_cb_arg = hub_config->proc_req_cb_arg;

View File

@@ -22,7 +22,6 @@ extern "C" {
// ---------------------------------------------------- HID Mouse ------------------------------------------------------ // ---------------------------------------------------- HID Mouse ------------------------------------------------------
/* /*
Note: The mock HID mouse tests require that USB low speed mouse be connected. The mouse should... Note: The mock HID mouse tests require that USB low speed mouse be connected. The mouse should...

View File

@@ -70,7 +70,6 @@ components_not_formatted_temporary:
- "/components/esp_rom/" - "/components/esp_rom/"
- "/components/esp_wifi/" - "/components/esp_wifi/"
- "/components/esp-tls/" - "/components/esp-tls/"
- "/components/espcoredump/"
- "/components/esptool_py/" - "/components/esptool_py/"
- "/components/fatfs/" - "/components/fatfs/"
- "/components/hal/" - "/components/hal/"
@@ -165,6 +164,8 @@ components_not_formatted_permanent:
# Example resource files (generated) # Example resource files (generated)
- "/examples/peripherals/lcd/i80_controller/main/images/" - "/examples/peripherals/lcd/i80_controller/main/images/"
- "/examples/peripherals/dac/dac_continuous/dac_audio/main/audio_example_file.h" - "/examples/peripherals/dac/dac_continuous/dac_audio/main/audio_example_file.h"
# Coredump (generated)
- /components/espcoredump/include_core_dump/elf.h
docs: docs:
# Docs directory contains some .inc files, which are not C include files # Docs directory contains some .inc files, which are not C include files