From: Peter Collingbourne Date: Thu, 2 Mar 2023 04:20:29 +0000 (-0800) Subject: target/image: zero-initialize ELF segments up to p_memsz X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=047b1a8fc237;hp=a7f8a1d7fb8e6628f34340a5777ce600dc27f8d8 target/image: zero-initialize ELF segments up to p_memsz We were previously not zero-initializing ELF segments between p_filesz and p_memsz (aka BSS). However, this may be necessary depending on the user's application. Therefore, start doing so. Change-Id: I5a743390069583aca7ee276f53afeccf2cac0855 Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/7513 Tested-by: jenkins Reviewed-by: Antonio Borneo --- diff --git a/src/target/image.c b/src/target/image.c index f8de7a23e3..6aa609d397 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -407,12 +407,10 @@ static int image_elf32_read_headers(struct image *image) return ERROR_FILEIO_OPERATION_FAILED; } - /* count useful segments (loadable), ignore BSS section */ + /* count useful segments (loadable) */ image->num_sections = 0; for (i = 0; i < elf->segment_count; i++) - if ((field32(elf, - elf->segments32[i].p_type) == PT_LOAD) && - (field32(elf, elf->segments32[i].p_filesz) != 0)) + if (field32(elf, elf->segments32[i].p_type) == PT_LOAD) image->num_sections++; if (image->num_sections == 0) { @@ -449,10 +447,8 @@ static int image_elf32_read_headers(struct image *image) } for (i = 0, j = 0; i < elf->segment_count; i++) { - if ((field32(elf, - elf->segments32[i].p_type) == PT_LOAD) && - (field32(elf, elf->segments32[i].p_filesz) != 0)) { - image->sections[j].size = field32(elf, elf->segments32[i].p_filesz); + if (field32(elf, elf->segments32[i].p_type) == PT_LOAD) { + image->sections[j].size = field32(elf, elf->segments32[i].p_memsz); if (load_to_vaddr) image->sections[j].base_address = field32(elf, elf->segments32[i].p_vaddr); @@ -532,12 +528,10 @@ static int image_elf64_read_headers(struct image *image) return ERROR_FILEIO_OPERATION_FAILED; } - /* count useful segments (loadable), ignore BSS section */ + /* count useful segments (loadable) */ image->num_sections = 0; for (i = 0; i < elf->segment_count; i++) - if ((field32(elf, - elf->segments64[i].p_type) == PT_LOAD) && - (field64(elf, elf->segments64[i].p_filesz) != 0)) + if (field32(elf, elf->segments64[i].p_type) == PT_LOAD) image->num_sections++; if (image->num_sections == 0) { @@ -574,10 +568,8 @@ static int image_elf64_read_headers(struct image *image) } for (i = 0, j = 0; i < elf->segment_count; i++) { - if ((field32(elf, - elf->segments64[i].p_type) == PT_LOAD) && - (field64(elf, elf->segments64[i].p_filesz) != 0)) { - image->sections[j].size = field64(elf, elf->segments64[i].p_filesz); + if (field32(elf, elf->segments64[i].p_type) == PT_LOAD) { + image->sections[j].size = field64(elf, elf->segments64[i].p_memsz); if (load_to_vaddr) image->sections[j].base_address = field64(elf, elf->segments64[i].p_vaddr); @@ -651,6 +643,8 @@ static int image_elf32_read_section(struct image *image, { struct image_elf *elf = image->type_private; Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private; + uint32_t filesz = field32(elf, segment->p_filesz); + uint32_t memsz = field32(elf, segment->p_memsz); size_t read_size, really_read; int retval; @@ -659,9 +653,9 @@ static int image_elf32_read_section(struct image *image, LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size); /* read initialized data in current segment if any */ - if (offset < field32(elf, segment->p_filesz)) { + if (offset < filesz) { /* maximal size present in file for the current segment */ - read_size = MIN(size, field32(elf, segment->p_filesz) - offset); + read_size = MIN(size, filesz - offset); LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size, field32(elf, segment->p_offset) + offset); /* read initialized area of the segment */ @@ -675,6 +669,8 @@ static int image_elf32_read_section(struct image *image, LOG_ERROR("cannot read ELF segment content, read failed"); return retval; } + buffer += read_size; + offset += read_size; size -= read_size; *size_read += read_size; /* need more data ? */ @@ -682,6 +678,13 @@ static int image_elf32_read_section(struct image *image, return ERROR_OK; } + /* clear bss in current segment if any */ + if (offset >= filesz) { + uint32_t memset_size = MIN(size, memsz - filesz); + memset(buffer, 0, memset_size); + *size_read += memset_size; + } + return ERROR_OK; } @@ -694,6 +697,8 @@ static int image_elf64_read_section(struct image *image, { struct image_elf *elf = image->type_private; Elf64_Phdr *segment = (Elf64_Phdr *)image->sections[section].private; + uint64_t filesz = field64(elf, segment->p_filesz); + uint64_t memsz = field64(elf, segment->p_memsz); size_t read_size, really_read; int retval; @@ -702,9 +707,9 @@ static int image_elf64_read_section(struct image *image, LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size); /* read initialized data in current segment if any */ - if (offset < field64(elf, segment->p_filesz)) { + if (offset < filesz) { /* maximal size present in file for the current segment */ - read_size = MIN(size, field64(elf, segment->p_filesz) - offset); + read_size = MIN(size, filesz - offset); LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size, field64(elf, segment->p_offset) + offset); /* read initialized area of the segment */ @@ -718,6 +723,8 @@ static int image_elf64_read_section(struct image *image, LOG_ERROR("cannot read ELF segment content, read failed"); return retval; } + buffer += read_size; + offset += read_size; size -= read_size; *size_read += read_size; /* need more data ? */ @@ -725,6 +732,13 @@ static int image_elf64_read_section(struct image *image, return ERROR_OK; } + /* clear bss in current segment if any */ + if (offset >= filesz) { + uint64_t memset_size = MIN(size, memsz - filesz); + memset(buffer, 0, memset_size); + *size_read += memset_size; + } + return ERROR_OK; }