mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 18:10:57 +02:00
Merge branch 'fix/coredump_max_tasks_num_v5.3' into 'release/v5.3'
fix(coredump): implement CONFIG_ESP_COREDUMP_MAX_TASKS_NUM limitation (v5.3) See merge request espressif/esp-idf!41129
This commit is contained in:
@@ -86,7 +86,9 @@ menu "Core dump"
|
|||||||
depends on ESP_COREDUMP_ENABLE
|
depends on ESP_COREDUMP_ENABLE
|
||||||
default 64
|
default 64
|
||||||
help
|
help
|
||||||
Maximum number of tasks snapshots in core dump.
|
Maximum number of tasks that will be included in the core dump.
|
||||||
|
Crashed task registers and stacks are always included.
|
||||||
|
Other tasks are included in order of their priority. (Highest priority ready task first)
|
||||||
|
|
||||||
config ESP_COREDUMP_UART_DELAY
|
config ESP_COREDUMP_UART_DELAY
|
||||||
int "Delay before print to UART"
|
int "Delay before print to UART"
|
||||||
|
@@ -412,6 +412,7 @@ static int elf_process_tasks_regs(core_dump_elf_t *self)
|
|||||||
void *task = NULL;
|
void *task = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int tasks_num = 0;
|
||||||
|
|
||||||
esp_core_dump_reset_tasks_snapshots_iter();
|
esp_core_dump_reset_tasks_snapshots_iter();
|
||||||
task = esp_core_dump_get_current_task_handle();
|
task = esp_core_dump_get_current_task_handle();
|
||||||
@@ -425,6 +426,7 @@ static int elf_process_tasks_regs(core_dump_elf_t *self)
|
|||||||
ELF_CHECK_ERR((ret > 0), ret, "Task %x, PR_STATUS write failed, return (%d).", task, ret);
|
ELF_CHECK_ERR((ret > 0), ret, "Task %x, PR_STATUS write failed, return (%d).", task, ret);
|
||||||
}
|
}
|
||||||
len += ret;
|
len += ret;
|
||||||
|
tasks_num++;
|
||||||
}
|
}
|
||||||
// processes PR_STATUS and register dump for each task
|
// processes PR_STATUS and register dump for each task
|
||||||
// each call to the processing function appends PR_STATUS note into note segment
|
// each call to the processing function appends PR_STATUS note into note segment
|
||||||
@@ -435,6 +437,11 @@ static int elf_process_tasks_regs(core_dump_elf_t *self)
|
|||||||
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 (tasks_num > CONFIG_ESP_COREDUMP_MAX_TASKS_NUM) {
|
||||||
|
ESP_COREDUMP_LOG_PROCESS("Reached maximum number of tasks (%d), stopping task register processing",
|
||||||
|
CONFIG_ESP_COREDUMP_MAX_TASKS_NUM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
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) {
|
||||||
@@ -444,6 +451,7 @@ static int elf_process_tasks_regs(core_dump_elf_t *self)
|
|||||||
ELF_CHECK_ERR((ret > 0), ret, "Task %x, PR_STATUS write failed, return (%d).", task, ret);
|
ELF_CHECK_ERR((ret > 0), ret, "Task %x, PR_STATUS write failed, return (%d).", task, ret);
|
||||||
}
|
}
|
||||||
len += ret;
|
len += ret;
|
||||||
|
tasks_num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = elf_process_note_segment(self, len); // tasks regs note
|
ret = elf_process_note_segment(self, len); // tasks regs note
|
||||||
@@ -467,23 +475,69 @@ static int elf_save_task(core_dump_elf_t *self, core_dump_task_header_t *task)
|
|||||||
return elf_len;
|
return elf_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int elf_save_interrupted_stack(core_dump_elf_t *self, core_dump_mem_seg_header_t *interrupted_stack)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#if !CONFIG_ESP_COREDUMP_CAPTURE_DRAM
|
||||||
|
/* interrupt stacks:
|
||||||
|
- 'port_IntStack' is in the data section for xtensa
|
||||||
|
- 'xIsrStack' is in the bss section for risc-v
|
||||||
|
When DRAM capture is enabled, interrupt stack saving can be done during the full section store
|
||||||
|
*/
|
||||||
|
if (interrupted_stack->size > 0) {
|
||||||
|
ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x",
|
||||||
|
interrupted_stack->size, interrupted_stack->start);
|
||||||
|
ret = elf_add_segment(self, PT_LOAD,
|
||||||
|
(uint32_t)interrupted_stack->start,
|
||||||
|
(void*)interrupted_stack->start,
|
||||||
|
(uint32_t)interrupted_stack->size);
|
||||||
|
ELF_CHECK_ERR((ret > 0), ret, "Interrupted task stack write failed, return (%d).", ret);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int elf_process_task_data(core_dump_elf_t *self)
|
static int elf_process_task_data(core_dump_elf_t *self)
|
||||||
{
|
{
|
||||||
int elf_len = 0;
|
int elf_len = 0;
|
||||||
core_dump_task_header_t task_hdr = { 0 };
|
core_dump_task_header_t task_hdr = { 0 };
|
||||||
core_dump_mem_seg_header_t interrupted_stack = { 0 };
|
core_dump_mem_seg_header_t interrupted_stack = { 0 };
|
||||||
TaskIterator_t task_iter;
|
TaskIterator_t task_iter;
|
||||||
uint16_t tasks_num = 0;
|
int tasks_num = 0;
|
||||||
uint16_t bad_tasks_num = 0;
|
int bad_tasks_num = 0;
|
||||||
|
|
||||||
ESP_COREDUMP_LOG_PROCESS("================ Processing task data ================");
|
ESP_COREDUMP_LOG_PROCESS("================ Processing task data ================");
|
||||||
// processes all task's stack data and writes segment data into partition
|
|
||||||
// if flash configuration is set
|
// first write crashed task data
|
||||||
esp_core_dump_reset_tasks_snapshots_iter();
|
esp_core_dump_reset_tasks_snapshots_iter();
|
||||||
|
void *current_task = esp_core_dump_get_current_task_handle();
|
||||||
|
if (esp_core_dump_get_task_snapshot(current_task, &task_hdr, &interrupted_stack)) {
|
||||||
|
int ret = elf_save_task(self, &task_hdr);
|
||||||
|
ELF_CHECK_ERR((ret > 0), ret,
|
||||||
|
"Task %x, TCB write failed, return (%d).", current_task, ret);
|
||||||
|
elf_len += ret;
|
||||||
|
|
||||||
|
// Handle interrupted stack (only relevant for current task)
|
||||||
|
ret = elf_save_interrupted_stack(self, &interrupted_stack);
|
||||||
|
if (ret > 0) {
|
||||||
|
elf_len += ret;
|
||||||
|
}
|
||||||
|
tasks_num++;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
// Skip the current task (already processed above)
|
||||||
|
if (!task_iter.pxTaskHandle || task_iter.pxTaskHandle == current_task) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tasks_num > CONFIG_ESP_COREDUMP_MAX_TASKS_NUM) {
|
||||||
|
ESP_COREDUMP_LOG_PROCESS("Reached maximum number of tasks (%d), stopping task data processing",
|
||||||
|
CONFIG_ESP_COREDUMP_MAX_TASKS_NUM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
tasks_num++;
|
tasks_num++;
|
||||||
if (!esp_core_dump_get_task_snapshot(task_iter.pxTaskHandle, &task_hdr, &interrupted_stack)) {
|
if (!esp_core_dump_get_task_snapshot(task_iter.pxTaskHandle, &task_hdr, NULL)) {
|
||||||
bad_tasks_num++;
|
bad_tasks_num++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -491,23 +545,6 @@ static int elf_process_task_data(core_dump_elf_t *self)
|
|||||||
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;
|
||||||
/* interrupt stacks:
|
|
||||||
- 'port_IntStack' is in the data section for xtensa
|
|
||||||
- 'xIsrStack' is in the bss section for risc-v
|
|
||||||
When DRAM capture is enabled, interrupt stack saving can be done during the full section store
|
|
||||||
*/
|
|
||||||
#if !CONFIG_ESP_COREDUMP_CAPTURE_DRAM
|
|
||||||
if (interrupted_stack.size > 0) {
|
|
||||||
ESP_COREDUMP_LOG_PROCESS("Add interrupted task stack %lu bytes @ %x",
|
|
||||||
interrupted_stack.size, interrupted_stack.start);
|
|
||||||
ret = elf_add_segment(self, PT_LOAD,
|
|
||||||
(uint32_t)interrupted_stack.start,
|
|
||||||
(void*)interrupted_stack.start,
|
|
||||||
(uint32_t)interrupted_stack.size);
|
|
||||||
ELF_CHECK_ERR((ret > 0), ret, "Interrupted task stack write failed, return (%d).", ret);
|
|
||||||
elf_len += ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
ESP_COREDUMP_LOG_PROCESS("Found %d bad task out of %d", bad_tasks_num, tasks_num);
|
ESP_COREDUMP_LOG_PROCESS("Found %d bad task out of %d", bad_tasks_num, tasks_num);
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ The ELF format contains extended features and allows more information regarding
|
|||||||
|
|
||||||
The Binary format is kept for compatibility reasons. Binary format core dump files are smaller while provide better performance.
|
The Binary format is kept for compatibility reasons. Binary format core dump files are smaller while provide better performance.
|
||||||
|
|
||||||
The :ref:`CONFIG_ESP_COREDUMP_MAX_TASKS_NUM` option configures the number of task snapshots saved by the core dump.
|
The :ref:`CONFIG_ESP_COREDUMP_MAX_TASKS_NUM` option configures the number of task snapshots saved by the core dump. Crashed task registers and the stack are always saved, regardless of this configuration option. Other tasks are included in order of their priority (starting with the highest-priority ready task).
|
||||||
|
|
||||||
Core dump data integrity checking is supported via the ``Components`` > ``Core dump`` > ``Core dump data integrity check`` option.
|
Core dump data integrity checking is supported via the ``Components`` > ``Core dump`` > ``Core dump data integrity check`` option.
|
||||||
|
|
||||||
@@ -46,7 +46,6 @@ Core dump data integrity checking is supported via the ``Components`` > ``Core d
|
|||||||
|
|
||||||
The SHA256 hash algorithm provides a greater probability of detecting corruption than a CRC32 with multiple-bit errors.
|
The SHA256 hash algorithm provides a greater probability of detecting corruption than a CRC32 with multiple-bit errors.
|
||||||
|
|
||||||
|
|
||||||
Reserved Stack Size
|
Reserved Stack Size
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -58,7 +57,6 @@ Setting this option to 0 bytes will cause the core dump routines to run from the
|
|||||||
|
|
||||||
If a separate stack is used, the recommended stack size should be larger than 1300 bytes to ensure that the core dump routines themselves do not cause a stack overflow.
|
If a separate stack is used, the recommended stack size should be larger than 1300 bytes to ensure that the core dump routines themselves do not cause a stack overflow.
|
||||||
|
|
||||||
|
|
||||||
.. only:: not esp32c5
|
.. only:: not esp32c5
|
||||||
|
|
||||||
Core Dump Memory Regions
|
Core Dump Memory Regions
|
||||||
|
@@ -31,7 +31,7 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误
|
|||||||
|
|
||||||
出于兼容性考虑,核心转储文件保留二进制格式。二进制格式的核心转储文件更小,性能更优。
|
出于兼容性考虑,核心转储文件保留二进制格式。二进制格式的核心转储文件更小,性能更优。
|
||||||
|
|
||||||
选项 :ref:`CONFIG_ESP_COREDUMP_MAX_TASKS_NUM` 配置核心转储保存的任务快照数量。
|
选项 :ref:`CONFIG_ESP_COREDUMP_MAX_TASKS_NUM` 可用于配置核心转储保存的任务快照数量。崩溃任务的寄存器和栈总是会被保存,不受此配置选项影响。其他任务的快照将根据优先级顺序(从就绪状态下优先级最高的任务开始)依次保存。
|
||||||
|
|
||||||
通过 ``Components`` > ``Core dump`` > ``Core dump data integrity check`` 选项可进行核心转储数据完整性检查。
|
通过 ``Components`` > ``Core dump`` > ``Core dump data integrity check`` 选项可进行核心转储数据完整性检查。
|
||||||
|
|
||||||
@@ -46,7 +46,6 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误
|
|||||||
|
|
||||||
SHA256 哈希算法检测到损坏的概率高于具有多位错误的 CRC32。
|
SHA256 哈希算法检测到损坏的概率高于具有多位错误的 CRC32。
|
||||||
|
|
||||||
|
|
||||||
保留栈大小
|
保留栈大小
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user