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