Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def add_line(*args) -> None:
add(*args)
tokens.append(Token(T.NEWLINE))
# Label.
label = self.log.get_label(instr.pc, instr.subroutine_pc)
if label:
if instr.pc in self.log.jump_table_targets:
add_line(T.JUMP_TABLE_LABEL, label)
else:
add_line(T.LABEL, label)
# Stack manipulation.
if verbose and instr.stack_manipulation != StackManipulation.NONE:
if instr.stack_manipulation == StackManipulation.CAUSES_UNKNOWN_STATE:
add_line(T.FATAL_STACK_MANIPULATION_HEADER)
else:
add_line(T.STACK_MANIPULATION_HEADER)
# Operation + Operand.
tokens.append(Token(T.OPERATION, instr.name))
if instr.argument_alias:
if instr.argument_alias in hw_registers:
add(T.HW_REGISTER, instr.argument_alias)
elif instr.argument_alias in self.preview_excluded_labels:
add(T.HIGHLIGHTED_OPERAND_LABEL, instr.argument_alias)
elif instr.pc in self.log.jump_table_targets:
add(T.JUMP_TABLE_OPERAND_LABEL, instr.argument_alias)
else:
add(T.OPERAND_LABEL, instr.argument_alias)
else:
# No custom assertion, we need to stop here.
unknown_reason = unknown_reason or UnknownReason.UNKNOWN
self.state_change = StateChange(unknown_reason=unknown_reason)
self.log.add_subroutine_state(
self.subroutine_pc, instruction.pc, copy(self.state_change)
)
# If the unknown state is due to stack manipulation:
if unknown_reason == UnknownReason.STACK_MANIPULATION:
# If we know which instruction performed the
# manipulation, we flag it.
if stack_manipulator:
self.subroutine.has_stack_manipulation = True
stack_manipulator.stack_manipulation = (
StackManipulation.CAUSES_UNKNOWN_STATE
)
return False
def change_stack(self, i: Instruction) -> None:
if i.operation == Op.TCS:
a = self.registers.a.get_whole()
self.stack.set_pointer(i, a)
if a is not None:
return
# We keep the disassembly going if the stack manipulation
# doesn't otherwise influence the state of the processor.
i.stack_manipulation = StackManipulation.HARMLESS
registers: Dict[str, Optional[int]],
state_change_before: StateChange,
):
super().__init__()
self.log = log
self.pc = pc
self.state = State(p)
self.registers = registers
self.subroutine_pc = subroutine_pc
self.opcode = opcode
self._argument = argument
self.state_change_before = state_change_before
self.state_change_after = StateChange(unknown_reason=UnknownReason.UNKNOWN)
self.stack_manipulation = StackManipulation.NONE
self.ret_indirect_type = RetIndirectType.NONE
tokens.append(Token(*args))
def add_line(*args) -> None:
add(*args)
tokens.append(Token(T.NEWLINE))
# Label.
label = self.log.get_label(instr.pc, instr.subroutine_pc)
if label:
if instr.pc in self.log.jump_table_targets:
add_line(T.JUMP_TABLE_LABEL, label)
else:
add_line(T.LABEL, label)
# Stack manipulation.
if verbose and instr.stack_manipulation != StackManipulation.NONE:
if instr.stack_manipulation == StackManipulation.CAUSES_UNKNOWN_STATE:
add_line(T.FATAL_STACK_MANIPULATION_HEADER)
else:
add_line(T.STACK_MANIPULATION_HEADER)
# Operation + Operand.
tokens.append(Token(T.OPERATION, instr.name))
if instr.argument_alias:
if instr.argument_alias in hw_registers:
add(T.HW_REGISTER, instr.argument_alias)
elif instr.argument_alias in self.preview_excluded_labels:
add(T.HIGHLIGHTED_OPERAND_LABEL, instr.argument_alias)
elif instr.pc in self.log.jump_table_targets:
add(T.JUMP_TABLE_OPERAND_LABEL, instr.argument_alias)
else:
add(T.OPERAND_LABEL, instr.argument_alias)
stack_entries = self.stack.pop(ret_size)
# Check for stack manipulations.
stack_manipulator = self._check_stack_manipulation(i, stack_entries)
if not stack_manipulator:
return standard_return()
# If the stack is constructed in such a way that
# we would return to the next instruction, it is
# effectively a subroutine call.
if self.stack.match(i.pc, ret_size):
i.ret_indirect_type = RetIndirectType.CALL
self.log.assert_jump(i.pc, set_dirty=False)
for s in self.stack.pop(ret_size):
if s.instruction:
s.instruction.stack_manipulation = StackManipulation.HARMLESS
return self.call(i, self.log.jump_assertions[i.pc])
# Otherwise, if we know this is a jump table, then it's a simple jump.
elif i.is_jump_table:
i.ret_indirect_type = RetIndirectType.JUMP
for s in stack_entries:
if s.instruction:
s.instruction.stack_manipulation = StackManipulation.HARMLESS
self.jump(i, self.log.jump_assertions[i.pc])
return False
# We don't know for certain that this is a jump table, signal
# an unknown state.
else:
self._unknown_subroutine_state(
i,