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