From 34a44860e0850a9b0f04e7fb5b0986080303b189 Mon Sep 17 00:00:00 2001 From: Anton Lydike Date: Sun, 18 Apr 2021 09:10:03 +0200 Subject: [PATCH] added name field to executables for easy debugging --- riscemu/Executable.py | 18 ++++++++++++++---- riscemu/ExecutableParser.py | 4 ++-- riscemu/MMU.py | 2 ++ riscemu/Tokenizer.py | 11 +++++++++-- riscemu/__main__.py | 10 ++-------- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/riscemu/Executable.py b/riscemu/Executable.py index 46e2978..b348588 100644 --- a/riscemu/Executable.py +++ b/riscemu/Executable.py @@ -59,6 +59,7 @@ class Executable: sections: Dict[str, MemorySection] symbols: Dict[str, Tuple[str, int]] stack_pref: Optional[int] + name: str def __repr__(self): return "{}(sections = {}, symbols = {}, stack = {}, run_ptr = {})".format( @@ -129,6 +130,7 @@ class LoadedMemorySection: size: int content: Union[List[LoadedInstruction], bytearray] = field(repr=False) flags: MemoryFlags + owner: str def read(self, offset: int, size: int): if offset < 0: @@ -220,6 +222,7 @@ class LoadedExecutable: It still holds a symbol table, that is not accessible memory since I don't want to deal with binary strings in memory etc. """ + name: str base_addr: int sections_by_name: Dict[str, LoadedMemorySection] sections: List[LoadedMemorySection] @@ -228,6 +231,7 @@ class LoadedExecutable: stack_heap: Tuple[int, int] # pointers to stack and heap, are nullptr if no stack/heap is available def __init__(self, exe: Executable, base_addr: int): + self.name = exe.name self.base_addr = base_addr self.sections = list() self.sections_by_name = dict() @@ -240,7 +244,8 @@ class LoadedExecutable: base_addr, exe.stack_pref, bytearray(exe.stack_pref), - MemoryFlags(read_only=False, executable=False) + MemoryFlags(read_only=False, executable=False), + self.name )) self.stack_heap = (self.base_addr, self.base_addr + exe.stack_pref) else: @@ -253,7 +258,8 @@ class LoadedExecutable: curr, sec.size, sec.continuous_content(self), - sec.flags + sec.flags, + self.name ) self.sections.append(loaded_sec) self.sections_by_name[loaded_sec.name] = loaded_sec @@ -269,8 +275,12 @@ class LoadedExecutable: run_ptr_sec, run_ptr_off = exe.run_ptr self.run_ptr = self.sections_by_name[run_ptr_sec].base + run_ptr_off - print("successfully loaded binary\n\tsize: {}\n\tsections: {}\n\trun_ptr: 0x{:08x}".format( + def __repr__(self): + return '{}[{}](base=0x{:08X}, size={}bytes, sections={}, run_ptr=0x{:08X})'.format( + self.__class__.__name__, + self.name, + self.base_addr, self.size, " ".join(self.sections_by_name.keys()), self.run_ptr - )) + ) diff --git a/riscemu/ExecutableParser.py b/riscemu/ExecutableParser.py index 1bd8495..0cfbd17 100644 --- a/riscemu/ExecutableParser.py +++ b/riscemu/ExecutableParser.py @@ -27,7 +27,7 @@ class ExecutableParser: self.handle_symbol(token) elif isinstance(token, RiscVPseudoOpToken): self.handle_pseudo_op(token) - return self + return self.get_execuable() def get_execuable(self): start_ptr = ('text', 0) @@ -35,7 +35,7 @@ class ExecutableParser: start_ptr = self.symbols['_start'] elif 'main' in self.symbols: start_ptr = self.symbols['main'] - return Executable(start_ptr, self.sections, self.symbols, self.stack_pref) + return Executable(start_ptr, self.sections, self.symbols, self.stack_pref, self.tokenizer.name) def parse_instruction(self, ins: 'RiscVInstructionToken'): if self.active_section is None: diff --git a/riscemu/MMU.py b/riscemu/MMU.py index 1a94fca..b739833 100644 --- a/riscemu/MMU.py +++ b/riscemu/MMU.py @@ -43,6 +43,8 @@ class MMU: for sec in loaded_bin.sections: self.sections.append(sec) + print("Successfully loaded {}".format(loaded_bin)) + return loaded_bin def get_sec_containing(self, addr: int): diff --git a/riscemu/Tokenizer.py b/riscemu/Tokenizer.py index c870ba4..a95baaa 100644 --- a/riscemu/Tokenizer.py +++ b/riscemu/Tokenizer.py @@ -78,10 +78,16 @@ def split_accepting_quotes(string, at=REG_ARG_SPLIT, quotes=('"', "'")): class RiscVInput: - def __init__(self, content: str): + def __init__(self, content: str, name: str): self.content = content self.pos = 0 self.len = len(content) + self.name = name + + @staticmethod + def from_file(src: str): + with open(src, 'r') as f: + return RiscVInput(f.read(), src) def peek(self, offset: int = 0, size: int = 1, regex: re.Pattern = None, text: str = None, regex_group: int = 0): at = self.pos + offset @@ -89,7 +95,7 @@ class RiscVInput: if regex: if not isinstance(regex, re.Pattern): print("uncompiled regex passed to peek!") - reges = re.compile(regex) + regex = re.compile(regex) match = regex.match(self.content[at:]) if match is None: return None @@ -241,6 +247,7 @@ class RiscVTokenizer: def __init__(self, input: RiscVInput): self.input = input self.tokens: List[RiscVToken] = [] + self.name = input.name def tokenize(self): while self.input.has_next(): diff --git a/riscemu/__main__.py b/riscemu/__main__.py index 808b0ad..3b2eec0 100644 --- a/riscemu/__main__.py +++ b/riscemu/__main__.py @@ -20,7 +20,6 @@ if __name__ == '__main__': args = parser.parse_args() - print(args) cfg = RunConfig( color=not args.no_color, @@ -34,10 +33,7 @@ if __name__ == '__main__': FMT_NONE = "" FMT_PRINT = "" - with open(args.file, 'r') as f: - asm = f.read() - - tk = RiscVTokenizer(RiscVInput(asm)) + tk = RiscVTokenizer(RiscVInput.from_file(args.file)) tk.tokenize() if args.print_tokens: @@ -45,9 +41,7 @@ if __name__ == '__main__': for token in tk.tokens: print(token) - executable = ExecutableParser(tk).parse().get_execuable() - - print(FMT_PRINT + "Executable:" + FMT_NONE, executable) + executable = ExecutableParser(tk).parse() cpu = CPU(cfg) le = cpu.load(executable)