| 18 | using namespace machine; |
| 19 | |
| 20 | ProgramLoader::ProgramLoader(const QString &file) : elf_file(file) { |
| 21 | const GElf_Ehdr *elf_ehdr; |
| 22 | // Initialize elf library |
| 23 | if (elf_version(EV_CURRENT) == EV_NONE) { |
| 24 | throw SIMULATOR_EXCEPTION( |
| 25 | Input, "Elf library initialization failed", elf_errmsg(-1)); |
| 26 | } |
| 27 | // Open source file - option QIODevice::ExistingOnly cannot be used on Qt |
| 28 | // <5.11 |
| 29 | if (!elf_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) { |
| 30 | throw SIMULATOR_EXCEPTION( |
| 31 | Input, |
| 32 | QString("Can't open input elf file for reading (") + QString(file) |
| 33 | + QString(")"), |
| 34 | std::strerror(errno)); |
| 35 | } |
| 36 | // Initialize elf |
| 37 | if (!(this->elf = elf_begin(elf_file.handle(), ELF_C_READ, nullptr))) { |
| 38 | throw SIMULATOR_EXCEPTION( |
| 39 | Input, "Elf read begin failed", elf_errmsg(-1)); |
| 40 | } |
| 41 | // Check elf kind |
| 42 | if (elf_kind(this->elf) != ELF_K_ELF) { |
| 43 | throw SIMULATOR_EXCEPTION( |
| 44 | Input, "Invalid input file elf format, plain elf file expected", |
| 45 | ""); |
| 46 | } |
| 47 | |
| 48 | elf_ehdr = gelf_getehdr(this->elf, &this->hdr); |
| 49 | if (!elf_ehdr) { |
| 50 | throw SIMULATOR_EXCEPTION( |
| 51 | Input, "Getting elf file header failed", elf_errmsg(-1)); |
| 52 | } |
| 53 | |
| 54 | executable_entry = Address(elf_ehdr->e_entry); |
| 55 | // Check elf file format, executable expected, nothing else. |
| 56 | if (this->hdr.e_type != ET_EXEC) { |
| 57 | throw SIMULATOR_EXCEPTION(Input, "Invalid input file type", ""); |
| 58 | } |
| 59 | // Check elf file architecture, of course only mips is supported. |
| 60 | // Note: This also checks that this is big endian as EM_MIPS is suppose to |
| 61 | // be: MIPS R3000 big-endian |
| 62 | if (this->hdr.e_machine != EM_RISCV) { |
| 63 | throw SIMULATOR_EXCEPTION(Input, "Invalid input file architecture", ""); |
| 64 | } |
| 65 | // Check elf file class, only 32bit architecture is supported. |
| 66 | int elf_class; |
| 67 | if ((elf_class = gelf_getclass(this->elf)) == ELFCLASSNONE) { |
| 68 | throw SIMULATOR_EXCEPTION( |
| 69 | Input, "Getting elf class failed", elf_errmsg(-1)); |
| 70 | } |
| 71 | // Get number of program sections in elf file |
| 72 | if (elf_getphdrnum(this->elf, &this->n_secs)) { |
| 73 | throw SIMULATOR_EXCEPTION( |
| 74 | Input, "Elf program sections count query failed", elf_errmsg(-1)); |
| 75 | } |
| 76 | |
| 77 | if (elf_class == ELFCLASS32) { |
nothing calls this directly
no test coverage detected