def generateStacktrace(state: programState.ProgramState, error: programState.RunError, fileName: str, lines: List[str]) -> str: # Get return addresses from the stack sp: int = state.getReg("SP") stackSize = state.getLabelAddress("__STACKSIZE") stack: List[nodes.Node] = state.memory[sp >> 2:stackSize >> 2] callbacks = list( map( lambda n: generateStacktraceElement(state, n.value, fileName, lines ), filter( lambda x: isinstance(x, nodes.DataNode) and x.source == "LR", stack))) # Generate the error res = f"\033[31m" # Red color res += "Traceback (most recent call first):\n" res += generateStacktraceElement(state, state.getReg("PC"), fileName, lines) + '\n' if not state.hasReturned: res += generateStacktraceElement(state, state.getReg("LR"), fileName, lines) + '\n' if len(callbacks) > 0: res += reduce(lambda a, b: a + "\n" + b, callbacks) + '\n' res += error.message + '\n' return res + f"\033[0m" # Normal color
def ldrLabel(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: val: Union[int, programState.RunError] = state.getLabelAddress(label.label) if isinstance(val, programState.RunError): return state, val else: state.setReg(dest.contents, val) return state, None
def branchToLabel(state: programState.ProgramState, label: str) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: # Save return address in LR state.setReg("LR", state.getReg("PC")) address: Union[int, programState.RunError] = state.getLabelAddress(label) if isinstance(address, programState.RunError): return state, programState.RunError(f"Unknown startup label: {label}", programState.RunError.ErrorType.Error) else: # Subtract 4 because we will add 4 to the address later in the run loop and we need to start at address and not address+4 state.setReg("PC", address - 4) state.hasReturned = False return state, None
def branchTo( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if condition(state.status): address: Union[int, programState.RunError] = state.getLabelAddress( label.contents) if isinstance(address, programState.RunError): return state, address else: # Subtract 4 because we will add 4 to the address later in the run loop and we need to start at address and not address+4 state.setReg("PC", address - 4) return state, None
def pop(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if len(regs) == 0: return state, None # head, *tail = registers address = state.getReg("SP") # check address is in 0...stacksize if address > (state.getLabelAddress("__STACKSIZE")) or address < 0: return state, programState.RunError("All stack entries have been pop'ed already", programState.RunError.ErrorType.Error) for reg in regs: err = state.loadRegister(address, 32, False, reg) address += 4 if err is not None: return state, err state.setReg("SP", address) return state, None
def push(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if len(regs) == 0: return state, None # head, *tail = registers address = state.getReg("SP") # check address is in 0...stacksize if address > (state.getLabelAddress("__STACKSIZE")) or address < 0: return state, programState.RunError("Stack overflow", programState.RunError.ErrorType.Error) for reg in regs: address -= 4 err = state.storeRegister(address, reg, 32) if err is not None: return state, err state.setReg("SP", address) return state, None
def branchTo( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: # Save return address in LR pc, _ = state.getReg("PC") state.setReg("LR", pc) address: Union[int, programState.RunError] = state.getLabelAddress( label.contents) if isinstance(address, programState.RunError): return state, address else: # Subtract 4 because we will add 4 to the address later in the run loop and we need to start at address and not address+4 state.setReg("PC", address - 4) state.hasReturned = False return state, None