InfoStreamBuilder &getInfoBuilder();
DbiStreamBuilder &getDbiBuilder();
TpiStreamBuilder &getTpiBuilder();
+ TpiStreamBuilder &getIpiBuilder();
Expected<std::unique_ptr<PDBFile>>
build(std::unique_ptr<msf::WritableStream> PdbFileBuffer);
std::unique_ptr<InfoStreamBuilder> Info;
std::unique_ptr<DbiStreamBuilder> Dbi;
std::unique_ptr<TpiStreamBuilder> Tpi;
+ std::unique_ptr<TpiStreamBuilder> Ipi;
};
}
}
class TpiStreamBuilder {
public:
- explicit TpiStreamBuilder(msf::MSFBuilder &Msf);
+ explicit TpiStreamBuilder(msf::MSFBuilder &Msf, uint32_t StreamIdx);
~TpiStreamBuilder();
TpiStreamBuilder(const TpiStreamBuilder &) = delete;
std::unique_ptr<msf::ByteStream> HashValueStream;
const TpiStreamHeader *Header;
+ uint32_t Idx;
};
}
}
TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
if (!Tpi)
- Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf);
+ Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
return *Tpi;
}
+TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
+ if (!Ipi)
+ Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
+ return *Ipi;
+}
+
Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
if (Info) {
if (auto EC = Info->finalizeMsfLayout())
if (auto EC = Tpi->finalizeMsfLayout())
return std::move(EC);
}
+ if (Ipi) {
+ if (auto EC = Ipi->finalizeMsfLayout())
+ return std::move(EC);
+ }
return Msf->build();
}
File->Tpi = std::move(*ExpectedTpi);
}
+ if (Ipi) {
+ auto ExpectedIpi = Ipi->build(*File, *PdbFileBuffer);
+ if (!ExpectedIpi)
+ return ExpectedIpi.takeError();
+ File->Ipi = std::move(*ExpectedIpi);
+ }
+
if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
return llvm::make_error<RawError>(
raw_error_code::corrupt_file,
return EC;
}
+ if (Ipi) {
+ if (auto EC = Ipi->commit(Layout, Buffer))
+ return EC;
+ }
+
return Buffer.commit();
}
\ No newline at end of file
using namespace llvm::pdb;
using namespace llvm::support;
-TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf)
- : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr) {}
+TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
+ : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
+}
TpiStreamBuilder::~TpiStreamBuilder() {}
Error TpiStreamBuilder::finalizeMsfLayout() {
uint32_t Length = calculateSerializedLength();
- if (auto EC = Msf.setStreamSize(StreamTPI, Length))
+ if (auto EC = Msf.setStreamSize(Idx, Length))
return EC;
uint32_t HashBufferSize = calculateHashBufferSize();
if (auto EC = finalize())
return std::move(EC);
- auto StreamData = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
- Buffer, StreamTPI);
+ auto StreamData =
+ MappedBlockStream::createIndexedStream(File.getMsfLayout(), Buffer, Idx);
auto Tpi = llvm::make_unique<TpiStream>(File, std::move(StreamData));
Tpi->Header = Header;
Tpi->TypeRecords = VarStreamArray<codeview::CVType>(TypeRecordStream);
return EC;
auto InfoS =
- WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamTPI);
+ WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
StreamWriter Writer(*InfoS);
if (auto EC = Writer.writeObject(*Header))
IO.mapOptional("PdbStream", Obj.PdbStream);
IO.mapOptional("DbiStream", Obj.DbiStream);
IO.mapOptionalWithContext("TpiStream", Obj.TpiStream, Obj.Allocator);
+ IO.mapOptionalWithContext("IpiStream", Obj.IpiStream, Obj.Allocator);
}
void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
Optional<PdbInfoStream> PdbStream;
Optional<PdbDbiStream> DbiStream;
Optional<PdbTpiStream> TpiStream;
+ Optional<PdbTpiStream> IpiStream;
BumpPtrAllocator &Allocator;
};
if (auto EC = dumpTpiStream())
return EC;
+ if (auto EC = dumpIpiStream())
+ return EC;
+
flush();
return Error::success();
}
return Error::success();
}
+Error YAMLOutputStyle::dumpIpiStream() {
+ if (!opts::pdb2yaml::IpiStream)
+ return Error::success();
+
+ auto IpiS = File.getPDBIpiStream();
+ if (!IpiS)
+ return IpiS.takeError();
+
+ auto &IS = IpiS.get();
+ Obj.IpiStream.emplace();
+ Obj.IpiStream->Version = IS.getTpiVersion();
+ for (auto &Record : IS.types(nullptr)) {
+ yaml::PdbTpiRecord R;
+ R.Record = Record;
+ Obj.IpiStream->Records.push_back(R);
+ }
+
+ return Error::success();
+}
+
void YAMLOutputStyle::flush() {
Out << Obj;
outs().flush();
Error dumpPDBStream();
Error dumpDbiStream();
Error dumpTpiStream();
+ Error dumpIpiStream();
void flush();
cl::desc("Dump the TPI Stream (Stream 3)"),
cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> IpiStream("ipi-stream",
+ cl::desc("Dump the IPI Stream (Stream 5)"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
cl::list<std::string> InputFilename(cl::Positional,
cl::desc("<input PDB file>"), cl::Required,
cl::sub(PdbToYamlSubcommand));
TpiBuilder.addTypeRecord(R.Record);
}
+ if (YamlObj.IpiStream.hasValue()) {
+ auto &IpiBuilder = Builder.getIpiBuilder();
+ IpiBuilder.setVersionHeader(YamlObj.IpiStream->Version);
+ for (const auto &R : YamlObj.IpiStream->Records)
+ IpiBuilder.addTypeRecord(R.Record);
+ }
+
ExitOnErr(Builder.commit(*FileByteStream));
}
extern llvm::cl::opt<bool> DbiModuleInfo;
extern llvm::cl::opt<bool> DbiModuleSourceFileInfo;
extern llvm::cl::opt<bool> TpiStream;
+extern llvm::cl::opt<bool> IpiStream;
extern llvm::cl::list<std::string> InputFilename;
}
}