Error commit();
private:
+ Error initializeModInfoArray();
Error initializeSectionContributionData();
Error initializeSectionHeadersData();
Error initializeSectionMapData();
#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"
class DbiStreamBuilder {
public:
- DbiStreamBuilder();
+ DbiStreamBuilder(BumpPtrAllocator &Allocator);
DbiStreamBuilder(const DbiStreamBuilder &) = delete;
DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete;
uint32_t calculateSerializedLength() const;
+ Error addModuleInfo(StringRef ObjFile, StringRef Module);
+ Error addModuleSourceFile(StringRef Module, StringRef File);
+
Expected<std::unique_ptr<DbiStream>> build(PDBFile &File);
private:
+ uint32_t calculateModiSubstreamSize() const;
+ uint32_t calculateFileInfoSubstreamSize() const;
+ uint32_t calculateNamesBufferSize() const;
+
+ Error generateModiSubstream();
+ Error generateFileInfoSubstream();
+
+ struct ModuleInfo {
+ std::vector<StringRef> SourceFiles;
+ StringRef Obj;
+ StringRef Mod;
+ };
+
+ BumpPtrAllocator &Allocator;
+
Optional<PdbRaw_DbiVer> VerHeader;
uint32_t Age;
uint16_t BuildNumber;
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
+
+ StringMap<std::unique_ptr<ModuleInfo>> ModuleInfos;
+ std::vector<ModuleInfo *> ModuleInfoList;
+
+ StringMap<uint32_t> SourceFileNames;
+
+ codeview::StreamRef NamesBuffer;
+ codeview::ByteStream<true> ModInfoBuffer;
+ codeview::ByteStream<true> FileInfoBuffer;
};
}
}
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/Support/Endian.h"
#include <cstdint>
#include <vector>
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();
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,
};
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();
}
return make_error<RawError>(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<ModInfo> 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))
"Unsupported DBI Section Contribution version");
}
+Error DbiStream::initializeModInfoArray() {
+ if (ModInfoSubstream.getLength() == 0)
+ return Error::success();
+
+ // 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<ModInfo> 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)
}
uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
- return DbgStreams[static_cast<uint16_t>(Type)];
+ uint16_t T = static_cast<uint16_t>(Type);
+ if (T >= DbgStreams.size())
+ return DbiStream::InvalidStreamIndex;
+ return DbgStreams[T];
}
Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
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<RawError>(raw_error_code::invalid_format,
+ "Unexpected bytes found in DBI Stream");
return Error::success();
}
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; }
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>();
+ 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<RawError>(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<RawError>(raw_error_code::no_entry,
+ "The specified module was not found");
+ uint32_t Index = SourceFileNames.size();
+ 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<uint8_t>(Size);
+
+ ModInfoBuffer = ByteStream<true>(MutableArrayRef<uint8_t>(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<RawError>(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<uint8_t>(Size);
+ uint32_t NamesOffset = Size - NameSize;
+
+ FileInfoBuffer = ByteStream<true>(MutableArrayRef<uint8_t>(Data, Size));
+
+ StreamRef MetadataBuffer = StreamRef(FileInfoBuffer).keep_front(NamesOffset);
+ StreamWriter MetadataWriter(MetadataBuffer);
+
+ uint16_t ModiCount = std::min<uint16_t>(UINT16_MAX, ModuleInfos.size());
+ uint16_t FileCount = std::min<uint16_t>(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<uint16_t>(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<RawError>(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<RawError>(raw_error_code::invalid_format,
+ "The names buffer contained unexpected data.");
+
+ if (MetadataWriter.bytesRemaining() > 0)
+ return make_error<RawError>(
+ raw_error_code::invalid_format,
+ "The metadata buffer contained unexpected data.");
+
+ return Error::success();
}
Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) {
static_cast<DbiStream::HeaderInfo *>(DS->getAllocator().Allocate(
sizeof(DbiStream::HeaderInfo),
llvm::AlignOf<DbiStream::HeaderInfo>::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;
H->MachineType = static_cast<uint16_t>(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;
auto Dbi = llvm::make_unique<DbiStream>(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);
}
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) {}
DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
if (!Dbi)
- Dbi = llvm::make_unique<DbiStreamBuilder>();
+ Dbi = llvm::make_unique<DbiStreamBuilder>(File->Allocator);
return *Dbi;
}
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:
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:
IO.mapRequired("PdbDllRbld", Obj.PdbDllRbld);
IO.mapRequired("Flags", Obj.Flags);
IO.mapRequired("MachineType", Obj.MachineType);
+ IO.mapOptional("Modules", Obj.ModInfos);
}
void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
IO.mapRequired("Name", Obj.StreamName);
IO.mapRequired("StreamNum", Obj.StreamNumber);
}
+
+void MappingTraits<PdbDbiModuleInfo>::mapping(IO &IO, PdbDbiModuleInfo &Obj) {
+ IO.mapRequired("Module", Obj.Mod);
+ IO.mapRequired("ObjFile", Obj.Obj);
+ IO.mapOptional("SourceFiles", Obj.SourceFiles);
+}
std::vector<NamedStreamMapping> NamedStreams;
};
+struct PdbDbiModuleInfo {
+ StringRef Obj;
+ StringRef Mod;
+ std::vector<StringRef> SourceFiles;
+};
+
struct PdbDbiStream {
PdbRaw_DbiVer VerHeader;
uint32_t Age;
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
+
+ std::vector<PdbDbiModuleInfo> ModInfos;
};
struct PdbObject {
template <> struct MappingTraits<pdb::yaml::NamedStreamMapping> {
static void mapping(IO &IO, pdb::yaml::NamedStreamMapping &Obj);
};
+
+template <> struct MappingTraits<pdb::yaml::PdbDbiModuleInfo> {
+ static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj);
+};
}
}
LLVM_YAML_IS_FLOW_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
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;
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();
}
cl::opt<bool> DbiStream("dbi-stream",
cl::desc("Dump the DBI Stream (Stream 2)"),
cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool>
+ DbiModuleInfo("dbi-module-info",
+ cl::desc("Dump DBI Module Information (implies -dbi-stream)"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> 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<std::string> InputFilename(cl::Positional,
cl::desc("<input PDB file>"), cl::Required,
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();
extern llvm::cl::opt<bool> StreamDirectory;
extern llvm::cl::opt<bool> PdbStream;
extern llvm::cl::opt<bool> DbiStream;
+extern llvm::cl::opt<bool> DbiModuleInfo;
+extern llvm::cl::opt<bool> DbiModuleSourceFileInfo;
extern llvm::cl::list<std::string> InputFilename;
}
}