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