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 consumeError(Publics.takeError()); 393 return nullptr; 394 } 395 396 auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream(); 397 if (!ExpectedSyms) { 398 consumeError(ExpectedSyms.takeError()); 399 return nullptr; 400 } 401 BinaryStreamRef SymStream = 402 ExpectedSyms->getSymbolArray().getUnderlyingStream(); 403 404 // Use binary search to find the first public symbol with an address greater 405 // than or equal to Sect, Offset. 406 auto AddrMap = Publics->getAddressMap(); 407 auto First = AddrMap.begin(); 408 auto It = AddrMap.begin(); 409 size_t Count = AddrMap.size(); 410 size_t Half; 411 while (Count > 0) { 412 It = First; 413 Half = Count / 2; 414 It += Half; 415 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It); 416 if (!Sym) { 417 consumeError(Sym.takeError()); 418 return nullptr; 419 } 420 421 auto PS = 422 cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get())); 423 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) { 424 First = ++It; 425 Count -= Half + 1; 426 } else 427 Count = Half; 428 } 429 if (It == AddrMap.begin()) 430 return nullptr; 431 --It; 432 433 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It); 434 if (!Sym) { 435 consumeError(Sym.takeError()); 436 return nullptr; 437 } 438 439 // Check if the symbol is already cached. 440 auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get())); 441 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset}); 442 if (Found != AddressToPublicSymId.end()) 443 return getSymbolById(Found->second); 444 445 // Otherwise, create a new symbol. 446 SymIndexId Id = createSymbol<NativePublicSymbol>(PS); 447 AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id}); 448 return getSymbolById(Id); 449 } 450 451 std::vector<SymbolCache::LineTableEntry> 452 SymbolCache::findLineTable(uint16_t Modi) const { 453 // Check if this module has already been added. 454 auto [LineTableIter, Inserted] = LineTable.try_emplace(Modi); 455 if (!Inserted) 456 return LineTableIter->second; 457 458 std::vector<LineTableEntry> &ModuleLineTable = LineTableIter->second; 459 460 // If there is an error or there are no lines, just return the 461 // empty vector. 462 Expected<ModuleDebugStreamRef> ExpectedModS = 463 Session.getModuleDebugStream(Modi); 464 if (!ExpectedModS) { 465 consumeError(ExpectedModS.takeError()); 466 return ModuleLineTable; 467 } 468 469 std::vector<std::vector<LineTableEntry>> EntryList; 470 for (const auto &SS : ExpectedModS->getSubsectionsArray()) { 471 if (SS.kind() != DebugSubsectionKind::Lines) 472 continue; 473 474 DebugLinesSubsectionRef Lines; 475 BinaryStreamReader Reader(SS.getRecordData()); 476 if (auto EC = Lines.initialize(Reader)) { 477 consumeError(std::move(EC)); 478 continue; 479 } 480 481 uint32_t RelocSegment = Lines.header()->RelocSegment; 482 uint32_t RelocOffset = Lines.header()->RelocOffset; 483 for (const LineColumnEntry &Group : Lines) { 484 if (Group.LineNumbers.empty()) 485 continue; 486 487 std::vector<LineTableEntry> Entries; 488 489 // If there are column numbers, then they should be in a parallel stream 490 // to the line numbers. 491 auto ColIt = Group.Columns.begin(); 492 auto ColsEnd = Group.Columns.end(); 493 494 // Add a line to mark the beginning of this section. 495 uint64_t StartAddr = 496 Session.getVAFromSectOffset(RelocSegment, RelocOffset); 497 LineInfo FirstLine(Group.LineNumbers.front().Flags); 498 uint32_t ColNum = 499 (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0; 500 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false}); 501 502 for (const LineNumberEntry &LN : Group.LineNumbers) { 503 uint64_t VA = 504 Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset); 505 LineInfo Line(LN.Flags); 506 ColNum = 0; 507 508 if (Lines.hasColumnInfo() && ColIt != ColsEnd) { 509 ColNum = ColIt->StartColumn; 510 ++ColIt; 511 } 512 Entries.push_back({VA, Line, ColNum, Group.NameIndex, false}); 513 } 514 515 // Add a terminal entry line to mark the end of this subsection. 516 uint64_t EndAddr = StartAddr + Lines.header()->CodeSize; 517 LineInfo LastLine(Group.LineNumbers.back().Flags); 518 ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0; 519 Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true}); 520 521 EntryList.push_back(Entries); 522 } 523 } 524 525 // Sort EntryList, and add flattened contents to the line table. 526 llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS, 527 const std::vector<LineTableEntry> &RHS) { 528 return LHS[0].Addr < RHS[0].Addr; 529 }); 530 for (std::vector<LineTableEntry> &I : EntryList) 531 llvm::append_range(ModuleLineTable, I); 532 533 return ModuleLineTable; 534 } 535 536 std::unique_ptr<IPDBEnumLineNumbers> 537 SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { 538 uint16_t Modi; 539 if (!Session.moduleIndexForVA(VA, Modi)) 540 return nullptr; 541 542 std::vector<LineTableEntry> Lines = findLineTable(Modi); 543 if (Lines.empty()) 544 return nullptr; 545 546 // Find the first line in the line table whose address is not greater than 547 // the one we are searching for. 548 auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) { 549 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry)); 550 }); 551 552 // Try to back up if we've gone too far. 553 if (LineIter == Lines.end() || LineIter->Addr > VA) { 554 if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry) 555 return nullptr; 556 --LineIter; 557 } 558 559 Expected<ModuleDebugStreamRef> ExpectedModS = 560 Session.getModuleDebugStream(Modi); 561 if (!ExpectedModS) { 562 consumeError(ExpectedModS.takeError()); 563 return nullptr; 564 } 565 Expected<DebugChecksumsSubsectionRef> ExpectedChecksums = 566 ExpectedModS->findChecksumsSubsection(); 567 if (!ExpectedChecksums) { 568 consumeError(ExpectedChecksums.takeError()); 569 return nullptr; 570 } 571 572 // Populate a vector of NativeLineNumbers that have addresses in the given 573 // address range. 574 std::vector<NativeLineNumber> LineNumbers; 575 while (LineIter != Lines.end()) { 576 if (LineIter->IsTerminalEntry) { 577 ++LineIter; 578 continue; 579 } 580 581 // If the line is still within the address range, create a NativeLineNumber 582 // and add to the list. 583 if (LineIter->Addr > VA + Length) 584 break; 585 586 uint32_t LineSect, LineOff; 587 Session.addressForVA(LineIter->Addr, LineSect, LineOff); 588 uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr; 589 auto ChecksumIter = 590 ExpectedChecksums->getArray().at(LineIter->FileNameIndex); 591 uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter); 592 NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber, 593 LineSect, LineOff, LineLength, SrcFileId, Modi); 594 LineNumbers.push_back(LineNum); 595 ++LineIter; 596 } 597 return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers)); 598 } 599 600 std::unique_ptr<PDBSymbolCompiland> 601 SymbolCache::getOrCreateCompiland(uint32_t Index) { 602 if (!Dbi) 603 return nullptr; 604 605 if (Index >= Compilands.size()) 606 return nullptr; 607 608 if (Compilands[Index] == 0) { 609 const DbiModuleList &Modules = Dbi->modules(); 610 Compilands[Index] = 611 createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index)); 612 } 613 614 return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]); 615 } 616 617 std::unique_ptr<IPDBSourceFile> 618 SymbolCache::getSourceFileById(SymIndexId FileId) const { 619 assert(FileId < SourceFiles.size()); 620 621 // Id 0 is reserved. 622 if (FileId == 0) 623 return nullptr; 624 625 return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].get()); 626 } 627 628 SymIndexId 629 SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const { 630 auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset); 631 if (Iter != FileNameOffsetToId.end()) 632 return Iter->second; 633 634 SymIndexId Id = SourceFiles.size(); 635 auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums); 636 SourceFiles.push_back(std::move(SrcFile)); 637 FileNameOffsetToId[Checksums.FileNameOffset] = Id; 638 return Id; 639 } 640 641 642