/* * Copyright (C) 2010 Tobias Klauser * * This file is part of nios2sim-ng. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ #include #include #include #include #include "nios2sim-ng.h" #include "image.h" /* not defined with libelf */ #define EM_ALTERA_NIOS2 113 /* * http://elftoolchain.sourceforge.net/for-review/libelf-by-example-20100112.pdf */ static int elf_read_sections(Elf *e, struct memory *mem) { Elf_Scn *scn = NULL; size_t shstrndx; char *name; if (elf_getshdrstrndx(e, &shstrndx) != 0) { err("elf_getshdrstrndx() failed: %s\n", elf_errmsg(-1)); return -1; } while ((scn = elf_nextscn(e, scn)) != NULL) { GElf_Shdr shdr; GElf_Phdr phdr; if (gelf_getshdr(scn, &shdr) == NULL) { err("Couldn't get section header: %s\n", elf_errmsg(-1)); return -1; } /* Is it a .text section? */ if (shdr.sh_type == SHT_PROGBITS && (shdr.sh_flags & ~SHF_WRITE) == (SHF_ALLOC | SHF_EXECINSTR)) { Elf_Data *data; size_t n; if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) { err("Couldn't get section name: %s\n", elf_errmsg(-1)); return -1; } dbg("Section %zu: %s (size=%zu, flags=%08lx, addr=%08lx, off=%08lx)\n", elf_ndxscn(scn), name, shdr.sh_size, shdr.sh_flags, shdr.sh_addr, shdr.sh_offset); data = NULL; n = 0; while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) { memcpy(&mem->base[(shdr.sh_addr + n) / 4], data->d_buf, data->d_size); n += data->d_size; } } } return 0; } int elf_load(FILE *fp, const char *name, struct memory *mem) { int fd = fileno(fp); int ret; Elf *e; GElf_Ehdr ehdr; size_t n; if (unlikely(fd < 0)) { err("Couldn't get file descriptor for '%s'\n", name); return -1; } if (elf_version(EV_CURRENT) == EV_NONE) { err("ELF library initialization failed\n"); return -1; } ret = -1; e = elf_begin(fd, ELF_C_READ, NULL); if (unlikely(e == NULL)) { err("Couldn't get ELF file handle for '%s': %s\n", name, elf_errmsg(-1)); goto out; } if (elf_kind(e) != ELF_K_ELF) { err("'%s' is not an ELF object\n", name); goto out; } if (gelf_getclass(e) != ELFCLASS32) { err("'%s' has invalid ELF class\n", name); goto out; } if (gelf_getehdr(e, &ehdr) == NULL) { err("gelf_getehdr() failed: %s\n", elf_errmsg(-1)); goto out; } if (ehdr.e_type != ET_EXEC || ehdr.e_machine != EM_ALTERA_NIOS2) { err("'%s' is not a Nios2 ELF executable (%x, %x)\n", name, ehdr.e_type, ehdr.e_machine); goto out; } ret = elf_read_sections(e, mem); out: elf_end(e); return ret; }