This is an automated email from Gerrit. Franck Jullien ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/1671
-- gerrit commit c0091c16723369044ef072e0ed2584d48f8532cc Author: Franck Jullien <[email protected]> Date: Sat Sep 28 23:35:56 2013 +0200 image: use section header is program header is empty Some ELF files may not have program header. However, this is perfectly valid and we must handle this case. This patch separate segments and sections processing in image_elf_read_headers. If no program header is found, it now tries to read the section header. Change-Id: Ia75a345f3e2ddd9bfa3977d20cb0ecc1d1358a07 Signed-off-by: Franck Jullien <[email protected]> diff --git a/src/target/image.c b/src/target/image.c index f47ba22..265a760 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -334,53 +334,13 @@ static int image_ihex_buffer_complete(struct image *image) return retval; } -static int image_elf_read_headers(struct image *image) +static int process_segments(struct image_elf *elf, struct image *image) { - struct image_elf *elf = image->type_private; - size_t read_bytes; uint32_t i, j; int retval; + size_t read_bytes; uint32_t nload, load_to_vaddr = 0; - elf->header = malloc(sizeof(Elf32_Ehdr)); - - if (elf->header == NULL) { - LOG_ERROR("insufficient memory to perform operation "); - return ERROR_FILEIO_OPERATION_FAILED; - } - - retval = fileio_read(&elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes); - if (retval != ERROR_OK) { - LOG_ERROR("cannot read ELF file header, read failed"); - return ERROR_FILEIO_OPERATION_FAILED; - } - if (read_bytes != sizeof(Elf32_Ehdr)) { - LOG_ERROR("cannot read ELF file header, only partially read"); - return ERROR_FILEIO_OPERATION_FAILED; - } - - if (strncmp((char *)elf->header->e_ident, ELFMAG, SELFMAG) != 0) { - LOG_ERROR("invalid ELF file, bad magic number"); - return ERROR_IMAGE_FORMAT_ERROR; - } - if (elf->header->e_ident[EI_CLASS] != ELFCLASS32) { - LOG_ERROR("invalid ELF file, only 32bits files are supported"); - return ERROR_IMAGE_FORMAT_ERROR; - } - - elf->endianness = elf->header->e_ident[EI_DATA]; - if ((elf->endianness != ELFDATA2LSB) - && (elf->endianness != ELFDATA2MSB)) { - LOG_ERROR("invalid ELF file, unknown endianness setting"); - return ERROR_IMAGE_FORMAT_ERROR; - } - - elf->segment_count = field16(elf, elf->header->e_phnum); - if (elf->segment_count == 0) { - LOG_ERROR("invalid ELF file, no program headers"); - return ERROR_IMAGE_FORMAT_ERROR; - } - retval = fileio_seek(&elf->fileio, field32(elf, elf->header->e_phoff)); if (retval != ERROR_OK) { LOG_ERROR("cannot seek to ELF program header table, read failed"); @@ -450,6 +410,7 @@ static int image_elf_read_headers(struct image *image) elf->segments[i].p_paddr); image->sections[j].private = &elf->segments[i]; image->sections[j].flags = field32(elf, elf->segments[i].p_flags); + image->sections[j].offset = field32(elf, elf->segments[i].p_offset); j++; } } @@ -460,6 +421,120 @@ static int image_elf_read_headers(struct image *image) return ERROR_OK; } +static int process_sections(struct image_elf *elf, struct image *image) +{ + uint32_t i; + int retval; + size_t read_bytes; + + retval = fileio_seek(&elf->fileio, field32(elf, elf->header->e_shoff)); + if (retval != ERROR_OK) { + LOG_ERROR("cannot seek to ELF section header table, read failed"); + return retval; + } + + elf->sections = malloc(elf->section_count*sizeof(Elf32_Shdr)); + if (elf->sections == NULL) { + LOG_ERROR("insufficient memory to perform operation "); + return ERROR_FILEIO_OPERATION_FAILED; + } + + retval = fileio_read(&elf->fileio, elf->section_count*sizeof(Elf32_Shdr), + (uint8_t *)elf->sections, &read_bytes); + if (retval != ERROR_OK) { + LOG_ERROR("cannot read ELF section headers, read failed"); + return retval; + } + + if (read_bytes != elf->section_count*sizeof(Elf32_Shdr)) { + LOG_ERROR("cannot read ELF section headers, only partially read"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + /* count useful segments (loadable), ignore BSS section */ + image->num_sections = 0; + for (i = 0; i < elf->section_count; i++) + if ((field32(elf, elf->sections[i].sh_type) == SHT_PROGBITS) && + (field32(elf, elf->sections[i].sh_flags) & SHF_ALLOC) && + (field32(elf, elf->sections[i].sh_size) != 0)) + image->num_sections++; + + assert(image->num_sections > 0); + + /* alloc and fill sections array with loadable segments */ + image->sections = malloc(image->num_sections * sizeof(struct imagesection)); + for (i = 0; i < elf->section_count; i++) { + if ((field32(elf, elf->sections[i].sh_type) == SHT_PROGBITS) && + (field32(elf, elf->sections[i].sh_flags) & SHF_ALLOC) && + (field32(elf, elf->sections[i].sh_size) != 0)) { + image->sections[i].size = field32(elf, elf->sections[i].sh_size); + image->sections[i].base_address = field32(elf, elf->sections[i].sh_addr); + image->sections[i].private = &elf->sections[i]; + image->sections[i].flags = field32(elf, elf->sections[i].sh_flags); + image->sections[i].offset = field32(elf, elf->sections[i].sh_offset); + } + } + + image->start_address_set = 1; + image->start_address = field32(elf, elf->header->e_entry); + + return ERROR_OK; +} + +static int image_elf_read_headers(struct image *image) +{ + struct image_elf *elf = image->type_private; + int retval; + size_t read_bytes; + + elf->header = malloc(sizeof(Elf32_Ehdr)); + + if (elf->header == NULL) { + LOG_ERROR("insufficient memory to perform operation "); + return ERROR_FILEIO_OPERATION_FAILED; + } + + retval = fileio_read(&elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes); + if (retval != ERROR_OK) { + LOG_ERROR("cannot read ELF file header, read failed"); + return ERROR_FILEIO_OPERATION_FAILED; + } + if (read_bytes != sizeof(Elf32_Ehdr)) { + LOG_ERROR("cannot read ELF file header, only partially read"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + if (strncmp((char *)elf->header->e_ident, ELFMAG, SELFMAG) != 0) { + LOG_ERROR("invalid ELF file, bad magic number"); + return ERROR_IMAGE_FORMAT_ERROR; + } + if (elf->header->e_ident[EI_CLASS] != ELFCLASS32) { + LOG_ERROR("invalid ELF file, only 32bits files are supported"); + return ERROR_IMAGE_FORMAT_ERROR; + } + + elf->endianness = elf->header->e_ident[EI_DATA]; + if ((elf->endianness != ELFDATA2LSB) + && (elf->endianness != ELFDATA2MSB)) { + LOG_ERROR("invalid ELF file, unknown endianness setting"); + return ERROR_IMAGE_FORMAT_ERROR; + } + + elf->segment_count = field16(elf, elf->header->e_phnum); + if (elf->segment_count) + return process_segments(elf, image); + else + LOG_WARNING("no program header in ELF file"); + + elf->section_count = field16(elf, elf->header->e_shnum); + if (elf->section_count) + return process_sections(elf, image); + else { + LOG_ERROR("invalid ELF file, no program or section headers"); + return ERROR_IMAGE_FORMAT_ERROR; + } +} + static int image_elf_read_section(struct image *image, int section, uint32_t offset, @@ -468,7 +543,7 @@ static int image_elf_read_section(struct image *image, size_t *size_read) { struct image_elf *elf = image->type_private; - Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private; + /*Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private;*/ size_t read_size, really_read; int retval; @@ -477,13 +552,13 @@ static int image_elf_read_section(struct image *image, LOG_DEBUG("load segment %d at 0x%" PRIx32 " (sz = 0x%" PRIx32 ")", section, offset, size); /* read initialized data in current segment if any */ - if (offset < field32(elf, segment->p_filesz)) { + if (offset < image->sections[section].size) { /* maximal size present in file for the current segment */ - read_size = MIN(size, field32(elf, segment->p_filesz) - offset); + read_size = MIN(size, image->sections[section].size - offset); LOG_DEBUG("read elf: size = 0x%zu at 0x%" PRIx32 "", read_size, - field32(elf, segment->p_offset) + offset); + image->sections[section].offset + offset); /* read initialized area of the segment */ - retval = fileio_seek(&elf->fileio, field32(elf, segment->p_offset) + offset); + retval = fileio_seek(&elf->fileio, image->sections[section].offset + offset); if (retval != ERROR_OK) { LOG_ERROR("cannot find ELF segment content, seek failed"); return retval; @@ -736,6 +811,7 @@ int image_open(struct image *image, const char *url, const char *type_string) struct image_elf *image_elf; image_elf = image->type_private = malloc(sizeof(struct image_elf)); + memset(image_elf, 0, sizeof(struct image_elf)); retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) @@ -965,6 +1041,11 @@ void image_close(struct image *image) free(image_elf->segments); image_elf->segments = NULL; } + + if (image_elf->sections) { + free(image_elf->sections); + image_elf->sections = NULL; + } } else if (image->type == IMAGE_MEMORY) { struct image_memory *image_memory = image->type_private; diff --git a/src/target/image.h b/src/target/image.h index 9741308..0e1d8a1 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -52,6 +52,7 @@ struct imagesection { uint32_t size; int flags; void *private; /* private data */ + uint32_t offset; }; struct image { @@ -63,6 +64,7 @@ struct image { long long base_address; /* base address, if one is set */ int start_address_set; /* whether the image has a start address (entry point) associated */ uint32_t start_address; /* start address, if one is set */ + int sections_type; /* */ }; struct image_binary { @@ -84,7 +86,9 @@ struct image_elf { struct fileio fileio; Elf32_Ehdr *header; Elf32_Phdr *segments; + Elf32_Shdr *sections; uint32_t segment_count; + uint32_t section_count; uint8_t endianness; }; -- ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60133471&iu=/4140/ostg.clktrk _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
