X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fimage.c;h=c0aabecd5838cf47c3628053fbc81292da90a643;hp=ca7123adc37947c3adb2bb819a72cef8c9100aa3;hb=3a550e5b5fe011e526b150a5d234b48e8e2aaad6;hpb=964c3639e2464b18d72f16fa175fee9beb843b36 diff --git a/src/target/image.c b/src/target/image.c index ca7123adc3..c0aabecd58 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -32,7 +32,7 @@ #include "image.h" #include "target.h" -#include "log.h" +#include /* convert ELF header field to host endianness */ @@ -147,7 +147,7 @@ static int identify_image_type(struct image *image, const char *type_string, con return ERROR_OK; } -static int image_ihex_buffer_complete_inner(struct image *image, char *lpszLine, struct imageection *section) +static int image_ihex_buffer_complete_inner(struct image *image, char *lpszLine, struct imagesection *section) { struct image_ihex *ihex = image->type_private; struct fileio *fileio = &ihex->fileio; @@ -158,7 +158,13 @@ static int image_ihex_buffer_complete_inner(struct image *image, char *lpszLine, /* we can't determine the number of sections that we'll have to create ahead of time, * so we locally hold them until parsing is finished */ - ihex->buffer = malloc(fileio->size >> 1); + int filesize; + int retval; + retval = fileio_size(fileio, &filesize); + if (retval != ERROR_OK) + return retval; + + ihex->buffer = malloc(filesize >> 1); cooked_bytes = 0x0; image->num_sections = 0; section[image->num_sections].private = &ihex->buffer[cooked_bytes]; @@ -230,7 +236,7 @@ static int image_ihex_buffer_complete_inner(struct image *image, char *lpszLine, image->num_sections++; /* copy section information */ - image->sections = malloc(sizeof(struct imageection) * image->num_sections); + image->sections = malloc(sizeof(struct imagesection) * image->num_sections); for (i = 0; i < image->num_sections; i++) { image->sections[i].private = section[i].private; @@ -341,7 +347,6 @@ static int image_ihex_buffer_complete_inner(struct image *image, char *lpszLine, } sscanf(&lpszLine[bytes_read], "%2" SCNx32 , &checksum); - bytes_read += 2; if ((uint8_t)checksum != (uint8_t)(~cal_checksum + 1)) { @@ -367,7 +372,7 @@ static int image_ihex_buffer_complete(struct image *image) LOG_ERROR("Out of memory"); return ERROR_FAIL; } - struct imageection *section = malloc(sizeof(struct imageection) * IMAGE_MAX_SECTIONS); + struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS); if (section == NULL) { free(lpszLine); @@ -390,6 +395,7 @@ static int image_elf_read_headers(struct image *image) size_t read_bytes; uint32_t i,j; int retval; + uint32_t nload,load_to_vaddr=0; elf->header = malloc(sizeof(Elf32_Ehdr)); @@ -425,7 +431,7 @@ static int image_elf_read_headers(struct image *image) if ((elf->endianness != ELFDATA2LSB) &&(elf->endianness != ELFDATA2MSB)) { - LOG_ERROR("invalid ELF file, unknown endianess setting"); + LOG_ERROR("invalid ELF file, unknown endianness setting"); return ERROR_IMAGE_FORMAT_ERROR; } @@ -465,14 +471,39 @@ static int image_elf_read_headers(struct image *image) for (i = 0;i < elf->segment_count;i++) if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0)) image->num_sections++; + + assert(image->num_sections > 0); + + /** + * some ELF linkers produce binaries with *all* the program header + * p_paddr fields zero (there can be however one loadable segment + * that has valid physical address 0x0). + * If we have such a binary with more than + * one PT_LOAD header, then use p_vaddr instead of p_paddr + * (ARM ELF standard demands p_paddr = 0 anyway, and BFD + * library uses this approach to workaround zero-initialized p_paddrs + * when obtaining lma - look at elf.c of BDF) + */ + for (nload = 0, i = 0; i < elf->segment_count; i++) + if (elf->segments[i].p_paddr != 0) + break; + else if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_memsz) != 0)) + ++nload; + + if (i >= elf->segment_count && nload > 1) + load_to_vaddr = 1; + /* alloc and fill sections array with loadable segments */ - image->sections = malloc(image->num_sections * sizeof(struct imageection)); + image->sections = malloc(image->num_sections * sizeof(struct imagesection)); for (i = 0,j = 0;i < elf->segment_count;i++) { if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0)) { image->sections[j].size = field32(elf,elf->segments[i].p_filesz); - image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr); + if (load_to_vaddr) + image->sections[j].base_address = field32(elf,elf->segments[i].p_vaddr); + else + image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr); image->sections[j].private = &elf->segments[i]; image->sections[j].flags = field32(elf,elf->segments[i].p_flags); j++; @@ -514,9 +545,7 @@ static int image_elf_read_section(struct image *image, int section, uint32_t off LOG_ERROR("cannot read ELF segment content, read failed"); return retval; } - buffer += read_size; size -= read_size; - offset += read_size; *size_read += read_size; /* need more data ? */ if (!size) @@ -526,7 +555,7 @@ static int image_elf_read_section(struct image *image, int section, uint32_t off return ERROR_OK; } -static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, struct imageection *section) +static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, struct imagesection *section) { struct image_mot *mot = image->type_private; struct fileio *fileio = &mot->fileio; @@ -537,7 +566,13 @@ static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, /* we can't determine the number of sections that we'll have to create ahead of time, * so we locally hold them until parsing is finished */ - mot->buffer = malloc(fileio->size >> 1); + int retval; + int filesize; + retval = fileio_size(fileio, &filesize); + if (retval != ERROR_OK) + return retval; + + mot->buffer = malloc(filesize >> 1); cooked_bytes = 0x0; image->num_sections = 0; section[image->num_sections].private = &mot->buffer[cooked_bytes]; @@ -660,7 +695,7 @@ static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, image->num_sections++; /* copy section information */ - image->sections = malloc(sizeof(struct imageection) * image->num_sections); + image->sections = malloc(sizeof(struct imagesection) * image->num_sections); for (i = 0; i < image->num_sections; i++) { image->sections[i].private = section[i].private; @@ -680,7 +715,6 @@ static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, /* account for checksum, will always be 0xFF */ sscanf(&lpszLine[bytes_read], "%2" SCNx32 , &checksum); cal_checksum += (uint8_t)checksum; - bytes_read += 2; if (cal_checksum != 0xFF) { @@ -706,7 +740,7 @@ static int image_mot_buffer_complete(struct image *image) LOG_ERROR("Out of memory"); return ERROR_FAIL; } - struct imageection *section = malloc(sizeof(struct imageection) * IMAGE_MAX_SECTIONS); + struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS); if (section == NULL) { free(lpszLine); @@ -743,11 +777,18 @@ int image_open(struct image *image, const char *url, const char *type_string) { return retval; } + int filesize; + retval = fileio_size(&image_binary->fileio, &filesize); + if (retval != ERROR_OK) + { + fileio_close(&image_binary->fileio); + return retval; + } image->num_sections = 1; - image->sections = malloc(sizeof(struct imageection)); + image->sections = malloc(sizeof(struct imagesection)); image->sections[0].base_address = 0x0; - image->sections[0].size = image_binary->fileio.size; + image->sections[0].size = filesize; image->sections[0].flags = 0; } else if (image->type == IMAGE_IHEX) @@ -798,7 +839,7 @@ int image_open(struct image *image, const char *url, const char *type_string) struct image_memory *image_memory; image->num_sections = 1; - image->sections = malloc(sizeof(struct imageection)); + image->sections = malloc(sizeof(struct imagesection)); image->sections[0].base_address = 0x0; image->sections[0].size = 0xffffffff; image->sections[0].flags = 0; @@ -861,7 +902,7 @@ int image_read_section(struct image *image, int section, uint32_t offset, uint32 { LOG_DEBUG("read past end of section: 0x%8.8" PRIx32 " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "", offset, size, image->sections[section].size); - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } if (image->type == IMAGE_BINARY) @@ -870,7 +911,7 @@ int image_read_section(struct image *image, int section, uint32_t offset, uint32 /* only one section in a plain binary */ if (section != 0) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; /* seek to offset */ if ((retval = fileio_seek(&image_binary->fileio, offset)) != ERROR_OK) @@ -954,11 +995,11 @@ int image_read_section(struct image *image, int section, uint32_t offset, uint32 int image_add_section(struct image *image, uint32_t base, uint32_t size, int flags, uint8_t *data) { - struct imageection *section; + struct imagesection *section; /* only image builder supports adding sections */ if (image->type != IMAGE_BUILDER) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; /* see if there's a previous section */ if (image->num_sections) @@ -978,7 +1019,7 @@ int image_add_section(struct image *image, uint32_t base, uint32_t size, int fla /* allocate new section */ image->num_sections++; - image->sections = realloc(image->sections, sizeof(struct imageection) * image->num_sections); + image->sections = realloc(image->sections, sizeof(struct imagesection) * image->num_sections); section = &image->sections[image->num_sections - 1]; section->base_address = base; section->size = size;