1 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" 2 3 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 4 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 5 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" 6 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 7 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 8 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 9 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 10 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 11 #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" 12 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" 13 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" 14 #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 15 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" 16 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" 17 #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" 18 #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" 19 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" 20 #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" 21 #include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h" 22 #include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" 23 #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h" 24 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" 25 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 26 #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h" 27 #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" 28 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" 29 #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h" 30 #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" 31 #include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h" 32 #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" 33 #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h" 34 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 35 #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" 36 #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" 37 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 38 #include "llvm/DebugInfo/PDB/PDBSymbol.h" 39 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 40 41 using namespace llvm; 42 using namespace llvm::codeview; 43 using namespace llvm::pdb; 44 45 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary 46 // to instantiate a NativeBuiltinSymbol for that type. 47 static const struct BuiltinTypeEntry { 48 codeview::SimpleTypeKind Kind; 49 PDB_BuiltinType Type; 50 uint32_t Size; 51 } BuiltinTypes[] = { 52 {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0}, 53 {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0}, 54 {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4}, 55 {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2}, 56 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2}, 57 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4}, 58 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4}, 59 {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4}, 60 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4}, 61 {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8}, 62 {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8}, 63 {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1}, 64 {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2}, 65 {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2}, 66 {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4}, 67 {codeview::SimpleTypeKind::Character8, PDB_BuiltinType::Char8, 1}, 68 {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, 69 {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, 70 {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4}, 71 {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8}, 72 {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10}, 73 {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}, 74 // This table can be grown as necessary, but these are the only types we've 75 // needed so far. 76 }; 77 78 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) 79 : Session(Session), Dbi(Dbi) { 80 // Id 0 is reserved for the invalid symbol. 81 Cache.push_back(nullptr); 82 SourceFiles.push_back(nullptr); 83 84 if (Dbi) 85 Compilands.resize(Dbi->modules().getModuleCount()); 86 } 87 88 std::unique_ptr<IPDBEnumSymbols> 89 SymbolCache::createTypeEnumerator(TypeLeafKind Kind) { 90 return createTypeEnumerator(std::vector<TypeLeafKind>{Kind}); 91 } 92 93 std::unique_ptr<IPDBEnumSymbols> 94 SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) { 95 auto Tpi = Session.getPDBFile().getPDBTpiStream(); 96 if (!Tpi) { 97 consumeError(Tpi.takeError()); 98 return nullptr; 99 } 100 auto &Types = Tpi->typeCollection(); 101 return std::unique_ptr<IPDBEnumSymbols>( 102 new NativeEnumTypes(Session, Types, std::move(Kinds))); 103 } 104 105 std::unique_ptr<IPDBEnumSymbols> 106 SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) { 107 return std::unique_ptr<IPDBEnumSymbols>( 108 new NativeEnumGlobals(Session, {Kind})); 109 } 110 111 SymIndexId SymbolCache::createSimpleType(TypeIndex Index, 112 ModifierOptions Mods) const { 113 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) 114 return createSymbol<NativeTypePointer>(Index); 115 116 const auto Kind = Index.getSimpleKind(); 117 const auto It = 118 llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) { 119 return Builtin.Kind == Kind; 120 }); 121 if (It == std::end(BuiltinTypes)) 122 return 0; 123 return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size); 124 } 125 126 SymIndexId 127 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, 128 codeview::CVType CVT) const { 129 ModifierRecord Record; 130 if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) { 131 consumeError(std::move(EC)); 132 return 0; 133 } 134 135 if (Record.ModifiedType.isSimple()) 136 return createSimpleType(Record.ModifiedType, Record.Modifiers); 137 138 // Make sure we create and cache a record for the unmodified type. 139 SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType); 140 NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId]; 141 142 switch (UnmodifiedNRS.getSymTag()) { 143 case PDB_SymType::Enum: 144 return createSymbol<NativeTypeEnum>( 145 static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record)); 146 case PDB_SymType::UDT: 147 return createSymbol<NativeTypeUDT>( 148 static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record)); 149 default: 150 // No other types can be modified. (LF_POINTER, for example, records 151 // its modifiers a different way. 152 assert(false && "Invalid LF_MODIFIER record"); 153 break; 154 } 155 return 0; 156 } 157 158 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const { 159 // First see if it's already in our cache. 160 const auto Entry = TypeIndexToSymbolId.find(Index); 161 if (Entry != TypeIndexToSymbolId.end()) 162 return Entry->second; 163 164 // Symbols for built-in types are created on the fly. 165 if (Index.isSimple()) { 166 SymIndexId Result = createSimpleType(Index, ModifierOptions::None); 167 assert(TypeIndexToSymbolId.count(Index) == 0); 168 TypeIndexToSymbolId[Index] = Result; 169 return Result; 170 } 171 172 // We need to instantiate and cache the desired type symbol. 173 auto Tpi = Session.getPDBFile().getPDBTpiStream(); 174 if (!Tpi) { 175 consumeError(Tpi.takeError()); 176 return 0; 177 } 178 codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); 179 codeview::CVType CVT = Types.getType(Index); 180 181 if (isUdtForwardRef(CVT)) { 182 Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index); 183 184 if (!EFD) 185 consumeError(EFD.takeError()); 186 else if (*EFD != Index) { 187 assert(!isUdtForwardRef(Types.getType(*EFD))); 188 SymIndexId Result = findSymbolByTypeIndex(*EFD); 189 // Record a mapping from ForwardRef -> SymIndex of complete type so that 190 // we'll take the fast path next time. 191 assert(TypeIndexToSymbolId.count(Index) == 0); 192 TypeIndexToSymbolId[Index] = Result; 193 return Result; 194 } 195 } 196 197 // At this point if we still have a forward ref udt it means the full decl was 198 // not in the PDB. We just have to deal with it and use the forward ref. 199 SymIndexId Id = 0; 200 switch (CVT.kind()) { 201 case codeview::LF_ENUM: 202 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT)); 203 break; 204 case codeview::LF_ARRAY: 205 Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index, 206 std::move(CVT)); 207 break; 208 case codeview::LF_CLASS: 209 case codeview::LF_STRUCTURE: 210 case codeview::LF_INTERFACE: 211 Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT)); 212 break; 213 case codeview::LF_UNION: 214 Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT)); 215 break; 216 case codeview::LF_POINTER: 217 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index, 218 std::move(CVT)); 219 break; 220 case codeview::LF_MODIFIER: 221 Id = createSymbolForModifiedType(Index, std::move(CVT)); 222 break; 223 case codeview::LF_PROCEDURE: 224 Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>( 225 Index, std::move(CVT)); 226 break; 227 case codeview::LF_MFUNCTION: 228 Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>( 229 Index, std::move(CVT)); 230 break; 231 case codeview::LF_VTSHAPE: 232 Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>( 233 Index, std::move(CVT)); 234 break; 235 default: 236 Id = createSymbolPlaceholder(); 237 break; 238 } 239 if (Id != 0) { 240 assert(TypeIndexToSymbolId.count(Index) == 0); 241 TypeIndexToSymbolId[Index] = Id; 242 } 243 return Id; 244 } 245 246 std::unique_ptr<PDBSymbol> 247 SymbolCache::getSymbolById(SymIndexId SymbolId) const { 248 assert(SymbolId < Cache.size()); 249 250 // Id 0 is reserved. 251 if (SymbolId == 0 || SymbolId >= Cache.size()) 252 return nullptr; 253 254 // Make sure to handle the case where we've inserted a placeholder symbol 255 // for types we don't yet support. 256 NativeRawSymbol *NRS = Cache[SymbolId].get(); 257 if (!NRS) 258 return nullptr; 259 260 return PDBSymbol::create(Session, *NRS); 261 } 262 263 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const { 264 return *Cache[SymbolId]; 265 } 266 267 uint32_t SymbolCache::getNumCompilands() const { 268 if (!Dbi) 269 return 0; 270 271 return Dbi->modules().getModuleCount(); 272 } 273 274 SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) { 275 auto Iter = GlobalOffsetToSymbolId.find(Offset); 276 if (Iter != GlobalOffsetToSymbolId.end()) 277 return Iter->second; 278 279 SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream()); 280 CVSymbol CVS = SS.readRecord(Offset); 281 SymIndexId Id = 0; 282 switch (CVS.kind()) { 283 case SymbolKind::S_UDT: { 284 UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS)); 285 Id = createSymbol<NativeTypeTypedef>(std::move(US)); 286 break; 287 } 288 default: 289 Id = createSymbolPlaceholder(); 290 break; 291 } 292 if (Id != 0) { 293 assert(GlobalOffsetToSymbolId.count(Offset) == 0); 294 GlobalOffsetToSymbolId[Offset] = Id; 295 } 296 297 return Id; 298 } 299 300 SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym, 301 uint64_t ParentAddr, 302 uint16_t Modi, 303 uint32_t RecordOffset) const { 304 auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset}); 305 if (Iter != SymTabOffsetToSymbolId.end()) 306 return Iter->second; 307 308 SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr); 309 SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id}); 310 return Id; 311 } 312 313 std::unique_ptr<PDBSymbol> 314 SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, 315 PDB_SymType Type) { 316 switch (Type) { 317 case PDB_SymType::Function: 318 return findFunctionSymbolBySectOffset(Sect, Offset); 319 case PDB_SymType::PublicSymbol: 320 return findPublicSymbolBySectOffset(Sect, Offset); 321 case PDB_SymType::Compiland: { 322 uint16_t Modi; 323 if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi)) 324 return nullptr; 325 return getOrCreateCompiland(Modi); 326 } 327 case PDB_SymType::None: { 328 // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but 329 // only uses it to find the symbol length. 330 if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset)) 331 return Sym; 332 return nullptr; 333 } 334 default: 335 return nullptr; 336 } 337 } 338 339 std::unique_ptr<PDBSymbol> 340 SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) { 341 auto Iter = AddressToSymbolId.find({Sect, Offset}); 342 if (Iter != AddressToSymbolId.end()) 343 return getSymbolById(Iter->second); 344 345 if (!Dbi) 346 return nullptr; 347 348 uint16_t Modi; 349 if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi)) 350 return nullptr; 351 352 Expected<ModuleDebugStreamRef> ExpectedModS = 353 Session.getModuleDebugStream(Modi); 354 if (!ExpectedModS) { 355 consumeError(ExpectedModS.takeError()); 356 return nullptr; 357 } 358 CVSymbolArray Syms = ExpectedModS->getSymbolArray(); 359 360 // Search for the symbol in this module. 361 for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) { 362 if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32) 363 continue; 364 auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I)); 365 if (Sect == PS.Segment && Offset >= PS.CodeOffset && 366 Offset < PS.CodeOffset + PS.CodeSize) { 367 // Check if the symbol is already cached. 368 auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset}); 369 if (Found != AddressToSymbolId.end()) 370 return getSymbolById(Found->second); 371 372 // Otherwise, create a new symbol. 373 SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset()); 374 AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id}); 375 return getSymbolById(Id); 376 } 377 378 // Jump to the end of this ProcSym. 379 I = Syms.at(PS.End); 380 } 381 return nullptr; 382 } 383 384 std::unique_ptr<PDBSymbol> 385 SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) { 386 auto Iter = AddressToPublicSymId.find({Sect, Offset}); 387 if (Iter != AddressToPublicSymId.end()) 388 return getSymbolById(Iter->second); 389 390 auto Publics = Session.getPDBFile().getPDBPublicsStream(); 391 if (!Publics) 392 return nullptr; 393 394 auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream(); 395 if (!ExpectedSyms) 396 return nullptr; 397 BinaryStreamRef SymStream = 398 ExpectedSyms->getSymbolArray().getUnderlyingStream(); 399 400 // Use binary search to find the first public symbol with an address greater 401 // than or equal to Sect, Offset. 402 auto AddrMap = Publics->getAddressMap(); 403 auto First = AddrMap.begin(); 404 auto It = AddrMap.begin(); 405 size_t Count = AddrMap.size(); 406 size_t Half; 407 while (Count > 0) { 408 It = First; 409 Half = Count / 2; 410 It += Half; 411 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It); 412 if (!Sym) { 413 consumeError(Sym.takeError()); 414 return nullptr; 415 } 416 417 auto PS = 418 cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get())); 419 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) { 420 First = ++It; 421 Count -= Half + 1; 422 } else 423 Count = Half; 424 } 425 if (It == AddrMap.begin()) 426 return nullptr; 427 --It; 428 429 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It); 430 if (!Sym) { 431 consumeError(Sym.takeError()); 432 return nullptr; 433 } 434 435 // Check if the symbol is already cached. 436 auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get())); 437 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset}); 438 if (Found != AddressToPublicSymId.end()) 439 return getSymbolById(Found->second); 440 441 // Otherwise, create a new symbol. 442 SymIndexId Id = createSymbol<NativePublicSymbol>(PS); 443 AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id}); 444 return getSymbolById(Id); 445 } 446 447 std::vector<SymbolCache::LineTableEntry> 448 SymbolCache::findLineTable(uint16_t Modi) const { 449 // Check if this module has already been added. 450 auto LineTableIter = LineTable.find(Modi); 451 if (LineTableIter != LineTable.end()) 452 return LineTableIter->second; 453 454 std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi]; 455 456 // If there is an error or there are no lines, just return the 457 // empty vector. 458 Expected<ModuleDebugStreamRef> ExpectedModS = 459 Session.getModuleDebugStream(Modi); 460 if (!ExpectedModS) { 461 consumeError(ExpectedModS.takeError()); 462 return ModuleLineTable; 463 } 464 465 std::vector<std::vector<LineTableEntry>> EntryList; 466 for (const auto &SS : ExpectedModS->getSubsectionsArray()) { 467 if (SS.kind() != DebugSubsectionKind::Lines) 468 continue; 469 470 DebugLinesSubsectionRef Lines; 471 BinaryStreamReader Reader(SS.getRecordData()); 472 if (auto EC = Lines.initialize(Reader)) { 473 consumeError(std::move(EC)); 474 continue; 475 } 476 477 uint32_t RelocSegment = Lines.header()->RelocSegment; 478 uint32_t RelocOffset = Lines.header()->RelocOffset; 479 for (const LineColumnEntry &Group : Lines) { 480 if (Group.LineNumbers.empty()) 481 continue; 482 483 std::vector<LineTableEntry> Entries; 484 485 // If there are column numbers, then they should be in a parallel stream 486 // to the line numbers. 487 auto ColIt = Group.Columns.begin(); 488 auto ColsEnd = Group.Columns.end(); 489 490 // Add a line to mark the beginning of this section. 491 uint64_t StartAddr = 492 Session.getVAFromSectOffset(RelocSegment, RelocOffset); 493 LineInfo FirstLine(Group.LineNumbers.front().Flags); 494 uint32_t ColNum = 495 (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0; 496 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false}); 497 498 for (const LineNumberEntry &LN : Group.LineNumbers) { 499 uint64_t VA = 500 Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset); 501 LineInfo Line(LN.Flags); 502 ColNum = 0; 503 504 if (Lines.hasColumnInfo() && ColIt != ColsEnd) { 505 ColNum = ColIt->StartColumn; 506 ++ColIt; 507 } 508 Entries.push_back({VA, Line, ColNum, Group.NameIndex, false}); 509 } 510 511 // Add a terminal entry line to mark the end of this subsection. 512 uint64_t EndAddr = StartAddr + Lines.header()->CodeSize; 513 LineInfo LastLine(Group.LineNumbers.back().Flags); 514 ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0; 515 Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true}); 516 517 EntryList.push_back(Entries); 518 } 519 } 520 521 // Sort EntryList, and add flattened contents to the line table. 522 llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS, 523 const std::vector<LineTableEntry> &RHS) { 524 return LHS[0].Addr < RHS[0].Addr; 525 }); 526 for (std::vector<LineTableEntry> &I : EntryList) 527 llvm::append_range(ModuleLineTable, I); 528 529 return ModuleLineTable; 530 } 531 532 std::unique_ptr<IPDBEnumLineNumbers> 533 SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { 534 uint16_t Modi; 535 if (!Session.moduleIndexForVA(VA, Modi)) 536 return nullptr; 537 538 std::vector<LineTableEntry> Lines = findLineTable(Modi); 539 if (Lines.empty()) 540 return nullptr; 541 542 // Find the first line in the line table whose address is not greater than 543 // the one we are searching for. 544 auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) { 545 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry)); 546 }); 547 548 // Try to back up if we've gone too far. 549 if (LineIter == Lines.end() || LineIter->Addr > VA) { 550 if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry) 551 return nullptr; 552 --LineIter; 553 } 554 555 Expected<ModuleDebugStreamRef> ExpectedModS = 556 Session.getModuleDebugStream(Modi); 557 if (!ExpectedModS) { 558 consumeError(ExpectedModS.takeError()); 559 return nullptr; 560 } 561 Expected<DebugChecksumsSubsectionRef> ExpectedChecksums = 562 ExpectedModS->findChecksumsSubsection(); 563 if (!ExpectedChecksums) { 564 consumeError(ExpectedChecksums.takeError()); 565 return nullptr; 566 } 567 568 // Populate a vector of NativeLineNumbers that have addresses in the given 569 // address range. 570 std::vector<NativeLineNumber> LineNumbers; 571 while (LineIter != Lines.end()) { 572 if (LineIter->IsTerminalEntry) { 573 ++LineIter; 574 continue; 575 } 576 577 // If the line is still within the address range, create a NativeLineNumber 578 // and add to the list. 579 if (LineIter->Addr > VA + Length) 580 break; 581 582 uint32_t LineSect, LineOff; 583 Session.addressForVA(LineIter->Addr, LineSect, LineOff); 584 uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr; 585 auto ChecksumIter = 586 ExpectedChecksums->getArray().at(LineIter->FileNameIndex); 587 uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter); 588 NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber, 589 LineSect, LineOff, LineLength, SrcFileId, Modi); 590 LineNumbers.push_back(LineNum); 591 ++LineIter; 592 } 593 return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers)); 594 } 595 596 std::unique_ptr<PDBSymbolCompiland> 597 SymbolCache::getOrCreateCompiland(uint32_t Index) { 598 if (!Dbi) 599 return nullptr; 600 601 if (Index >= Compilands.size()) 602 return nullptr; 603 604 if (Compilands[Index] == 0) { 605 const DbiModuleList &Modules = Dbi->modules(); 606 Compilands[Index] = 607 createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index)); 608 } 609 610 return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]); 611 } 612 613 std::unique_ptr<IPDBSourceFile> 614 SymbolCache::getSourceFileById(SymIndexId FileId) const { 615 assert(FileId < SourceFiles.size()); 616 617 // Id 0 is reserved. 618 if (FileId == 0) 619 return nullptr; 620 621 return std::unique_ptr<NativeSourceFile>( 622 new NativeSourceFile(*SourceFiles[FileId].get())); 623 } 624 625 SymIndexId 626 SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const { 627 auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset); 628 if (Iter != FileNameOffsetToId.end()) 629 return Iter->second; 630 631 SymIndexId Id = SourceFiles.size(); 632 auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums); 633 SourceFiles.push_back(std::move(SrcFile)); 634 FileNameOffsetToId[Checksums.FileNameOffset] = Id; 635 return Id; 636 } 637 638 639