diff --git a/components/espcoredump/src/core_dump_elf.c b/components/espcoredump/src/core_dump_elf.c index 4b6852f318..4a4ccdb955 100644 --- a/components/espcoredump/src/core_dump_elf.c +++ b/components/espcoredump/src/core_dump_elf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -196,15 +196,28 @@ static int elf_add_segment(core_dump_elf_t *self, return data_len; } -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) +/* + * Example Note Segment + * +================================================================+ + * | Offset | +0 | +1 | +2 | +3 | Description | + * +----------------------------------------------------------------+ + * | 0 | 0x05 | 0x00 | 0x00 | 0x00 | namesz = 5 | + * | 4 | 0x06 | 0x00 | 0x00 | 0x00 | descsz = 6 | + * | 8 | 0x01 | 0x00 | 0x00 | 0x00 | type = 1 | + * | 12 | 'C' | 'O' | 'R' | 'E' | name ("CORE") | + * | 16 | 0x00 | pad | pad | pad | NULL + padding | + * | 20 | 0x1 | 0x2 | 0x3 | 0x4 | desc (6 bytes) | + * | 24 | 0x5 | 0x6 | pad | pad | desc + padding | + * +================================================================+ +*/ +static int elf_write_note_header(core_dump_elf_t *self, const char* name, uint32_t data_sz, uint32_t type) { // temporary aligned buffer for note name static char name_buffer[ELF_NOTE_NAME_MAX_SIZE] = { 0 }; elf_note note_hdr = { 0 }; - memcpy(name_buffer, name, name_len); - note_hdr.n_namesz = ALIGN_UP(name_len + 1, 4); + size_t name_len = strlcpy(name_buffer, name, sizeof(name_buffer)); + note_hdr.n_namesz = name_len + 1; /* name_buffer must be null terminated */ note_hdr.n_descsz = data_sz; note_hdr.n_type = type; // write note header @@ -212,7 +225,7 @@ static int elf_write_note_header(core_dump_elf_t *self, ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, "Write ELF note header failure (%d)", err); // write note name - err = esp_core_dump_write_data(&self->write_data, name_buffer, note_hdr.n_namesz); + err = esp_core_dump_write_data(&self->write_data, name_buffer, ALIGN_UP(note_hdr.n_namesz, 4)); ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, "Write ELF note name failure (%d)", err); @@ -226,18 +239,17 @@ static int elf_write_note(core_dump_elf_t *self, uint32_t data_sz) { esp_err_t err = ESP_FAIL; - 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 name_len = strlen(name) + 1; // get name length including terminator ELF_CHECK_ERR((name_len <= ELF_NOTE_NAME_MAX_SIZE), 0, "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, 4) + ALIGN_UP(data_sz, 4) + sizeof(elf_note); // write segment data during second pass if (self->elf_stage == ELF_STAGE_PLACE_DATA) { ELF_CHECK_ERR(data, ELF_PROC_ERR_OTHER, "Invalid data pointer %x.", (uint32_t)data); - err = elf_write_note_header(self, name, strlen(name), data_sz, type); + err = elf_write_note_header(self, name, data_sz, type); if (err != ESP_OK) { return err; } @@ -246,8 +258,8 @@ static int elf_write_note(core_dump_elf_t *self, // which might not be aligned by default. Therefore, we need to verify alignment and add padding if necessary. err = esp_core_dump_write_data(&self->write_data, data, data_sz); if (err == ESP_OK) { - int pad_size = data_len - data_sz; - if (pad_size != 0) { + const int pad_size = ALIGN_UP(data_sz, 4) - data_sz; + if (pad_size > 0) { uint8_t pad_bytes[3] = {0}; ESP_COREDUMP_LOG_PROCESS("Core dump note data needs %d bytes padding", pad_size); err = esp_core_dump_write_data(&self->write_data, pad_bytes, pad_size); @@ -621,7 +633,7 @@ static void elf_write_core_dump_note_cb(void *opaque, const char *data) static int elf_add_wdt_panic_details(core_dump_elf_t *self) { - uint32_t name_len = sizeof(ELF_ESP_CORE_DUMP_PANIC_DETAILS_NOTE_NAME) - 1; + uint32_t name_len = sizeof(ELF_ESP_CORE_DUMP_PANIC_DETAILS_NOTE_NAME); /* len includes the null terminator */ core_dump_elf_opaque_t param = { .self = self, .total_size = 0, @@ -636,7 +648,6 @@ static int elf_add_wdt_panic_details(core_dump_elf_t *self) } else if (self->elf_stage == ELF_STAGE_PLACE_DATA) { esp_err_t err = elf_write_note_header(self, ELF_ESP_CORE_DUMP_PANIC_DETAILS_NOTE_NAME, - name_len, self->note_data_size, ELF_ESP_CORE_DUMP_PANIC_DETAILS_TYPE); if (err != ESP_OK) { @@ -645,17 +656,16 @@ static int elf_add_wdt_panic_details(core_dump_elf_t *self) esp_task_wdt_print_triggered_tasks(elf_write_core_dump_note_cb, ¶m, NULL); ELF_CHECK_ERR((param.total_size > 0), ELF_PROC_ERR_WRITE_FAIL, "Write ELF note data failure (%d)", err); - const uint32_t mod = self->note_data_size & 3; - if (mod != 0) { + const int pad_size = ALIGN_UP(self->note_data_size, 4) - self->note_data_size; + if (pad_size > 0) { uint8_t pad_bytes[3] = {0}; - uint32_t pad_size = 4 - mod; ESP_COREDUMP_LOG_PROCESS("Core dump note needs %d bytes padding", pad_size); err = esp_core_dump_write_data(&self->write_data, pad_bytes, pad_size); ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, "Write ELF note padding failure (%d)", err); } } - return ALIGN_UP(ALIGN_UP(name_len, 4) + ALIGN_UP(self->note_data_size, 4) + sizeof(elf_note), 4); + return ALIGN_UP(name_len, 4) + ALIGN_UP(self->note_data_size, 4) + sizeof(elf_note); } #endif //CONFIG_ESP_TASK_WDT_EN @@ -928,14 +938,14 @@ static void esp_core_dump_parse_note_section(uint8_t *coredump_data, elf_note_co for (size_t idx = 0; idx < size; ++idx) { if (target_notes[idx].n_type == note->n_type) { char *nm = (char *)¬e[1]; - target_notes[idx].n_ptr = nm + note->n_namesz; + target_notes[idx].n_ptr = nm + ALIGN_UP(note->n_namesz, 4); target_notes[idx].n_descsz = note->n_descsz; ESP_COREDUMP_LOGD("%d bytes target note (%X) found in the note section", note->n_descsz, note->n_type); break; } } - consumed_note_sz += ALIGN_UP(note->n_namesz + note->n_descsz + sizeof(elf_note), 4); + consumed_note_sz += ALIGN_UP(note->n_namesz, 4) + ALIGN_UP(note->n_descsz, 4) + sizeof(elf_note); } } } diff --git a/components/espcoredump/src/core_dump_uart.c b/components/espcoredump/src/core_dump_uart.c index 69ab1c2805..60e4ffc133 100644 --- a/components/espcoredump/src/core_dump_uart.c +++ b/components/espcoredump/src/core_dump_uart.c @@ -154,7 +154,7 @@ static esp_err_t esp_core_dump_uart_hw_init(void) //Make sure txd/rxd are enabled // use direct reg access instead of gpio_pullup_dis which can cause exception when flash cache is disabled - REG_CLR_BIT(GPIO_PIN_REG_1, FUN_PU); //TODO: IDF-9948 + gpio_hal_pullup_dis(&gpio_hal, U0TXD_GPIO_NUM); gpio_hal_func_sel(&gpio_hal, U0RXD_GPIO_NUM, U0RXD_MUX_FUNC); gpio_hal_func_sel(&gpio_hal, U0TXD_GPIO_NUM, U0TXD_MUX_FUNC); ESP_COREDUMP_LOGI("Press Enter to print core dump to UART..."); diff --git a/components/espcoredump/src/port/xtensa/core_dump_port.c b/components/espcoredump/src/port/xtensa/core_dump_port.c index 8efae60d57..3aff19c537 100644 --- a/components/espcoredump/src/port/xtensa/core_dump_port.c +++ b/components/espcoredump/src/port/xtensa/core_dump_port.c @@ -241,7 +241,7 @@ static esp_err_t esp_core_dump_get_regs_from_stack(void* stack_addr, for (int i = 0; i < XT_SOL_AR_NUM; i++) { regs->ar[i] = stack_arr[XT_SOL_AR_START + i]; } - regs->pc = (regs->pc & 0x3fffffff); + if (regs->pc & 0x80000000) { regs->pc = (regs->pc & 0x3fffffff); }