+ /**
+ * 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->segments32[i].p_paddr != 0)
+ break;
+ else if ((field32(elf,
+ elf->segments32[i].p_type) == PT_LOAD) &&
+ (field32(elf, elf->segments32[i].p_memsz) != 0))
+ ++nload;
+
+ if (i >= elf->segment_count && nload > 1)
+ load_to_vaddr = true;
+
+ /* alloc and fill sections array with loadable segments */
+ image->sections = malloc(image->num_sections * sizeof(struct imagesection));
+ if (!image->sections) {
+ LOG_ERROR("insufficient memory to perform operation");
+ return ERROR_FILEIO_OPERATION_FAILED;
+ }
+
+ 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 (load_to_vaddr)
+ image->sections[j].base_address = field32(elf,
+ elf->segments32[i].p_vaddr);
+ else
+ image->sections[j].base_address = field32(elf,
+ elf->segments32[i].p_paddr);
+ image->sections[j].private = &elf->segments32[i];
+ image->sections[j].flags = field32(elf, elf->segments32[i].p_flags);
+ j++;
+ }
+ }
+
+ image->start_address_set = true;
+ image->start_address = field32(elf, elf->header32->e_entry);
+
+ return ERROR_OK;
+}
+
+static int image_elf64_read_headers(struct image *image)
+{
+ struct image_elf *elf = image->type_private;
+ size_t read_bytes;
+ uint32_t i, j;
+ int retval;
+ uint32_t nload;
+ bool load_to_vaddr = false;
+
+ retval = fileio_seek(elf->fileio, 0);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("cannot seek to ELF file header, read failed");
+ return retval;
+ }
+
+ elf->header64 = malloc(sizeof(Elf64_Ehdr));
+
+ if (!elf->header64) {
+ LOG_ERROR("insufficient memory to perform operation");
+ return ERROR_FILEIO_OPERATION_FAILED;
+ }
+
+ retval = fileio_read(elf->fileio, sizeof(Elf64_Ehdr), (uint8_t *)elf->header64, &read_bytes);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("cannot read ELF file header, read failed");
+ return ERROR_FILEIO_OPERATION_FAILED;
+ }
+ if (read_bytes != sizeof(Elf64_Ehdr)) {
+ LOG_ERROR("cannot read ELF file header, only partially read");
+ return ERROR_FILEIO_OPERATION_FAILED;
+ }
+
+ elf->segment_count = field16(elf, elf->header64->e_phnum);
+ if (elf->segment_count == 0) {