1# DExTer : Debugging Experience Tester 2# ~~~~~~ ~ ~~ ~ ~~ 3# 4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5# See https://llvm.org/LICENSE.txt for license information. 6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7"""Classes which are used to represent debugger steps.""" 8 9import json 10 11from collections import OrderedDict 12from typing import List 13from enum import Enum 14from dex.dextIR.FrameIR import FrameIR 15from dex.dextIR.LocIR import LocIR 16from dex.dextIR.ProgramState import ProgramState 17 18 19class StopReason(Enum): 20 BREAKPOINT = 0 21 STEP = 1 22 PROGRAM_EXIT = 2 23 ERROR = 3 24 OTHER = 4 25 26 27class StepKind(Enum): 28 FUNC = 0 29 FUNC_EXTERNAL = 1 30 FUNC_UNKNOWN = 2 31 VERTICAL_FORWARD = 3 32 SAME = 4 33 VERTICAL_BACKWARD = 5 34 UNKNOWN = 6 35 HORIZONTAL_FORWARD = 7 36 HORIZONTAL_BACKWARD = 8 37 38 39class StepIR: 40 """A debugger step. 41 42 Args: 43 watches (OrderedDict): { expression (str), result (ValueIR) } 44 """ 45 46 def __init__(self, 47 step_index: int, 48 stop_reason: StopReason, 49 frames: List[FrameIR], 50 step_kind: StepKind = None, 51 watches: OrderedDict = None, 52 program_state: ProgramState = None): 53 self.step_index = step_index 54 self.step_kind = step_kind 55 self.stop_reason = stop_reason 56 self.program_state = program_state 57 58 if frames is None: 59 frames = [] 60 self.frames = frames 61 62 if watches is None: 63 watches = {} 64 self.watches = watches 65 66 def __str__(self): 67 try: 68 frame = self.current_frame 69 frame_info = (frame.function, frame.loc.path, frame.loc.lineno, 70 frame.loc.column) 71 except AttributeError: 72 frame_info = (None, None, None, None) 73 74 step_info = (self.step_index, ) + frame_info + ( 75 str(self.stop_reason), str(self.step_kind), 76 [w for w in self.watches]) 77 78 return '{}{}'.format('. ' * (self.num_frames - 1), 79 json.dumps(step_info)) 80 81 @property 82 def num_frames(self): 83 return len(self.frames) 84 85 @property 86 def current_frame(self): 87 if not len(self.frames): 88 return None 89 return self.frames[0] 90 91 @property 92 def current_function(self): 93 try: 94 return self.current_frame.function 95 except AttributeError: 96 return None 97 98 @property 99 def current_location(self): 100 try: 101 return self.current_frame.loc 102 except AttributeError: 103 return LocIR(path=None, lineno=None, column=None) 104