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