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 enum import *
11from functools import reduce, partial
12
13from .symgroup import SymbolGroup, IDebugSymbolGroup2
14from .utils import *
15
16class SymbolOptionFlags(IntFlag):
17  SYMOPT_CASE_INSENSITIVE          = 0x00000001
18  SYMOPT_UNDNAME                   = 0x00000002
19  SYMOPT_DEFERRED_LOADS            = 0x00000004
20  SYMOPT_NO_CPP                    = 0x00000008
21  SYMOPT_LOAD_LINES                = 0x00000010
22  SYMOPT_OMAP_FIND_NEAREST         = 0x00000020
23  SYMOPT_LOAD_ANYTHING             = 0x00000040
24  SYMOPT_IGNORE_CVREC              = 0x00000080
25  SYMOPT_NO_UNQUALIFIED_LOADS      = 0x00000100
26  SYMOPT_FAIL_CRITICAL_ERRORS      = 0x00000200
27  SYMOPT_EXACT_SYMBOLS             = 0x00000400
28  SYMOPT_ALLOW_ABSOLUTE_SYMBOLS    = 0x00000800
29  SYMOPT_IGNORE_NT_SYMPATH         = 0x00001000
30  SYMOPT_INCLUDE_32BIT_MODULES     = 0x00002000
31  SYMOPT_PUBLICS_ONLY              = 0x00004000
32  SYMOPT_NO_PUBLICS                = 0x00008000
33  SYMOPT_AUTO_PUBLICS              = 0x00010000
34  SYMOPT_NO_IMAGE_SEARCH           = 0x00020000
35  SYMOPT_SECURE                    = 0x00040000
36  SYMOPT_NO_PROMPTS                = 0x00080000
37  SYMOPT_DEBUG                     = 0x80000000
38
39class ScopeGroupFlags(IntFlag):
40  DEBUG_SCOPE_GROUP_ARGUMENTS    = 0x00000001
41  DEBUG_SCOPE_GROUP_LOCALS       = 0x00000002
42  DEBUG_SCOPE_GROUP_ALL          = 0x00000003
43  DEBUG_SCOPE_GROUP_BY_DATAMODEL = 0x00000004
44
45class DebugModuleNames(IntEnum):
46  DEBUG_MODNAME_IMAGE        = 0x00000000
47  DEBUG_MODNAME_MODULE       = 0x00000001
48  DEBUG_MODNAME_LOADED_IMAGE = 0x00000002
49  DEBUG_MODNAME_SYMBOL_FILE  = 0x00000003
50  DEBUG_MODNAME_MAPPED_IMAGE = 0x00000004
51
52class DebugModuleFlags(IntFlag):
53  DEBUG_MODULE_LOADED            = 0x00000000
54  DEBUG_MODULE_UNLOADED          = 0x00000001
55  DEBUG_MODULE_USER_MODE         = 0x00000002
56  DEBUG_MODULE_EXE_MODULE        = 0x00000004
57  DEBUG_MODULE_EXPLICIT          = 0x00000008
58  DEBUG_MODULE_SECONDARY         = 0x00000010
59  DEBUG_MODULE_SYNTHETIC         = 0x00000020
60  DEBUG_MODULE_SYM_BAD_CHECKSUM  = 0x00010000
61
62class DEBUG_MODULE_PARAMETERS(Structure):
63  _fields_ = [
64      ("Base", c_ulonglong),
65      ("Size", c_ulong),
66      ("TimeDateStamp", c_ulong),
67      ("Checksum", c_ulong),
68      ("Flags", c_ulong),
69      ("SymbolType", c_ulong),
70      ("ImageNameSize", c_ulong),
71      ("ModuleNameSize", c_ulong),
72      ("LoadedImageNameSize", c_ulong),
73      ("SymbolFileNameSize", c_ulong),
74      ("MappedImageNameSize", c_ulong),
75      ("Reserved", c_ulonglong * 2)
76    ]
77PDEBUG_MODULE_PARAMETERS = POINTER(DEBUG_MODULE_PARAMETERS)
78
79class DEBUG_MODULE_AND_ID(Structure):
80  _fields_ = [
81      ("ModuleBase", c_ulonglong),
82      ("Id", c_ulonglong)
83    ]
84PDEBUG_MODULE_AND_ID = POINTER(DEBUG_MODULE_AND_ID)
85
86class DEBUG_SYMBOL_ENTRY(Structure):
87  _fields_ = [
88      ("ModuleBase", c_ulonglong),
89      ("Offset", c_ulonglong),
90      ("Id", c_ulonglong),
91      ("Arg64", c_ulonglong),
92      ("Size", c_ulong),
93      ("Flags", c_ulong),
94      ("TypeId", c_ulong),
95      ("NameSize", c_ulong),
96      ("Token", c_ulong),
97      ("Tag", c_ulong),
98      ("Arg32", c_ulong),
99      ("Reserved", c_ulong)
100    ]
101PDEBUG_SYMBOL_ENTRY = POINTER(DEBUG_SYMBOL_ENTRY)
102
103# UUID for DebugSymbols5 interface.
104DebugSymbols5IID = IID(0xc65fa83e, 0x1e69, 0x475e, IID_Data4_Type(0x8e, 0x0e, 0xb5, 0xd7, 0x9e, 0x9c, 0xc1, 0x7e))
105
106class IDebugSymbols5(Structure):
107  pass
108
109class IDebugSymbols5Vtbl(Structure):
110  wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSymbols5))
111  ids_getsymboloptions = wrp(c_ulong_p)
112  ids_setsymboloptions = wrp(c_ulong)
113  ids_getmoduleparameters = wrp(c_ulong, c_ulong64_p, c_ulong, PDEBUG_MODULE_PARAMETERS)
114  ids_getmodulenamestring = wrp(c_ulong, c_ulong, c_ulonglong, c_char_p, c_ulong, c_ulong_p)
115  ids_getoffsetbyname = wrp(c_char_p, c_ulong64_p)
116  ids_getlinebyoffset = wrp(c_ulonglong, c_ulong_p, c_char_p, c_ulong, c_ulong_p, c_ulong64_p)
117  ids_getsymbolentriesbyname = wrp(c_char_p, c_ulong, PDEBUG_MODULE_AND_ID, c_ulong, c_ulong_p)
118  ids_getsymbolentrystring = wrp(PDEBUG_MODULE_AND_ID, c_ulong, c_char_p, c_ulong, c_ulong_p)
119  ids_getsymbolentryinformation = wrp(PDEBUG_MODULE_AND_ID, PDEBUG_SYMBOL_ENTRY)
120  ids_getcurrentscopeframeindex = wrp(c_ulong_p)
121  ids_getnearnamebyoffset = wrp(c_ulonglong, c_long, c_char_p, c_ulong, c_ulong_p, c_ulong64_p)
122  ids_setscopeframebyindex = wrp(c_ulong)
123  ids_getscopesymbolgroup2 = wrp(c_ulong, POINTER(IDebugSymbolGroup2), POINTER(POINTER(IDebugSymbolGroup2)))
124  ids_getnamebyinlinecontext = wrp(c_ulonglong, c_ulong, c_char_p, c_ulong, c_ulong_p, c_ulong64_p)
125  ids_getlinebyinlinecontext = wrp(c_ulonglong, c_ulong, c_ulong_p, c_char_p, c_ulong, c_ulong_p, c_ulong64_p)
126  _fields_ = [
127      ("QueryInterface", c_void_p),
128      ("AddRef", c_void_p),
129      ("Release", c_void_p),
130      ("GetSymbolOptions", ids_getsymboloptions),
131      ("AddSymbolOptions", c_void_p),
132      ("RemoveSymbolOptions", c_void_p),
133      ("SetSymbolOptions", ids_setsymboloptions),
134      ("GetNameByOffset", c_void_p),
135      ("GetOffsetByName", ids_getoffsetbyname),
136      ("GetNearNameByOffset", ids_getnearnamebyoffset),
137      ("GetLineByOffset", ids_getlinebyoffset),
138      ("GetOffsetByLine", c_void_p),
139      ("GetNumberModules", c_void_p),
140      ("GetModuleByIndex", c_void_p),
141      ("GetModuleByModuleName", c_void_p),
142      ("GetModuleByOffset", c_void_p),
143      ("GetModuleNames", c_void_p),
144      ("GetModuleParameters", ids_getmoduleparameters),
145      ("GetSymbolModule", c_void_p),
146      ("GetTypeName", c_void_p),
147      ("GetTypeId", c_void_p),
148      ("GetTypeSize", c_void_p),
149      ("GetFieldOffset", c_void_p),
150      ("GetSymbolTypeId", c_void_p),
151      ("GetOffsetTypeId", c_void_p),
152      ("ReadTypedDataVirtual", c_void_p),
153      ("WriteTypedDataVirtual", c_void_p),
154      ("OutputTypedDataVirtual", c_void_p),
155      ("ReadTypedDataPhysical", c_void_p),
156      ("WriteTypedDataPhysical", c_void_p),
157      ("OutputTypedDataPhysical", c_void_p),
158      ("GetScope", c_void_p),
159      ("SetScope", c_void_p),
160      ("ResetScope", c_void_p),
161      ("GetScopeSymbolGroup", c_void_p),
162      ("CreateSymbolGroup", c_void_p),
163      ("StartSymbolMatch", c_void_p),
164      ("GetNextSymbolMatch", c_void_p),
165      ("EndSymbolMatch", c_void_p),
166      ("Reload", c_void_p),
167      ("GetSymbolPath", c_void_p),
168      ("SetSymbolPath", c_void_p),
169      ("AppendSymbolPath", c_void_p),
170      ("GetImagePath", c_void_p),
171      ("SetImagePath", c_void_p),
172      ("AppendImagePath", c_void_p),
173      ("GetSourcePath", c_void_p),
174      ("GetSourcePathElement", c_void_p),
175      ("SetSourcePath", c_void_p),
176      ("AppendSourcePath", c_void_p),
177      ("FindSourceFile", c_void_p),
178      ("GetSourceFileLineOffsets", c_void_p),
179      ("GetModuleVersionInformation", c_void_p),
180      ("GetModuleNameString", ids_getmodulenamestring),
181      ("GetConstantName", c_void_p),
182      ("GetFieldName", c_void_p),
183      ("GetTypeOptions", c_void_p),
184      ("AddTypeOptions", c_void_p),
185      ("RemoveTypeOptions", c_void_p),
186      ("SetTypeOptions", c_void_p),
187      ("GetNameByOffsetWide", c_void_p),
188      ("GetOffsetByNameWide", c_void_p),
189      ("GetNearNameByOffsetWide", c_void_p),
190      ("GetLineByOffsetWide", c_void_p),
191      ("GetOffsetByLineWide", c_void_p),
192      ("GetModuleByModuleNameWide", c_void_p),
193      ("GetSymbolModuleWide", c_void_p),
194      ("GetTypeNameWide", c_void_p),
195      ("GetTypeIdWide", c_void_p),
196      ("GetFieldOffsetWide", c_void_p),
197      ("GetSymbolTypeIdWide", c_void_p),
198      ("GetScopeSymbolGroup2", ids_getscopesymbolgroup2),
199      ("CreateSymbolGroup2", c_void_p),
200      ("StartSymbolMatchWide", c_void_p),
201      ("GetNextSymbolMatchWide", c_void_p),
202      ("ReloadWide", c_void_p),
203      ("GetSymbolPathWide", c_void_p),
204      ("SetSymbolPathWide", c_void_p),
205      ("AppendSymbolPathWide", c_void_p),
206      ("GetImagePathWide", c_void_p),
207      ("SetImagePathWide", c_void_p),
208      ("AppendImagePathWide", c_void_p),
209      ("GetSourcePathWide", c_void_p),
210      ("GetSourcePathElementWide", c_void_p),
211      ("SetSourcePathWide", c_void_p),
212      ("AppendSourcePathWide", c_void_p),
213      ("FindSourceFileWide", c_void_p),
214      ("GetSourceFileLineOffsetsWide", c_void_p),
215      ("GetModuleVersionInformationWide", c_void_p),
216      ("GetModuleNameStringWide", c_void_p),
217      ("GetConstantNameWide", c_void_p),
218      ("GetFieldNameWide", c_void_p),
219      ("IsManagedModule", c_void_p),
220      ("GetModuleByModuleName2", c_void_p),
221      ("GetModuleByModuleName2Wide", c_void_p),
222      ("GetModuleByOffset2", c_void_p),
223      ("AddSyntheticModule", c_void_p),
224      ("AddSyntheticModuleWide", c_void_p),
225      ("RemoveSyntheticModule", c_void_p),
226      ("GetCurrentScopeFrameIndex", ids_getcurrentscopeframeindex),
227      ("SetScopeFrameByIndex", ids_setscopeframebyindex),
228      ("SetScopeFromJitDebugInfo", c_void_p),
229      ("SetScopeFromStoredEvent", c_void_p),
230      ("OutputSymbolByOffset", c_void_p),
231      ("GetFunctionEntryByOffset", c_void_p),
232      ("GetFieldTypeAndOffset", c_void_p),
233      ("GetFieldTypeAndOffsetWide", c_void_p),
234      ("AddSyntheticSymbol", c_void_p),
235      ("AddSyntheticSymbolWide", c_void_p),
236      ("RemoveSyntheticSymbol", c_void_p),
237      ("GetSymbolEntriesByOffset", c_void_p),
238      ("GetSymbolEntriesByName", ids_getsymbolentriesbyname),
239      ("GetSymbolEntriesByNameWide", c_void_p),
240      ("GetSymbolEntryByToken", c_void_p),
241      ("GetSymbolEntryInformation", ids_getsymbolentryinformation),
242      ("GetSymbolEntryString", ids_getsymbolentrystring),
243      ("GetSymbolEntryStringWide", c_void_p),
244      ("GetSymbolEntryOffsetRegions", c_void_p),
245      ("GetSymbolEntryBySymbolEntry", c_void_p),
246      ("GetSourceEntriesByOffset", c_void_p),
247      ("GetSourceEntriesByLine", c_void_p),
248      ("GetSourceEntriesByLineWide", c_void_p),
249      ("GetSourceEntryString", c_void_p),
250      ("GetSourceEntryStringWide", c_void_p),
251      ("GetSourceEntryOffsetRegions", c_void_p),
252      ("GetsourceEntryBySourceEntry", c_void_p),
253      ("GetScopeEx", c_void_p),
254      ("SetScopeEx", c_void_p),
255      ("GetNameByInlineContext", ids_getnamebyinlinecontext),
256      ("GetNameByInlineContextWide", c_void_p),
257      ("GetLineByInlineContext", ids_getlinebyinlinecontext),
258      ("GetLineByInlineContextWide", c_void_p),
259      ("OutputSymbolByInlineContext", c_void_p),
260      ("GetCurrentScopeFrameIndexEx", c_void_p),
261      ("SetScopeFrameByIndexEx", c_void_p)
262    ]
263
264IDebugSymbols5._fields_ = [("lpVtbl", POINTER(IDebugSymbols5Vtbl))]
265
266SymbolId = namedtuple("SymbolId", ["ModuleBase", "Id"])
267SymbolEntry = namedtuple("SymbolEntry", ["ModuleBase", "Offset", "Id", "Arg64", "Size", "Flags", "TypeId", "NameSize", "Token", "Tag", "Arg32"])
268DebugModuleParams = namedtuple("DebugModuleParams", ["Base", "Size", "TimeDateStamp", "Checksum", "Flags", "SymbolType", "ImageNameSize", "ModuleNameSize", "LoadedImageNameSize", "SymbolFileNameSize", "MappedImageNameSize"])
269
270class SymTags(IntEnum):
271  Null = 0
272  Exe = 1
273  SymTagFunction = 5
274
275def make_debug_module_params(cdata):
276  fieldvalues = map(lambda y: getattr(cdata, y), DebugModuleParams._fields)
277  return DebugModuleParams(*fieldvalues)
278
279class Symbols(object):
280  def __init__(self, symbols):
281    self.ptr = symbols
282    self.symbols = symbols.contents
283    self.vt = self.symbols.lpVtbl.contents
284    # Keep some handy ulongs for passing into C methods.
285    self.ulong = c_ulong()
286    self.ulong64 = c_ulonglong()
287
288  def GetCurrentScopeFrameIndex(self):
289    res = self.vt.GetCurrentScopeFrameIndex(self.symbols, byref(self.ulong))
290    aborter(res, "GetCurrentScopeFrameIndex")
291    return self.ulong.value
292
293  def SetScopeFrameByIndex(self, idx):
294    res = self.vt.SetScopeFrameByIndex(self.symbols, idx)
295    aborter(res, "SetScopeFrameByIndex", ignore=[E_EINVAL])
296    return res != E_EINVAL
297
298  def GetOffsetByName(self, name):
299    res = self.vt.GetOffsetByName(self.symbols, name.encode("ascii"), byref(self.ulong64))
300    aborter(res, "GetOffsetByName {}".format(name))
301    return self.ulong64.value
302
303  def GetNearNameByOffset(self, addr):
304    ptr = create_string_buffer(256)
305    pulong = c_ulong()
306    disp = c_ulonglong()
307    # Zero arg -> "delta" indicating how many symbols to skip
308    res = self.vt.GetNearNameByOffset(self.symbols, addr, 0, ptr, 255, byref(pulong), byref(disp))
309    if res == E_NOINTERFACE:
310      return "{noname}"
311    aborter(res, "GetNearNameByOffset")
312    ptr[255] = '\0'.encode("ascii")
313    return '{}+{}'.format(string_at(ptr).decode("ascii"), disp.value)
314
315  def GetModuleByModuleName2(self, name):
316    # First zero arg -> module index to search from, second zero arg ->
317    # DEBUG_GETMOD_* flags, none of which we use.
318    res = self.vt.GetModuleByModuleName2(self.symbols, name, 0, 0, None, byref(self.ulong64))
319    aborter(res, "GetModuleByModuleName2")
320    return self.ulong64.value
321
322  def GetScopeSymbolGroup2(self):
323    retptr = POINTER(IDebugSymbolGroup2)()
324    res = self.vt.GetScopeSymbolGroup2(self.symbols, ScopeGroupFlags.DEBUG_SCOPE_GROUP_ALL, None, retptr)
325    aborter(res, "GetScopeSymbolGroup2")
326    return SymbolGroup(retptr)
327
328  def GetSymbolEntryString(self, idx, module):
329    symid = DEBUG_MODULE_AND_ID()
330    symid.ModuleBase = module
331    symid.Id = idx
332    ptr = create_string_buffer(1024)
333    # Zero arg is the string index -- symbols can have multiple names, for now
334    # only support the first one.
335    res = self.vt.GetSymbolEntryString(self.symbols, symid, 0, ptr, 1023, byref(self.ulong))
336    aborter(res, "GetSymbolEntryString")
337    return string_at(ptr).decode("ascii")
338
339  def GetSymbolEntryInformation(self, module, theid):
340    symid = DEBUG_MODULE_AND_ID()
341    symentry = DEBUG_SYMBOL_ENTRY()
342    symid.ModuleBase = module
343    symid.Id = theid
344    res = self.vt.GetSymbolEntryInformation(self.symbols, symid, symentry)
345    aborter(res, "GetSymbolEntryInformation")
346    # Fetch fields into SymbolEntry object
347    fields = map(lambda x: getattr(symentry, x), SymbolEntry._fields)
348    return SymbolEntry(*fields)
349
350  def GetSymbolEntriesByName(self, symstr):
351    # Initial query to find number of symbol entries
352    res = self.vt.GetSymbolEntriesByName(self.symbols, symstr.encode("ascii"), 0, None, 0, byref(self.ulong))
353    aborter(res, "GetSymbolEntriesByName")
354
355    # Build a buffer and query for 'length' entries
356    length = self.ulong.value
357    symrecs = (DEBUG_MODULE_AND_ID * length)()
358    # Zero arg -> flags, of which there are none defined.
359    res = self.vt.GetSymbolEntriesByName(self.symbols, symstr.encode("ascii"), 0, symrecs, length, byref(self.ulong))
360    aborter(res, "GetSymbolEntriesByName")
361
362    # Extract 'length' number of SymbolIds
363    length = self.ulong.value
364    def extract(x):
365      sym = symrecs[x]
366      return SymbolId(sym.ModuleBase, sym.Id)
367    return [extract(x) for x in range(length)]
368
369  def GetSymbolPath(self):
370    # Query for length of buffer to allocate
371    res = self.vt.GetSymbolPath(self.symbols, None, 0, byref(self.ulong))
372    aborter(res, "GetSymbolPath", ignore=[S_FALSE])
373
374    # Fetch 'length' length symbol path string
375    length = self.ulong.value
376    arr = create_string_buffer(length)
377    res = self.vt.GetSymbolPath(self.symbols, arr, length, byref(self.ulong))
378    aborter(res, "GetSymbolPath")
379
380    return string_at(arr).decode("ascii")
381
382  def GetSourcePath(self):
383    # Query for length of buffer to allocate
384    res = self.vt.GetSourcePath(self.symbols, None, 0, byref(self.ulong))
385    aborter(res, "GetSourcePath", ignore=[S_FALSE])
386
387    # Fetch a string of len 'length'
388    length = self.ulong.value
389    arr = create_string_buffer(length)
390    res = self.vt.GetSourcePath(self.symbols, arr, length, byref(self.ulong))
391    aborter(res, "GetSourcePath")
392
393    return string_at(arr).decode("ascii")
394
395  def SetSourcePath(self, string):
396    res = self.vt.SetSourcePath(self.symbols, string.encode("ascii"))
397    aborter(res, "SetSourcePath")
398    return
399
400  def GetModuleParameters(self, base):
401    self.ulong64.value = base
402    params = DEBUG_MODULE_PARAMETERS()
403    # Fetch one module params struct, starting at idx zero
404    res = self.vt.GetModuleParameters(self.symbols, 1, byref(self.ulong64), 0, byref(params))
405    aborter(res, "GetModuleParameters")
406    return make_debug_module_params(params)
407
408  def GetSymbolOptions(self):
409    res = self.vt.GetSymbolOptions(self.symbols, byref(self.ulong))
410    aborter(res, "GetSymbolOptions")
411    return SymbolOptionFlags(self.ulong.value)
412
413  def SetSymbolOptions(self, opts):
414    assert isinstance(opts, SymbolOptionFlags)
415    res = self.vt.SetSymbolOptions(self.symbols, opts.value)
416    aborter(res, "SetSymbolOptions")
417    return
418
419  def GetLineByOffset(self, offs):
420    # Initial query for filename buffer size
421    res = self.vt.GetLineByOffset(self.symbols, offs, None, None, 0, byref(self.ulong), None)
422    if res == E_FAIL:
423      return None # Sometimes we just can't get line numbers, of course
424    aborter(res, "GetLineByOffset", ignore=[S_FALSE])
425
426    # Allocate filename buffer and query for line number too
427    filenamelen = self.ulong.value
428    text = create_string_buffer(filenamelen)
429    line = c_ulong()
430    res = self.vt.GetLineByOffset(self.symbols, offs, byref(line), text, filenamelen, byref(self.ulong), None)
431    aborter(res, "GetLineByOffset")
432
433    return string_at(text).decode("ascii"), line.value
434
435  def GetModuleNameString(self, whichname, base):
436    # Initial query for name string length
437    res = self.vt.GetModuleNameString(self.symbols, whichname, DEBUG_ANY_ID, base, None, 0, byref(self.ulong))
438    aborter(res, "GetModuleNameString", ignore=[S_FALSE])
439
440    module_name_len = self.ulong.value
441    module_name = (c_char * module_name_len)()
442    res = self.vt.GetModuleNameString(self.symbols, whichname, DEBUG_ANY_ID, base, module_name, module_name_len, None)
443    aborter(res, "GetModuleNameString")
444
445    return string_at(module_name).decode("ascii")
446
447  def GetNameByInlineContext(self, pc, ctx):
448    # None args -> ignore output name size and displacement
449    buf = create_string_buffer(256)
450    res = self.vt.GetNameByInlineContext(self.symbols, pc, ctx, buf, 255, None, None)
451    aborter(res, "GetNameByInlineContext")
452    return string_at(buf).decode("ascii")
453
454  def GetLineByInlineContext(self, pc, ctx):
455    # None args -> ignore output filename size and displacement
456    buf = create_string_buffer(256)
457    res = self.vt.GetLineByInlineContext(self.symbols, pc, ctx, byref(self.ulong), buf, 255, None, None)
458    aborter(res, "GetLineByInlineContext")
459    return string_at(buf).decode("ascii"), self.ulong.value
460
461  def get_all_symbols(self):
462    main_module_name = self.get_exefile_module_name()
463    idnumbers = self.GetSymbolEntriesByName("{}!*".format(main_module_name))
464    lst = []
465    for symid in idnumbers:
466      s = self.GetSymbolEntryString(symid.Id, symid.ModuleBase)
467      symentry = self.GetSymbolEntryInformation(symid.ModuleBase, symid.Id)
468      lst.append((s, symentry))
469    return lst
470
471  def get_all_functions(self):
472    syms = self.get_all_symbols()
473    return [x for x in syms if x[1].Tag == SymTags.SymTagFunction]
474
475  def get_all_modules(self):
476    params = DEBUG_MODULE_PARAMETERS()
477    idx = 0
478    res = 0
479    all_modules = []
480    while res != E_EINVAL:
481      res = self.vt.GetModuleParameters(self.symbols, 1, None, idx, byref(params))
482      aborter(res, "GetModuleParameters", ignore=[E_EINVAL])
483      all_modules.append(make_debug_module_params(params))
484      idx += 1
485    return all_modules
486
487  def get_exefile_module(self):
488    all_modules = self.get_all_modules()
489    reduce_func = lambda x, y: y if y.Flags & DebugModuleFlags.DEBUG_MODULE_EXE_MODULE else x
490    main_module = reduce(reduce_func, all_modules, None)
491    if main_module is None:
492      raise Exception("Couldn't find the exefile module")
493    return main_module
494
495  def get_module_name(self, base):
496    return self.GetModuleNameString(DebugModuleNames.DEBUG_MODNAME_MODULE, base)
497
498  def get_exefile_module_name(self):
499    return self.get_module_name(self.get_exefile_module().Base)
500