# 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 import os from .utils import * class Frame(object): def __init__(self, frame, idx, Symbols): # Store some base information about the frame self.ip = frame.InstructionOffset self.scope_idx = idx self.virtual = frame.Virtual self.inline_frame_context = frame.InlineFrameContext self.func_tbl_entry = frame.FuncTableEntry # Fetch the module/symbol we're in, with displacement. Useful for debugging. self.descr = Symbols.GetNearNameByOffset(self.ip) split = self.descr.split('!')[0] self.module = split[0] self.symbol = split[1] # Fetch symbol group for this scope. prevscope = Symbols.GetCurrentScopeFrameIndex() if Symbols.SetScopeFrameByIndex(idx): symgroup = Symbols.GetScopeSymbolGroup2() Symbols.SetScopeFrameByIndex(prevscope) self.symgroup = symgroup else: self.symgroup = None # Fetch the name according to the line-table, using inlining context. name = Symbols.GetNameByInlineContext(self.ip, self.inline_frame_context) self.function_name = name.split('!')[-1] try: tup = Symbols.GetLineByInlineContext(self.ip, self.inline_frame_context) self.source_file, self.line_no = tup except WinError as e: # Fall back to trying to use a non-inlining-aware line number # XXX - this is not inlining aware sym = Symbols.GetLineByOffset(self.ip) if sym is not None: self.source_file, self.line_no = sym else: self.source_file = None self.line_no = None self.basename = None if self.source_file is not None: self.basename = os.path.basename(self.source_file) else: self.basename = None def __str__(self): return '{}:{}({}) {}'.format(self.basename, self.line, self.descr, self.function_name) def main_on_stack(Symbols, frames): module_name = Symbols.get_exefile_module_name() main_name = "{}!main".format(module_name) for x in frames: if main_name in x.descr: # Could be less hard coded... return True return False def probe_state(Client): # Fetch the state of the program -- represented by the stack frames. frames, numframes = Client.Control.GetStackTraceEx() the_frames = [Frame(frames[x], x, Client.Symbols) for x in range(numframes)] if not main_on_stack(Client.Symbols, the_frames): return None return the_frames