175112133SCarlos Alberto Enciso //===- InputFile.cpp ------------------------------------------ *- C++ --*-===// 275112133SCarlos Alberto Enciso // 375112133SCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 475112133SCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information. 575112133SCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 675112133SCarlos Alberto Enciso // 775112133SCarlos Alberto Enciso //===----------------------------------------------------------------------===// 875112133SCarlos Alberto Enciso 975112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/InputFile.h" 1075112133SCarlos Alberto Enciso 1175112133SCarlos Alberto Enciso #include "llvm/BinaryFormat/Magic.h" 1275112133SCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/CodeView.h" 1375112133SCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 1475112133SCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" 1575112133SCarlos Alberto Enciso #include "llvm/DebugInfo/MSF/MappedBlockStream.h" 1675112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 1775112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/FormatUtil.h" 1875112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/LinePrinter.h" 1975112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 2075112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 2175112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" 2275112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/RawError.h" 2375112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 2475112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/PDB.h" 2575112133SCarlos Alberto Enciso #include "llvm/Object/COFF.h" 2675112133SCarlos Alberto Enciso #include "llvm/Support/FileSystem.h" 2775112133SCarlos Alberto Enciso #include "llvm/Support/FormatVariadic.h" 2875112133SCarlos Alberto Enciso 2975112133SCarlos Alberto Enciso using namespace llvm; 3075112133SCarlos Alberto Enciso using namespace llvm::codeview; 3175112133SCarlos Alberto Enciso using namespace llvm::object; 3275112133SCarlos Alberto Enciso using namespace llvm::pdb; 3375112133SCarlos Alberto Enciso 3462c64be4SKazu Hirata InputFile::InputFile() = default; 3562c64be4SKazu Hirata InputFile::~InputFile() = default; 3675112133SCarlos Alberto Enciso 3775112133SCarlos Alberto Enciso Expected<ModuleDebugStreamRef> 3875112133SCarlos Alberto Enciso llvm::pdb::getModuleDebugStream(PDBFile &File, StringRef &ModuleName, 3975112133SCarlos Alberto Enciso uint32_t Index) { 4075112133SCarlos Alberto Enciso Expected<DbiStream &> DbiOrErr = File.getPDBDbiStream(); 4175112133SCarlos Alberto Enciso if (!DbiOrErr) 4275112133SCarlos Alberto Enciso return DbiOrErr.takeError(); 4375112133SCarlos Alberto Enciso DbiStream &Dbi = *DbiOrErr; 4475112133SCarlos Alberto Enciso const auto &Modules = Dbi.modules(); 4575112133SCarlos Alberto Enciso if (Index >= Modules.getModuleCount()) 4675112133SCarlos Alberto Enciso return make_error<RawError>(raw_error_code::index_out_of_bounds, 4775112133SCarlos Alberto Enciso "Invalid module index"); 4875112133SCarlos Alberto Enciso 4975112133SCarlos Alberto Enciso auto Modi = Modules.getModuleDescriptor(Index); 5075112133SCarlos Alberto Enciso 5175112133SCarlos Alberto Enciso ModuleName = Modi.getModuleName(); 5275112133SCarlos Alberto Enciso 5375112133SCarlos Alberto Enciso uint16_t ModiStream = Modi.getModuleStreamIndex(); 5475112133SCarlos Alberto Enciso if (ModiStream == kInvalidStreamIndex) 5575112133SCarlos Alberto Enciso return make_error<RawError>(raw_error_code::no_stream, 5675112133SCarlos Alberto Enciso "Module stream not present"); 5775112133SCarlos Alberto Enciso 5875112133SCarlos Alberto Enciso auto ModStreamData = File.createIndexedStream(ModiStream); 5975112133SCarlos Alberto Enciso 6075112133SCarlos Alberto Enciso ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); 6175112133SCarlos Alberto Enciso if (auto EC = ModS.reload()) 6275112133SCarlos Alberto Enciso return make_error<RawError>(raw_error_code::corrupt_file, 6375112133SCarlos Alberto Enciso "Invalid module stream"); 6475112133SCarlos Alberto Enciso 6575112133SCarlos Alberto Enciso return std::move(ModS); 6675112133SCarlos Alberto Enciso } 6775112133SCarlos Alberto Enciso 6875112133SCarlos Alberto Enciso Expected<ModuleDebugStreamRef> llvm::pdb::getModuleDebugStream(PDBFile &File, 6975112133SCarlos Alberto Enciso uint32_t Index) { 7075112133SCarlos Alberto Enciso Expected<DbiStream &> DbiOrErr = File.getPDBDbiStream(); 7175112133SCarlos Alberto Enciso if (!DbiOrErr) 7275112133SCarlos Alberto Enciso return DbiOrErr.takeError(); 7375112133SCarlos Alberto Enciso DbiStream &Dbi = *DbiOrErr; 7475112133SCarlos Alberto Enciso const auto &Modules = Dbi.modules(); 7575112133SCarlos Alberto Enciso auto Modi = Modules.getModuleDescriptor(Index); 7675112133SCarlos Alberto Enciso 7775112133SCarlos Alberto Enciso uint16_t ModiStream = Modi.getModuleStreamIndex(); 7875112133SCarlos Alberto Enciso if (ModiStream == kInvalidStreamIndex) 7975112133SCarlos Alberto Enciso return make_error<RawError>(raw_error_code::no_stream, 8075112133SCarlos Alberto Enciso "Module stream not present"); 8175112133SCarlos Alberto Enciso 8275112133SCarlos Alberto Enciso auto ModStreamData = File.createIndexedStream(ModiStream); 8375112133SCarlos Alberto Enciso 8475112133SCarlos Alberto Enciso ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); 8575112133SCarlos Alberto Enciso if (Error Err = ModS.reload()) 8675112133SCarlos Alberto Enciso return make_error<RawError>(raw_error_code::corrupt_file, 8775112133SCarlos Alberto Enciso "Invalid module stream"); 8875112133SCarlos Alberto Enciso 8975112133SCarlos Alberto Enciso return std::move(ModS); 9075112133SCarlos Alberto Enciso } 9175112133SCarlos Alberto Enciso 9275112133SCarlos Alberto Enciso static inline bool isCodeViewDebugSubsection(object::SectionRef Section, 9375112133SCarlos Alberto Enciso StringRef Name, 9475112133SCarlos Alberto Enciso BinaryStreamReader &Reader) { 9575112133SCarlos Alberto Enciso if (Expected<StringRef> NameOrErr = Section.getName()) { 9675112133SCarlos Alberto Enciso if (*NameOrErr != Name) 9775112133SCarlos Alberto Enciso return false; 9875112133SCarlos Alberto Enciso } else { 9975112133SCarlos Alberto Enciso consumeError(NameOrErr.takeError()); 10075112133SCarlos Alberto Enciso return false; 10175112133SCarlos Alberto Enciso } 10275112133SCarlos Alberto Enciso 10375112133SCarlos Alberto Enciso Expected<StringRef> ContentsOrErr = Section.getContents(); 10475112133SCarlos Alberto Enciso if (!ContentsOrErr) { 10575112133SCarlos Alberto Enciso consumeError(ContentsOrErr.takeError()); 10675112133SCarlos Alberto Enciso return false; 10775112133SCarlos Alberto Enciso } 10875112133SCarlos Alberto Enciso 10975112133SCarlos Alberto Enciso Reader = BinaryStreamReader(*ContentsOrErr, support::little); 11075112133SCarlos Alberto Enciso uint32_t Magic; 11175112133SCarlos Alberto Enciso if (Reader.bytesRemaining() < sizeof(uint32_t)) 11275112133SCarlos Alberto Enciso return false; 11375112133SCarlos Alberto Enciso cantFail(Reader.readInteger(Magic)); 11475112133SCarlos Alberto Enciso if (Magic != COFF::DEBUG_SECTION_MAGIC) 11575112133SCarlos Alberto Enciso return false; 11675112133SCarlos Alberto Enciso return true; 11775112133SCarlos Alberto Enciso } 11875112133SCarlos Alberto Enciso 11975112133SCarlos Alberto Enciso static inline bool isDebugSSection(object::SectionRef Section, 12075112133SCarlos Alberto Enciso DebugSubsectionArray &Subsections) { 12175112133SCarlos Alberto Enciso BinaryStreamReader Reader; 12275112133SCarlos Alberto Enciso if (!isCodeViewDebugSubsection(Section, ".debug$S", Reader)) 12375112133SCarlos Alberto Enciso return false; 12475112133SCarlos Alberto Enciso 12575112133SCarlos Alberto Enciso cantFail(Reader.readArray(Subsections, Reader.bytesRemaining())); 12675112133SCarlos Alberto Enciso return true; 12775112133SCarlos Alberto Enciso } 12875112133SCarlos Alberto Enciso 12975112133SCarlos Alberto Enciso static bool isDebugTSection(SectionRef Section, CVTypeArray &Types) { 13075112133SCarlos Alberto Enciso BinaryStreamReader Reader; 13175112133SCarlos Alberto Enciso if (!isCodeViewDebugSubsection(Section, ".debug$T", Reader) && 13275112133SCarlos Alberto Enciso !isCodeViewDebugSubsection(Section, ".debug$P", Reader)) 13375112133SCarlos Alberto Enciso return false; 13475112133SCarlos Alberto Enciso cantFail(Reader.readArray(Types, Reader.bytesRemaining())); 13575112133SCarlos Alberto Enciso return true; 13675112133SCarlos Alberto Enciso } 13775112133SCarlos Alberto Enciso 13875112133SCarlos Alberto Enciso static std::string formatChecksumKind(FileChecksumKind Kind) { 13975112133SCarlos Alberto Enciso switch (Kind) { 14075112133SCarlos Alberto Enciso RETURN_CASE(FileChecksumKind, None, "None"); 14175112133SCarlos Alberto Enciso RETURN_CASE(FileChecksumKind, MD5, "MD5"); 14275112133SCarlos Alberto Enciso RETURN_CASE(FileChecksumKind, SHA1, "SHA-1"); 14375112133SCarlos Alberto Enciso RETURN_CASE(FileChecksumKind, SHA256, "SHA-256"); 14475112133SCarlos Alberto Enciso } 14575112133SCarlos Alberto Enciso return formatUnknownEnum(Kind); 14675112133SCarlos Alberto Enciso } 14775112133SCarlos Alberto Enciso 14875112133SCarlos Alberto Enciso template <typename... Args> 14975112133SCarlos Alberto Enciso static void formatInternal(LinePrinter &Printer, bool Append, Args &&...args) { 15075112133SCarlos Alberto Enciso if (Append) 15175112133SCarlos Alberto Enciso Printer.format(std::forward<Args>(args)...); 15275112133SCarlos Alberto Enciso else 15375112133SCarlos Alberto Enciso Printer.formatLine(std::forward<Args>(args)...); 15475112133SCarlos Alberto Enciso } 15575112133SCarlos Alberto Enciso 15675112133SCarlos Alberto Enciso SymbolGroup::SymbolGroup(InputFile *File, uint32_t GroupIndex) : File(File) { 15775112133SCarlos Alberto Enciso if (!File) 15875112133SCarlos Alberto Enciso return; 15975112133SCarlos Alberto Enciso 16075112133SCarlos Alberto Enciso if (File->isPdb()) 16175112133SCarlos Alberto Enciso initializeForPdb(GroupIndex); 16275112133SCarlos Alberto Enciso else { 16375112133SCarlos Alberto Enciso Name = ".debug$S"; 16475112133SCarlos Alberto Enciso uint32_t I = 0; 16575112133SCarlos Alberto Enciso for (const auto &S : File->obj().sections()) { 16675112133SCarlos Alberto Enciso DebugSubsectionArray SS; 16775112133SCarlos Alberto Enciso if (!isDebugSSection(S, SS)) 16875112133SCarlos Alberto Enciso continue; 16975112133SCarlos Alberto Enciso 17075112133SCarlos Alberto Enciso if (!SC.hasChecksums() || !SC.hasStrings()) 17175112133SCarlos Alberto Enciso SC.initialize(SS); 17275112133SCarlos Alberto Enciso 17375112133SCarlos Alberto Enciso if (I == GroupIndex) 17475112133SCarlos Alberto Enciso Subsections = SS; 17575112133SCarlos Alberto Enciso 17675112133SCarlos Alberto Enciso if (SC.hasChecksums() && SC.hasStrings()) 17775112133SCarlos Alberto Enciso break; 17875112133SCarlos Alberto Enciso } 17975112133SCarlos Alberto Enciso rebuildChecksumMap(); 18075112133SCarlos Alberto Enciso } 18175112133SCarlos Alberto Enciso } 18275112133SCarlos Alberto Enciso 18375112133SCarlos Alberto Enciso StringRef SymbolGroup::name() const { return Name; } 18475112133SCarlos Alberto Enciso 18575112133SCarlos Alberto Enciso void SymbolGroup::updateDebugS(const codeview::DebugSubsectionArray &SS) { 18675112133SCarlos Alberto Enciso Subsections = SS; 18775112133SCarlos Alberto Enciso } 18875112133SCarlos Alberto Enciso 18975112133SCarlos Alberto Enciso void SymbolGroup::updatePdbModi(uint32_t Modi) { initializeForPdb(Modi); } 19075112133SCarlos Alberto Enciso 19175112133SCarlos Alberto Enciso void SymbolGroup::initializeForPdb(uint32_t Modi) { 19275112133SCarlos Alberto Enciso assert(File && File->isPdb()); 19375112133SCarlos Alberto Enciso 19475112133SCarlos Alberto Enciso // PDB always uses the same string table, but each module has its own 19575112133SCarlos Alberto Enciso // checksums. So we only set the strings if they're not already set. 19675112133SCarlos Alberto Enciso if (!SC.hasStrings()) { 19775112133SCarlos Alberto Enciso auto StringTable = File->pdb().getStringTable(); 19875112133SCarlos Alberto Enciso if (StringTable) 19975112133SCarlos Alberto Enciso SC.setStrings(StringTable->getStringTable()); 20075112133SCarlos Alberto Enciso else 20175112133SCarlos Alberto Enciso consumeError(StringTable.takeError()); 20275112133SCarlos Alberto Enciso } 20375112133SCarlos Alberto Enciso 20475112133SCarlos Alberto Enciso SC.resetChecksums(); 20575112133SCarlos Alberto Enciso auto MDS = getModuleDebugStream(File->pdb(), Name, Modi); 20675112133SCarlos Alberto Enciso if (!MDS) { 20775112133SCarlos Alberto Enciso consumeError(MDS.takeError()); 20875112133SCarlos Alberto Enciso return; 20975112133SCarlos Alberto Enciso } 21075112133SCarlos Alberto Enciso 21175112133SCarlos Alberto Enciso DebugStream = std::make_shared<ModuleDebugStreamRef>(std::move(*MDS)); 21275112133SCarlos Alberto Enciso Subsections = DebugStream->getSubsectionsArray(); 21375112133SCarlos Alberto Enciso SC.initialize(Subsections); 21475112133SCarlos Alberto Enciso rebuildChecksumMap(); 21575112133SCarlos Alberto Enciso } 21675112133SCarlos Alberto Enciso 21775112133SCarlos Alberto Enciso void SymbolGroup::rebuildChecksumMap() { 21875112133SCarlos Alberto Enciso if (!SC.hasChecksums()) 21975112133SCarlos Alberto Enciso return; 22075112133SCarlos Alberto Enciso 22175112133SCarlos Alberto Enciso for (const auto &Entry : SC.checksums()) { 22275112133SCarlos Alberto Enciso auto S = SC.strings().getString(Entry.FileNameOffset); 22375112133SCarlos Alberto Enciso if (!S) 22475112133SCarlos Alberto Enciso continue; 22575112133SCarlos Alberto Enciso ChecksumsByFile[*S] = Entry; 22675112133SCarlos Alberto Enciso } 22775112133SCarlos Alberto Enciso } 22875112133SCarlos Alberto Enciso 22975112133SCarlos Alberto Enciso const ModuleDebugStreamRef &SymbolGroup::getPdbModuleStream() const { 23075112133SCarlos Alberto Enciso assert(File && File->isPdb() && DebugStream); 23175112133SCarlos Alberto Enciso return *DebugStream; 23275112133SCarlos Alberto Enciso } 23375112133SCarlos Alberto Enciso 23475112133SCarlos Alberto Enciso Expected<StringRef> SymbolGroup::getNameFromStringTable(uint32_t Offset) const { 23575112133SCarlos Alberto Enciso return SC.strings().getString(Offset); 23675112133SCarlos Alberto Enciso } 23775112133SCarlos Alberto Enciso 23875112133SCarlos Alberto Enciso Expected<StringRef> SymbolGroup::getNameFromChecksums(uint32_t Offset) const { 23975112133SCarlos Alberto Enciso StringRef Name; 24075112133SCarlos Alberto Enciso if (!SC.hasChecksums()) { 24175112133SCarlos Alberto Enciso return std::move(Name); 24275112133SCarlos Alberto Enciso } 24375112133SCarlos Alberto Enciso 24475112133SCarlos Alberto Enciso auto Iter = SC.checksums().getArray().at(Offset); 24575112133SCarlos Alberto Enciso if (Iter == SC.checksums().getArray().end()) { 24675112133SCarlos Alberto Enciso return std::move(Name); 24775112133SCarlos Alberto Enciso } 24875112133SCarlos Alberto Enciso 24975112133SCarlos Alberto Enciso uint32_t FO = Iter->FileNameOffset; 25075112133SCarlos Alberto Enciso auto ExpectedFile = getNameFromStringTable(FO); 25175112133SCarlos Alberto Enciso if (!ExpectedFile) { 25275112133SCarlos Alberto Enciso return std::move(Name); 25375112133SCarlos Alberto Enciso } 25475112133SCarlos Alberto Enciso 25575112133SCarlos Alberto Enciso return *ExpectedFile; 25675112133SCarlos Alberto Enciso } 25775112133SCarlos Alberto Enciso 25875112133SCarlos Alberto Enciso void SymbolGroup::formatFromFileName(LinePrinter &Printer, StringRef File, 25975112133SCarlos Alberto Enciso bool Append) const { 26075112133SCarlos Alberto Enciso auto FC = ChecksumsByFile.find(File); 26175112133SCarlos Alberto Enciso if (FC == ChecksumsByFile.end()) { 26275112133SCarlos Alberto Enciso formatInternal(Printer, Append, "- (no checksum) {0}", File); 26375112133SCarlos Alberto Enciso return; 26475112133SCarlos Alberto Enciso } 26575112133SCarlos Alberto Enciso 26675112133SCarlos Alberto Enciso formatInternal(Printer, Append, "- ({0}: {1}) {2}", 26775112133SCarlos Alberto Enciso formatChecksumKind(FC->getValue().Kind), 26875112133SCarlos Alberto Enciso toHex(FC->getValue().Checksum), File); 26975112133SCarlos Alberto Enciso } 27075112133SCarlos Alberto Enciso 27175112133SCarlos Alberto Enciso void SymbolGroup::formatFromChecksumsOffset(LinePrinter &Printer, 27275112133SCarlos Alberto Enciso uint32_t Offset, 27375112133SCarlos Alberto Enciso bool Append) const { 27475112133SCarlos Alberto Enciso if (!SC.hasChecksums()) { 27575112133SCarlos Alberto Enciso formatInternal(Printer, Append, "(unknown file name offset {0})", Offset); 27675112133SCarlos Alberto Enciso return; 27775112133SCarlos Alberto Enciso } 27875112133SCarlos Alberto Enciso 27975112133SCarlos Alberto Enciso auto Iter = SC.checksums().getArray().at(Offset); 28075112133SCarlos Alberto Enciso if (Iter == SC.checksums().getArray().end()) { 28175112133SCarlos Alberto Enciso formatInternal(Printer, Append, "(unknown file name offset {0})", Offset); 28275112133SCarlos Alberto Enciso return; 28375112133SCarlos Alberto Enciso } 28475112133SCarlos Alberto Enciso 28575112133SCarlos Alberto Enciso uint32_t FO = Iter->FileNameOffset; 28675112133SCarlos Alberto Enciso auto ExpectedFile = getNameFromStringTable(FO); 28775112133SCarlos Alberto Enciso if (!ExpectedFile) { 28875112133SCarlos Alberto Enciso formatInternal(Printer, Append, "(unknown file name offset {0})", Offset); 28975112133SCarlos Alberto Enciso consumeError(ExpectedFile.takeError()); 29075112133SCarlos Alberto Enciso return; 29175112133SCarlos Alberto Enciso } 29275112133SCarlos Alberto Enciso if (Iter->Kind == FileChecksumKind::None) { 29375112133SCarlos Alberto Enciso formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile); 29475112133SCarlos Alberto Enciso } else { 29575112133SCarlos Alberto Enciso formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile, 29675112133SCarlos Alberto Enciso formatChecksumKind(Iter->Kind), toHex(Iter->Checksum)); 29775112133SCarlos Alberto Enciso } 29875112133SCarlos Alberto Enciso } 29975112133SCarlos Alberto Enciso 30075112133SCarlos Alberto Enciso Expected<InputFile> InputFile::open(StringRef Path, bool AllowUnknownFile) { 30175112133SCarlos Alberto Enciso InputFile IF; 30275112133SCarlos Alberto Enciso if (!llvm::sys::fs::exists(Path)) 30375112133SCarlos Alberto Enciso return make_error<StringError>(formatv("File {0} not found", Path), 30475112133SCarlos Alberto Enciso inconvertibleErrorCode()); 30575112133SCarlos Alberto Enciso 30675112133SCarlos Alberto Enciso file_magic Magic; 30775112133SCarlos Alberto Enciso if (auto EC = identify_magic(Path, Magic)) 30875112133SCarlos Alberto Enciso return make_error<StringError>( 30975112133SCarlos Alberto Enciso formatv("Unable to identify file type for file {0}", Path), EC); 31075112133SCarlos Alberto Enciso 31175112133SCarlos Alberto Enciso if (Magic == file_magic::coff_object) { 31275112133SCarlos Alberto Enciso Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Path); 31375112133SCarlos Alberto Enciso if (!BinaryOrErr) 31475112133SCarlos Alberto Enciso return BinaryOrErr.takeError(); 31575112133SCarlos Alberto Enciso 31675112133SCarlos Alberto Enciso IF.CoffObject = std::move(*BinaryOrErr); 31775112133SCarlos Alberto Enciso IF.PdbOrObj = llvm::cast<COFFObjectFile>(IF.CoffObject.getBinary()); 31875112133SCarlos Alberto Enciso return std::move(IF); 31975112133SCarlos Alberto Enciso } 32075112133SCarlos Alberto Enciso 32175112133SCarlos Alberto Enciso if (Magic == file_magic::pdb) { 32275112133SCarlos Alberto Enciso std::unique_ptr<IPDBSession> Session; 32375112133SCarlos Alberto Enciso if (auto Err = loadDataForPDB(PDB_ReaderType::Native, Path, Session)) 32475112133SCarlos Alberto Enciso return std::move(Err); 32575112133SCarlos Alberto Enciso 32675112133SCarlos Alberto Enciso IF.PdbSession.reset(static_cast<NativeSession *>(Session.release())); 32775112133SCarlos Alberto Enciso IF.PdbOrObj = &IF.PdbSession->getPDBFile(); 32875112133SCarlos Alberto Enciso 32975112133SCarlos Alberto Enciso return std::move(IF); 33075112133SCarlos Alberto Enciso } 33175112133SCarlos Alberto Enciso 33275112133SCarlos Alberto Enciso if (!AllowUnknownFile) 33375112133SCarlos Alberto Enciso return make_error<StringError>( 33475112133SCarlos Alberto Enciso formatv("File {0} is not a supported file type", Path), 33575112133SCarlos Alberto Enciso inconvertibleErrorCode()); 33675112133SCarlos Alberto Enciso 33775112133SCarlos Alberto Enciso auto Result = MemoryBuffer::getFile(Path, /*IsText=*/false, 33875112133SCarlos Alberto Enciso /*RequiresNullTerminator=*/false); 33975112133SCarlos Alberto Enciso if (!Result) 34075112133SCarlos Alberto Enciso return make_error<StringError>( 34175112133SCarlos Alberto Enciso formatv("File {0} could not be opened", Path), Result.getError()); 34275112133SCarlos Alberto Enciso 34375112133SCarlos Alberto Enciso IF.UnknownFile = std::move(*Result); 34475112133SCarlos Alberto Enciso IF.PdbOrObj = IF.UnknownFile.get(); 34575112133SCarlos Alberto Enciso return std::move(IF); 34675112133SCarlos Alberto Enciso } 34775112133SCarlos Alberto Enciso 34875112133SCarlos Alberto Enciso PDBFile &InputFile::pdb() { 34975112133SCarlos Alberto Enciso assert(isPdb()); 35075112133SCarlos Alberto Enciso return *PdbOrObj.get<PDBFile *>(); 35175112133SCarlos Alberto Enciso } 35275112133SCarlos Alberto Enciso 35375112133SCarlos Alberto Enciso const PDBFile &InputFile::pdb() const { 35475112133SCarlos Alberto Enciso assert(isPdb()); 35575112133SCarlos Alberto Enciso return *PdbOrObj.get<PDBFile *>(); 35675112133SCarlos Alberto Enciso } 35775112133SCarlos Alberto Enciso 35875112133SCarlos Alberto Enciso object::COFFObjectFile &InputFile::obj() { 35975112133SCarlos Alberto Enciso assert(isObj()); 36075112133SCarlos Alberto Enciso return *PdbOrObj.get<object::COFFObjectFile *>(); 36175112133SCarlos Alberto Enciso } 36275112133SCarlos Alberto Enciso 36375112133SCarlos Alberto Enciso const object::COFFObjectFile &InputFile::obj() const { 36475112133SCarlos Alberto Enciso assert(isObj()); 36575112133SCarlos Alberto Enciso return *PdbOrObj.get<object::COFFObjectFile *>(); 36675112133SCarlos Alberto Enciso } 36775112133SCarlos Alberto Enciso 36875112133SCarlos Alberto Enciso MemoryBuffer &InputFile::unknown() { 36975112133SCarlos Alberto Enciso assert(isUnknown()); 37075112133SCarlos Alberto Enciso return *PdbOrObj.get<MemoryBuffer *>(); 37175112133SCarlos Alberto Enciso } 37275112133SCarlos Alberto Enciso 37375112133SCarlos Alberto Enciso const MemoryBuffer &InputFile::unknown() const { 37475112133SCarlos Alberto Enciso assert(isUnknown()); 37575112133SCarlos Alberto Enciso return *PdbOrObj.get<MemoryBuffer *>(); 37675112133SCarlos Alberto Enciso } 37775112133SCarlos Alberto Enciso 37875112133SCarlos Alberto Enciso StringRef InputFile::getFilePath() const { 37975112133SCarlos Alberto Enciso if (isPdb()) 38075112133SCarlos Alberto Enciso return pdb().getFilePath(); 38175112133SCarlos Alberto Enciso if (isObj()) 38275112133SCarlos Alberto Enciso return obj().getFileName(); 38375112133SCarlos Alberto Enciso assert(isUnknown()); 38475112133SCarlos Alberto Enciso return unknown().getBufferIdentifier(); 38575112133SCarlos Alberto Enciso } 38675112133SCarlos Alberto Enciso 38775112133SCarlos Alberto Enciso bool InputFile::hasTypes() const { 38875112133SCarlos Alberto Enciso if (isPdb()) 38975112133SCarlos Alberto Enciso return pdb().hasPDBTpiStream(); 39075112133SCarlos Alberto Enciso 39175112133SCarlos Alberto Enciso for (const auto &Section : obj().sections()) { 39275112133SCarlos Alberto Enciso CVTypeArray Types; 39375112133SCarlos Alberto Enciso if (isDebugTSection(Section, Types)) 39475112133SCarlos Alberto Enciso return true; 39575112133SCarlos Alberto Enciso } 39675112133SCarlos Alberto Enciso return false; 39775112133SCarlos Alberto Enciso } 39875112133SCarlos Alberto Enciso 39975112133SCarlos Alberto Enciso bool InputFile::hasIds() const { 40075112133SCarlos Alberto Enciso if (isObj()) 40175112133SCarlos Alberto Enciso return false; 40275112133SCarlos Alberto Enciso return pdb().hasPDBIpiStream(); 40375112133SCarlos Alberto Enciso } 40475112133SCarlos Alberto Enciso 40575112133SCarlos Alberto Enciso bool InputFile::isPdb() const { return PdbOrObj.is<PDBFile *>(); } 40675112133SCarlos Alberto Enciso 40775112133SCarlos Alberto Enciso bool InputFile::isObj() const { 40875112133SCarlos Alberto Enciso return PdbOrObj.is<object::COFFObjectFile *>(); 40975112133SCarlos Alberto Enciso } 41075112133SCarlos Alberto Enciso 41175112133SCarlos Alberto Enciso bool InputFile::isUnknown() const { return PdbOrObj.is<MemoryBuffer *>(); } 41275112133SCarlos Alberto Enciso 41375112133SCarlos Alberto Enciso codeview::LazyRandomTypeCollection & 41475112133SCarlos Alberto Enciso InputFile::getOrCreateTypeCollection(TypeCollectionKind Kind) { 41575112133SCarlos Alberto Enciso if (Types && Kind == kTypes) 41675112133SCarlos Alberto Enciso return *Types; 41775112133SCarlos Alberto Enciso if (Ids && Kind == kIds) 41875112133SCarlos Alberto Enciso return *Ids; 41975112133SCarlos Alberto Enciso 42075112133SCarlos Alberto Enciso if (Kind == kIds) { 42175112133SCarlos Alberto Enciso assert(isPdb() && pdb().hasPDBIpiStream()); 42275112133SCarlos Alberto Enciso } 42375112133SCarlos Alberto Enciso 42475112133SCarlos Alberto Enciso // If the collection was already initialized, we should have just returned it 42575112133SCarlos Alberto Enciso // in step 1. 42675112133SCarlos Alberto Enciso if (isPdb()) { 42775112133SCarlos Alberto Enciso TypeCollectionPtr &Collection = (Kind == kIds) ? Ids : Types; 42875112133SCarlos Alberto Enciso auto &Stream = cantFail((Kind == kIds) ? pdb().getPDBIpiStream() 42975112133SCarlos Alberto Enciso : pdb().getPDBTpiStream()); 43075112133SCarlos Alberto Enciso 43175112133SCarlos Alberto Enciso auto &Array = Stream.typeArray(); 43275112133SCarlos Alberto Enciso uint32_t Count = Stream.getNumTypeRecords(); 43375112133SCarlos Alberto Enciso auto Offsets = Stream.getTypeIndexOffsets(); 43475112133SCarlos Alberto Enciso Collection = 43575112133SCarlos Alberto Enciso std::make_unique<LazyRandomTypeCollection>(Array, Count, Offsets); 43675112133SCarlos Alberto Enciso return *Collection; 43775112133SCarlos Alberto Enciso } 43875112133SCarlos Alberto Enciso 43975112133SCarlos Alberto Enciso assert(isObj()); 44075112133SCarlos Alberto Enciso assert(Kind == kTypes); 44175112133SCarlos Alberto Enciso assert(!Types); 44275112133SCarlos Alberto Enciso 44375112133SCarlos Alberto Enciso for (const auto &Section : obj().sections()) { 44475112133SCarlos Alberto Enciso CVTypeArray Records; 44575112133SCarlos Alberto Enciso if (!isDebugTSection(Section, Records)) 44675112133SCarlos Alberto Enciso continue; 44775112133SCarlos Alberto Enciso 44875112133SCarlos Alberto Enciso Types = std::make_unique<LazyRandomTypeCollection>(Records, 100); 44975112133SCarlos Alberto Enciso return *Types; 45075112133SCarlos Alberto Enciso } 45175112133SCarlos Alberto Enciso 45275112133SCarlos Alberto Enciso Types = std::make_unique<LazyRandomTypeCollection>(100); 45375112133SCarlos Alberto Enciso return *Types; 45475112133SCarlos Alberto Enciso } 45575112133SCarlos Alberto Enciso 45675112133SCarlos Alberto Enciso codeview::LazyRandomTypeCollection &InputFile::types() { 45775112133SCarlos Alberto Enciso return getOrCreateTypeCollection(kTypes); 45875112133SCarlos Alberto Enciso } 45975112133SCarlos Alberto Enciso 46075112133SCarlos Alberto Enciso codeview::LazyRandomTypeCollection &InputFile::ids() { 46175112133SCarlos Alberto Enciso // Object files have only one type stream that contains both types and ids. 46275112133SCarlos Alberto Enciso // Similarly, some PDBs don't contain an IPI stream, and for those both types 46375112133SCarlos Alberto Enciso // and IDs are in the same stream. 46475112133SCarlos Alberto Enciso if (isObj() || !pdb().hasPDBIpiStream()) 46575112133SCarlos Alberto Enciso return types(); 46675112133SCarlos Alberto Enciso 46775112133SCarlos Alberto Enciso return getOrCreateTypeCollection(kIds); 46875112133SCarlos Alberto Enciso } 46975112133SCarlos Alberto Enciso 47075112133SCarlos Alberto Enciso iterator_range<SymbolGroupIterator> InputFile::symbol_groups() { 47175112133SCarlos Alberto Enciso return make_range<SymbolGroupIterator>(symbol_groups_begin(), 47275112133SCarlos Alberto Enciso symbol_groups_end()); 47375112133SCarlos Alberto Enciso } 47475112133SCarlos Alberto Enciso 47575112133SCarlos Alberto Enciso SymbolGroupIterator InputFile::symbol_groups_begin() { 47675112133SCarlos Alberto Enciso return SymbolGroupIterator(*this); 47775112133SCarlos Alberto Enciso } 47875112133SCarlos Alberto Enciso 47975112133SCarlos Alberto Enciso SymbolGroupIterator InputFile::symbol_groups_end() { 48075112133SCarlos Alberto Enciso return SymbolGroupIterator(); 48175112133SCarlos Alberto Enciso } 48275112133SCarlos Alberto Enciso 48375112133SCarlos Alberto Enciso SymbolGroupIterator::SymbolGroupIterator() : Value(nullptr) {} 48475112133SCarlos Alberto Enciso 48575112133SCarlos Alberto Enciso SymbolGroupIterator::SymbolGroupIterator(InputFile &File) : Value(&File) { 48675112133SCarlos Alberto Enciso if (File.isObj()) { 48775112133SCarlos Alberto Enciso SectionIter = File.obj().section_begin(); 48875112133SCarlos Alberto Enciso scanToNextDebugS(); 48975112133SCarlos Alberto Enciso } 49075112133SCarlos Alberto Enciso } 49175112133SCarlos Alberto Enciso 49275112133SCarlos Alberto Enciso bool SymbolGroupIterator::operator==(const SymbolGroupIterator &R) const { 49375112133SCarlos Alberto Enciso bool E = isEnd(); 49475112133SCarlos Alberto Enciso bool RE = R.isEnd(); 49575112133SCarlos Alberto Enciso if (E || RE) 49675112133SCarlos Alberto Enciso return E == RE; 49775112133SCarlos Alberto Enciso 49875112133SCarlos Alberto Enciso if (Value.File != R.Value.File) 49975112133SCarlos Alberto Enciso return false; 50075112133SCarlos Alberto Enciso return Index == R.Index; 50175112133SCarlos Alberto Enciso } 50275112133SCarlos Alberto Enciso 50375112133SCarlos Alberto Enciso const SymbolGroup &SymbolGroupIterator::operator*() const { 50475112133SCarlos Alberto Enciso assert(!isEnd()); 50575112133SCarlos Alberto Enciso return Value; 50675112133SCarlos Alberto Enciso } 50775112133SCarlos Alberto Enciso SymbolGroup &SymbolGroupIterator::operator*() { 50875112133SCarlos Alberto Enciso assert(!isEnd()); 50975112133SCarlos Alberto Enciso return Value; 51075112133SCarlos Alberto Enciso } 51175112133SCarlos Alberto Enciso 51275112133SCarlos Alberto Enciso SymbolGroupIterator &SymbolGroupIterator::operator++() { 51375112133SCarlos Alberto Enciso assert(Value.File && !isEnd()); 51475112133SCarlos Alberto Enciso ++Index; 51575112133SCarlos Alberto Enciso if (isEnd()) 51675112133SCarlos Alberto Enciso return *this; 51775112133SCarlos Alberto Enciso 51875112133SCarlos Alberto Enciso if (Value.File->isPdb()) { 51975112133SCarlos Alberto Enciso Value.updatePdbModi(Index); 52075112133SCarlos Alberto Enciso return *this; 52175112133SCarlos Alberto Enciso } 52275112133SCarlos Alberto Enciso 52375112133SCarlos Alberto Enciso scanToNextDebugS(); 52475112133SCarlos Alberto Enciso return *this; 52575112133SCarlos Alberto Enciso } 52675112133SCarlos Alberto Enciso 52775112133SCarlos Alberto Enciso void SymbolGroupIterator::scanToNextDebugS() { 52875112133SCarlos Alberto Enciso assert(SectionIter.hasValue()); 52975112133SCarlos Alberto Enciso auto End = Value.File->obj().section_end(); 53075112133SCarlos Alberto Enciso auto &Iter = *SectionIter; 53175112133SCarlos Alberto Enciso assert(!isEnd()); 53275112133SCarlos Alberto Enciso 53375112133SCarlos Alberto Enciso while (++Iter != End) { 53475112133SCarlos Alberto Enciso DebugSubsectionArray SS; 53575112133SCarlos Alberto Enciso SectionRef SR = *Iter; 53675112133SCarlos Alberto Enciso if (!isDebugSSection(SR, SS)) 53775112133SCarlos Alberto Enciso continue; 53875112133SCarlos Alberto Enciso 53975112133SCarlos Alberto Enciso Value.updateDebugS(SS); 54075112133SCarlos Alberto Enciso return; 54175112133SCarlos Alberto Enciso } 54275112133SCarlos Alberto Enciso } 54375112133SCarlos Alberto Enciso 54475112133SCarlos Alberto Enciso bool SymbolGroupIterator::isEnd() const { 54575112133SCarlos Alberto Enciso if (!Value.File) 54675112133SCarlos Alberto Enciso return true; 54775112133SCarlos Alberto Enciso if (Value.File->isPdb()) { 54875112133SCarlos Alberto Enciso DbiStream &Dbi = cantFail(Value.File->pdb().getPDBDbiStream()); 54975112133SCarlos Alberto Enciso uint32_t Count = Dbi.modules().getModuleCount(); 55075112133SCarlos Alberto Enciso assert(Index <= Count); 55175112133SCarlos Alberto Enciso return Index == Count; 55275112133SCarlos Alberto Enciso } 55375112133SCarlos Alberto Enciso 55475112133SCarlos Alberto Enciso assert(SectionIter.hasValue()); 55575112133SCarlos Alberto Enciso return *SectionIter == Value.File->obj().section_end(); 55675112133SCarlos Alberto Enciso } 55775112133SCarlos Alberto Enciso 55875112133SCarlos Alberto Enciso static bool isMyCode(const SymbolGroup &Group) { 55975112133SCarlos Alberto Enciso if (Group.getFile().isObj()) 56075112133SCarlos Alberto Enciso return true; 56175112133SCarlos Alberto Enciso 56275112133SCarlos Alberto Enciso StringRef Name = Group.name(); 56375112133SCarlos Alberto Enciso if (Name.startswith("Import:")) 56475112133SCarlos Alberto Enciso return false; 56575112133SCarlos Alberto Enciso if (Name.endswith_insensitive(".dll")) 56675112133SCarlos Alberto Enciso return false; 56775112133SCarlos Alberto Enciso if (Name.equals_insensitive("* linker *")) 56875112133SCarlos Alberto Enciso return false; 56975112133SCarlos Alberto Enciso if (Name.startswith_insensitive("f:\\binaries\\Intermediate\\vctools")) 57075112133SCarlos Alberto Enciso return false; 57175112133SCarlos Alberto Enciso if (Name.startswith_insensitive("f:\\dd\\vctools\\crt")) 57275112133SCarlos Alberto Enciso return false; 57375112133SCarlos Alberto Enciso return true; 57475112133SCarlos Alberto Enciso } 57575112133SCarlos Alberto Enciso 57610c11f5cSCarlos Alberto Enciso bool llvm::pdb::shouldDumpSymbolGroup(uint32_t Idx, const SymbolGroup &Group, 57710c11f5cSCarlos Alberto Enciso const FilterOptions &Filters) { 57810c11f5cSCarlos Alberto Enciso if (Filters.JustMyCode && !isMyCode(Group)) 57975112133SCarlos Alberto Enciso return false; 58075112133SCarlos Alberto Enciso 58175112133SCarlos Alberto Enciso // If the arg was not specified on the command line, always dump all modules. 582*a6487249SZequan Wu if (!Filters.DumpModi) 58375112133SCarlos Alberto Enciso return true; 58475112133SCarlos Alberto Enciso 58575112133SCarlos Alberto Enciso // Otherwise, only dump if this is the same module specified. 58610c11f5cSCarlos Alberto Enciso return (Filters.DumpModi == Idx); 58775112133SCarlos Alberto Enciso } 588