diff --git a/riscemu/priv/ElfLoader.py b/riscemu/priv/ElfLoader.py index 8f71740..9f8a172 100644 --- a/riscemu/priv/ElfLoader.py +++ b/riscemu/priv/ElfLoader.py @@ -1,9 +1,6 @@ from dataclasses import dataclass from typing import List, Dict, Tuple -from elftools.elf.elffile import ELFFile -from elftools.elf.sections import Section, SymbolTableSection - from .Exceptions import * from ..Exceptions import RiscemuBaseException from ..Executable import MemoryFlags, LoadedMemorySection @@ -12,6 +9,9 @@ from ..helpers import FMT_PARSE, FMT_NONE, FMT_GREEN, FMT_BOLD FMT_ELF = FMT_GREEN + FMT_BOLD +if typing.TYPE_CHECKING: + from elftools.elf.elffile import ELFFile + from elftools.elf.sections import Section, SymbolTableSection # This requires pyelftools package! @@ -29,11 +29,18 @@ class ElfExecutable: self.sections_by_name = dict() self.symbols = dict() - with open(name, 'rb') as f: - print(FMT_ELF + "[ElfLoader] Loading elf executable from: {}".format(name) + FMT_NONE) - self._read_elf(ELFFile(f)) + try: + from elftools.elf.elffile import ELFFile + from elftools.elf.sections import Section, SymbolTableSection + + with open(name, 'rb') as f: + print(FMT_ELF + "[ElfLoader] Loading elf executable from: {}".format(name) + FMT_NONE) + self._read_elf(ELFFile(f)) + except ImportError as e: + print(FMT_PARSE + "[ElfLoader] Cannot load elf files without PyElfTools package! You can install them using pip install pyelftools!" + FMT_NONE) + raise e - def _read_elf(self, elf: ELFFile): + def _read_elf(self, elf: 'ELFFile'): if not elf.header.e_machine == 'EM_RISCV': raise InvalidElfException("Not a RISC-V elf file!") if not elf.header.e_ident.EI_CLASS == 'ELFCLASS32': @@ -41,6 +48,7 @@ class ElfExecutable: self.run_ptr = elf.header.e_entry + from elftools.elf.sections import SymbolTableSection for sec in elf.iter_sections(): if isinstance(sec, SymbolTableSection): self._parse_symtab(sec) @@ -51,7 +59,7 @@ class ElfExecutable: self.add_sec(self._lms_from_elf_sec(sec, 'kernel')) - def _lms_from_elf_sec(self, sec: Section, owner: str): + def _lms_from_elf_sec(self, sec: 'Section', owner: str): is_code = sec.name in ('.text',) data = bytearray(sec.data()) flags = MemoryFlags(is_code, is_code) @@ -65,7 +73,7 @@ class ElfExecutable: owner ) - def _parse_symtab(self, symtab: SymbolTableSection): + def _parse_symtab(self, symtab: 'SymbolTableSection'): self.symbols = { sym.name: sym.entry.st_value for sym in symtab.iter_symbols() if sym.name }