# 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
from collections import namedtuple
from ctypes import *
from functools import partial
from .utils import *
Symbol = namedtuple("Symbol", ["num", "name", "type", "value"])
class IDebugSymbolGroup2(Structure):
pass
class IDebugSymbolGroup2Vtbl(Structure):
wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSymbolGroup2))
ids_getnumbersymbols = wrp(c_ulong_p)
ids_getsymbolname = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p)
ids_getsymboltypename = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p)
ids_getsymbolvaluetext = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p)
_fields_ = [
("QueryInterface", c_void_p),
("AddRef", c_void_p),
("Release", c_void_p),
("GetNumberSymbols", ids_getnumbersymbols),
("AddSymbol", c_void_p),
("RemoveSymbolByName", c_void_p),
("RemoveSymbolByIndex", c_void_p),
("GetSymbolName", ids_getsymbolname),
("GetSymbolParameters", c_void_p),
("ExpandSymbol", c_void_p),
("OutputSymbols", c_void_p),
("WriteSymbol", c_void_p),
("OutputAsType", c_void_p),
("AddSymbolWide", c_void_p),
("RemoveSymbolByNameWide", c_void_p),
("GetSymbolNameWide", c_void_p),
("WritesymbolWide", c_void_p),
("OutputAsTypeWide", c_void_p),
("GetSymbolTypeName", ids_getsymboltypename),
("GetSymbolTypeNameWide", c_void_p),
("GetSymbolSize", c_void_p),
("GetSymbolOffset", c_void_p),
("GetSymbolRegister", c_void_p),
("GetSymbolValueText", ids_getsymbolvaluetext),
("GetSymbolValueTextWide", c_void_p),
("GetSymbolEntryInformation", c_void_p),
]
IDebugSymbolGroup2._fields_ = [("lpVtbl", POINTER(IDebugSymbolGroup2Vtbl))]
class SymbolGroup(object):
def __init__(self, symgroup):
self.symgroup = symgroup.contents
self.vt = self.symgroup.lpVtbl.contents
self.ulong = c_ulong()
def GetNumberSymbols(self):
res = self.vt.GetNumberSymbols(self.symgroup, byref(self.ulong))
aborter(res, "GetNumberSymbols")
return self.ulong.value
def GetSymbolName(self, idx):
buf = create_string_buffer(256)
res = self.vt.GetSymbolName(self.symgroup, idx, buf, 255, byref(self.ulong))
aborter(res, "GetSymbolName")
thelen = self.ulong.value
return string_at(buf).decode("ascii")
def GetSymbolTypeName(self, idx):
buf = create_string_buffer(256)
res = self.vt.GetSymbolTypeName(self.symgroup, idx, buf, 255, byref(self.ulong))
aborter(res, "GetSymbolTypeName")
thelen = self.ulong.value
return string_at(buf).decode("ascii")
def GetSymbolValueText(self, idx, handleserror=False):
buf = create_string_buffer(256)
res = self.vt.GetSymbolValueText(
self.symgroup, idx, buf, 255, byref(self.ulong)
)
if res != 0 and handleserror:
return None
aborter(res, "GetSymbolTypeName")
thelen = self.ulong.value
return string_at(buf).decode("ascii")
def get_symbol(self, idx):
name = self.GetSymbolName(idx)
thetype = self.GetSymbolTypeName(idx)
value = self.GetSymbolValueText(idx)
return Symbol(idx, name, thetype, value)
def get_all_symbols(self):
num_syms = self.GetNumberSymbols()
return list(map(self.get_symbol, list(range(num_syms))))