Index: include/llvm/DebugInfo/PDB/Raw/DbiStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -106,6 +106,7 @@ Error commit(); private: + Error initializeModInfoArray(); Error initializeSectionContributionData(); Error initializeSectionHeadersData(); Error initializeSectionMapData(); Index: include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h +++ include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h @@ -11,8 +11,10 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Error.h" +#include "llvm/DebugInfo/CodeView/ByteStream.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" @@ -24,7 +26,7 @@ class DbiStreamBuilder { public: - DbiStreamBuilder(); + DbiStreamBuilder(BumpPtrAllocator &Allocator); DbiStreamBuilder(const DbiStreamBuilder &) = delete; DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete; @@ -39,9 +41,27 @@ uint32_t calculateSerializedLength() const; + Error addModuleInfo(StringRef ObjFile, StringRef Module); + Error addModuleSourceFile(StringRef Module, StringRef File); + Expected> build(PDBFile &File); private: + uint32_t calculateModiSubstreamSize() const; + uint32_t calculateFileInfoSubstreamSize() const; + uint32_t calculateNamesBufferSize() const; + + Error generateModiSubstream(); + Error generateFileInfoSubstream(); + + struct ModuleInfo { + std::vector SourceFiles; + StringRef Obj; + StringRef Mod; + }; + + BumpPtrAllocator &Allocator; + Optional VerHeader; uint32_t Age; uint16_t BuildNumber; @@ -49,6 +69,15 @@ uint16_t PdbDllRbld; uint16_t Flags; PDB_Machine MachineType; + + StringMap> ModuleInfos; + std::vector ModuleInfoList; + + StringMap SourceFileNames; + + codeview::StreamRef NamesBuffer; + codeview::ByteStream ModInfoBuffer; + codeview::ByteStream FileInfoBuffer; }; } } Index: include/llvm/DebugInfo/PDB/Raw/ModInfo.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/ModInfo.h +++ include/llvm/DebugInfo/PDB/Raw/ModInfo.h @@ -13,6 +13,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/Support/Endian.h" #include #include @@ -20,8 +21,59 @@ namespace pdb { class ModInfo { + friend class DbiStreamBuilder; + private: - struct FileLayout; + typedef support::ulittle16_t ulittle16_t; + typedef support::ulittle32_t ulittle32_t; + typedef support::little32_t little32_t; + + struct SCBytes { + ulittle16_t Section; + char Padding1[2]; + little32_t Offset; + little32_t Size; + ulittle32_t Characteristics; + ulittle16_t ModuleIndex; + char Padding2[2]; + ulittle32_t DataCrc; + ulittle32_t RelocCrc; + }; + + // struct Flags { + // uint16_t fWritten : 1; // True if ModInfo is dirty + // uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?) + // uint16_t unused : 6; // Reserved + // uint16_t iTSM : 8; // Type Server Index for this module + //}; + const uint16_t HasECFlagMask = 0x2; + + const uint16_t TypeServerIndexMask = 0xFF00; + const uint16_t TypeServerIndexShift = 8; + + struct FileLayout { + ulittle32_t Mod; // Currently opened module. This field is a + // pointer in the reference implementation, but + // that won't work on 64-bit systems, and anyway + // it doesn't make sense to read a pointer from a + // file. For now it is unused, so just ignore it. + SCBytes SC; // First section contribution of this module. + ulittle16_t Flags; // See Flags definition. + ulittle16_t ModDiStream; // Stream Number of module debug info + ulittle32_t SymBytes; // Size of local symbol debug info in above stream + ulittle32_t LineBytes; // Size of line number debug info in above stream + ulittle32_t C13Bytes; // Size of C13 line number info in above stream + ulittle16_t NumFiles; // Number of files contributing to this module + char Padding1[2]; // Padding so the next field is 4-byte aligned. + ulittle32_t FileNameOffs; // array of [0..NumFiles) DBI name buffer offsets. + // This field is a pointer in the reference + // implementation, but as with `Mod`, we ignore it + // for now since it is unused. + ulittle32_t SrcFileNameNI; // Name Index for src file name + ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB + // Null terminated Module name + // Null terminated Obj File Name + }; public: ModInfo(); Index: include/llvm/DebugInfo/PDB/Raw/RawError.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/RawError.h +++ include/llvm/DebugInfo/PDB/Raw/RawError.h @@ -19,11 +19,14 @@ enum class raw_error_code { unspecified = 1, feature_unsupported, + invalid_format, corrupt_file, insufficient_buffer, no_stream, index_out_of_bounds, invalid_block_address, + duplicate_entry, + no_entry, not_writable, invalid_tpi_hash, }; Index: lib/DebugInfo/CodeView/StreamWriter.cpp =================================================================== --- lib/DebugInfo/CodeView/StreamWriter.cpp +++ lib/DebugInfo/CodeView/StreamWriter.cpp @@ -54,7 +54,8 @@ Error StreamWriter::writeStreamRef(StreamRef Ref) { if (auto EC = writeStreamRef(Ref, Ref.getLength())) return EC; - Offset += Ref.getLength(); + // Don't increment Offset here, it is done by the overloaded call to + // writeStreamRef. return Error::success(); } Index: lib/DebugInfo/PDB/Raw/DbiStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -142,14 +142,11 @@ return make_error(raw_error_code::corrupt_file, "DBI type server substream not aligned."); - // Since each ModInfo in the stream is a variable length, we have to iterate - // them to know how many there actually are. - VarStreamArray ModInfoArray; - if (auto EC = Reader.readArray(ModInfoArray, Header->ModiSubstreamSize)) + if (auto EC = + Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize)) + return EC; + if (auto EC = initializeModInfoArray()) return EC; - for (auto &Info : ModInfoArray) { - ModuleInfos.emplace_back(Info); - } if (auto EC = Reader.readStreamRef(SecContrSubstream, Header->SecContrSubstreamSize)) @@ -285,6 +282,24 @@ "Unsupported DBI Section Contribution version"); } +Error DbiStream::initializeModInfoArray() { + if (ModInfoSubstream.getLength() == 0) + return 0; + + // Since each ModInfo in the stream is a variable length, we have to iterate + // them to know how many there actually are. + StreamReader Reader(ModInfoSubstream); + + VarStreamArray ModInfoArray; + if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength())) + return EC; + for (auto &Info : ModInfoArray) { + ModuleInfos.emplace_back(Info); + } + + return Error::success(); +} + // Initializes this->SectionHeaders. Error DbiStream::initializeSectionHeadersData() { if (DbgStreams.size() == 0) @@ -437,7 +452,10 @@ } uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const { - return DbgStreams[static_cast(Type)]; + uint16_t T = static_cast(Type); + if (T >= DbgStreams.size()) + return DbiStream::InvalidStreamIndex; + return DbgStreams[T]; } Expected DbiStream::getFileNameForIndex(uint32_t Index) const { @@ -458,5 +476,26 @@ if (auto EC = Writer.writeObject(*Header)) return EC; + if (auto EC = Writer.writeStreamRef(ModInfoSubstream)) + return EC; + + if (auto EC = Writer.writeStreamRef(SecContrSubstream, + SecContrSubstream.getLength())) + return EC; + if (auto EC = + Writer.writeStreamRef(SecMapSubstream, SecMapSubstream.getLength())) + return EC; + if (auto EC = Writer.writeStreamRef(FileInfoSubstream, + FileInfoSubstream.getLength())) + return EC; + if (auto EC = Writer.writeStreamRef(TypeServerMapSubstream, + TypeServerMapSubstream.getLength())) + return EC; + if (auto EC = Writer.writeStreamRef(ECSubstream, ECSubstream.getLength())) + return EC; + + if (Writer.bytesRemaining() > 0) + return make_error(raw_error_code::invalid_format, + "Unexpected bytes found in DBI Stream"); return Error::success(); } Index: lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp +++ lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp @@ -18,9 +18,13 @@ using namespace llvm::codeview; using namespace llvm::pdb; -DbiStreamBuilder::DbiStreamBuilder() - : Age(1), BuildNumber(0), PdbDllVersion(0), PdbDllRbld(0), Flags(0), - MachineType(PDB_Machine::x86) {} +namespace { +class ModiSubstreamBuilder {}; +} + +DbiStreamBuilder::DbiStreamBuilder(BumpPtrAllocator &Allocator) + : Allocator(Allocator), Age(1), BuildNumber(0), PdbDllVersion(0), + PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86) {} void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; } @@ -38,7 +42,157 @@ uint32_t DbiStreamBuilder::calculateSerializedLength() const { // For now we only support serializing the header. - return sizeof(DbiStream::HeaderInfo); + return sizeof(DbiStream::HeaderInfo) + calculateFileInfoSubstreamSize() + + calculateModiSubstreamSize(); +} + +Error DbiStreamBuilder::addModuleInfo(StringRef ObjFile, StringRef Module) { + auto Entry = llvm::make_unique(); + ModuleInfo *M = Entry.get(); + Entry->Mod = Module; + Entry->Obj = ObjFile; + auto Result = ModuleInfos.insert(std::make_pair(Module, std::move(Entry))); + if (!Result.second) + return make_error(raw_error_code::duplicate_entry, + "The specified module already exists"); + ModuleInfoList.push_back(M); + return Error::success(); +} + +Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) { + auto ModIter = ModuleInfos.find(Module); + if (ModIter == ModuleInfos.end()) + return make_error(raw_error_code::no_entry, + "The specified module was not found"); + uint32_t Index = SourceFileNames.size(); + auto Result = SourceFileNames.insert(std::make_pair(File, Index)); + auto &ModEntry = *ModIter; + ModEntry.second->SourceFiles.push_back(File); + return Error::success(); +} + +uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { + uint32_t Size = 0; + for (const auto &M : ModuleInfoList) { + Size += sizeof(ModInfo::FileLayout); + Size += M->Mod.size() + 1; + Size += M->Obj.size() + 1; + } + return Size; +} + +uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const { + // ulittle16_t NumModules; + // ulittle16_t NumSourceFiles; + // ulittle16_t ModIndices[NumModules]; + // ulittle16_t ModFileCounts[NumModules]; + // ulittle32_t FileNameOffsets[NumSourceFiles]; + // char Names[NumSourceFiles][]; + uint32_t Size = 0; + Size += sizeof(ulittle16_t); // NumModules + Size += sizeof(ulittle16_t); // NumSourceFiles + Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModIndices + Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModFileCounts + uint32_t NumFileInfos = 0; + for (const auto &M : ModuleInfoList) + NumFileInfos += M->SourceFiles.size(); + Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets + Size += calculateNamesBufferSize(); + return Size; +} + +uint32_t DbiStreamBuilder::calculateNamesBufferSize() const { + uint32_t Size = 0; + for (const auto &F : SourceFileNames) { + Size += F.getKeyLength() + 1; // Names[I]; + } + return Size; +} + +Error DbiStreamBuilder::generateModiSubstream() { + uint32_t Size = calculateModiSubstreamSize(); + auto Data = Allocator.Allocate(Size); + + ModInfoBuffer = ByteStream(MutableArrayRef(Data, Size)); + + StreamWriter ModiWriter(ModInfoBuffer); + for (const auto &M : ModuleInfoList) { + ModInfo::FileLayout Layout = {}; + Layout.ModDiStream = DbiStream::InvalidStreamIndex; + Layout.NumFiles = M->SourceFiles.size(); + if (auto EC = ModiWriter.writeObject(Layout)) + return EC; + if (auto EC = ModiWriter.writeZeroString(M->Mod)) + return EC; + if (auto EC = ModiWriter.writeZeroString(M->Obj)) + return EC; + } + if (ModiWriter.bytesRemaining() != 0) + return make_error(raw_error_code::invalid_format, + "Unexpected bytes in Modi Stream Data"); + return Error::success(); +} + +Error DbiStreamBuilder::generateFileInfoSubstream() { + uint32_t Size = calculateFileInfoSubstreamSize(); + uint32_t NameSize = calculateNamesBufferSize(); + auto Data = Allocator.Allocate(Size); + uint32_t NamesOffset = Size - NameSize; + + FileInfoBuffer = ByteStream(MutableArrayRef(Data, Size)); + + StreamRef MetadataBuffer = StreamRef(FileInfoBuffer).keep_front(NamesOffset); + StreamWriter MetadataWriter(MetadataBuffer); + + uint16_t ModiCount = std::min(UINT16_MAX, ModuleInfos.size()); + uint16_t FileCount = std::min(UINT16_MAX, SourceFileNames.size()); + if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules + return EC; + if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles + return EC; + for (uint16_t I = 0; I < ModiCount; ++I) { + if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices + return EC; + } + for (const auto MI : ModuleInfoList) { + FileCount = static_cast(MI->SourceFiles.size()); + if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts + return EC; + } + + // Before writing the FileNameOffsets array, write the NamesBuffer array. + // A side effect of this is that this will actually compute the various + // file name offsets, so we can then go back and write the FileNameOffsets + // array to the other substream. + NamesBuffer = StreamRef(FileInfoBuffer).drop_front(NamesOffset); + StreamWriter NameBufferWriter(NamesBuffer); + for (auto &Name : SourceFileNames) { + Name.second = NameBufferWriter.getOffset(); + if (auto EC = NameBufferWriter.writeZeroString(Name.getKey())) + return EC; + } + + for (const auto MI : ModuleInfoList) { + for (StringRef Name : MI->SourceFiles) { + auto Result = SourceFileNames.find(Name); + if (Result == SourceFileNames.end()) + return make_error(raw_error_code::no_entry, + "The source file was not found."); + if (auto EC = MetadataWriter.writeInteger(Result->second)) + return EC; + } + } + + if (NameBufferWriter.bytesRemaining() > 0) + return make_error(raw_error_code::invalid_format, + "The names buffer contained unexpected data."); + + if (MetadataWriter.bytesRemaining() > 0) + return make_error( + raw_error_code::invalid_format, + "The metadata buffer contained unexpected data."); + + return Error::success(); } Expected> DbiStreamBuilder::build(PDBFile &File) { @@ -54,6 +208,12 @@ static_cast(DS->getAllocator().Allocate( sizeof(DbiStream::HeaderInfo), llvm::AlignOf::Alignment)); + + if (auto EC = generateModiSubstream()) + return std::move(EC); + if (auto EC = generateFileInfoSubstream()) + return std::move(EC); + H->VersionHeader = *VerHeader; H->VersionSignature = -1; H->Age = Age; @@ -64,8 +224,8 @@ H->MachineType = static_cast(MachineType); H->ECSubstreamSize = 0; - H->FileInfoSize = 0; - H->ModiSubstreamSize = 0; + H->FileInfoSize = FileInfoBuffer.getLength(); + H->ModiSubstreamSize = ModInfoBuffer.getLength(); H->OptionalDbgHdrSize = 0; H->SecContrSubstreamSize = 0; H->SectionMapSize = 0; @@ -77,5 +237,11 @@ auto Dbi = llvm::make_unique(File, std::move(DS)); Dbi->Header = H; + Dbi->FileInfoSubstream = StreamRef(FileInfoBuffer); + Dbi->ModInfoSubstream = StreamRef(ModInfoBuffer); + if (auto EC = Dbi->initializeModInfoArray()) + return std::move(EC); + if (auto EC = Dbi->initializeFileInfo()) + return std::move(EC); return std::move(Dbi); } Index: lib/DebugInfo/PDB/Raw/ModInfo.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/ModInfo.cpp +++ lib/DebugInfo/PDB/Raw/ModInfo.cpp @@ -17,55 +17,6 @@ using namespace llvm::pdb; using namespace llvm::support; -namespace { - -struct SCBytes { - ulittle16_t Section; - char Padding1[2]; - little32_t Offset; - little32_t Size; - ulittle32_t Characteristics; - ulittle16_t ModuleIndex; - char Padding2[2]; - ulittle32_t DataCrc; - ulittle32_t RelocCrc; -}; - -// struct Flags { -// uint16_t fWritten : 1; // True if ModInfo is dirty -// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?) -// uint16_t unused : 6; // Reserved -// uint16_t iTSM : 8; // Type Server Index for this module -//}; -const uint16_t HasECFlagMask = 0x2; - -const uint16_t TypeServerIndexMask = 0xFF00; -const uint16_t TypeServerIndexShift = 8; -} - -struct ModInfo::FileLayout { - ulittle32_t Mod; // Currently opened module. This field is a - // pointer in the reference implementation, but - // that won't work on 64-bit systems, and anyway - // it doesn't make sense to read a pointer from a - // file. For now it is unused, so just ignore it. - SCBytes SC; // First section contribution of this module. - ulittle16_t Flags; // See Flags definition. - ulittle16_t ModDiStream; // Stream Number of module debug info - ulittle32_t SymBytes; // Size of local symbol debug info in above stream - ulittle32_t LineBytes; // Size of line number debug info in above stream - ulittle32_t C13Bytes; // Size of C13 line number info in above stream - ulittle16_t NumFiles; // Number of files contributing to this module - char Padding1[2]; // Padding so the next field is 4-byte aligned. - ulittle32_t FileNameOffs; // array of [0..NumFiles) DBI name buffer offsets. - // This field is a pointer in the reference - // implementation, but as with `Mod`, we ignore it - // for now since it is unused. - ulittle32_t SrcFileNameNI; // Name Index for src file name - ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB - // Null terminated Module name - // Null terminated Obj File Name -}; ModInfo::ModInfo() : Layout(nullptr) {} Index: lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp +++ lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp @@ -53,7 +53,7 @@ DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() { if (!Dbi) - Dbi = llvm::make_unique(); + Dbi = llvm::make_unique(File->Allocator); return *Dbi; } Index: lib/DebugInfo/PDB/Raw/RawError.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/RawError.cpp +++ lib/DebugInfo/PDB/Raw/RawError.cpp @@ -19,6 +19,8 @@ return "An unknown error has occurred."; case raw_error_code::feature_unsupported: return "The feature is unsupported by the implementation."; + case raw_error_code::invalid_format: + return "The record is in an unexpected format."; case raw_error_code::corrupt_file: return "The PDB file is corrupt."; case raw_error_code::insufficient_buffer: @@ -30,6 +32,10 @@ return "The specified item does not exist in the array."; case raw_error_code::invalid_block_address: return "The specified block address is not valid."; + case raw_error_code::duplicate_entry: + return "The entry already exists."; + case raw_error_code::no_entry: + return "The entry does not exist."; case raw_error_code::not_writable: return "The PDB does not support writing."; case raw_error_code::invalid_tpi_hash: Index: tools/llvm-pdbdump/PdbYaml.h =================================================================== --- tools/llvm-pdbdump/PdbYaml.h +++ tools/llvm-pdbdump/PdbYaml.h @@ -51,6 +51,12 @@ std::vector NamedStreams; }; +struct PdbDbiModuleInfo { + StringRef Obj; + StringRef Mod; + std::vector SourceFiles; +}; + struct PdbDbiStream { PdbRaw_DbiVer VerHeader; uint32_t Age; @@ -59,6 +65,8 @@ uint16_t PdbDllRbld; uint16_t Flags; PDB_Machine MachineType; + + std::vector ModInfos; }; struct PdbObject { @@ -102,11 +110,17 @@ template <> struct MappingTraits { static void mapping(IO &IO, pdb::yaml::NamedStreamMapping &Obj); }; + +template <> struct MappingTraits { + static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj); +}; } } LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) #endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H Index: tools/llvm-pdbdump/PdbYaml.cpp =================================================================== --- tools/llvm-pdbdump/PdbYaml.cpp +++ tools/llvm-pdbdump/PdbYaml.cpp @@ -153,6 +153,7 @@ IO.mapRequired("PdbDllRbld", Obj.PdbDllRbld); IO.mapRequired("Flags", Obj.Flags); IO.mapRequired("MachineType", Obj.MachineType); + IO.mapOptional("Modules", Obj.ModInfos); } void MappingTraits::mapping(IO &IO, @@ -160,3 +161,9 @@ IO.mapRequired("Name", Obj.StreamName); IO.mapRequired("StreamNum", Obj.StreamNumber); } + +void MappingTraits::mapping(IO &IO, PdbDbiModuleInfo &Obj) { + IO.mapRequired("Module", Obj.Mod); + IO.mapRequired("ObjFile", Obj.Obj); + IO.mapOptional("SourceFiles", Obj.SourceFiles); +} Index: tools/llvm-pdbdump/YAMLOutputStyle.cpp =================================================================== --- tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -25,6 +25,10 @@ Error YAMLOutputStyle::dump() { if (opts::pdb2yaml::StreamDirectory) opts::pdb2yaml::StreamMetadata = true; + if (opts::pdb2yaml::DbiModuleSourceFileInfo) + opts::pdb2yaml::DbiModuleInfo = true; + if (opts::pdb2yaml::DbiModuleInfo) + opts::pdb2yaml::DbiStream = true; if (auto EC = dumpFileHeaders()) return EC; @@ -133,6 +137,16 @@ Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld(); Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion(); Obj.DbiStream->VerHeader = DS.getDbiVersion(); + if (opts::pdb2yaml::DbiModuleInfo) { + for (const auto &MI : DS.modules()) { + yaml::PdbDbiModuleInfo DMI; + DMI.Mod = MI.Info.getModuleName(); + DMI.Obj = MI.Info.getObjFileName(); + if (opts::pdb2yaml::DbiModuleSourceFileInfo) + DMI.SourceFiles = MI.SourceFiles; + Obj.DbiStream->ModInfos.push_back(DMI); + } + } return Error::success(); } Index: tools/llvm-pdbdump/llvm-pdbdump.h =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.h +++ tools/llvm-pdbdump/llvm-pdbdump.h @@ -62,6 +62,8 @@ extern llvm::cl::opt StreamDirectory; extern llvm::cl::opt PdbStream; extern llvm::cl::opt DbiStream; +extern llvm::cl::opt DbiModuleInfo; +extern llvm::cl::opt DbiModuleSourceFileInfo; extern llvm::cl::list InputFilename; } } Index: tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.cpp +++ tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -285,6 +285,16 @@ cl::opt DbiStream("dbi-stream", cl::desc("Dump the DBI Stream (Stream 2)"), cl::sub(PdbToYamlSubcommand), cl::init(false)); +cl::opt + DbiModuleInfo("dbi-module-info", + cl::desc("Dump DBI Module Information (implies -dbi-stream)"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + +cl::opt DbiModuleSourceFileInfo( + "dbi-module-source-info", + cl::desc( + "Dump DBI Module Source File Information (implies -dbi-module-info"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); cl::list InputFilename(cl::Positional, cl::desc(""), cl::Required, @@ -375,6 +385,11 @@ DbiBuilder.setPdbDllRbld(YamlObj.DbiStream->PdbDllRbld); DbiBuilder.setPdbDllVersion(YamlObj.DbiStream->PdbDllVersion); DbiBuilder.setVersionHeader(YamlObj.DbiStream->VerHeader); + for (const auto &MI : YamlObj.DbiStream->ModInfos) { + ExitOnErr(DbiBuilder.addModuleInfo(MI.Obj, MI.Mod)); + for (auto S : MI.SourceFiles) + ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S)); + } } auto Pdb = Builder.build();