Skip to content

Commit

Permalink
Merge branch 'fix/coredump_note_section_alignment_v5.3' into 'release…
Browse files Browse the repository at this point in the history
…/v5.3'

Fix/coredump note section headers and alignments (v5.3)

See merge request espressif/esp-idf!36881
  • Loading branch information
gerekon committed Feb 12, 2025
2 parents ca8638a + e2818f6 commit f46d4f6
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 22 deletions.
50 changes: 30 additions & 20 deletions components/espcoredump/src/core_dump_elf.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -196,23 +196,36 @@ 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
esp_err_t err = esp_core_dump_write_data(&self->write_data, &note_hdr, sizeof(note_hdr));
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);

Expand All @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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) {
Expand All @@ -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, &param, 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

Expand Down Expand Up @@ -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 *)&note[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);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion components/espcoredump/src/core_dump_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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...");
Expand Down
2 changes: 1 addition & 1 deletion components/espcoredump/src/port/xtensa/core_dump_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit f46d4f6

Please sign in to comment.