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 8import os 9 10from .utils import * 11 12class Frame(object): 13 def __init__(self, frame, idx, Symbols): 14 # Store some base information about the frame 15 self.ip = frame.InstructionOffset 16 self.scope_idx = idx 17 self.virtual = frame.Virtual 18 self.inline_frame_context = frame.InlineFrameContext 19 self.func_tbl_entry = frame.FuncTableEntry 20 21 # Fetch the module/symbol we're in, with displacement. Useful for debugging. 22 self.descr = Symbols.GetNearNameByOffset(self.ip) 23 split = self.descr.split('!')[0] 24 self.module = split[0] 25 self.symbol = split[1] 26 27 # Fetch symbol group for this scope. 28 prevscope = Symbols.GetCurrentScopeFrameIndex() 29 if Symbols.SetScopeFrameByIndex(idx): 30 symgroup = Symbols.GetScopeSymbolGroup2() 31 Symbols.SetScopeFrameByIndex(prevscope) 32 self.symgroup = symgroup 33 else: 34 self.symgroup = None 35 36 # Fetch the name according to the line-table, using inlining context. 37 name = Symbols.GetNameByInlineContext(self.ip, self.inline_frame_context) 38 self.function_name = name.split('!')[-1] 39 40 try: 41 tup = Symbols.GetLineByInlineContext(self.ip, self.inline_frame_context) 42 self.source_file, self.line_no = tup 43 except WinError as e: 44 # Fall back to trying to use a non-inlining-aware line number 45 # XXX - this is not inlining aware 46 sym = Symbols.GetLineByOffset(self.ip) 47 if sym is not None: 48 self.source_file, self.line_no = sym 49 else: 50 self.source_file = None 51 self.line_no = None 52 self.basename = None 53 54 if self.source_file is not None: 55 self.basename = os.path.basename(self.source_file) 56 else: 57 self.basename = None 58 59 60 61 def __str__(self): 62 return '{}:{}({}) {}'.format(self.basename, self.line, self.descr, self.function_name) 63 64def main_on_stack(Symbols, frames): 65 module_name = Symbols.get_exefile_module_name() 66 main_name = "{}!main".format(module_name) 67 for x in frames: 68 if main_name in x.descr: # Could be less hard coded... 69 return True 70 return False 71 72def probe_state(Client): 73 # Fetch the state of the program -- represented by the stack frames. 74 frames, numframes = Client.Control.GetStackTraceEx() 75 76 the_frames = [Frame(frames[x], x, Client.Symbols) for x in range(numframes)] 77 if not main_on_stack(Client.Symbols, the_frames): 78 return None 79 80 return the_frames 81