| # DExTer : Debugging Experience Tester |
| # ~~~~~~ ~ ~~ ~ ~~ |
| # |
| # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| # See https://llvm.org/LICENSE.txt for license information. |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| """Classes which are used to represent debugger steps.""" |
| |
| import json |
| |
| from collections import OrderedDict |
| from typing import List |
| from enum import Enum |
| from dex.dextIR.FrameIR import FrameIR |
| from dex.dextIR.LocIR import LocIR |
| from dex.dextIR.ProgramState import ProgramState |
| |
| |
| class StopReason(Enum): |
| BREAKPOINT = 0 |
| STEP = 1 |
| PROGRAM_EXIT = 2 |
| ERROR = 3 |
| OTHER = 4 |
| |
| |
| class StepKind(Enum): |
| FUNC = 0 |
| FUNC_EXTERNAL = 1 |
| FUNC_UNKNOWN = 2 |
| VERTICAL_FORWARD = 3 |
| SAME = 4 |
| VERTICAL_BACKWARD = 5 |
| UNKNOWN = 6 |
| HORIZONTAL_FORWARD = 7 |
| HORIZONTAL_BACKWARD = 8 |
| |
| |
| class StepIR: |
| """A debugger step. |
| |
| Args: |
| watches (OrderedDict): { expression (str), result (ValueIR) } |
| """ |
| |
| def __init__( |
| self, |
| step_index: int, |
| stop_reason: StopReason, |
| frames: List[FrameIR], |
| step_kind: StepKind = None, |
| watches: OrderedDict = None, |
| program_state: ProgramState = None, |
| ): |
| self.step_index = step_index |
| self.step_kind = step_kind |
| self.stop_reason = stop_reason |
| self.program_state = program_state |
| |
| if frames is None: |
| frames = [] |
| self.frames = frames |
| |
| if watches is None: |
| watches = {} |
| self.watches = watches |
| |
| def __str__(self): |
| try: |
| frame = self.current_frame |
| frame_info = ( |
| frame.function, |
| frame.loc.path, |
| frame.loc.lineno, |
| frame.loc.column, |
| ) |
| except AttributeError: |
| frame_info = (None, None, None, None) |
| |
| step_info = ( |
| (self.step_index,) |
| + frame_info |
| + (str(self.stop_reason), str(self.step_kind), [w for w in self.watches]) |
| ) |
| |
| return "{}{}".format(". " * (self.num_frames - 1), json.dumps(step_info)) |
| |
| @property |
| def num_frames(self): |
| return len(self.frames) |
| |
| @property |
| def current_frame(self): |
| if not len(self.frames): |
| return None |
| return self.frames[0] |
| |
| @property |
| def current_function(self): |
| try: |
| return self.current_frame.function |
| except AttributeError: |
| return None |
| |
| @property |
| def current_location(self): |
| try: |
| return self.current_frame.loc |
| except AttributeError: |
| return LocIR(path=None, lineno=None, column=None) |