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__( 47 self, 48 step_index: int, 49 stop_reason: StopReason, 50 frames: List[FrameIR], 51 step_kind: StepKind = None, 52 watches: OrderedDict = None, 53 program_state: ProgramState = None, 54 ): 55 self.step_index = step_index 56 self.step_kind = step_kind 57 self.stop_reason = stop_reason 58 self.program_state = program_state 59 60 if frames is None: 61 frames = [] 62 self.frames = frames 63 64 if watches is None: 65 watches = {} 66 self.watches = watches 67 68 def __str__(self): 69 try: 70 frame = self.current_frame 71 frame_info = ( 72 frame.function, 73 frame.loc.path, 74 frame.loc.lineno, 75 frame.loc.column, 76 ) 77 except AttributeError: 78 frame_info = (None, None, None, None) 79 80 step_info = ( 81 (self.step_index,) 82 + frame_info 83 + (str(self.stop_reason), str(self.step_kind), [w for w in self.watches]) 84 ) 85 86 return "{}{}".format(". " * (self.num_frames - 1), json.dumps(step_info)) 87 88 @property 89 def num_frames(self): 90 return len(self.frames) 91 92 @property 93 def current_frame(self): 94 if not len(self.frames): 95 return None 96 return self.frames[0] 97 98 @property 99 def current_function(self): 100 try: 101 return self.current_frame.function 102 except AttributeError: 103 return None 104 105 @property 106 def current_location(self): 107 try: 108 return self.current_frame.loc 109 except AttributeError: 110 return LocIR(path=None, lineno=None, column=None) 111