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 8from collections import namedtuple 9from ctypes import * 10from functools import partial 11 12from .utils import * 13 14Symbol = namedtuple("Symbol", ["num", "name", "type", "value"]) 15 16 17class IDebugSymbolGroup2(Structure): 18 pass 19 20 21class IDebugSymbolGroup2Vtbl(Structure): 22 wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSymbolGroup2)) 23 ids_getnumbersymbols = wrp(c_ulong_p) 24 ids_getsymbolname = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p) 25 ids_getsymboltypename = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p) 26 ids_getsymbolvaluetext = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p) 27 _fields_ = [ 28 ("QueryInterface", c_void_p), 29 ("AddRef", c_void_p), 30 ("Release", c_void_p), 31 ("GetNumberSymbols", ids_getnumbersymbols), 32 ("AddSymbol", c_void_p), 33 ("RemoveSymbolByName", c_void_p), 34 ("RemoveSymbolByIndex", c_void_p), 35 ("GetSymbolName", ids_getsymbolname), 36 ("GetSymbolParameters", c_void_p), 37 ("ExpandSymbol", c_void_p), 38 ("OutputSymbols", c_void_p), 39 ("WriteSymbol", c_void_p), 40 ("OutputAsType", c_void_p), 41 ("AddSymbolWide", c_void_p), 42 ("RemoveSymbolByNameWide", c_void_p), 43 ("GetSymbolNameWide", c_void_p), 44 ("WritesymbolWide", c_void_p), 45 ("OutputAsTypeWide", c_void_p), 46 ("GetSymbolTypeName", ids_getsymboltypename), 47 ("GetSymbolTypeNameWide", c_void_p), 48 ("GetSymbolSize", c_void_p), 49 ("GetSymbolOffset", c_void_p), 50 ("GetSymbolRegister", c_void_p), 51 ("GetSymbolValueText", ids_getsymbolvaluetext), 52 ("GetSymbolValueTextWide", c_void_p), 53 ("GetSymbolEntryInformation", c_void_p), 54 ] 55 56 57IDebugSymbolGroup2._fields_ = [("lpVtbl", POINTER(IDebugSymbolGroup2Vtbl))] 58 59 60class SymbolGroup(object): 61 def __init__(self, symgroup): 62 self.symgroup = symgroup.contents 63 self.vt = self.symgroup.lpVtbl.contents 64 self.ulong = c_ulong() 65 66 def GetNumberSymbols(self): 67 res = self.vt.GetNumberSymbols(self.symgroup, byref(self.ulong)) 68 aborter(res, "GetNumberSymbols") 69 return self.ulong.value 70 71 def GetSymbolName(self, idx): 72 buf = create_string_buffer(256) 73 res = self.vt.GetSymbolName(self.symgroup, idx, buf, 255, byref(self.ulong)) 74 aborter(res, "GetSymbolName") 75 thelen = self.ulong.value 76 return string_at(buf).decode("ascii") 77 78 def GetSymbolTypeName(self, idx): 79 buf = create_string_buffer(256) 80 res = self.vt.GetSymbolTypeName(self.symgroup, idx, buf, 255, byref(self.ulong)) 81 aborter(res, "GetSymbolTypeName") 82 thelen = self.ulong.value 83 return string_at(buf).decode("ascii") 84 85 def GetSymbolValueText(self, idx, handleserror=False): 86 buf = create_string_buffer(256) 87 res = self.vt.GetSymbolValueText( 88 self.symgroup, idx, buf, 255, byref(self.ulong) 89 ) 90 if res != 0 and handleserror: 91 return None 92 aborter(res, "GetSymbolTypeName") 93 thelen = self.ulong.value 94 return string_at(buf).decode("ascii") 95 96 def get_symbol(self, idx): 97 name = self.GetSymbolName(idx) 98 thetype = self.GetSymbolTypeName(idx) 99 value = self.GetSymbolValueText(idx) 100 return Symbol(idx, name, thetype, value) 101 102 def get_all_symbols(self): 103 num_syms = self.GetNumberSymbols() 104 return list(map(self.get_symbol, list(range(num_syms)))) 105