Merge branch 'fix/coredump_note_section_alignment_v5.2' into 'release/v5.2'

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

See merge request espressif/esp-idf!36882
This commit is contained in:
Alexey Gerenkov 2025-03-04 00:12:41 +08:00
commit f038c00a5b

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -200,15 +200,28 @@ static int elf_add_segment(core_dump_elf_t *self,
return data_len; 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 // 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 };
elf_note note_hdr = { 0 }; elf_note note_hdr = { 0 };
memcpy(name_buffer, name, name_len); size_t name_len = strlcpy(name_buffer, name, sizeof(name_buffer));
note_hdr.n_namesz = ALIGN_UP(name_len + 1, 4); note_hdr.n_namesz = name_len + 1; /* name_buffer must be null terminated */
note_hdr.n_descsz = data_sz; note_hdr.n_descsz = data_sz;
note_hdr.n_type = type; note_hdr.n_type = type;
// write note header // write note header
@ -216,7 +229,7 @@ static int elf_write_note_header(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 header failure (%d)", err); "Write ELF note header failure (%d)", err);
// write note name // 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, 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);
@ -230,18 +243,17 @@ static int elf_write_note(core_dump_elf_t *self,
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 = strlen(name) + 1; // get name length including terminator
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, 4) + ALIGN_UP(data_sz, 4) + sizeof(elf_note);
// write segment data during second pass // write segment data during second pass
if (self->elf_stage == ELF_STAGE_PLACE_DATA) { if (self->elf_stage == ELF_STAGE_PLACE_DATA) {
ELF_CHECK_ERR(data, ELF_PROC_ERR_OTHER, "Invalid data pointer %x.", (uint32_t)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) { if (err != ESP_OK) {
return err; return err;
} }
@ -250,8 +262,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. // 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); err = esp_core_dump_write_data(&self->write_data, data, data_sz);
if (err == ESP_OK) { if (err == ESP_OK) {
int pad_size = data_len - data_sz; const int pad_size = ALIGN_UP(data_sz, 4) - data_sz;
if (pad_size != 0) { if (pad_size > 0) {
uint8_t pad_bytes[3] = {0}; uint8_t pad_bytes[3] = {0};
ESP_COREDUMP_LOG_PROCESS("Core dump note data needs %d bytes padding", pad_size); 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); err = esp_core_dump_write_data(&self->write_data, pad_bytes, pad_size);
@ -543,7 +555,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) 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 = { core_dump_elf_opaque_t param = {
.self = self, .self = self,
.total_size = 0, .total_size = 0,
@ -557,27 +569,25 @@ 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, 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;
} }
esp_task_wdt_print_triggered_tasks(elf_write_core_dump_note_cb, &param, NULL); 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); 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; const int pad_size = ALIGN_UP(self->note_data_size, 4) - self->note_data_size;
if (mod != 0) { if (pad_size > 0) {
uint8_t pad_bytes[3] = {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); 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); 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); 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 #endif //CONFIG_ESP_TASK_WDT_EN
@ -839,17 +849,17 @@ static void esp_core_dump_parse_note_section(uint8_t *coredump_data, elf_note_co
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 + ALIGN_UP(note->n_namesz, 4);
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, 4) + ALIGN_UP(note->n_descsz, 4) + sizeof(elf_note);
} }
} }
} }