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