mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-03 10:30:58 +02:00
fix(coredump): implement CONFIG_ESP_COREDUMP_MAX_TASKS_NUM limitation
Closes https://github.com/espressif/esp-idf/issues/14407
This commit is contained in:
@@ -62,7 +62,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"
|
||||||
|
@@ -409,6 +409,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;
|
||||||
|
uint16_t 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();
|
||||||
@@ -422,6 +423,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
|
||||||
@@ -432,6 +434,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) {
|
||||||
@@ -441,6 +448,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
|
||||||
@@ -464,6 +472,28 @@ 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;
|
||||||
@@ -474,13 +504,37 @@ static int elf_process_task_data(core_dump_elf_t *self)
|
|||||||
uint16_t bad_tasks_num = 0;
|
uint16_t 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;
|
||||||
}
|
}
|
||||||
@@ -488,23 +542,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 @@ Format & Size
|
|||||||
|
|
||||||
Core dump files are generated in ELF format, which contains extended features and allows comprehensive information regarding erroneous tasks and crashed software to be saved. The ELF format is flexible and can be extended in future revisions to save additional information.
|
Core dump files are generated in ELF format, which contains extended features and allows comprehensive information regarding erroneous tasks and crashed software to be saved. The ELF format is flexible and can be extended in future revisions to save additional information.
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
Data Integrity Check
|
Data Integrity Check
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@@ -31,14 +31,13 @@
|
|||||||
|
|
||||||
核心转储文件以 ELF 格式生成,该格式具有可扩展性,能够在系统崩溃时完整保存错误任务和故障软件的详细信息。ELF 格式具备良好的扩展灵活性,便于未来版本升级时存储更多诊断信息。
|
核心转储文件以 ELF 格式生成,该格式具有可扩展性,能够在系统崩溃时完整保存错误任务和故障软件的详细信息。ELF 格式具备良好的扩展灵活性,便于未来版本升级时存储更多诊断信息。
|
||||||
|
|
||||||
选项 :ref:`CONFIG_ESP_COREDUMP_MAX_TASKS_NUM` 可用于配置核心转储保存的任务快照数量。
|
选项 :ref:`CONFIG_ESP_COREDUMP_MAX_TASKS_NUM` 可用于配置核心转储保存的任务快照数量。崩溃任务的寄存器和栈总是会被保存,不受此配置选项影响。其他任务的快照将根据优先级顺序(从就绪状态下优先级最高的任务开始)依次保存。
|
||||||
|
|
||||||
数据完整性检查
|
数据完整性检查
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
核心转储文件包含 SHA256 校验和,用于验证核心转储文件的完整性,确保文件未被损坏。SHA256 哈希算法在检测损坏方面具有很高的准确率,包括多位错误。
|
核心转储文件包含 SHA256 校验和,用于验证核心转储文件的完整性,确保文件未被损坏。SHA256 哈希算法在检测损坏方面具有很高的准确率,包括多位错误。
|
||||||
|
|
||||||
|
|
||||||
保留栈大小
|
保留栈大小
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user